2. Django와 WSGI 서버(Gunicorn) 연동 에서 Gunicorn과 Django 연동을 통해 실제 8000번 포트로 http request를 받아 처리하는 서버를 띄운적이 있다.
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라는 파일을 만들고 아래의 내용을 복붙한다.
proxy_pass는 Gunicorn 서버의 주소를 지정해준다. Gunicorn을 unix domain socket으로 통신하도록 설정했다면 http주소 말고 unix domain socket이 위치한다.
nginx 설정이 끝났으면 Django의 settings.py도 수정해줘야 한다. Django의 settings.py 파일을 열고 ALLOWED_HOSTS를 찾아 아래와 같이 바꿔준다.
이제 nginx를 새로운 설정파일과 함께 실행해준다
http://localhost로 접속하면 Django의 default 페이지가 보인다.
Client로부터 80번 포트로 http 요청이 오면 nginx가 이를 받아서 처리하게 된다. 요청이 static한 자원에 대한 요청이면 직접 처리하고(위에 예시에는 static file지정을 하진 않았음) dynamic한 자원에 대한 요청이면 WSGI서버(8000번 포트)로 해당 요청을 넘긴다.
이후 동작은 앞서 설명한 WSGI서버의 동작과 동일하다.