Django Framework 기반의 백엔드 어플리케이션을 위한 WSGI 서버이다.
그럼 WSGI는 뭘까?
👉WSGI (Web Server Gateway Interface): Python 웹 어플리케이션이 웹 서버와 통신을 하기 위한 인터페이스이다. 웹 서버의 요청을 받아 Python 어플리케이션에 전달하는 역할을 한다.
이러한 WSGI의 대표적인 예 중 하나가 Gunicorn이다.
이 외에도, uWSGI, mode_wsgi, CherryPy 등이 있으며, 아래 이미지와 같이 웹 서버와 어플리케이션 서버 사이의 요청을 처리하는 역할을 한다.
이미지 출처: https://leffept.tistory.com/345
이렇게 파이썬 어플리케이션의 실행을 도와주는 WSGI에도 단점이 있다.
WSGI는 요청을 받고 응답을 반환하는 동작이 단일 동기 호출 방식으로 처리 된다는 점이다. 오랜 시간 연결을 유지해야 하는 Websocket이나 긴 HTTP 요청을 처리하기에 이 방식이 적합하지 않다.
이와 같은 단점을 보완하고자 등장한 것이 ASGI(Asynchronous Server Gateway Interface) 이다!
WSGI보다 나중에 나온 인터페이스로 WSGI의 단점을 보완하고, 비동기 코드를 처리하는 데에 효과적이다.
클라이언트로부터 여러 이벤트를 주고 받을 수 있고, 백그라운드 코루틴을 실행할 수 있다.
앞서 설명한 비동기 인터페이스를 통해 구현된 ASGI 웹 서버가 uvicorn이다.
단일 프로세스에서 uvloop 기반 비동기 Python code를 실행한다.
하지만, 단일 프로세스이기 때문에 서버 성능 저하가 발생할 수 있다.
그래서 우리는 웹 서버이자 프로세스 관리자인 gunocorn을 활용해 여러 개의 uvicorn을 관리하여 멀티 프로세스 환경을 구성한다.
아래의 구동 예시를 살펴보자.
gunicorn main:app --workers 3 --worker-class uvicorn.workers.UvicornWorker --daemon --access-logfile ./log.log
--workers : 프로세스 개수 (최대 vcpu 개수 * 2만큼 설정을 권장)
--worker-class : 프로세스를 다중으로 실행하기 위해 필요한 옵션
--daemon : 백그라운드로 실행
--access-logfile ./access_log.log : access_log.log 이름으로 로그를 저장
구동 방법은 알겠다. 그런데 왜 멀티 프로세스로 돌리는거지?
위에 작성한 내용과 관련이 있다. 하나의 요청을 받고, 해당 요청을 수행하는 과정이 오래 걸리면, 그 시간 동안 다른 요청을 처리하지 못하게 된다. 실제 서비스하는 환경에서 이러한 이슈가 발생한다면...🤦♀️
worker의 개수를 늘려 여러 개로 병렬 처리를 한다면 위와 같은 문제는 발생하지 않을 것이다.
이전에 프로젝트를 위해서 WebSocket을 사용했어야 해서 Nginx, Uvicorn, Redis를 손봤던 기억이 떠오르네요ㅋㅋ 그때는 아는 게 없어서 삽질도 많이 했었죠ㅎㅎ..