팀 프로젝트에서 저는 백엔드 및 AI 개발을 맡았고,
FastAPI 와 python 을 이용해 백엔드 서버 개발을 마쳤습니다.
이제 클라우드 담당 팀원으로부터 전달받은 서버 인스턴스에 개발한 백엔드 코드를 배포하여
프론트엔드 담당 팀원이 API를 이용할 수 있게 해야 합니다.
이 때, 프론트엔드 팀원의 요청으로 SSL 을 지원해야 했고요.
(https 이용 가능하도록.)
백엔드 서버 코드를 배포하기 위해 웹 서버가 필요한데,
다양한 웹 서버 중 NginX 를 사용하겠습니다.
Nginx는 특히 파이썬 웹 프레임워크인 Django나 Flask 와 함께 사용되므로
마찬가지로 파이썬 웹 프레임워크인 FastAPI 와 함께 사용하기에 적합하다고 생각했기 때문입니다.
NginX 공식 홈페이지에서는 NginX 를 이렇게 한 줄로 설명하고 있네요.
NGINX: Advanced Load Balancer, Web Server, & Reverse Proxy
Reverse Proxy
: 클라이언트와 웹 서버 사이에서 중개 역할을 하는 서버 또는 소프트웨어의 한 형태.
클라이언트 요청을 받아 해당 요청을 다른 서버로 중계하고, 해당 서버로부터 받은 응답을 클라이언트에게 반환합니다.
그렇기 때문에 Load Balancer
의 역할을 할 수 있는 것이지요.
로드 밸런싱이란 여러 웹 서버 또는 애플리케이션 서버 사이에서 요청을 분산하여 서버 부하를 분산하고 성능을 향상시키는 기술을 말합니다.
NginX 가 SSL 지원이 가능한 것도 Reverse Proxy 를 지원하기 때문인데,
Reverse Proxy 를 사용하면 클라이언트와의 SSL/TLS 연결을 처리하고 원격 서버와는 암호화되지 않은 연결을 사용하여 SSL/TLS 부하를 감소시킬 수 있기 때문입니다.
또한 빠른 비동기 처리를 제공하는 점,
높은 성능 (동시 연결 처리, 메모리 사용량, CPU 이용률 등에서 효율적으로 동작함),
가벼움 (작은 메모리와 CPU 리소스를 사용) 등이 NginX 를 사용하는 이유로 꼽힙니다.
쉬운 설명 : https://blog.naver.com/gi_balja/223028077537
NginX 설치 시 생성되는 디렉토리 구조 및 주요 파일은 다음 포스팅을 참고해 주세요.
https://whatisthenext.tistory.com/123
sudo apt install nginx
FastAPI 와 NginX 연동을 위한 NginX 설정파일을 작성합니다.
/etc/nginx/sites-available/[설정파일명].conf
server {
listen 80;
server_name [ip 또는 domain];
location / {
include proxy_params;
proxy_pass http://127.0.0.1:8000;
}
}
listen 80
: 웹 서버를 80 포트로 서비스 ( HTTP 프로토콜 기본 포트 = 80)server_name
: 고정 IP (인스턴스 IP)location / { ... }
: / URL로 시작하는 모든 요청을 uvicorn 내지 Gunicorn 소켓이 처리하게 함앞서 /etc/nginx/sites-available/
경로에 설정 파일을 작성하였는데요,
이 폴더에 여러 설정파일들을 생성해 두고, 이 중 활성화하고 싶은 설정만을 선택하여 이용합니다.
이를 위해 심볼릭 링크 (symlink) 기능을 이용하여
설정 파일을 /etc/nginx/sites-enabled
폴더에 동기화합니다.
심볼릭 링크는 파일이나 디렉터리에 대한 참조를 나타내는 특별한 유형의 파일로,
링크된 파일이나 디렉터리에 대한 경로를 가리키기 때문에 다른 파일이나 디렉터리로의 간편한 접근을 제공합니다.
심볼릭 링크를 생성하려면 ln -s
명령어를 사용할 수 있으며,
ln -s /원본/파일/경로 /링크/될/경로
이렇게 하면 /링크/될/경로
위치에 심볼릭 링크가 생성되며,
이 링크를 통해 원본 파일 또는 디렉터리에 쉽게 액세스할 수 있습니다.
NginX symlink
sudo ln -s /etc/nginx/sites-available/fastapi.conf /etc/nginx/sites-enabled/fastapi.conf
설정 파일이 오류 없이 작성되었는지 테스트합니다.
sudo nginx -t
# 시작
sudo systemctl start nginx
# 재시작
sudo systemctl restart nginx
uvicorn main:app --reload
이 경우 uvicorn 서버를 실행중인 터미널이 종료되면 서버와의 연결이 끊어지므로
임시 방편으로 nohup 명령어를 이용하여 uvicorn 을 지속적으로 실행시킬 수 있습니다.
nohup uvicorn main:app --reload &
SSL 을 적용하여 https 연결을 지원합니다.
SSL 을 이용하기 위해서는 인증서를 발급(생성) 해야 하는데, 이 과정에서 도메인이 필요합니다.
도메인이 없는 경우 ip만으로 인증서를 발급할 수 있지만 그 방법이 조금 더 복잡합니다.
(도메인은 클라우드 담당 팀원이 생성하여 전달하였고, 인증서는 인스턴스를 사용하는 백엔드 담당 팀원(=나) 가 발급하였습니다.)
HTTPS 설정 방법은 HTTP 와 거의 동일하며, NginX 설정 파일에 SSL 인증서 경로를 포함한 SSL 서버 정보를 추가합니다.
무료로 SSL 인증서를 발급해 주는 Let's Encrypt 서비스를 사용하겠습니다.
1-1. certbot 설치
sudo apt install certbot
sudo apt install python3-certbot-nginx
1-2. Let's Encrypt의 인증서 발급
sudo certbot certonly --nginx
(인증서 발급 과정 중 입력할 부분은 다음 링크 참조:
https://wikidocs.net/177320)
발급이 완료되면 다음 위치에 각각 2종류의 인증서가 생성됩니다.
/etc/letsencrypt/live/[Domain Name]/fullchain.pem # 인증서 파일
/etc/letsencrypt/live/[Domain Name]/privkey.pem # 개인키 파일
/etc/nginx/sites-available/[설정파일명].conf
에 SSL 정보를 추가합니다.
(HTTPS 로 변경 시 사용자가 HTTP 로 접속했을 때 HTTPS 로 리다이렉트되도록 설정하는 경우가 많은데요,
저는 HTTPS 가 정상적으로 동작하지 않을 경우를 대비하여
HTTP, HTTPS 모두 가능하도록 설정 파일을 수정하였습니다.)
server {
listen 80;
server_name cs93.site;
location / {
include proxy_params;
proxy_pass http://127.0.0.1:8000;
}
}
server {
listen 443 ssl; # SSL 포트번호
server_name cs93.site;
ssl_certificate /etc/letsencrypt/live/cs93.site/fullchain.pem; #인증서 파일 경로
ssl_certificate_key /etc/letsencrypt/live/cs93.site/privkey.pem; #개인키 파일 지정
include /etc/letsencrypt/options-ssl-nginx.conf; # SSL 설정파일
location / {
include proxy_params;
proxy_pass http://127.0.0.1:8000;
}
}
수정한 설정값을 NginX 서버에 반영합니다.
uvicorn 대신 Gunicorn 을 사용해 봅시다.
운영 환경에서 FastAPI 서버를 구동하기 위해서는 터미널에서 다음과 같은 명령을 실행합니다.
uvicorn main:app --reload (생략가능 : --host=0.0.0.0)
이 경우 터미널을 종료하면 FastAPI 서버도 종료됩니다.
따라서 이를 방지하려면 uvicorn 프로세스를 백그라운드로 실행해야 하며, Gunicorn을 사용하면 uvicorn 프로세스를 백그라운드로 실행할 수 있습니다.
Gunicorn 은 로드 밸런싱 기능 이외에도 여러 편의 기능들을 제공하는데,
예를 들어 Gunicorn 서비스를 등록하면 로깅, 서비스 시작, 중지 같은 작업을 쉽게 할 수 있습니다.
https://wikidocs.net/177269
Gunicorn에서 FastAPI 앱을 실행합니다.
gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app
명령어를 입력할 때, uvicorn의 worker를 사용하도록 추가로 설정을 해주어야 ASGI 프로토콜에 맞게 동작합니다.
-w
: 서버의 worker 갯수 (n개의 worker 를 로드밸런싱하며 실행)
https://dev-in-seoul.tistory.com/47
https://sengwoolee.dev/133
https://webisfree.com/2020-11-12/nginx-%EC%84%9C%EB%B2%84-%EC%9E%AC%EC%8B%9C%EC%9E%91-%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95-restart-reload
https://wikidocs.net/177320
https://wikidocs.net/176224