NERD WORLD

AWS EC2 인스턴스에 Django+Nginx+uWSGI+PostgreSQL로 배포하기 본문

Python - Django

AWS EC2 인스턴스에 Django+Nginx+uWSGI+PostgreSQL로 배포하기

학부생7년차 2016. 6. 16. 14:06

플스방에서 친구들이랑 위닝 일레븐 게임하고나서 전적을 기록하고 언제나 확인할 수 있도록 Django로 웹 서비스를 만들고 있다. 스마트폰 어플리케이션으로 만들면 더 좋았겠지만, 안드로이드 개발이 약해서 모바일 웹을 타겟으로 만들고 있다. 


추가 구현해야할 기능들이 꽤 남아 있지만, 구현이 일단락은 되었다는 생각이 들어서 친구들과 함께 사용할 수 있도록 AWS EC2에 배포해봤다. Ubuntu OS가 익숙치 않아서, 배포해나가는 과정이 어려웠다. 올바르게 배포한건지는 모르겠다. 다만 EC2 인스턴스의 Public IP로 접속PostgreSQL DB와 연동하는 과정에서 문제가 없었으므로 한번 정리해두고 넘어가려 한다.


Unix domain socket

이번 포스트의 키워드는 Django, Nginx, uWSGI, PostgreSQL이다. 각각에 대해서는 간략한 개념은 알고 있었다. Django는 Python으로 작성된 풀스택 웹 프레임워크, Nginx는 웹 서버, uWSGI는 웹 어플리케이션 서버, PostgreSQL은 RDBMS와 같은 식으로 말이다. 그래서 직접 배포해보는 것은 처음이었음에도, 가이드에서 소개하는 내용들이 그리 낯설지 않았다. 하지만 Nginx와 uWSGI를 연동할때 등장한 Unix socket의 개념은 처음이었다. 그래서 간략히 정의만 음미해보고 싶었다. 아래는 영문 위키피디아의 소개에서 발췌한 것이다.

A Unix domain socket or IPC socket (inter-process communication socket) is a data communications endpoint for exchanging data between processes executing on the same host operating system.

(...) 

The API for Unix domain sockets is similar to that of an Internet socket, but rather than using an underlying network protocol, all communication occurs entirely within the operating system kernel. Unix domain sockets use the file system as their address name space. Processes reference Unix domain sockets as file system inodes, so two processes can communicate by opening the same socket.

동일한 OS에서 실행중인 프로세스들간의 데이터 통신을 위해 사용하며, 흔히들 소켓이라고 하면 생각하는 Internet Domain Socket과 API가 유사하고, 네트워크 프로토콜 상에서 동작하는 것이 아니라 파일 시스템시스템 커널 상에서 동작하는 소켓이라고 이해할 수 있겠다.


Toy Architecture


배포 과정을 이해하기 위해서, 아키텍쳐를 간단하게 그림으로 정리해봤다.

: 웹 클라이언트웹 서버(Nginx)에 HTTP 프로토콜로 요청(request)를 보낸다.

: CSS, JavaScript, Images, PDF 문서 등 파일 시스템에 저장되어있는 각종 정적 파일(static file)들은 웹 서버가 바로 처리할 수 있다.

: 정적 파일 외의 동적인 부분은 웹 서버가 처리할 수 없으므로 웹 어플리케이션 서버(uWSGI)에게 위임한다. 웹 서버가 웹 어플리케이션 서버에게 요청을 위임하고, 웹 어플리케이션 서버가 이를 대행해서 웹 서버에게 응답해주는 관계다. 이 사이를 매개해주는게 바로 앞에서 설명한 Unix Socket이다. 웹 서버와 웹 어플리케이션 서버 사이의 통신도 HTTP 프로토콜을 사용할 수 있지만, 같은 OS상에 존재하는 두 개체이므로 더 빠른 uwsgi 프로토콜을 사용한다.

: 웹 클라이언트가 요청한 HTTP 프로토콜의 메시지를, Python call로 변환해줘야 Python으로 기술된 어플리케이션이 동작할 수 있다. Python에서는 이 매핑 관계로 WSGI를 표준으로 사용한다. WSGI는 Web Server Gateway Interface의 약자이다. uWSGI는 이 WSGI 표준의 구현이라고 이해하면 된다. uWSGI는 웹 서버에게서 받은 HTTP 요청을 Python call로 변환해서 Django 프레임워크와 협업한다.

: Django 프레임워크는 사용자가 Python으로 작성한 어플리케이션 코드를 실행한다.

: 또한 필요하다면 ORM(Object-Relational Mapping)을 사용해서 DB에서 데이터를 읽거나 쓴다. 여담이지만, 프레임워크가 제공해주는 강력한 기능 중 하나가 ORM이라고 생각한다. SQL 문법을 몰라도, Python 코드로 DB를 다룰 수 있다.


** 위의 기술에서 "Django 프레임워크"라고 지칭한 주체가 정확히 누구인지 아직 이해하지 못했다. django-admin startproject 커맨드가 생성해주는 wsgi.py이 아닐까 생각하고 있다.


Deployment

이전까지 개념적으로 정리하고 싶었던 내용들을 간단히 정리해봤다. 실제 배포작업을 위한 일련의 과정들은, 이미 많은 사람들이 친절하게 잘 설명해놓은 튜토리얼, 가이드들이 많이 있어서 구글링으로 쉽게 찾을 수 있었다. 도움 받은 레퍼런스들을 언급하고, 내가 맞닿뜨렸던 문제들에 대해서만 적어볼까 한다.


1) How To Serve Django Applications with uWSGI and Nginx on Ubuntu 14.04 : AWS EC2 인스턴스를 생성할때, Ubuntu Server 14.04 OS를 선택했다. 이 튜토리얼이 Ubuntu OS에서 Nginx/uWSGI를 사용해서 Django application을 배포하는 과정에 대해서 친절하게 잘 설명해주고 있어서 큰 참고가 되었다.


위의 튜토리얼에서는 커맨드 라인에서 Django 프로젝트를 생성함을 가정하고 있다. 나는 로컬 머신에서 개발한 Django 프로젝트를 GitHub repository에 업로드하고, EC2 인스턴스에서는 pull로 다운로드했다. 두 경우의 차이점은 Django 프로젝트 디렉토리의 owner/owner group이다. 후자의 경우 owner/owner group이 둘 다 root로 설정되어서 튜토리얼을 따라하는 과정중에 collectstatic 커맨드에서 오류가 난다. root가 소유한 디렉토리에 다른 유저가 서브 디렉토리를 생성하려고 했기 때문이다. 그러나 이런 맥락을 이해하지 못하고 있었기 때문에 오류를 수정하는데에 많은 시간이 걸렸다. 해결 방법에 대해서는 "Change folder permissions and ownership" 링크를 참고했다.

(프로젝트 폴더)$ sudo chown -R user:user project_directory_name


또 하나의 이슈는 settings 파일을 변경하는 것이다. 프로젝트 GitHub repository는 2개의 settings 파일을 가지고있다. django-admin 커맨드가 만들어주는 default settings 파일을 로컬 개발 머신에서 사용하고, 이를 내포하고 부분을 수정한 settings_prod 파일을 배포 머신에서 사용하고 싶었다. 1)의 튜토리얼을 처음부터 끝까지 따라해보면, default settings 파일을 사용하게 된다. Django 문서를 읽어보면 "DJANGO_SETTINGS_MODULE" 환경변수가 존재하지 않으면 default settings 파일을 사용하게 됨을 알 수 있다. 그러니 다른 settings 파일을 사용하고 싶다면, 환경변수를 설정해주면 된다. 주의할 점은, Ubuntu OS에서 .bashrc 파일에 환경변수를 기술하더라도 uWSGI가 이를 인식하지 못한다는 점이다. 아마 서로 다른 환경변수 스페이스를 사용하기 때문인가보다. 그러니 .bashrc 파일에 환경변수값을 작성하지 말고, 튜토리얼에서 작성한 /etc/init/uwsgi.conf 파일에 env 변수이름=변수값 으로 설정한다.


2) How To Use PostgreSQL with your Django Application on Ubuntu 14.04 : Ubuntu 14.04에서 Django 어플리케이션에 PostgreSQL를 결합시키는 과정에 대한 튜토리얼이다. 그대로 따라하면 된다. DigitalOcean에게 늘 큰 도움을 받는다.


여기까지 완료하고 nginx, uwsgi 프로세스를 가동한 뒤 EC2 인스턴스의 Public IP로 접속해보면 원활하게 배포되었음을 확인할 수 있다.

Comments