시작에 앞서
해당 내용은 <가장 빠른 풀스택을 위한 Flask & FastAPI>, Dave Lee 지음. BJ Public 출판.
내용을 토대로 작성되었습니다. 보다 자세한 사항은 해당 교재를 참고하시기 바랍니다.
배포(Deployment)
배포란,
개발한 웹 애플리케이션을 실제 사용자가 접근할 수 있는 환경에 올리는 과정.
내 컴퓨터에만 작동하는 애플리케이션을 인터넷에 연결된 서버에 올려서 누구나 웹 브라우저를 통해 사용할 수 있게 만드는 것이다.
웹 서버와 SGI
웹 서버: 실제로 사용자의 요청을 받고 응답을 주는 개체. 네트워크 통신의 전반적인 부분을 담당
예. 엔진엑스(Nginx), 아파치(Apache) 등
서버 게이트웨이 인터페이스(SGI, Server Gateway Interface): 웹 서버와 웹 애플리케이션 사이에 필요한 통신 규약
이 규약을 통해 웹 서버는 사용자의 HTTP 요청을 웹 애플리케이션에 전달하고, 애플리케이션의 응답을 다시 사용자에게 전달한다.
플라스크의 SGI는 플라스크 웹 애플리케이션과 웹 서버 사이의 통신 방식만을 정의한다.
[flask run vs SGI]
- flask run 명령은 개발 환경에서 테스트 목적으로 사용되며 내부적으로 간단한 WSGI 서버를 실행시킨다. 이는 개발 시 빠른 테스트를 위해 플라스크가 지원하는 기능이나, 운영 환경에서 사용하기에는 부족한 부분이 많다.
- 성능 이슈: 플라스크의 내장 서버는 단순하고 가볍기 때문에 많은 트래픽을 처리하기에는 부적합
- 보안 문제: 플라스크의 내장 서버는 보안 기능이 부족하여 직접 인터넷에 노출하는 것은 위험
- 확정성과 유지보수: 복잡한 운영 환경에서는 웹 서버 소프트웨어가 제공하는 다양한 기능이 필요
SGI는 WSGI (Web Server Gateway Interface) 와 ASGI(Asynchronous Server Gateway Interface)로 나뉘는데,
차이점은 주로 동기와 비동기의 지원 여부이다.
- WSGI - 동기적 처리 (플라스크, 장고 등)
- ASGI - 비동기적 처리 지원(FastAPI, Django Channels 등)
WSGI를 지원하는 플라스크
플라스크는 파이썬의 WSGI를 지원하는 웹 프레임워크이다.
WSGI는 웹 서버와 애플리케이션 간의 통신을 가능하게 한다.
Gunicorn은 파이썬 WSGI HTTP 서버로, 플라스크 애플리케이션을 실행하기 위해 많이 선택되는 프로그램이다.
[몇 가지 대안적인 WSGI 서버]
- uWSGI: Gunicorn과 매우 비슷하지만, 좀 더 복잡한 설정을 가지고 있으며 성능이 더 뛰어나다고 알려져있다. Nginx와 통합이 잘 되어 함께 사용할 때 가장 잘 동작한다
- Daphne: 주로 장고에서 사용되지만 플라스크와도 호환된다. 이 서버는 비동기 파이썬 웹 프레임워크를 위해 설계되었으며, 웹소켓과 같은 실시간 기능을 필요로 하는 애플리케이션에 적합하다
- mod_wsgi: 아파치의 모듈로, 플라스크 애플리케이션을 직접 아파치 웹 서버 내에서 실행할 수 있게 해준다. (아파치를 이미 사용하고 있는 경우에 편리함)
Gunicorn으로 플라스크 애플리케이션 배포하기
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello, World!'
위의 코드를 app.py 이름의 파일로 저장하고, Gunicorn으로 플라스크 애플리케이션을 실행하는 방법 수행
◆ Gunicorn 설치 및 실행
pip install gunicorn==21.2.0
gunicorn "app:app"
기본 설정으로 app.py 파일의 플라스크 애플리케이션 실행.
※ 첫번째 app = 파일 이름 (.py 제외), 두번째 app = 플라스크 인스턴스
◆ Gunicorn 옵션 설명
- 워커 프로세스 설정(-w 또는 --workers)
gunicorn -w 4 "app:app"
▶ 워커 프로세스를 4개로 설정하여 애플리케이션 실행
※ 워커 프로세스란? (출처: 챗GPT)
Nginx나 IIS와 같은 웹 서버에서 실질적인 요청 처리를 담당하는 프로세스를 말합니다.
이 프로세스들은 메인 프로세스에서 생성되며, 각각이 독립적으로 요청을 처리하여 병렬적으로 작업을 수행합니다.
웹 서버는 이 방식으로 여러 요청을 동시에 처리할 수 있어서 효율적인 성능을 제공합니다.
워커 프로세스의 개수는 서버의 CPU 코어 수에 맞춰 설정할 수 있으며, 이는 서버의 성능과 부하 분산에 중요한 영향을 미칩니다. 예를 들어, CPU 코어가 4개라면, Nginx에서는 4개의 워커 프로세스를 생성하여 각각의 코어가 한 프로세스를 처리하게 됩니다.
웹 서버의 성능 최적화를 위해 워커 프로세스의 수와 CPU 코어 수를 잘 조정하는 것이 중요합니다.
- 서버 바인딩(-b 또는 --bind)
gunicorn -b 0.0.0.0:8000 "app:app"
▶ 서버를 모든 인터페이스의 8000 포트에 바인딩한다.
※ 서버바인딩과 8000 포트 (출처: 챗GPT)
- 서버 바인딩
서버 바인딩은 서버의 특정 네트워크 인터페이스와 포트를 특정 서비스나 애플리케이션에 연결하는 과정입니다. 이 과정은 서버가 클라이언트 요청을 수신할 수 있게 하기 위해 필요합니다. 예를 들어, 웹 서버는 일반적으로 80번 포트(HTTP)와 443번 포트(HTTPS)에 바인딩됩니다. 바인딩이 제대로 이루어지지 않으면 서버는 클라이언트 요청을 수신할 수 없습니다 .
- 8000 포트
8000 포트는 일반적으로 개발 환경에서 자주 사용되는 포트입니다. 예를 들어, Django 웹 프레임워크에서는 기본적으로 python manage.py runserver 명령어를 실행하면 8000 포트를 사용하여 개발 서버를 실행합니다 . 이는 개발자가 웹 애플리케이션을 테스트하고 디버깅할 때 주로 사용됩니다. 프로덕션 환경에서는 보통 80번이나 443번 포트와 같이 표준 포트를 사용하지만, 개발 단계에서는 충돌을 피하기 위해 8000번과 같은 다른 포트를 사용할 수 있습니다.
- 데몬 모드 실행(--daemon)
gunicorn --daemon "app:app"
▶ 애플리케이션을 백그라운드에서 실행
※ 데몬: 사용자가 직접적으로 제어하지 않고, 백그라운드에서 돌면서 여러 작업을 하는 프로그램을 말한다.
- 로그 파일 설정(--access-logfile 및 --error-logfile)
gunicorn --access-logfile access.log --error-logfile error.log "app:app"
▶ 액세스 및 에러 로그를 각각 access.log와 error.log 파일에 기록
- 타임아웃 설정(--timeout)
gunicorn --timeout 120 "app:app"
▶ 워커가 120초 동안 응답하지 않으면 재시작
※ 워커(worker)
Gunicorn 서버가 동시에 처리할 수 있는 요청의 수를 결정하는 프로세스이다.
플라스크 애플리케이션의 동시성을 다루는 데 사용되며, 각 워커는 독립적으로 요청을 받아 처리할 수 있는 별도의 프로세스이다.
여러 워커를 사용하면 동시에 여러 요청을 처리할 수 있으므로 애플리케이션의 처리 능력이 향상되나, 워커가 많을수록 더 많은 시스템 자원(CPU, 메모리)을 사용하게 되므로 서버의 사양에 맞게 적절한 수를 설정해야 한다.
◆ Gunicorn과 Nginx 연동
플라스크 애플리케이션을 직접 외부에 노출하는 것은 성능과 보안 측면에서 좋지 않기 때문에, Gunicorn을 사용하여 플라스크 애플리케이션을 실행하고, Ngnix나 아파치 같은 웹 서버와 연동하여 안정성과 효율성을 높이는 것이 일반적인 방식이다.
Gunicorn이 여러 워커를 관리하여 애플리케이션 요청을 처리하고, Nginx나 아파치는 정적 파일을 처리하거나 HTTPS 같은 보안 프로토콜을 제공하여 전체적인 성능과 보안을 강화한다.
[Gunicorn 설정 시 중요한 옵션]
- -w 또는 --workers 옵션은 동시에 처리할 수 있는 워커의 수를 정하는 것으로 CPU 코어 수의 두 배를 사용하는 것이 효과적
- --bind 옵션은 Gunicorn이 네트워크 소켓을 어디에 바인딩 할지를 지정
※ Gunicorn이 이미 설치되어 있고 플라스크 애플리케이션이 'myapp.py' 파일에 'app' 이라는 이름으로 정의되어 있다고 가정
- TCP/IP 주소와 포트(예. 127.0.0.1:8000)를 사용하는 일반적인 바인딩
gunicorn --workers=4 --bind=127.0.0.1:8000 mayapp:app
- UNIX 소켓 파일을 사용하여 서버 구성
gunicorn --workers=4 --bind unix:/tmp/myapp.sock myapp:app
▶ Gunicorn은 'tmp/myapp.sock' 라는 소켓 파일에 바인딩하여 통신한다. (리눅스 등 서버 환경에서만 가능)
[Nginx 설정하기]
- Nginx를 설정할 때는 /etc/nginx/sites-available/에 있는 설정 파일을 수정하거나 새로운 파일을 생성
- /etc/nginx/sites-enabled/ 에 심볼릭 링크를 만들어 활성화
※ 심볼릭 링크
심볼릭 링크는 리눅스에서 다른 파일이나 폴더를 가리키는 파일이며, 이는 윈도우 OS에서의 바로가기와 비슷한 개념이다.
◆ Nginx의 설정 파일 예시 및 설명
server {
liston 80; #Nginx가 HTTP요청을 listen할 포트
server_name example.com; # 관리하고자 하는 도메인 이름
location / {
proxy_pass http://127.0.0.1:8000 # Gunicorn 서버로 요청 전달
proxy_set_header Host $host; # 요청 헤더에 Host 설정
proxy_set_header X-Real-IP $remote_addr; # 클라이언트의 실제 IP 주소
proxy_set_header X-Forwarded-For $proxy_add_x_fowarded_for;
# 프록시를 통해 전달된 요청의 IP 주소
proxy_set_header X-Forwarded-Proto $scheme; #요청에 사용된 프로토콜(http 또는 https)
}
# 정적 파일에 대한 처리. Nginx가 직접 제공하는 것이 효율적
location /static/ {
alias /path/to/your/static/files; #정적 파일이 위치한 경로
expired 30d; # 정적 파일 캐시 만료 기간 설정
}
}
- listen: 이 지시어는 Nginx가 클라이언트의 요청을 기다리는 포트 번호를 설정. 80은 기본적으로 HTTP 요청에 사용되는 포트
- server_name: 이 서버 블록에서 처리할 도메인 또는 서브도메인을 지정
- location /: 이 블록은 모든 요청에 대해 실행. proxy_pass를 통해 이 요청들을 Gunicorn으로 전달
- proxy_set_header: 프록시 서버를 통해 요청을 전달할 때, 원본 요청 정보를 유지할 수 있도록 헤더를 설정
- location /static/: 이 지시어는 정적 파일을 처리하는 방법을 구체화. alias를 통해 정적 파일이 위치한 서버 내의 실제 경로를 설정
◆ 테스트 및 재시작
설정이 끝난 후에는 Nginx를 재시작해야 변경 사항이 적용된다.
다음 명령은 서버 환경에 따라 다를 수 있다.
sudo nginx -t # 설정 파일의 문법 오류 검사
sudo systemctl restart nginx # Nginx 서비스 재시작
변경 사항이 적용되면 정상적으로 백엔드 API 가 동작한다.
보안을 위해서는 SSL/TLS 설정을 추가하여 HTTPS를 통한 암호화된 연결을 사용할 것을 권장.
(Let's Encrypt는 무료로 SSL 인증서를 발급해주며, Certbot 같은 도구를 사용하여 자동으로 Nginx 설정을 업데이트 할 수 있다)
★ SSL, TLS, 그리고 HTTPS
출처: DigiCert Logo
[SSL 개념 및 중요성]
보안 소켓 계층(Secure Sockets Layer, SSL) 인증서는 종종 디지털 인증서로 불리며, 브라우저(사용자의 컴퓨터)와 서버(웹사이트) 사이의 암호화된 연결을 수립하는 데 사용된다.
SSL은 웹사이트와 브라우저 사이(또는 두 서버 사이)에 전송되는 데이터를 암호화하여 인터넷 연결을 보호하기 위한 표준 기술이다. 이 기술은 해커가 개인 데이터나 금융 데이터 등의 전송되는 정보를 보거나 훔치는 것을 방지한한다.
[TLS 개념]
TLS: 전송 계층 보안(Transport Layer Security)
TLS은 SSL의 향상된, 더욱 안전한 버전이다.
[HTTPS 개념]
HTTPS: 하이퍼 텍스트 전송 프로토콜 보안(Hyper Text Transfer Protocol Secure)
웹사이트가 SSL/TLS 인증서로 보호되는 경우 HTTPS가 URL에 표시된다. 사용자는 브라우저 표시줄의 자물쇠 기호를 클릭해 발급 기관 및 웹사이트 소유자의 상호를 포함한 인증서의 세부 정보를 볼 수 있다.
'[파이썬 Projects] > <파이썬 웹개발>' 카테고리의 다른 글
[파이썬] 플라스크(Flask) - 성능 개선 팁 (2) | 2024.07.23 |
---|---|
[파이썬] 플라스크(Flask) - 테스팅(testing) (2) | 2024.07.22 |
[파이썬] 플라스크(Flask) - 캐싱(caching) (0) | 2024.07.21 |
[파이썬] 플라스크(Flask) - RESTful API (0) | 2024.07.21 |
[파이썬] 플라스크(Flask) - 인증과 세션(2) (0) | 2024.07.21 |