IT 엘도라도 로고
IT 엘도라도
황금

AWS EC2, RDS에 Django REST API 서버 배포하기 (Amazon Linux 2, PostgreSQL, Gunicorn)

2020-11-29 19:32

AWS EC2, RDS에 Django REST API 서버 배포하기 (Amazon Linux 2, PostgreSQL, Gunicorn)

여기서는 EC2 인스턴스(AMI: Amazon Linux 2)와 RDS 인스턴스(엔진: PostgreSQL)를 이미 생성했고, EC2 인스턴스에 SSH로 접속하는 방법을 알고 있으며, EC2 인스턴스에서 RDS 인스턴스로 접근이 가능하도록 인바운드 규칙까지 설정해둔 상태라고 가정한다. 더불어 EC2 인스턴스에 Nginx라는 웹 서버를 깔고 기본적인 설정도 이미 해둔 상태를 가정한다. 이와 관련해서는 EC2에 대해 설명하는 이 포스팅RDS에 대해 설명하는 이 포스팅, 그리고 EC2에 Nginx를 세팅하는 것을 다루는 이 포스팅을 반드시 먼저 읽고 오길 바란다. 아래에서 설명하는 명령어들은 기본적으로 해당 EC2 인스턴스에 SSH 접속이 이뤄진 상태에서 입력하는 것들에 해당한다고 보면 된다.
💡
  • 하나의 EC2 인스턴스에 프론트 엔드 서버와 백 엔드 서버를 두는 경우를 가정한다.
  • 즉 하나의 웹 서버(Nginx)가 정적 파일의 서비스뿐 아니라 백 엔드 서버로 요청을 전달하는 프록시 서버 역할도 수행할 것이다.
  • 이러한 방식(프록시 서버 이용)의 장점은 CORS 문제와 쿠키 응답 문제의 해결이다. 관련 내용은 이곳을 참고하자.
  • 또한, Django 어플리케이션의 URL은 모두 api/로 시작한다고 가정한다. 따라서 클라이언트도 API 호출 시 api/를 붙여야 한다.
 

1. 기본 소프트웨어 설치

현재 EC2 인스턴스에 설치되어 있는 모든 소프트웨어 패키지들을 업데이트한다. 개발자라면 yum 혹은 apt 명령어에 대해 한 번쯤은 들어봤을 것이다. yumapt는 둘 다 Linux 운영체제에서 소프트웨어 패키지들을 쉽게 설치 및 관리할 수 있도록 도와주는 패키지 관리자(Package Manager)이다. 즉 Linux 운영체제의 컴퓨터에서는 각종 소프트웨어를 설치할 때 yum 혹은 apt를 사용하게 된다.
개발을 위한 각종 도구 및 유틸리티(git, gcc 등등)를 설치한다. yum은 패키지들을 용도에 따라 그룹으로 분류하므로, 그룹 단위로도 패키지 설치가 가능하다.
 

2. 파이썬 가상 환경 구축

2-1. pyenv 패키지 설치

pyenv 패키지는 하나의 로컬 시스템에서 다양한 버전의 파이썬을 사용하고 관리할 수 있도록 하는 도구이다. 다음은 pyenv 패키지를 설치하고 pyenv를 사용하기 위한 몇 가지 초기 설정 작업을 수행하는 것을 나타낸다.

2-2. pyenv-virtualenv 패키지 설치

pyenv-virtualenv 패키지는 pyenv를 이용하여 특정 파이썬 버전의 가상 환경을 쉽게 만들고 관리할 수 있도록 하는 도구이다.

2-3. 파이썬 및 가상 환경 설치

pyenv를 이용하여 원하는 버전의 파이썬을 설치하고, 그 버전을 바탕으로 가상 환경을 생성한다.

2-4. 프로젝트 폴더 Clone 및 가상 환경 지정

원격 저장소에서 Django 프로젝트의 리포지토리를 Clone 해온다. 그리고 그 폴더에 들어가면 자동으로 앞서 만든 가상 환경에 진입이 되도록 설정한다.
 

3. PostgreSQL 클라이언트 설치

Django 어플리케이션이 RDS 인스턴스의 PostgreSQL 서버와 통신할 수 있도록 PostgreSQL 클라이언트를 설치해줘야 한다. 그리고 나면 당연히 Django의 설정 파일에도 PostgreSQL 서버를 사용하도록 설정을 해줘야 하는데, 이에 대해서는 아래에서 다루도록 하겠다. 일단 PostgreSQL 클라이언트부터 설치하고, 이를 이용하여 RDS 인스턴스의 PostgreSQL 서버에 접속한 뒤 Django 어플리케이션이 사용할 데이터베이스를 하나 생성해주자. 참고로 루트 유저의 이름은 특별히 바꿔주지 않았다면 postgres이다.
 

4. EC2 인스턴스의 환경 변수 설정

Django 어플리케이션은 DJANGO_SETTINGS_MODULE이라는 이름의 환경 변수의 값을 읽어와서 어떠한 설정 파일을 사용할지 결정한다. 따라서 위 명령어를 통해 EC2 인스턴스의 환경 변수 목록에 DJANGO_SETTINGS_MODULE을 추가해주도록 하자. ###에는 사용할 Django 설정 파일의 상대 경로를 적어줘야 한다. 만약 Django 프로젝트의 루트 폴더 하위에 존재하는 config/settings/production.py 파일을 사용할 것이라면 config.settings.production이라고 적어야 한다.
Django 어플리케이션이 접근할 RDS 인스턴스의 데이터베이스 서버 정보도 환경 변수로 관리해주는 게 좋다. 이렇게 설정된 환경 변수 값들은 Django 설정 파일에서 읽어오게 될 것이다(뒷부분 설명 참고).
Django Secret Key도 환경 변수로 관리하는 것을 권장한다. 여기서 다루진 않겠다.
수정한 쉘 스크립트 파일을 실행한다. 즉, 쉘 스크립트 변동 사항을 적용한다.
 

5. 파이썬 의존성 패키지 설치

Clone 해온 프로젝트 폴더로 이동한다. 그러면 앞서 구축한 가상 환경에 자동으로 진입될 것이다.
pip을 최신 버전으로 업그레이드한다.
pip을 이용하여 해당 프로젝트의 파이썬 의존성 패키지들을 일괄 설치한다. 단, 해당 프로젝트에서 필요로 하는 파이썬 패키지(Django, Django REST Framework 포함)들의 목록이 requirements.txt 파일에 명시되어 있음을 가정한다(이것이 관습이다). 참고로 여기에는 psycopg2 패키지도 반드시 포함되어 있어야 한다. PostgreSQL 서버에 Django가 접근하기 위함이다.
 

6. Django 프로젝트 설정 및 테스트

6-1. Django 설정 파일 수정

앞에서 말한 것처럼 이제 Django 설정 파일에도 데이터베이스 관련 설정을 해줘야 한다. 접근할 데이터베이스의 종류를 SQLite3에서 PostgreSQL로 변경해주고(psycopg2 패키지가 설치되어 있어야 함), 미리 생성해 놓은 데이터베이스를 Django와 연결해준다(이 과정에서 os.environ.get 함수를 이용하여 환경 변수의 값을 읽어옴). 이로써 Django 어플리케이션이 PostgreSQL 서버와 통신하며 데이터를 주고받을 수 있게 되었다. 다음으로, ALLOWED_HOSTS 옵션에는 EC2 인스턴스의 IP 주소를 지정해주도록 하자.

6-2. 데이터베이스 마이그레이션

이제 Django 프로젝트 폴더로 찾아가서 다음 명령어를 수행한다. Django의 여러 (앱의) 기능들을 현재 연결된 데이터베이스에 적용시켜준다.

6-3. Django 개발 서버 실행 (테스트)

지금까지 한 설정을 바탕으로 Django (개발용) 서버를 실행시켜보자. (참고로 이는 개발에만 사용하도록 Django가 기본 제공하는 간단한 버전의 WSGI 서버이다. 실제로 배포할 때는 Gunicorn 등의 WSGI 서버를 사용하게 된다.) 그런데 이렇게 Django 서버를 테스트로 실행해보기 전에 먼저 설정해줘야 할 것이 있다. 바로 EC2 인스턴스의 보안 그룹을 설정해주는 것이다. AWS 콘솔로 들어가서 EC2 인스턴스의 보안 그룹을 찾고, 인바운드 규칙을 추가하여 8000번 포트에서의 접근을 허용해주도록 하자. 다음과 같이 말이다.
notion image
이제 Django 서버를 다음과 같이 실행해보자. 0.0.0.0:8000은 자기 자신 할당된 어떠한 IP 주소를 이용하여 접근을 하든 8000번 포트로 서버를 개방해주겠다는 의미이다.
성공적으로 실행이 되었다면 브라우저를 켜서 EC2 인스턴스의 IP 주소로 8000번 포트에 접속해보자. 물론 유효한 URL이어야 한다. 여기서는 에러가 발생하지 않는지 정도만 확인하자. 이때, Django의 Static 파일 관련 설정을 해주지 않았기에 CSS가 깨져 나오는 건 당연하니 이건 신경 안 써도 된다.
 

7. Gunicorn 설치 및 테스트 실행

이제 웹 서버(Nginx)와 Django 어플리케이션 사이에서 중계 역할을 수행하는 WSGI 서버를 설치해볼 것이다. 다음과 같이 pip 명령어를 이용하여 gunicorn 패키지를 설치해주자. 물론이지만 Python 가상 환경에 진입되어 있는 상태여야 한다.
이제 Django 서버가 아닌 Gunicorn을 실행시켜보자. 다음과 같이 실행할 수 있다. {wsgi.py 파일의 상대 경로}:application 부분의 경우, Django의 wsgi.py 파일이 현재 경로 기준으로 config/wsgi.py 경로에 위치한다면 config.wsgi:application이라고 적으면 된다.
이제 브라우저를 켜서 EC2 인스턴스의 IP 주소로 8000번 포트에 접속해보자. 접속에 성공한다면 Gunicorn이 정상적으로 동작하는 것이다. 테스트에 성공하고 나면 아까 생성했던 보안 그룹은 다시 삭제해주자. 우리는 하나의 EC2 인스턴스에 설치된 웹 서버(Nginx)가 프록시 서버의 역할을 수행하도록 하여 백 엔드 서버에 접근하게끔 할 것이기 때문이다. 즉, 외부에서 들어오는 80번 포트의 요청을 Nginx가 내부에서 돌아가는 Gunicorn에게 전달하도록 설정할 것이다. 이는 뒤에서 알아보자.
 

8. Gunicorn 서비스 등록 및 실행

Gunicorn이 정상적으로 실행되는 것을 확인했다면, 이제 이를 시스템에 서비스로 등록해보도록 하자. 이는 Gunicorn의 실행, 중지, 혹은 자동 실행 설정 등을 쉽게 하기 위함이다. 이를 위해서는 해당 서비스의 등록을 위한 스크립트를 작성해줘야 한다. /etc/systemd/system 경로에 다음과 같이 스크립트를 생성하자. AAA, BBB, CCC 부분에는 원하는 파일 이름을 적으면 된다.
BBB.env 파일은 무엇일까? 우린 이러한 파일을 생성한 적 없다. 이 파일은 바로 이어서 우리가 직접 생성해줄 것이다. 이 파일의 역할은 서비스로 등록되어 실행될 Gunicorn이 읽어야 할 환경 변수들을 담고 있는 것이다. 그런데 이상하지 않은가? 환경 변수는 이미 앞서 설정하지 않았는가? 사실 필자도 아직 이해하지 못한 부분인데, 서비스로 등록되어 실행되는 Gunicorn은 이미 설정되어 있는 환경 변수들을 읽지 못한다. 따라서 직접 우리가 명시해주고 읽게 만들어야 한다. (왜 그런지 아는 사람은 댓글로 알려주시면 감사하겠습니다.) 그러면 BBB 파일도 이어서 생성해보자. 경로는 /home/ec2-user/env로 정했다. 위에서 설정한 환경 변수들을 모두 적어주기 바란다.
다음으로, CCC.sock 파일은 무엇을 의미할까? 이는 Gunicorn을 실행하면서 생성할 소켓 파일의 이름이다. 나중에 Nginx까지 실행하면 Nginx가 80번 포트로 들어오는 API 요청들을 Gunicorn에게 전달해주기 위해 이 소켓 파일을 참조하게 될 것이다. 이와 관련된 Nginx 설정은 아래 설명(9번)을 참고하자.
이제 위에서 작성한 파일들을 토대로 Gunicorn을 실행하자. enable 명령어는 해당 서비스가 부팅 시에 자동으로 실행되도록 설정하는 것이고, start 명령어는 지금 즉시 실행하는 것이다. 그리고 나면 status 명령어로 Gunicorn이 정상 실행되는지도 확인해주자.
 

9. Nginx 프록시 설정 (Gunicorn으로의 리다이렉트)

이제 Nginx가 api/로 시작하는 URL로 들어오는 요청을 Gunicorn에게 전달하도록 설정해보자. Nginx 설정 파일에 다음과 같이 location 블록 하나를 추가 작성해주면 된다. proxy_pass 부분은 아까 Gunicorn을 실행시키면서 생성한 소켓 파일의 이름을 지정해준다. 필자의 경우, Nginx 설정 파일의 경로가 /etc/nginx/sites-available/이므로 sudo vi /etc/nginx/sites-available/파일명.conf 명령어를 입력하여 설정 파일을 열고 내용을 수정하였다. 각자 Nginx 설정 파일의 위치는 미리 파악해두도록 하자.
참고로 개발 모드에서는 package.json 파일에 proxy 속성을 지정해줌으로써 Webpack 개발 서버가 프록시 서버의 역할을 수행하도록 할 수 있다. 이와 관련해서는 Create React App의 공식 문서에 있는 이 설명을 참고하자.
이제 Nginx도 실행해보자. 이때 Nginx도 부팅 시에 자동 실행되도록 enable 명령어까지 실행해주자. 그리고 나면 Gunicorn 때와 마찬가지로 status 명령어로 Nginx가 정상적으로 실행되는지까지 확인 한 번 해주자.
말풍선
댓글 0
좋아요 8
    아직 작성된 댓글이 없어요.
사용자