Windows 에서 ubuntu 로 개발하기
Windows 에서 WLS 을 이용하여 Linux 를 설치하고 개발 환경을 구성해 보겠습니다.
대부분은 Windows
대부분의 PC 는 Windows 환경입니다. 저도 회사에도 개인적으로도 Windows 환경에서 개발을 하고 있습니다. 저 뿐만 아니라 많은 개발자들이 Windows 환경에서 개발합니다.
🔗 statcounter - Desktop Operating System Market Share Worldwide
개발은 맥북으로 !
많은 분들이 이런 말은 한번쯤은 들어보고, 또 많은 사람이 이 말에 동의 합니다. 그렇다면 왜 다들 그렇게 말하는 것일까요? 제가 느낀 Windows 에서 개발하면서 불편했던 점은 다음과 같습니다.
- 특정 라이브러리가 Windows 에서 지원되지 않거나, 동작하지 않는 경우
- 개발 이후 배포가 이루어지는 실제 서버 환경은 대부분 리눅스(Linux)를 운영체제 라는 점
배포 후 실제 코드가 동작하는 ‘서버와는 다른 환경에서 개발과 테스트를 할 수 밖에 없다’는게 가장 큰 불편한 점이 였습니다.
대안 : 클라우드 환경에서 개발하기
그래서 대안으로 생각했던 방법은 AWS EC2 와 같은 서비스를 이용하는 것 입니다. EC2 에도 vscode 를 연결해 개발하는게 충분히 가능했습니다. 하지만 여기도 문제가 있었습니다. 바로 EC2 자체의 성능이 문제였습니다.
> AWS EC2 프리티어의 성능
프리티어(FreeTier) EC2의 경우는 cpu 1개와 1GB 메모리 환경입니다. 실제로 vscode 를 연결해서 개발해보시면 CPU 사용량이 급격하게 올라가면서 비번히 EC2 자체가 먹통이 됩니다. 물론 더 성능이 좋은 EC2 를 사용하면 좋겠지만, 비용 문제도 무시 할 수 없습니다.
Windows 에서 Linux 설치하기
지금 대부분 사용하고 있는 컴퓨터는 프리티어 EC2 보다 훨씬 성능이 좋습니다. 저도 5년이 넘은 컴퓨터를 개발하는데 잘 사용하고 있습니다. 그렇다면 우리 컴퓨터에 Linux 를 설치하면 되겠죠?
Windows 에 Linux 환경을 구축하는 방법은 크게 3가지 정도 입니다.
- 멀티 부팅으로 Linux 설치
- 가상 머신으로 Linux 설치
- WSL 이용 하기
이러한 선택지 중에서 가장 쉽고 편리한 WSL을 이용해서 개발 환경을 구축해 보겠습니다. 여기서는 Ubuntu
환경을 구축해 보도록 하겠습니다.
WSL 환경 구성도
WSL 은 1버전과 2버전으로 나눠져 있습니다. 여기서에는 WSL2 을 이용해서 Ubuntu 를 설치하고 vscode 로 연결 후 간단한 Python Flask 앱을 동작 시킵니다. 그리고 Windows 에 설치된 MariaDB 에서 데이터를 가져오는 구성입니다.
> WSL 환경 구성
WSL 활성화 및 Ubuntu 설치
Windows 10 버전 2004 이상(빌드 19041 이상) 또는 Windows 11 에서 Powershell 을 관리자 권한으로 실행 합니다. 먼저 아래 명령으로 WSL 기능을 활성화하면서, 기본 Linux 배포판을 자동으로 함께 설치합니다.
> wsl --install
wsl --install
명령은 WSL 과 기본 Linux 배포판을 자동으로 설치합니다. 대부분의 경우 Ubuntu가 기본으로 설치됩니다. 설치 후 자동으로 설치된 배포판이 동작 합니다.
설치 후 사용자 이름과 암호를 입력합니다. 이 계정은 sudo(슈퍼 사용자 작업) 관리 명령을 실행할 수 있는 Linux 관리자로 간주됩니다. 저는 ubuntu
라고 사용자 이름과 비번을 입력하겠습니다.
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 를 이용해 동작하는 것을 알 수 있습니다.
> wsl -l -v
NAME STATE VERSION
* Ubuntu Running 2
docker-desktop-data Running 2
docker-desktop Running 2
만약 Docker Desktop 이 설치된 환경에서 기본 선택 대상이 docker 로 지정되어 있는 경우 이를 변경해주는 작업이 필요합니다. 아래의 명령에서 대상의 NAME
을 지정해 변경 가능합니다.
> wsl -s {NAME}
> wsl -s Ubuntu
배포판 지정 설치 & 삭제
특정 Linux 배포판을 설치하려면 해당 배포판의 이름을 명시적으로 지정해서 설치가 가능합니다. 우선 설치 가능한 배포판 목록을 wsl -l --online
명령어를 통해 확인 합니다.
> 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
을 아래의 명령어로 설치합니다.
> wsl --install -d Debian
삭제는 다음 명령어로 삭제 배포판의 NAME
을 지정합니다. WSL에서 제거하고, 해당 배포판의 모든 데이터를 삭제합니다. 다시 wsl --install {NAME}
명령으로 설치하면 새로운 데이터로 배포판을 사용할 수 있습니다.
만약 배포판의 설치 패키지까지 완전히 삭제하려면, 설치된 앱에서 삭제를 해야 합니다. 이렇게 하면 배포판의 설치 패키지와 모든 데이터가 시스템에서 완전히 제거됩니다.
> wsl --unregister Debian
vscode 연동하기
WSL 과 vscode 를 연동하기 위해서 우선 WSL Extension
설치합니다.
vscode 에서 ctrl
+ p
로 명령어 입력창을 열고 Remote: Show Remote Menu
라고 입력합니다. 또는 vscode 에서 좌측 하단에 아래와 같은 아이콘을 클릭합니다. 열리는 메뉴에서 Connect to WSL
을 선택하면 WSL 환경으로 vscode 가 연결됩니다. 이제 WSL 접속한 상태에서 폴더를 열면 손쉽게 파일을 생성하고 작성 할 수 있습니다.
> Open Remote Menu
> WSL 에 연결하자
WSL 에서 Host MariaDB 연동
WSL은 가상 머신이므로 localhost가 WSL 인스턴스를 가리킵니다. WSL 에서 Windows 를 Host
라고 지칭 합니다.
WSL 에서 Host 에 설치 되어있는 MariaDB에 접속 해보겠습니다. 이 경우, Host 실제 IP 주소를 찾아 사용해야 Host 에 설치된 MariaDB에 접속 할 수 있습니다. WSL 에서 Windows Host 주소는 다음 명령으로 찾을 수 있습니다.
$ ip route show | grep -i default | awk '{ print $3}'
172.25.16.1
WSL 의 IP 주소를 찾는 방법은 다음과 같습니다. 출력된 정보 중 inet
라인을 찾습니다. 이 라인에는 WSL2의 IP 주소가 포함되어 있습니다. 172.25.18.88
가 WSL IP 주소입니다.
$ 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에 접속을 시도합니다.
$ 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)
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
파일을 만들어서 작성했습니다.
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
옵션을 작성합니다.
$ sudo vim /etc/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 을 아래의 명령으로 종료 후 재시작 해보면 됩니다.
> wsl --terminate {NAME}
> wsl --terminate Ubuntu
flask-app 작성
이제 간단한 flask 코드를 작성하고, localhost:5000
으로 데이터를 잘 받아오는지 확인합니다. vscode 에서 F5
디버깅으로 동작시켜서 확인합니다.
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
와 같은, 실제 자신의 배포 환경과 유사하게 세팅해서 개발을 해 보시길 바랍니다. 그렇게하면 실제 배포시 일어날수 있는 문제를 적절히 대응 할 수 있습니다! 😊