ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [4월 2주차-4/7]🚀 Flask Pybo 프로젝트 운영 환경 배포 완전 정복 (with Gunicorn & Nginx)
    Why Not SW CAMP 5기/수업 기록 2025. 4. 7. 15:49

    오늘은 Flask로 만든 Q&A 게시판 Pybo 프로젝트를 실제 운영 환경에 맞게 설정 분리부터 Gunicorn, Nginx, 시스템 서비스 등록까지 쭉 정리해볼게요 💪


    📦 1. 개발/운영 환경 설정 분리

    ✅ config 디렉토리 구성

    c:\projects\myproject에 다음과 같이 config 폴더 만들기

    config/
    ├── __init__.py
    ├── default.py
    ├── development.py
    └── production.py
    

    ✅ default.py

    import os
    BASE_DIR = os.path.dirname(os.path.dirname(__file__))
    

    ✅ production.py

    python -c "import os; print(os.urandom(16))" 입력 후 나온 16진수 복사해서 SECRET_KEY로

    from config.default import *
    SQLALCHEMY_DATABASE_URI = 'sqlite:///{}'.format(os.path.join(BASE_DIR, 'pybo.db'))
    SQLALCHEMY_TRACK_MODIFICATIONS = False
    SECRET_KEY = b'I\xe4\xe4^\xda\xcd\x88\xcaA\x08\xc5s\xaft\xed\x18'
    

    ✅ development.py

    from config.default import *
    SQLALCHEMY_DATABASE_URI = 'sqlite:///{}'.format(os.path.join(BASE_DIR, 'pybo.db'))
    SQLALCHEMY_TRACK_MODIFICATIONS = False
    SECRET_KEY = "dev"
    

    ✅ pybo/init.py 변경

    # 기존 config import 제거
    app.config.from_envvar('APP_CONFIG_FILE')  # 환경변수로 설정파일 경로 지정
    

    ✅ 개발환경 실행용 cmd 예시 (Windows)

    set FLASK_APP=pybo
    set FLASK_DEBUG=true
    set APP_CONFIG_FILE=c:\projects\myproject\config\development.py
    flask run
    

     

    ✅ 자동화 설정

    C:/venvs/myproject.cmd 수정

    매번 환경 변수 APP_CONFIG_FILE을 설정하는 것을 피하기 위해

    @echo off
    cd c:/projects/myproject
    set FLASK_APP=pybo
    set FLASK_DEBUG=true
    set APP_CONFIG_FILE=c:\projects\myproject\config\development.py
    c:/venv/myproject/scripts/activate

     

    flask run 만 하면 바로 실행 가능!

     

    바뀐 내용 push 하기!


    서버로 와서 git pull 하기!

    🔧 2. 서버 환경 자동화 설정

    ✅ 환경변수 자동화 스크립트 (myproject.sh)

    (myproject) ubuntu@jumpto:~/projects/myproject$ cd /home/ubuntu/venvs/
    (myproject) ubuntu@jumpto:~/venvs$ nano myproject.sh
    #!/bin/bash
    cd ~/projects/myproject
    export FLASK_APP=pybo
    export FLASK_DEBUG=true
    export APP_CONFIG_FILE=/home/ubuntu/projects/myproject/config/production.py
    . ~/venvs/myproject/bin/activate
    
    # <Ctrl>+O를 눌러서 myproject.sh 파일을 저장한 뒤 <Ctrl>+X를 눌러서 편집기를 종료

    실행:

    . ~/venvs/myproject.sh
    

    🐍 3. Gunicorn으로 서비스 실행

    ✅ Gunicorn 설치 및 실행

    pip install gunicorn
    gunicorn --bind unix:/tmp/myproject.sock "pybo:create_app()"
    
    # url로 접속 해서 Gunicorn이 정상으로 동작하는 것 확인하기

    ✅ Gunicorn systemd 서비스 등록

    Gunicorn의 시작, 중지를 쉽게 하고 또 AWS 서버를 다시 시작할 때 Gunicorn을 자동으로 실행하기 위함

    # 환경 변수 파일 생성하기
    # [파일명: /home/ubuntu/venvs/myproject.env]
    (myproject) ubuntu@jumpto:~/venvs$ nano myproject.env
    
    FLASK_APP=pybo
    FLASK_DEBUG=true
    APP_CONFIG_FILE=/home/ubuntu/projects/myproject/config/production.py
    # 서비스 파일 생성하기
    # [파일명: /etc/systemd/system/myproject.service]
    # 핵심 역할: gunicorn을 백그라운드 데몬처럼 실행시키고 서버 시작 시 자동 실행
    (myproject) ubuntu@jumpto:/etc/systemd/system$ sudo nano myproject.service
    
    [Unit]
    Description=gunicorn daemon
    After=network.target
    
    [Service]
    User=ubuntu
    Group=ubuntu
    WorkingDirectory=/home/ubuntu/projects/myproject
    EnvironmentFile=/home/ubuntu/venvs/myproject.env
    ExecStart=/home/ubuntu/venvs/myproject/bin/gunicorn \
              --workers 2 \
              --bind unix:/tmp/myproject.sock \
              "pybo:create_app()"
    [Install]
    WantedBy=multi-user.target

    실행:

    sudo systemctl start myproject.service
    sudo systemctl status myproject.service
    sudo systemctl enable myproject.service  # 부팅 시 자동 실행
    

    🌐 4. Nginx 리버스 프록시 설정

    ✅ 설치

    sudo apt install nginx
    

    ✅ 설정 파일 (/etc/nginx/sites-available/myproject)

    sudo nano myproject

    server {
        listen 80;
        server_name 43.202.236.242;
    
        location = /favicon.ico { access_log off; log_not_found off; }
    
        location /static/ {
            alias /home/ubuntu/projects/myproject/pybo/static/;
        }
    
        location / {
            include proxy_params;
            proxy_pass http://unix:/tmp/myproject.sock;
        }
    }
    

    연결:

    # 작성한 myproject 파일을 Nginx가 환경 파일로 읽을 수 있도록 설정
    cd /etc/nginx/sites-enabled/
    
    # ls하면 default 있음. default는 삭제.
    sudo rm default
    
    # myproject 파일을 링크
    sudo ln -s /etc/nginx/sites-available/myproject

     

    실행

    sudo systemctl restart nginx

     


    ❗ CSS 안 먹힐 때 (403 Forbidden 해결법)

    ✅ static 폴더 및 상위 폴더 권한 부여

    sudo chmod 755 /home/ubuntu
    sudo chmod 755 /home/ubuntu/projects
    sudo chmod 755 /home/ubuntu/projects/myproject
    sudo chmod 755 /home/ubuntu/projects/myproject/pybo
    sudo chmod 755 /home/ubuntu/projects/myproject/pybo/static
    

    ✅ 이후 재시작

    sudo nginx -t
    sudo systemctl reload nginx
    


    🚀 5. 운영 환경으로 전환

    ✅ 환경 변수 수정 (/home/ubuntu/venvs/myproject.env)

    FLASK_APP=pybo
    FLASK_DEBUG=false
    APP_CONFIG_FILE=/home/ubuntu/projects/myproject/config/production.py
    

    ✅ 적용

    cd ~/projects/myproject
    git pull
    sudo systemctl restart myproject.service
    

     

    🌐6. 웹 브라우저와 서버, Pybo 동작 방식 이해하기

    웹 브라우저가 Pybo의 페이지를 요청하면 다음과 같은 흐름으로 동작:

    1. 웹 브라우저는 사용자의 요청을 서버로 전송
    2. Nginx 웹 서버가 먼저 요청을 받음
    3. 정적 파일이면 Nginx가 직접 처리, 아니라면 → WSGI 서버(Gunicorn)로 요청 전달
    4. Gunicorn은 Flask 앱(Pybo)을 실행해서 동적 페이지 생성
    5. 결과 HTML을 다시 Nginx → 브라우저로 전달

    📌 WSGI 서버는 Python 웹 앱을 실행해주는 미들웨어 서버이며, 여기선 Gunicorn을 사용함

    브라우저 → Nginx → Gunicorn → Flask(Pybo) → 응답 반환

    Gunicorn은 파이썬 프로그램을 실행하는 WSGI 서버입니다.


    📄 7. 404 오류 페이지 설정

    ✅ pybo/init.py

    from flask import Flask, render_template
    
    (... 생략 ...)
    
    def page_not_found(e):
        return render_template('404.html'), 404
    
    def create_app():
        (... 생략 ...)
        # 오류페이지
        app.register_error_handler(404, page_not_found)
    
        return app

    ✅ templates/404.html

    {% extends "base.html" %}
    {% block content %}
      <div class="error-page">
        <h2>🚫 페이지를 찾을 수 없습니다 (404)</h2>
        <p>요청하신 페이지는 존재하지 않거나 이동되었어요.</p>
        <a href="{{ url_for('main.index') }}" class="btn">메인으로 돌아가기</a>
      </div>
    {% endblock %}
    


    🛢️ 8. PostgreSQL 데이터베이스 적용하기 (Lightsail)

    ✅ 데이터베이스 생성

    • AWS 라이트세일 → 데이터베이스 → PostgreSQL 선택
    • 위치: 서울, 플랜: $15, 이름: Database-1

    ✅ 설정 확인

    • 엔드포인트 / 사용자 / 비밀번호 확인 (DB 접속 시 필요)

    ✅ 서버에서 PostgreSQL 클라이언트 설치 및 DB 생성

    # 서버에 PostgreSQL 클라이언트 설치하기
    sudo apt install postgresql-client
    
    # 데이터베이스 생성
    createdb flask_pybo --username=dbmasteruser -h <엔드포인트 주소>

    ✅ 파이보에서 데이터베이스에 접속하기 위해 모듈 설치

    pip install psycopg2-binary

    ✅ 별도의 파일을 환경파일로 사용하기 위한 모듈 설치

    데이터베이스 암호 등 중요한 정보를 따로 저장하기 위해 서버, 로컬 둘 다 설치

    (myproject) c:\projects\myproject> pip install python-dotenv
    (myproject) ubuntu@jumpto:~/projects/myproject$ pip install python-dotenv

    ✅ .env 파일 생성

    파일명: /home/ubuntu/projects/myproject/.env

    DB_NAME=flask_pybo
    DB_USER=dbmasteruser
    DB_HOST=<엔드포인트 주소>
    DB_PASSWORD=<비밀번호>

    ✅ config/production.py 수정

    dotenv 모듈을 사용하여 .env 파일에 저장한 정보를 os.getenv로 읽을수 있게

    from config.default import *
    from dotenv import load_dotenv
    load_dotenv(os.path.join(BASE_DIR, '.env'))
    
    SQLALCHEMY_DATABASE_URI = 'postgresql+psycopg2://{user}:{pw}@{url}/{db}'.format(
        user=os.getenv('DB_USER'),
        pw=os.getenv('DB_PASSWORD'),
        url=os.getenv('DB_HOST'),
        db=os.getenv('DB_NAME')
    )
    SQLALCHEMY_TRACK_MODIFICATIONS = False

    git push / pull !!

    ✅ 데이터베이스 초기화

    # SQLite 데이터베이스가 사용했던 migrations 디렉터리와 pybo.db 파일 삭제
    rm -rf migrations
    rm pybo.db
    
    # 초기화
    flask db init
    flask db migrate
    flask db upgrade
    
    # 실행 되는지 확인
    sudo systemctl restart myproject.service

    ✅ pgAdmin으로 로컬에서 연결

    1. Lightsail DB → 네트워킹 → 퍼블릭 액세스 허용
    2. pgAdmin 실행 → Server 등록 → 정보 입력
    3. 비밀번호 입력 후 접속 확인

    ✅ 마무리 체크

    • Flask 설정 분리 완료
    • Gunicorn WSGI 서버 사용
    • systemd 서비스 등록
    • Nginx 리버스 프록시 구성
    • 정적 파일 권한 설정
    • 404 오류 페이지 적용

    이제 Pybo는 운영 환경에서 완전한 배포 상태로 동작합니다!

Designed by Tistory.