ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Backend] Nginx 가이드 (Gunicorn + Uvicorn +FastAPI 백엔드 기준)
    WEB 2025. 6. 14. 19:04
    728x90
    🚀 [Backend] Nginx 가이드 (Gunicorn + Uvicorn + FastAPI 백엔드 기준)

     

     

    * 이전 포스트에서 이어집니다 (https://asidefine.tistory.com/334)

     


    모 채용 공고에서 본 담당 업무인데, 지금까지는 1번 2번 업무만 해본 것 같아서 아래도 공부해보고자 한다 

     

     

    그래서 GPT 한테 뭘 공부해야 되나 물어봤더니 

     

    타고 타고 가다가 nginx까지 나왔다 그래서 그게 뭔데

     


    들어가기 전 ...  Gunicorn 복습 

     

    전에도 말했다시피 Gunicorn으로도 로드 밸런싱은 된다

    Gunicorn은 여러 워커 프로세스(worker process) 를 띄워서, 내부적으로 라운드로빈 방식으로 요청을 분산하기 때문이다 

    라운드로빈  

    CPU 스케줄링 방법 중 하나로 배웠던 개념으로,

    프로세스들을 정해진 시간 간격으로 잘라 번갈아가면서 수행하고
    정해진 시간을 모두 사용하고 나서도 프로세스가 완료되지 않으면 큐의 맨 뒤에 삽입하는 선점 스케줄링 방식이다

    (https://asidefine.tistory.com/257)

     

    gunicorn -k uvicorn.workers.UvicornWorker main:app -w 4

    → 클라이언트는 localhost:8000으로 접속
    → Gunicorn이 내부에서 워커 4개 돌리며 요청 분산함
    단일 머신 내부에서만 작동, 외부 로드(=외부 사용자나 서비스에서 오는 요청 트래픽)는 못 나눔

       그러니까 Gunicorn만 냅다 써버리면, 100명의 사용자가 동시에 접속했을 때 이 요청이 Gunicorn에 직접 도달 Gunicorn이 자체적으로 워커 수만큼 분산하긴 하지만, 클라이언트 연결, 대기, 정적 파일 처리, SSL까지도 다 감당해야 함

     

     

     


    그렇다면 Nginx는 ? 

     

    • Nginx가 앞에 있을 때라면 이야기가 다른데,
      • 클라이언트 요청이 먼저 Nginx에 도착
      • Nginx가 부하를 판단해서 적절히 Gunicorn 인스턴스나 서버로 분산시킴
      • 동시에 정적 파일 처리, SSL, gzip 압축, 캐시 처리도 Nginx가 함

     

     

    • 그러니까 Nginx와 Gunicorn의 로드밸런싱의 차이점은 아래 표로 정리할 수 있다 
    항목 Gunicorn Nginx
    로드밸런싱 대상 내부 워커 프로세스 (메모리 공유 X) 외부 서버/프로세스 (포트 or IP)
    운영 계층 애플리케이션 서버 레벨 네트워크/프록시 레벨
    기능 범위 1개 머신 내부에서만 동작 여러 머신, 포트, 서비스 간 분산 가능
    세션/쿠키 관리 신경 안 씀 (stateless 가정) ip_hash 등 세션 고정 가능
    기본 역할 Python 앱을 다중 프로세스로 처리 클라이언트 요청 분산, 정적 파일 제공, SSL, 보안 등
    부하 분산 방식 내부 라운드로빈, 워커 수 만큼 라운드로빈, IP 해시, 가중치 등 다양

     

     

    ✅ 0. Nginx란?

    Nginx는 고성능 웹 서버이자 리버스 프록시, 로드 밸런서, 정적 파일 서버로 동작하는 소프트웨어

    • 빠르고 가볍고, 많은 트래픽을 효율적으로 처리 가능
    • FastAPI/Gunicorn 같은 Python 백엔드 서버와 함께 쓰이는 게 필수적

    ✅ 1. 핵심 역할 3가지

    웹 서버 HTML/CSS/JS/이미지 같은 정적 파일 직접 서빙
    리버스 프록시 외부 요청을 내부 FastAPI 서버로 전달함
    로드 밸런서 여러 서버에 트래픽을 나누어줌 (수평 확장 시 필요)

     


    ✅ 2. 리버스 프록시란?

    사용자의 요청을 대신 받아서, 내부에 있는 실제 서버(Gunicorn+FastAPI)에 전달하는 역할

    📦 왜 필요해?

    • FastAPI 서버는 외부 요청을 직접 처리하기엔 불안정
    • HTTPS 인증, 보안 처리, IP 차단 등은 Nginx가 더 적합
    • 하나의 FastAPI 서버에 너무 많은 요청이 오지 않도록 조절 가능

    💡 구조 예시

    [Client] → [Nginx] → [Gunicorn] → [Uvicorn Worker] → [FastAPI]

    ✅ 3. 정적 파일 서버란?

    변경되지 않는 파일(HTML, CSS, JS, 이미지 등)을 직접 사용자에게 제공하는 역할

    • FastAPI가 제공하면 느리고 부담 큼
    • Nginx는 C 기반 서버로 매우 빠름

    📁 기본 경로

    • Ubuntu 기준: /var/www/html/
    • Nginx 설정에서 rootalias로 경로 지정 가능

    예시 설정

    location /static/ {
        root /var/www/html/;
    }

    ✅ 4. 기본 설치 및 실행

    🔧 Ubuntu에서 설치

    sudo apt update
    sudo apt install nginx

    ▶️ 서비스 관리

    sudo systemctl start nginx   # 실행
    sudo systemctl stop nginx    # 중지
    sudo systemctl restart nginx # 재시작

    🌐 테스트

    • 브라우저에서 http://localhost 접속 시 Nginx 환영 페이지 뜨면 정상

    ✅ 5. FastAPI + Gunicorn + Nginx 연결 예제 1

    💡 가정:

    • FastAPI 서버는 Gunicorn으로 127.0.0.1:8000에서 실행 중

    📄 /etc/nginx/sites-available/fastapi.conf

    server {
        listen 80;
        server_name yourdomain.com;
    
        location / {
            proxy_pass http://127.0.0.1:8000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    
        location /static/ {
            root /var/www/html/;
        }
    }

    🔗 활성화 및 적용

    sudo ln -s /etc/nginx/sites-available/fastapi.conf /etc/nginx/sites-enabled/
    sudo nginx -t
    sudo systemctl restart nginx

     


    ✅ 6. FastAPI + Gunicorn + Nginx 연결 예제 2 :
          Nginx + Gunicorn 여러 개 = 외부 요청 부하 분산

    1. Gunicorn 인스턴스를 포트를 다르게 해서 여러 개 실행함
    2. Nginx가 앞단에서 클라이언트 요청을 받아서 그 중 하나로 분산시킴

    🔍 1. Gunicorn 여러 개 실행

     
    gunicorn -k uvicorn.workers.UvicornWorker main:app -w 1 -b 127.0.0.1:8001
    gunicorn -k uvicorn.workers.UvicornWorker main:app -w 1 -b 127.0.0.1:8002

    이건 아래 뜻이에요:

    • main:app: FastAPI 앱이 main.py 안에 있고, 거기서 app = FastAPI() 되어 있다는 뜻
    • -w 1: 워커 1개로 실행
    • -b 127.0.0.1:8001: 첫 번째 인스턴스는 8001 포트에서 대기
    • -b 127.0.0.1:8002: 두 번째 인스턴스는 8002 포트에서 대기

    👉 즉, 같은 앱을 두 포트에서 따로 실행 중


    🔍 2. Nginx 설정: 외부 요청을 이 둘로 나눠줌

     
    upstream backend {
      server 127.0.0.1:8001;
      server 127.0.0.1:8002;
    }
    
    server {
      listen 80;
      location / {
        proxy_pass http://backend;
      }
    }
    • upstream backend: 이름이 backend인 서버 묶음을 정의함
    • server 127.0.0.1:8001 & 8002: 위에서 띄운 Gunicorn 앱들을 여기에 등록
    • listen 80: 외부에서 들어오는 요청을 80번 포트로 받음 (웹 브라우저 기본 포트)
    • proxy_pass http://backend: 들어온 요청을 위에 등록한 backend 중 하나로 보내줌 (자동 분산)

    👉 즉, 외부에서 http://localhost로 요청을 보내면
    → Nginx가 8001이나 8002 중 하나로 보내주는 거예요


    🧠 왜 이렇게 하냐?

    ❌ Gunicorn만 사용하면:

    • 1개 포트만 열림 (예: 8000)
    • CPU 코어 여러 개 써도 한 서버 프로세스 안에서만 처리
    • 외부 트래픽 분산 불가능

    ✅ Nginx를 앞에 붙이면:

    • Gunicorn 인스턴스를 여러 개 띄우고
    • Nginx가 외부 요청을 알아서 분산
    • 로드밸런싱, SSL, 정적 파일, 압축 처리, 보안 설정 등도 함께 처리 가능

    🎯 한 줄 요약

    같은 앱을 여러 포트(8001, 8002)에서 따로 띄워두고,
    Nginx가 그 사이에서 외부 요청을 알아서 나눠주는 구조

     


    ✅ 7. HTTPS 적용 (Let’s Encrypt)

    sudo apt install certbot python3-certbot-nginx
    sudo certbot --nginx -d yourdomain.com
    • 자동으로 SSL 인증서 적용
    • 매 90일마다 자동 갱신

    ✅ 8. 디버깅 및 참고 명령어

    명령 설명
    nginx -t 설정 문법 오류 확인
    sudo nginx -s reload 설정만 다시 불러오기
    tail -f /var/log/nginx/access.log 실시간 요청 로그 확인
    tail -f /var/log/nginx/error.log 에러 로그 확인

     


    ✅ 9. 요약

    구성요소 역할
    Nginx 요청 분산, SSL 처리, 정적 파일 처리
    Gunicorn FastAPI 앱을 병렬 프로세스로 실행
    Uvicorn 실제 FastAPI 앱을 실행하는 ASGI 서버

     

     

     

    728x90
Designed by Tistory.