Windows 에서 ubuntu 로 개발하기

Windows 에서 WLS 을 이용하여 Linux 를 설치하고 개발 환경을 구성해 보겠습니다.

대부분은 Windows


대부분의 PC 는 Windows 환경입니다. 저도 회사에도 개인적으로도 Windows 환경에서 개발을 하고 있습니다. 저 뿐만 아니라 많은 개발자들이 Windows 환경에서 개발합니다.

OS 시장 점유률

🔗 statcounter - Desktop Operating System Market Share Worldwide

개발은 맥북으로 !


많은 분들이 이런 말은 한번쯤은 들어보고, 또 많은 사람이 이 말에 동의 합니다. 그렇다면 왜 다들 그렇게 말하는 것일까요? 제가 느낀 Windows 에서 개발하면서 불편했던 점은 다음과 같습니다.

  1. 특정 라이브러리가 Windows 에서 지원되지 않거나, 동작하지 않는 경우
  2. 개발 이후 배포가 이루어지는 실제 서버 환경은 대부분 리눅스(Linux)를 운영체제 라는 점

배포 후 실제 코드가 동작하는 ‘서버와는 다른 환경에서 개발과 테스트를 할 수 밖에 없다’는게 가장 큰 불편한 점이 였습니다.

대안 : 클라우드 환경에서 개발하기


그래서 대안으로 생각했던 방법은 AWS EC2 와 같은 서비스를 이용하는 것 입니다. EC2 에도 vscode 를 연결해 개발하는게 충분히 가능했습니다. 하지만 여기도 문제가 있었습니다. 바로 EC2 자체의 성능이 문제였습니다.

EC2 프리티어

> AWS EC2 프리티어의 성능

프리티어(FreeTier) EC2의 경우는 cpu 1개와 1GB 메모리 환경입니다. 실제로 vscode 를 연결해서 개발해보시면 CPU 사용량이 급격하게 올라가면서 비번히 EC2 자체가 먹통이 됩니다. 물론 더 성능이 좋은 EC2 를 사용하면 좋겠지만, 비용 문제도 무시 할 수 없습니다.

Windows 에서 Linux 설치하기


지금 대부분 사용하고 있는 컴퓨터는 프리티어 EC2 보다 훨씬 성능이 좋습니다. 저도 5년이 넘은 컴퓨터를 개발하는데 잘 사용하고 있습니다. 그렇다면 우리 컴퓨터에 Linux 를 설치하면 되겠죠?

Windows 에 Linux 환경을 구축하는 방법은 크게 3가지 정도 입니다.

  1. 멀티 부팅으로 Linux 설치
  2. 가상 머신으로 Linux 설치
  3. WSL 이용 하기

이러한 선택지 중에서 가장 쉽고 편리한 WSL을 이용해서 개발 환경을 구축해 보겠습니다. 여기서는 Ubuntu 환경을 구축해 보도록 하겠습니다.

WSL 환경 구성도


WSL 은 1버전과 2버전으로 나눠져 있습니다. 여기서에는 WSL2 을 이용해서 Ubuntu 를 설치하고 vscode 로 연결 후 간단한 Python Flask 앱을 동작 시킵니다. 그리고 Windows 에 설치된 MariaDB 에서 데이터를 가져오는 구성입니다.

EC2 프리티어

> WSL 환경 구성

WSL 활성화 및 Ubuntu 설치


Windows 10 버전 2004 이상(빌드 19041 이상) 또는 Windows 11 에서 Powershell 을 관리자 권한으로 실행 합니다. 먼저 아래 명령으로 WSL 기능을 활성화하면서, 기본 Linux 배포판을 자동으로 함께 설치합니다.

Powershell
> wsl --install

wsl --install 명령은 WSL 과 기본 Linux 배포판을 자동으로 설치합니다. 대부분의 경우 Ubuntu가 기본으로 설치됩니다. 설치 후 자동으로 설치된 배포판이 동작 합니다.

설치 후 사용자 이름과 암호를 입력합니다. 이 계정은 sudo(슈퍼 사용자 작업) 관리 명령을 실행할 수 있는 Linux 관리자로 간주됩니다. 저는 ubuntu 라고 사용자 이름과 비번을 입력하겠습니다.

Powershell
Enter new UNIX username: ubuntu
Enter new UNIX password: ubuntu
Retype new UNIX password: ubuntu
passwd: password updated successfully
Installation successful!

여기까지 하셨으면 Ubuntu 환경으로 쉘이 넘어 간걸 확인 하실 수 있습니다. 열린 창을 닫거나 exit 명령어로 Ubuntu 환경을 종료 할 수 있습니다.

ubuntu@DESKTOP-FR5BQJB:~$

WSL 기본 대상 변경


다시 PowerShell 에서 몇가지 명령어를 더 확인 해보겠습니다.

wsl -l -v 명령으로 WSL 로 실행 가능한 배포판 목록을 볼 수 있습니다. * 기호가 붙어있는 대상이 WSL 을 실행 하면 동작하게 되는 대상입니다. STATE 현재 동작 중인지, VERSION 은 2 라는 값은 WSL2 를 의미합니다. 참고로 Docker Desktop 같은 경우도 WSL2 를 이용해 동작하는 것을 알 수 있습니다.

Powershell
> wsl -l -v
  NAME                   STATE           VERSION
* Ubuntu                 Running         2
  docker-desktop-data    Running         2
  docker-desktop         Running         2

만약 Docker Desktop 이 설치된 환경에서 기본 선택 대상이 docker 로 지정되어 있는 경우 이를 변경해주는 작업이 필요합니다. 아래의 명령에서 대상의 NAME 을 지정해 변경 가능합니다.

Powershell
> wsl -s {NAME}

> wsl -s Ubuntu

배포판 지정 설치 & 삭제


특정 Linux 배포판을 설치하려면 해당 배포판의 이름을 명시적으로 지정해서 설치가 가능합니다. 우선 설치 가능한 배포판 목록을 wsl -l --online 명령어를 통해 확인 합니다.

Powershell
> wsl -l --online
NAME                                   FRIENDLY NAME
Ubuntu                                 Ubuntu
Debian                                 Debian GNU/Linux
kali-linux                             Kali Linux Rolling
Ubuntu-18.04                           Ubuntu 18.04 LTS

지정 가능한 배포판의 NAME 을 아래의 명령어로 설치합니다.

Powershell
> wsl --install -d Debian

삭제는 다음 명령어로 삭제 배포판의 NAME 을 지정합니다. WSL에서 제거하고, 해당 배포판의 모든 데이터를 삭제합니다. 다시 wsl --install {NAME} 명령으로 설치하면 새로운 데이터로 배포판을 사용할 수 있습니다.

만약 배포판의 설치 패키지까지 완전히 삭제하려면, 설치된 앱에서 삭제를 해야 합니다. 이렇게 하면 배포판의 설치 패키지와 모든 데이터가 시스템에서 완전히 제거됩니다.

Powershell
> wsl --unregister Debian

vscode 연동하기


WSL 과 vscode 를 연동하기 위해서 우선 WSL Extension 설치합니다.

Extension: WSL

🔗 Extension: WSL

vscode 에서 ctrl + p 로 명령어 입력창을 열고 Remote: Show Remote Menu 라고 입력합니다. 또는 vscode 에서 좌측 하단에 아래와 같은 아이콘을 클릭합니다. 열리는 메뉴에서 Connect to WSL 을 선택하면 WSL 환경으로 vscode 가 연결됩니다. 이제 WSL 접속한 상태에서 폴더를 열면 손쉽게 파일을 생성하고 작성 할 수 있습니다.

alt text

> Open Remote Menu

alt text

> WSL 에 연결하자

WSL 에서 Host MariaDB 연동


WSL은 가상 머신이므로 localhost가 WSL 인스턴스를 가리킵니다. WSL 에서 Windows 를 Host 라고 지칭 합니다.

WSL 에서 Host 에 설치 되어있는 MariaDB에 접속 해보겠습니다. 이 경우, Host 실제 IP 주소를 찾아 사용해야 Host 에 설치된 MariaDB에 접속 할 수 있습니다. WSL 에서 Windows Host 주소는 다음 명령으로 찾을 수 있습니다.

Ubuntu
$ ip route show | grep -i default | awk '{ print $3}'

172.25.16.1

WSL 의 IP 주소를 찾는 방법은 다음과 같습니다. 출력된 정보 중 inet 라인을 찾습니다. 이 라인에는 WSL2의 IP 주소가 포함되어 있습니다. 172.25.18.88 가 WSL IP 주소입니다.

Ubuntu
$ ip addr show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group
    link/ether 00:15:5d:68:e3:09 brd ff:ff:ff:ff:ff:ff
    inet 172.25.18.88/20 brd 172.25.31.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::215:5dff:fe68:e309/64 scope link 
       valid_lft forever preferred_lft forever

반드시 기억해야 할 점은 위에서 찾은 Host 의 주소와 WSL 의 주소는 언제든 변경될 수 있는 동적인 IP 주소입니다.

연결 테스트를 위해 필요한 패키지를 설치하고, 찾은 Host 주소 172.25.16.1 를 사용해 MariaDB에 접속을 시도합니다.

Ubuntu
$ sudo apt install mariadb-client-core-10.6
$ mariadb -h {host_ip} -P 3306 -u {your_username} -p

$ mariadb -h 172.25.16.1 -P 3306 -u root -p

여기서 아래와 같은 에러 메세지가 나오면 MariaDB에서 특정 사용자에게 IP에 대한 접근 권한을 부여해주면 접속이 가능합니다. 아래 명령에서 'username'@'WSL_ip' 으로 가능합니다. FLUSH PRIVILEGES; 는 사용자 계정이나 권한 설정을 변경한 후에, 이 변경사항을 즉시 적용해 줍니다.

여기서는 개발 환경이니 WSL 의 ip 가 변경되도 상관없게 전체 IP 에 대해서 접근 권한을 부여하겠습니다. 'username'@'%' 으로 명령을 실행하면 전체 ip 에 대해서 접근 권한을 부여합니다.

ERROR 1045 (28000): Access denied for user 'root'@'172.25.18.88' (using password: YES)
MariaDB
GRANT ALL PRIVILEGES ON *.* TO 'user_id'@'WSL_ip or %' IDENTIFIED BY 'your_password';

GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '1234qwer!';

FLUSH PRIVILEGES;

Host 주소 .env 에 자동삽입


이제 WSL 에서 Host 의 MariaDB 까지 잘 접속되는것을 확인했습니다. 이제 vscode 로 접속해서 개발하면 되겠죠? 저는 /home/ubuntu/flask-app 이라는 폴더를 만들고 Host MariaDB 정보를 .env 파일을 만들어서 작성했습니다.

.env
DB_ENGINE=mariadb+pymysql
DB_USER=root
DB_PASSWORD=1234qwer!
DB_HOST=172.25.16.1
DB_PORT=3306
DB_NAME=test

하지만 여기서 동적인 IP 를 가지는 Host 의 주소가 문제가 됩니다. Host 의 주소가 변경 될때마다 매번 접속 정보를 변경해줘야 하는 불편함이 있습니다. 이런 불편함을 해결하기 위해서 WSL이 매번 실행되면 .env 파일에 동적으로 변경 될 수 있게 해봅시다.

/etc/wsl.conf 파일은 WSL 이 실행될때 마다 동작을 설정하는데 사용됩니다. 여기서 [boot] 섹션에 command 옵션을 작성합니다.

Ubuntu
$ sudo vim /etc/wsl.conf
wsl.conf
[boot]
systemd=true

command = env_path=/home/ubuntu/flask-app/.env; \
        ip_address=$(ip route show | grep -i 'default' | awk '{ print $3}'); \
        sed -i "s/^DB_HOST=.*/DB_HOST=$ip_address/" $env_pat

이제 WSL 이 재부팅 될때마다 해당 command 을 실행해 Host의 IP 주소를 변경해줍니다. wsl 을 아래의 명령으로 종료 후 재시작 해보면 됩니다.

PowerShell
> wsl --terminate {NAME}

> wsl --terminate Ubuntu

flask-app 작성


이제 간단한 flask 코드를 작성하고, localhost:5000 으로 데이터를 잘 받아오는지 확인합니다. vscode 에서 F5 디버깅으로 동작시켜서 확인합니다.

app.py
from flask import Flask
from sqlalchemy.sql import text
from sqlalchemy.orm import Session
from sqlalchemy import make_engine

import os
from dotenv import load_dotenv

load_dotenv()

app = Flask(__name__)

DB_ENGINE = os.getenv("DB_ENGINE")
DB_USER = os.getenv("DB_USER")
DB_PASSWORD = os.getenv("DB_PASSWORD")
DB_HOST = os.getenv("DB_HOST")
DB_PORT = os.getenv("DB_PORT")
DB_NAME = os.getenv("DB_NAME")

engine = make_engine(
    url=f"{DB_ENGINE}://{DB_USER}:{DB_PASSWORD}@{DB_HOST}/{DB_NAME}"
)

@app.route("/")
def test_query():
    with Session(engine) as session:
        return session.execute(text("SELECT 'Hello WSL!'")).scalar_one()


if __name__ == "__main__":
    app.run(debug=True)

더 해보기


Windows 에서 WSL(Windows Subsystem for Linux) 을 이용해서 배포 환경과 유사하게 개발 환경을 구축해 봤습니다.

더 나아가서 Nginx 와 같은, 실제 자신의 배포 환경과 유사하게 세팅해서 개발을 해 보시길 바랍니다. 그렇게하면 실제 배포시 일어날수 있는 문제를 적절히 대응 할 수 있습니다! 😊

WSL ubuntu