Gunicorn만 있어도 http request들을 처리할 수 있지만, production 환경에서 사용하기에는 아직 부족한 점이 많다. 애초에 nginx, apache와 같은 웹서버가 존재하던 환경에서 python으로 구현된 웹 애플리케이션을 효율적으로 연동하기 위해 생겨난게 WSGI server이기 때문이다.
Gunicorn에는 없고 nginx만이 가지고 있는 주요한 특징들은 아래와 같다.
static, dynamic request에 대한 처리
Django의 media, css 등 변하지 않는 static한 요청은 직접 처리하고 dynamic한 요청들은 Gunicorn으로 넘긴다.
Gunicorn으로 요청이 넘어가는 순간 자원사용이 크게 늘기 때문에 static한 요청을 따로 처리해주는 것이 중요하다.
적은 메모리를 사용하여 많은 요청처리
nginx는 c로 구현되어있기때문에 속도나 메모리사용 측면에서 뛰어나다.
SSL termination
https에 대한 처리를 의미하며, 암호회된 요청을 복호화한다.
nginx와 Gunicorn까지 연동하면 동시에 많은 요청을 처리할 수 있고, 훨씬 안정화된 서버를 구축할 수 있다. 여기서 Django 내장서버(manage.py runserver로 실행)와 nginx를 직접 연동하면 안되는가에 대한 의문이 들 수 도 있다. 그 경우에 문제가 되는 것은 Django 내장서버는 단일 프로세스, 단일 쓰레드라는 점이다. 아무리 nginx에서 동시에 많은 요청을 처리한다 하더라도 결국 Django 내장서버에서 병목이 생기게 된다.
Gunicorn은 이와 다르게 worker process들의 pool을 관리하며 nginx로부터 요청이 올때마다 적절한 worker process에 요청을 할당하기 때문에 병렬적인 처리를 가능하게 해준다.
Nginx 연동하기
이제 Gunicorn과 nginx를 연동해보자. 우선 nginx를 설치한다.
설치하고나서 $ ps -ef | grep nginx 명령어를 통해 nginx process가 실행중인지 확인해본다.
nginx가 실행중이 아니라면 $ nginx 명령어로 nginx 프로세스를 시작해본다.
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use) 에러가 발생한다면 netstat -anp | grep 80 명령어로 80번 포트를 사용하고있는 process를 확인해보고, 존재한다면 종료후 다시 시도한다.
nginx가 잘 동작하는것을 확인했으니 nginx의 설정파일을 수정하여 Gunicorn과 연동해본다.
프로젝트의 root directory(README.md 있는곳)에 nginx.conf라는 파일을 만들고 아래의 내용을 복붙한다.