본문 바로가기

Server, DevOps/LINUX , OS

Python Nginx로 배포하고 Certbot으로 HTTPS 도메인까지 연결하기(+EC2)

들어가며

Nginx로 파이썬을 배포하고 Certbot을 사용하여 Https 도메인 연결을 설정하는 설명하려 합니다. 정글에서 2박3일로 진행한 유사 해커톤 서비스😅를 배포했던 방법을 정리하는 글입니다. 파이썬 배포 및 AWS 콘솔을 활용하지 않은 Https 연결과 관련된 글이 없어 배포하는데 어려움을 겪었기에, 그런 분들을 위한 글이기도 하고, 저 스스로도 다시 하나 하나 뜯어보며 체화시키기 위한 개념 설명 및 적용 글입니다.

 

Nginx

Nginx란 무엇일까요? chatGPT를 통해 확인해보면 아래와 같이 나옵니다.

Nginx는 웹 서버 소프트웨어로, HTTP 서버뿐만 아니라 리버스 프록시, 로드 밸런서, 메일 프록시 등의 역할을 할 수 있습니다. 높은 성능과 낮은 메모리 사용량을 자랑하며, 특히 정적 콘텐츠를 제공하거나 리버스 프록시로 사용될 때 뛰어난 성능을 발휘합니다.

 

잘 와닿지 않습니다.

 

다시 말해보자면 Nginx는 어딘가 띄워진 서버의 서비스가 아니라, 우리가 엑셀이나 파워포인트처럼 사용하는 소프트웨어입니다. 즉, 웹 호스팅을 해주는 터미널용 소프트웨어인 것이죠. 그래서 사실 그냥 Nginx가 서버를 띄워주는 것은, python app.py 로 저희가 터미널에서 명령을 내리는 것과 기본적인 개념은 같습니다. 다만, 여기서 이제 안정적으로 웹을 호스팅해주는 기능들이 추가됩니다.

 

안정적으로 웹을 호스팅하는 것은 뭘까요?

 

웹을 호스팅하기 위해서는 프로덕션 환경도 준비해야하고, 다양한 웹 서버 설정도 필요합니다. 예를 들어, 로드 밸런싱, SSL 인증서 관리, 도메인 연결 등이 필요해지죠. 방화벽 설정 등을 통해 보안 최적화도 필요하구요. 그런데 이 모든 것들을 Nginx에서 할 수 있습니다! 와우! 이제야 왜 Nginx를 사람들이 많이 사용하는지 이해가 됩니다.

 

배포 및 HTTPS 설정

 

자 이제 그럼 Nginx로 EC2에 서버를 한 번 띄워보겠습니다. 아까 Nginx는 소프트웨어라고 했죠? 그럼 먼저 설치를 해야겠죠. 설치를 해주겠습니다. EC2 터미널에 접속해주세요.

참고로 굳이 개인 터미널에서 접속하기 귀찮으신 분들은 AWS 콘솔로도 접속이 가능합니다. 인스턴스 연결 누르면 됩니다.

 

1단계: Nginx 및 필수 패키지 설치

sudo apt update
sudo apt install nginx python3-pip python3-venv

 

위의 단계는 FileZila와 같은 FTP 서비스를 이용해서 python 프로젝트 파일을 EC2로 모두 옮겨준 후에 실행하는 과정입니다.

 

2단계: 파이썬 애플리케이션 설정

rm -rf ./venv # 기존 가상환경이 있는 경우
python3 -m venv ./venv
source .venv/bin/activate
pip install flask # 등 필요한 패키지 설치

 

가상 환경을 생성해주고 프로젝트 파일에 필요한 패키지를 설치합니다. 필요한 패키지를 찾아보기 귀찮으면 python app.py를 입력하셔서 프로젝트를 실행시키고 나오는 패키지 에러를 보고 하나씩 설치해주셔도 됩니다.

 

3단계: WSGI 서버 설정

WSGI 서버를 설정해야한다고 합니다. 그런데 WSGI가 뭘까요? 잠시 알아보고 또 진행하겠습니다.

우선 WSGI는 Web Server Gateway Interface의 약자로 웹 애플리케이션을 서버와 연결하기 위한 표준 인터페이스입니다. 아직 이해가 안갑니다. 좀 더 자세히 알아보겠습니다.

 

Python에는 다양한 웹프레임워크(Django, Flask 등)가 사용됩니다. 우리가 알다시피 이 프레임워크들은 HTTP 요청을 처리하고, 그에 대한 응답을 생성하는 역할을 합니다. 그런데 이 어플리케이션이 웹서버(Nginx나 Apache 등)과 상호작용하기 위해서는 공통된 표준이 필요했고, 그렇게 나오게 된 것이 WSGI입니다.

 

WSGI는 Http 요청을 수신하고, Python 애플리케이션을 호출하고, 응답을 반환하는 역할을 합니다. 어, 그런데 잠시! 아까 전에 분명 이런 역할은 Nginx가 리버스 프록시로 한다고 했던 것 같습니다.

리버스 프록시
클라이언트 요청을 받아 백엔드 서버에 전달한 뒤, 백엔드 서버로부터 받은 응답을 클라이언트에서 전달하는 역할을 하는 서버.
실제 백엔드 서버의 위치와 구성이 클라이언트에 노출이 되지 않지만, 클라이언트는 서버와 직접 통신하는 것처럼 동작되는 것이 특징.

 

역할과 상당히 유사해보이는데 정확히 두 서버는 어떤 협력을 하고 있는 것일까요.

 

리버스 프록시와 WSGI 서버는 각기 다른 역할을 합니다. [1] Nginx는 웹 브라우저나 다른 클라이언트로 들어오는 HTTP/HTTPS 요청을 받습니다. 그리고 [2] Nginx는 이 요청을 직접 처리하지 않고, 요청을 적절한 WSGI같은 백엔드 서버로 전달합니다. 이 때, Nginx는 로드밸런싱, SSL 종료, 캐싱, 방화벽 설정 등과 같은 다양한 기능을 통해서 요청을 조정할 수 있습니다. 그리고 이미지, CSS, JS와 같은 정적 파일은 WSGI 서버로 넘기지 않고 바로 응답을 반환합니다. 그리고 [3] Nginx는 WSGI 서버로부터 받은 응답을 클라이언트에게 전달하여 요청-응답 사이클을 완성하게 됩니다.

 

아까 GPT가 해준 Nginx 설명을 위로 올라가 다시 읽어보면 이제야 이해가 되는 듯 합니다. 결론적으로 Nginx는 리버스 프록시 역할을 해서 요청을 받아드리고 이 요청을 WSGI 서버로 전달하고, WSGI는 파이썬 어플리케이션을 실행하여 요청을 처리하고 다시 Nginx로 돌려주는 역할을 하게되는 것입니다.

 

자 그럼 다시 설치로 돌아와서, 이 WSGI의 대표적인 Gunicorn을 이용해 배포해보겠습니다.

 

1. gunicorn 설치

pip install gunicorn

 

2. WSGI 서버 실행

gunicorn --bind 0.0.0.0:5000 app:app # 앞의 app은 파일 명, 뒤의 app은 실행 인스턴스명

 

포트 번호는 사용하는 포트 번호를 작성해주시면 됩니다. 뒤의 app:app의 경우, 저희 서비스는 app 인스턴스를 실행할 때, 이렇게 아래와 같이 함수로 실행을 했는데 이렇게 만약 함수 실행으로 하셨다면 다르게 명령어를 작성해야합니다.

from app import create_app

app = create_app()

 

이런 경우 아래와 같이 작성해주시면 됩니다. 

gunicorn --bind 0.0.0.0:5000 'app:create_app()'

 

서버가 잘 실행되나요? 축하드립니다. 다음 단계로 넘어갑시다.

 

4단계: Nginx 설정

이제 Nginx에게 명령을 내릴 차례입니다. 설정 파일을 작성해주겠습니다.

sudo nano /etc/nginx/sites-available/app

 

에디터는 nano가 아니어도 됩니다. 다음 내용을 추가해주겠습니다.

server {
    listen 80;
    listen [::]:80;
    server_name your_domain_or_IP; # server_name 옆에 도메인 이름 써주시면 됩니다.

    location / {
        proxy_pass http://127.0.0.1:5000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

 

명령어를 하나씩 이해해보겠습니다.

일단 server {...}은 Nginx의 서버 블록으로서 특정 도메인이나 IP 주소로 들어오는 요청을 어떻게 처리할 지 설정하는 부분입니다.

listen 80으로 기본 HTTP 포트를 열어줍니다. Nginx가 HTTP 프로토콜로 오는 요청을 수신하도록 설정하는 것입니다.

server_name 으로 서버블록을 적용할 도메인 이름이나 IP 주소를 지정해줄 수 있습니다.

location {...}은 특정 URI에 대해 어떻게 요청을 처리할지 지정할 수 있는 부분입니다. 

proxy_pass로는 요청을 전달할 수 있는데, 로컬 호스트의 포트 5000에서 동작 중인 우리의 WGSI 파이썬 서버에 요청을 전달한다는 뜻입니다.

proxy_set_header는 말그대로 헤더의 설정부분입니다. Host는 $host 변수로 요청된 호스트 이름이며, 이 이름으로 백엔드 서버가 요청이 온 도메인 정보를 알 수 있게 됩니다. 

X-Real-IP는 클라이언트의 IP 주소이고, X-Fowarded-For 는 원래 클라이언트의 IP 주소와 함께 요청이 거쳐온 모든 프록시 서버의 IP 주소를 전달받는 설정입니다.

마지막으로 X-Forwarded-Proto는 요청이 원래 HTTP 였는지 HTTPS였는지를 알려주는 요청 프로토콜을 백엔드 서버로 전달하는 부분입니다.

 

해당 부분을 복붙해서 작성하고 저장합니다. 참고로 nano는 Ctrl + X를 누르시고 엔터를 누르면 저장, 종료됩니다.

 

이제 이 작성한 부분을 심볼릭 링크를 만들어 활성화해주겠습니다.

sudo ln -s /etc/nginx/sites-available/app /etc/nginx/sites-enabled
sudo nginx -t  # 설정 테스트에서 Successful 뜨면 성공!
sudo systemctl restart nginx # Nginx 재시작

 

테스트 시에 Successful이 뜬다면 다음 단계로 넘어가실 수 있습니다.

 

아, 혹시나해서 말씀드리는데 그리고 도메인을 구입하신 곳의 DNS 레코드 관리에서 EC2 IP는 A레코드로 꼭 등록 미리 해두셔야합니다.

 

5. Certbot 설치 및 SSL 인증서 발급

이제 마지막 단계입니다. HTTPS 연결을 위해 Certbot을 설치하겠습니다. Certbot을 또 알아보고 가야겠죠?

 

Certbot은 무엇일까요?

Certbot은 무료로 SSL/TLS 인증서를 발급하고 자동으로 갱신해주는 오픈 소스 소프트웨어입니다. 이 인증서를 사용하면 웹사이트에서 HTTPS(보안 HTTP) 프로토콜을 통해 안전한 통신을 제공할 수 있습니다. Certbot은 Let’s Encrypt 라는 인증 기관(CA)과 협력하여 SSL/TLS 인증서를 쉽게 관리할 수 있도록 도와줍니다.

 

대략적인 과정은 이렇습니다. Certbot은 Let's Encrypt에서 SSL/TLS 인증서를 발급받는 과정을 자동화합니다. 인증서 발급은 웹서버의 소유권을 확인한 후 이루어지는데 이 부분이 아까 DNS 레코드관리에 꼭 IP를 등록해두라고 했던 부분입니다. 그리고 Certbot은 소유권을 확인하고 발급된 인증서를 Nginx, Apache 등 웹 서버에 자동으로 설치하고 설정해줍니다. 이를 통해서 HTTP 요청을 HTTPS로 리다이렉트하고, 우리의 웹사이트가 보안 통신이 가능하게 만들어줍니다.

 

그런데 Let's Encrypt에서 발급하는 인증서는 기본적으로 90일 동안만 유효합니다. 하지만 우리의 Certbot은 이 또한 만료되기 전에 자동으로 갱신하는 기능을 제공해서 SSL/TLS 인증서 관리의 번거로움을 줄여줍니다. 자세한 명령어는 아래에서 보실 수 있습니다.

 

자, 이제 설치해보겠습니다.

sudo apt install certbot python3-certbot-nginx

 

설치를 완료했다면 SSL 인증서를 발급하고 Nginx 설정을 자동으로 업데이트 해보겠습니다.

sudo certbot --nginx -d your_domain_or_IP # 적용할 도메인

 

이제 모든 과정이 완료되었습니다. 이렇게 마지막 명령을 거치고 나면 아까 작성했던  /etc/nginx/sites-available/app 해당 파일이 변경되어 있을 것입니다. 아까 명령어로 다시 한 번 확인해보셔도 됩니다.

 

그리고 만약 저처럼 잠시 서버를 올리는게 아니라, 계속 올려둘거라 인증서 자동 갱신 설정도 필요하다면 아래의 명령어를 추가적으로 진행해주시면 됩니다.

sudo systemctl status certbot.timer

 

이렇게 Nginx를 사용해 파이썬 어플리케이션 배포 Certbot을 이용한 Https 설정이 완료했습니다. Nginx를 좀 더 잘 아시는 분이라면 설정을 추가로 조정해서 더 높은 보안과 성능을 향상 시켜줄 수 있겠죠?

 

짤로마무리.. 엔진엑스 엔진ㅋㅅ

 

개인적으로는 이번 기회를 통해 Nginx가 무엇인지 Certbot, WSGI 등 웹 서버가 배포되고 동작하는 과정에 대해 제대로 알고 쓰게되어 정말 좋았습니다! 글이 도움이 되셨으면 좋겠습니다.

반응형