728x90
SMALL
- 오늘 작성하는 글은 앞서 만들었던 Flask 프로젝트를 Git으로 관리하고, AWS Lightsail에 배포한 이후 이어지는 내용입니다.
🧩 Flask 서버와 개발 환경 분리하기
- 기본적인 배포를 마친 후, 본격적으로 서버 환경과 개발 환경을 구분해야 할 시점이 왔습니다.
- 특히 SECRET_KEY 같은 보안 설정이나 데이터베이스 연결 정보는 환경마다 달라져야 하기 때문에 설정 파일을 분리해서 관리하는 것이 중요합니다.
💭 왜 설정을 분리해야 할까?
- 개발 환경에서는 디버깅을 쉽게 하기 위해 DEBUG 모드를 켜두거나, 간단한 SQLite 데이터베이스를 사용하는 경우가 많습니다.
- 하지만 운영 환경에서는 보안과 안정성을 위해 비공개 키를 설정하고, 더 안정적인 DB나 서비스 설정을 적용해야 합니다.
- 만약 설정을 하나의 파일에 모두 적어두면, 서버에 올라간 코드에서 실수로 개발자용 설정이 그대로 사용될 위험이 있습니다.
- 이런 사고를 방지하려면 환경에 맞는 설정을 별도 파일로 분리하고, Flask가 실행 시점에 어떤 설정을 쓸지 지정할 수 있어야 합니다.
✨ config 구조는 어떻게 바꾸면 좋을까?
- 기존에는 단일 config.py 파일에 모든 설정을 몰아두었다면, 이제는 config 폴더 아래에 다음처럼 파일을 나눠야합니다.
- 공통 설정은 default.py에,
- 로컬 개발용은 development.py에,
- 서버 운영용은 production.py에!
- Flask 앱은 실행될 때 환경 변수로 어느 설정 파일을 사용할지 알려주면 됩니다. 예를 들어서 개발 환경에서는 development.py, 서버에서는 production.py를 참조하게 하면 됩니다.
✨ 개발 환경에서는 어떻게 설정하지?
- Windows 기준으로는 .cmd 배치 파일을 하나 만들어두면 편합니다.
- 가상환경 진입과 함께 Flask 관련 환경 변수, 그리고 설정 파일 경로까지 한 번에 등록해줄 수 있게 됩니다. 이 파일을 실행하면 바로 개발 서버를 띄울 준비가 됩니다.
✨ 그럼 서버 환경에서는?
- AWS Lightsail 등의 리눅스 서버에서는 쉘 스크립트를 사용합니다. .sh 파일을 하나 만들어서 서버에 올린 후, 이 파일을 실행하면 자동으로 가상환경에 진입하고, 설정 파일까지 적용할 수 있도록 구성하는 것입니다.
- 이렇게 해두면 운영 서버에서도 일관되게 환경을 제어할 수 있습니다.
- 더 나아가, .bashrc나 .profile에 alias를 등록하면 간단한 명령어 한 줄로 서버 접속 후 환경까지 자동으로 셋팅할 수 있습니다.
🌐 Flask 웹 서버 구조 이해하기
- 단순히 flask run으로 서버를 띄우는 것과, 운영 환경에서의 구성은 어떻게 다를까요?
🧭 웹 브라우저의 요청에는 두 가지가 있다
- 웹 브라우저가 서버로 요청을 보낼 때, 요청은 크게 정적 페이지 요청과 동적 페이지 요청으로 나눌 수 있습니다.
🧾 정적 페이지 요청이란?
- 이미 서버에 저장되어 있는 .css, .js, .jpg 같은 파일을 그대로 내려받는 경우입니다. 예를 들어, 브라우저 주소창에 다음과 같이 입력하면,
http://<서버주소>/static/bootstrap.min.css
- CSS 코드가 텍스트로 출력됩니다. 브라우저는 단순히 파일을 그대로 요청하고, Flask는 이 파일을 찾아 돌려주는 역할을 합니다.
🔁 그럼 동적 페이지 요청이란?
- 정적인 파일이 아니라, 서버가 계산해서 만들어내는 응답을 요청하는 경우입니다.
- 예를 들어 질문 목록 페이지를 요청하면 Flask는 DB에서 데이터를 읽고 HTML을 만들어 응답합니다.
- 이처럼 데이터가 바뀌면 결과도 달라지게 되는 페이지를 동적 페이지라 부릅니다.
✨ 웹 서버는 혼자서 이 모든 걸 처리할 수 있을까?
- 결론부터 말하면 그럴 수가 없습니다.
- 웹 서버는 정적 파일은 잘 처리하지만, 파이썬 애플리케이션을 직접 실행해서 동적 페이지를 만드는 건 어렵습니다.
- 그래서 등장한 것이 WSGI 서버입니다.
🚪 WSGI 서버가 하는 일
- WSGI는 Web Server Gateway Interface의 약자로, 웹 서버와 파이썬 애플리케이션 사이를 이어주는 중간 관리자 역할을 합니다.
- 정적 요청은 웹 서버가 직접 처리하고, 동적 요청은 WSGI 서버가 Flask 앱을 호출해 결과를 응답하게 합니다. Flask, Django는 모두 WSGI 앱입니다.
🔧 Gunicorn, WSGI 서버의 대표주자
- WSGI 서버는 여러 종류가 있지만, Flask에서는 보통 Gunicorn을 사용합니다.
- 개발 환경에서는 flask run 명령이 Flask의 내장 서버를 실행합니다. 이 서버는 WSGI 서버 역할까지 일부 수행하지만, 단순한 구조라서 대량 트래픽이나 여러 사용자 요청을 안정적으로 처리하기 어렵습니다.
- 그래서 운영 환경에서는 내장 서버 대신 Gunicorn 같은 전문 WSGI 서버를 사용하는 것이 필수입니다.
💡 우리가 만든 프로젝트는?
- 지금까지 만든 애플리케이션은 사실상 WSGI 애플리케이션입니다. Flask 프레임워크가 기본적으로 WSGI 규격을 따르고 있기 때문입니다.
- 즉, 우리가 만든 프로젝트는 WSGI 서버가 호출할 수 있도록 준비된 상태라는 뜻입니다.
- 아래는 요청이 처리되는 과정을 요약한 구조도입니다.
🚨 운영 환경에서 flask run은 사용하면 안 되는 이유
- 개발할 때는 편하니까 flask run을 사용했지만, 실제 배포 서버에서는 아래 이유로 사용하지 않습니다.
- 여러 사용자의 동시 요청 처리에 약함
- 에러 발생 시 자동 복구 기능 없음
- 성능과 보안 측면에서 부족함
- 운영 환경에서는 Gunicorn 같은 WSGI 서버 + 웹 서버(Nginx 등) 구조로 실행하는 것이 일반적입니다.
🚀 Flask를 운영 환경에서 실행하려면?
- 이제는 Gunicorn을 설치하고 서비스로 등록해 Flask 앱을 운영 환경에서 안정적으로 실행하는 방법을 소개하겠습니다.
✨ Gunicorn 설치 및 실행 (서버에서만)
- 개발 환경(로컬)이 아닌 서버에서만 설치해 사용합니다.
- 가상환경 활성화 후 설치
- Flask 앱을 Gunicorn으로 실행
pip install gunicorn
gunicorn --bind 0:5000 "pybo:create_app()"
- -bind 0:5000: 포트 5000번에 바인딩
- "pybo:create_app()": Flask의 앱 팩토리 함수 호출
🧵 Unix 소켓 방식으로 실행하기
- 운영 환경에서는 포트보다 Unix 소켓 방식이 더 효율적입니다.
gunicorn --bind unix:/tmp/myproject.sock "pybo:create_app()"
- 이 방식은 웹 서버(Nginx 등)와 연동할 때 사용됩니다.
- 직접 접속은 불가능하며, 웹 서버가 이 소켓을 통해 Gunicorn과 통신합니다.
🧾 Gunicorn을 서비스로 등록하기 (systemd 사용)
- 단순 실행으로는 서버 재시작 시 앱이 꺼집니다. 이를 해결하려면 Gunicorn을 시스템 서비스로 등록해야 합니다.
💡 환경 변수 파일 만들기
# /home/ubuntu/venvs/myproject.env
FLASK_APP=pybo
FLASK_DEBUG=true
APP_CONFIG_FILE=/home/ubuntu/projects/myproject/config/production.py
💡 systemd 서비스 파일 생성하기
# /etc/systemd/system/myproject.service
[Unit]
Description=gunicorn daemon
After=network.target
[Service]
User=ubuntu
Group=ubuntu
WorkingDirectory=/home/ubuntu/flask-projects/myproject
EnvironmentFile=/home/ubuntu/venvs/myproject.env
ExecStart=/home/ubuntu/venvs/myproject/bin/gunicorn --workers 2 --bind unix:/tmp/myproject.sock "pybo:app"
[Install]
WantedBy=multi-user.target
- -workers 2: 서버 스펙에 맞춰 워커 수 설정 (저사양일 경우 2개 추천)
- .sock: Gunicorn이 바인딩될 Unix 소켓 경로
💡 서비스 실행 및 등록
sudo systemctl start myproject.service
sudo systemctl enable myproject.service
- 서비스가 정상적으로 실행되었는지 sudo systemctl status myproject.service로 확인할 수 있습니다.
- enable 명령어는 서버 재시작 시 자동으로 Gunicorn이 실행되도록 설정합니다.
- 서비스를 종료시킬 때는 sudo systemctl stop myproject.service,
- 서비스를 재시작할 때는 sudo systemctl restart myproject.service 명령어를 입력해줍니다.
🌐 이제 Nginx로 웹서버 연결하기
- 웹 브라우저에서 URL을 입력하면, 그 요청은 웹 서버(Nginx) → WSGI 서버(Gunicorn) → Flask 애플리케이션(서비스) 순으로 전달되어야 완전한 웹 서비스가 됩니다.
🧭 Nginx란?
- Nginx(엔진엑스)는 고성능 웹 서버입니다. 정적 파일(css, js, 이미지 등)은 Nginx가 직접 처리하고, 동적 요청은 WSGI 서버(Gunicorn)에게 넘기는 방식으로 빠르고 효율적인 웹 서비스 구성이 가능합니다.
💡 Ubuntu 서버에서 Nginx 설치하기
- 서버에 접속한 상태에서 아래 명령어로 Nginx를 설치합니다.
sudo apt install nginx
- 설치가 완료되면 자동으로 서비스가 실행됩니다.
💡 Nginx 설정 파일 작성하기
- Nginx의 설정 파일은 /etc/nginx/sites-available/에 저장합니다.
- 여기서 서비스에 대한 설정을 새로 만들어볼 수 있었습니다.
cd /etc/nginx/sites-available/
sudo nano myproject
- 설정 파일 내용은 다음과 같이 작성합니다.
server {
listen 80;
server_name [서버의 고정 IP];
location = /favicon.ico { access_log off; log_not_found off; }
location /static {
alias /home/ubuntu/flask-projects/myproject/pybo/static;
}
location / {
include proxy_params;
proxy_pass <http://unix>:/tmp/myproject.sock;
}
}
- listen 80: 80번 포트는 HTTP 기본 포트입니다. http://IP주소만 입력해도 접속 가능하게 합니다.
- server_name: 고정 IP 주소를 입력해줍니다.
- /static: CSS, JS, 이미지 등의 정적 파일을 Nginx가 직접 처리합니다.
- /: 그 외 모든 요청은 Gunicorn(소켓 방식)으로 전달합니다.
💡 설정 활성화하기
- Nginx는 sites-available 폴더에 있는 설정을 링크를 통해 활성화합니다.
cd /etc/nginx/sites-enabled/
sudo rm default # 기존 default 설정 제거
sudo ln -s /etc/nginx/sites-available/myproject
- ls 명령어로 보면 myproject 링크가 걸려있는 것을 확인할 수 있습니다.
💡 Nginx 재시작
- 설정을 적용하려면 Nginx를 재시작해야 합니다.
sudo systemctl restart nginx
- 정상적으로 실행되었는지 확인하려면
sudo nginx -t
- 설정 파일 문법이 이상이 없다면, syntax is ok test is successful가 출력됩니다.
🎉 접속 테스트
http://[서버 고정 IP]
- 위와 같이 포트 번호 없이 접속되며, 정적 파일도 정상적으로 적용되고, Gunicorn이 연결된 동적 페이지도 동작한다면 성공입니다!
🤔 49일차 회고
- 오늘은 Flask 프로젝트를 AWS Lightsail 서버에 배포하고, 운영 환경에 맞게 설정을 정리해보는 시간을 가졌습니다.
- 그동안은 그냥 flask run으로만 실행했었는데, Gunicorn과 Nginx 같은 구성 요소들을 직접 붙여보니까 정말 서버같다는 느낌이 드는 것 같습니다.
- 지금까지는 개발자 도구 느낌이 강했는데, 오늘은 진짜 서비스 운영자의 느낌을 살짝 맛본 하루인 듯 합니다.
- 처음에 config 파일을 나누는 게 좀 귀찮게 느껴졌는데, 환경별로 설정을 분리하고 나니까 훨씬 구조적으로 안정감이 생기는 느낌이 드는 것 같습니다. 특히 .env, systemd 서비스 등록 같은 부분은 실제 운영에 필요한 작업이라 더 실감났던 것 같습니다.
728x90
LIST
'부트캠프 > LG U+' 카테고리의 다른 글
🤔 드쟝고라고 했었던 Django에 관하여 (0) | 2025.04.29 |
---|---|
🤔 해도 해도 끝이 없는 AWS (0) | 2025.04.18 |
🤔 Flask에 스타일 입혀주기 (1) | 2025.04.01 |
🤔 이게 Flask였던가... (0) | 2025.03.31 |
🤔 타이타닉에서 살아남기 (0) | 2025.03.27 |