uWSGI 설치 & Emperor 설정 | Ubuntu 서버 세팅, 이 순서대로 하면 끝 (12)
uWSGI – 빠르고 유연한 Python 앱 배포
서버 세팅을 하면서 가장 많이 서버를 리셋하게 만든 건, 다름 아닌 이녀석 uWSGI였다.
특히 Emperor 모드 설정까지 포함하면, 권한 문제, 디렉토리 구조, 서비스 등록까지 한 번에 잘 되는 일이 드물었다.
여기 적는 이 순서를 그대로 따라가기만 하면 나처럼 삽질은 하지 않아도 될 거다.
(uWSGI로만 서버를 몇 번은 초기화했는지… 그 기억을 교훈 삼아 하나씩 정리해본다.)
1. uWSGI 설치
uWSGI는 Python 패키지로 설치되며,
현재 어떤 Python 환경에 설치하느냐가 매우 중요하다.
특히 pyenv를 사용 중이라면, 먼저 원하는 Python 버전이 선택되어 있는지 확인하자:
pyenv versions
현재 선택된 버전 앞에는 * 표시가 붙는다.
예: * 3.12.6 (set by /home/USERNAME/.pyenv/version)
이 상태에서 아래 명령어를 실행하면,
uWSGI는 pyenv가 선택한 버전의 환경에 정확히 설치된다:
pip install uwsgi
uwsgi --version # 설치 확인
⚠️ 주의: sudo pip install은 절대 사용하지 말 것!
시스템 전역 Python 환경에 설치되면서 충돌이나 예기치 않은 오류를 일으킬 수 있다.
반드시 pyenv로 선택한 사용자 환경에서 설치해야 한다.
2. Emperor 사전 세팅
uWSGI Emperor는 여러 개의 uWSGI 인스턴스를 효율적으로 관리할 수 있도록 도와주는 관리자다.
아래 명령어로 Emperor가 사용할 디렉토리를 만들고 권한을 설정하자:
sudo mkdir -p /etc/uwsgi/vassals/
sudo chown -R www-data:www-data /etc/uwsgi/vassals/
sudo mkdir -p /run/uwsgi/
sudo chown www-data:www-data /run/uwsgi/
sudo chmod 770 /run/uwsgi/
3. 프로젝트용 uWSGI 설정 파일 생성
각 프로젝트마다 개별 설정 파일이 필요하다. 예를 들어 tistory 프로젝트라면:
sudo vi /etc/uwsgi/vassals/tistory.ini
다음 내용을 입력한다:
[uwsgi]
chdir = /home/USERNAME/tistory
module = config.wsgi:application
socket = /run/uwsgi/tistory.sock
chmod-socket = 660
vacuum = true
home = /home/USERNAME/tistory/.venv
daemonize = /var/log/uwsgi/tistory.log
enable-threads = true
master = true
uid = www-data
gid = www-data
- chdir: Django 프로젝트 경로
- home: Python 가상환경 경로
- daemonize: 로그 파일 경로 (사전에 로그 디렉토리를 생성해야 함)
아래 명령어로 로그 디렉토리를 생성하자:
sudo mkdir -p /var/log/uwsgi/
4. uWSGI Emperor 서비스 등록
uWSGI를 systemd 서비스로 등록해서 서버 부팅 시 자동 실행되도록 설정한다:
sudo vi /etc/systemd/system/uwsgi.service
아래 내용을 입력한다:
[Unit]
Description=uWSGI Emperor service
[Service]
EnvironmentFile=/home/USERNAME/tistory/.env
ExecStart=/home/USERNAME/.pyenv/versions/3.12.6/bin/uwsgi --emperor /etc/uwsgi/vassals
Restart=on-failure
KillSignal=SIGQUIT
Type=notify
NotifyAccess=all
StandardError=syslog
[Install]
WantedBy=multi-user.target
- EnvironmentFile: uWSGI 실행 시 불러올 환경 변수 파일의 경로
.env 파일 안에는 DJANGO_SETTINGS_MODULE이나 SECRET_KEY, DATABASE_URL 등 프로젝트 실행에 필요한 민감한 값들이 들어간다.
autoenv 또는 dotenv 같은 도구를 사용하는 경우에도, systemd는 셸 환경이 아니기 때문에 명시적으로 파일을 지정해줘야 한다. - ExecStart: 실제 uWSGI 실행 경로
여기에는 pyenv로 설치된 Python 버전의 uwsgi 실행 파일 절대 경로를 지정한다.
다음 명령어로 확인할 수 있다:
which uwsgi
예: /home/USERNAME/.pyenv/versions/3.12.6/bin/uwsgi
systemd는 로그인 셸과 달리 pyenv를 자동으로 인식하지 못하므로, 경로를 명확히 적어야 한다.
- --emperor: 이 옵션은 Emperor 모드를 사용한다는 의미, uWSGI 설정 파일(.ini)의 경로
지정된 디렉토리(/etc/uwsgi/vassals) 안에 있는 .ini 설정 파일들을 자동으로 감지하고 실행한다.
여러 개의 프로젝트를 운영할 때, 각각의 .ini를 이 디렉토리에 넣기만 하면 uWSGI가 알아서 관리해준다.
5. uWSGI 서비스 실행
이제 서비스를 등록하고 실행한다:
sudo systemctl daemon-reload
sudo systemctl enable uwsgi
sudo systemctl start uwsgi
정상적으로 실행되었는지 확인하려면:
sudo systemctl status uwsgi
Active: active (running) 문구가 보인다면 성공! 😆
마무리
Django 앱을 배포하는 여정에서 가장 복잡한 관문 중 하나가 바로 uWSGI 설정이다.
특히 Emperor 모드까지 활용하면 여러 프로젝트를 한 서버에서 유연하게 관리할 수 있지만, 그만큼 초기 설정이 까다롭다.
하지만 이 단계를 잘 통과해두면, 이후 배포와 운영이 훨씬 깔끔하고 안정적으로 굴러간다.
이제 다음 글에서는 Nginx와 uWSGI를 연결해서, 외부 요청을 Django 앱으로 안전하게 전달하는 과정을 이어서 살펴보자.
서버는 점점 실전에 가까워지고 있다.
매뉴얼 순서