CAFE

Python

웹 브라우저 요청과 서버 구조: WSGI, ASGI, NGINX/Apache

작성자ParkYK|작성시간21.02.23|조회수531 목록 댓글 0

 

* Django의 기본 서버가 아닌 웹서버 연동 : NGINX + Django

 

 

🕸 웹 브라우저 요청과 웹 서버/애플리케이션 서버 구조 정리
(Django / Flask / FastAPI 배포 이해 문서)

1. 웹 브라우저의 요청 형태는 크게 두 가지로 나뉜다
   : 웹 브라우저가 웹서버에 정보를 요청하는 페이지 형태는 크게 두 가지로 나뉜다. 이 때 웹 서버(NGINX, Apache)는 웹 브라우저의 정적 요청과 동적 요청을 처리(또는 전달)하는 서버이다.

- 정적 페이지 요청 (Static Request) : 웹 브라우저로 js, css, image file 과 같은 파일 자체를 요청하는 것.
  특징: 웹 서버가 파일을 그대로 응답(서빙)한다.  빠르고 단순하며, 웹 서버가 가장 잘 처리한다.

- 동적 페이지 요청 (Dynamic Request)
  요청 시점, 사용자, 파라미터, DB 결과에 따라 응답이 달라질 수 있는 요청.
 주의(중요): /index.html 처럼 확장자가 html이라고 해서 동적/정적이 결정되지는 않는다.
               - index.html도 그냥 파일이면 “정적”
               - 같은 URL이라도 서버에서 템플릿 렌더링/DB 조회로 만들면 “동적”
               즉, 동적/정적의 기준은 “응답이 파일 그대로냐 vs 애플리케이션 실행 결과냐” 이다.

2. 동적 페이지 요청은 왜 더 복잡한가?
  : 동적 페이지 요청이 들어오면 웹 서버는 요청 처리를 위한 애플리케이션으로 파이썬 프로그램을 호출해야 한다. 예를 들어 검색 요청이 있는 경우 검색 내용을 조회하여 반환하는 파이썬 로직(ORM/SQL, 템플릿 렌더링, 인증/세션 처리 등)을 수행해야 한다.
   그런데 NGINX/Apache 같은 웹 서버는 파이썬 코드를 직접 실행하는 역할이 아니다. 그래서 웹 서버가 “파이썬 앱 실행 담당 서버(앱 서버)”에게 요청을 넘겨주는 구조가 필요하다.

3. WSGI / ASGI: 웹 서버와 파이썬 앱을 연결하는 표준
  : 여기서 등장하는 것이 “파이썬 앱을 실행하는 서버 + 표준 인터페이스”이다.

  1) WSGI (Web Server Gateway Interface)
     - 전통적인 파이썬 웹 표준 인터페이스
     - 주로 동기 방식 기반
     - WSGI 애플리케이션: Django, Flask
     - WSGI 서버(앱 실행기): Gunicorn, uWSGI
     정리: “웹 서버(NGINX/Apache)가 WSGI 서버를 통해 Django/Flask를 호출한다.”
  2) ASGI (Asynchronous Server Gateway Interface)
     - 비동기까지 포함한 현대 표준 인터페이스
     - FastAPI(대표), Starlette 같은 비동기 프레임워크에 적합
     - ASGI 서버: Uvicorn, Hypercorn
     - (실무에서) Gunicorn + UvicornWorker 조합도 많이 씀
     정리: “FastAPI는 WSGI가 아니라 ASGI로 실행하는 게 표준적이다.”

4. 대표적인 운영(실서비스) 배포 구조
   - 웹 서버(NGINX/Apache)는 앞단에서 정적 파일 처리 + 프록시(Reverse Proxy),
   - 앱 서버(Gunicorn/Uvicorn)는 파이썬 앱 실행
   A) Django 실서비스 구조(표준) : NGINX + Gunicorn + Django
       Browser → NGINX(정적 + Reverse Proxy) → Gunicorn(WSGI) → Django
   B) Apache + Django : Apache가 mod_wsgi로 Django를 붙이거나, Apache를 Reverse Proxy로 두고 Gunicorn으로 넘길 수도 있음(구성 선택)
   참고: Apache + Django: https://opentutorials.org/module/3923/25079

5. 샘플/참고 자료
   😎 샘플 프로젝트 구경하기
        [AWS] 웹 어플리케이션 배포하기 (EC2) : https://cherishvert.tistory.com/107
        Django + NginX 후 AWS로 서비스 : https://wikidocs.net/75558
        우분투와 NGINX Reverse Proxy : https://velog.io/@gudcks0305/우분투에서-Nginx로-Reverse-Proxy-설정하기


🕸  프레임워크별 적용 방법 (Django → Flask → FastAPI) ---
아래는 “운영 배포” 기준으로, 가장 흔한 정답 구조만 뽑아서 정리함. (세부 설정 파일은 별도 문서로 확장하면 됨)

1) Django 적용 (WSGI)
  구조 : NGINX → Gunicorn(WSGI) → Django
  적용 흐름(핵심 단계)
      - Django 앱 준비 (ALLOWED_HOSTS, DEBUG=False, DB/ENV 설정)
      - 정적 파일 수집: collectstatic
      - Gunicorn으로 Django 실행(서비스화 권장: systemd)
      - NGINX가 /static/은 파일로 직접 서빙. 나머지는 Gunicorn으로 프록시
2) Flask 적용 (WSGI)
  구조 : NGINX → Gunicorn(WSGI) → Flask
   적용 흐름(핵심 단계)
      - Flask 앱 준비 (app 객체, 환경변수, SECRET_KEY 등)
      - Gunicorn으로 app:app 형태로 실행(서비스화)
      - NGINX가 정적 파일 경로는 직접 서빙(선택). API/동적 요청은 Gunicorn으로 프록시
3) FastAPI 적용 (ASGI)
  구조 : NGINX → Uvicorn(ASGI) → FastAPI  (또는 NGINX → Gunicorn(UvicornWorker) → FastAPI)
  적용 흐름(핵심 단계)
      - FastAPI 앱 준비 (app = FastAPI())
      - Uvicorn(또는 Gunicorn+UvicornWorker)로 실행(서비스화)
      - NGINX가 정적은 직접 서빙(필요 시). API 요청은 Uvicorn으로 프록시
      - FastAPI는 비동기/고성능에 강점이 있어 API 서버에 특히 적합

정리하면
   - Django/Flask는 WSGI → Gunicorn
   - FastAPI는 ASGI → Uvicorn(또는 Gunicorn+UvicornWorker)
   - NGINX/Apache는 앞단에서 정적 처리 + Reverse Proxy


🕸   NGINX 설정 예시 3종(Django/Flask/FastAPI)
(모두 80 포트, Reverse Proxy, 정적 파일 분리 기준)
* 공통 전제
  - 설정 파일 위치(우분투 기준)
      /etc/nginx/sites-available/<서비스명>
      /etc/nginx/sites-enabled/에 심볼릭 링크
  - 기본 헤더(프록시 공통)
      Host, X-Real-IP, X-Forwarded-For, X-Forwarded-Proto

1) Django: NGINX → Gunicorn(WSGI) → Django       ~~~~~~~~~~~~~~~~~
(A) NGINX 설정 템플릿
server {
    listen 80;
    server_name example.com;  # 또는 EC2 퍼블릭IP

    # 정적 파일(collectstatic 결과)
    location /static/ {
        alias /var/www/django_static/;  # <-- STATIC_ROOT
        expires 30d;
        add_header Cache-Control "public";
    }

    # 업로드 미디어 파일(선택)
    location /media/ {
        alias /var/www/django_media/;   # <-- MEDIA_ROOT
        expires 30d;
        add_header Cache-Control "public";
    }

    # 동적 요청은 Gunicorn으로
    location / {
        proxy_pass http://unix:/run/gunicorn_django.sock;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

(B) Gunicorn은 보통 유닉스 소켓으로 실행
    소켓 예: /run/gunicorn_django.sock (systemd에서 생성/관리)

2) Flask: NGINX → Gunicorn(WSGI) → Flask   ~~~~~~~~~~~~~~~~~~~~
(A) NGINX 설정 템플릿
server {
    listen 80;
    server_name example.com;

    # Flask 정적(선택: 직접 서빙할 때)
    location /static/ {
        alias /var/www/flask_static/;
        expires 30d;
        add_header Cache-Control "public";
    }

    location / {
        proxy_pass http://unix:/run/gunicorn_flask.sock;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

3) FastAPI: NGINX → Uvicorn(ASGI) → FastAPI     ~~~~~~~~~~~~~~~~~~~~~~~~~~
    : FastAPI는 웹소켓/스트리밍이 흔해서, 프록시 설정에 그 옵션을 같이 넣는 게 안전하다.

(A) NGINX 설정 템플릿(권장)
server {
    listen 80;
    server_name example.com;

    # 정적 파일(필요할 때만)
    location /static/ {
        alias /var/www/fastapi_static/;
        expires 30d;
        add_header Cache-Control "public";
    }

    location / {
        proxy_pass http://127.0.0.1:8000;  # uvicorn이 여기에 떠있다고 가정
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # WebSocket/Streaming 대비(권장)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 300;
    }
}

유닉스 소켓으로 받고 싶으면 proxy_pass http://unix:/run/uvicorn_fastapi.sock; 형태도 가능.

4) 적용(공통 명령)
sudo ln -s /etc/nginx/sites-available/<서비스명> /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

 

 

다음검색
현재 게시글 추가 기능 열기

댓글

댓글 리스트
맨위로

카페 검색

카페 검색어 입력폼