1. WSGI
서버에 요청이 들어오면 nginx나 apache와 같은 웹 서버들은 애플리케이션을 호출해야 합니다.
하지만 보통의 웹 서버들은 애플리케이션을 이해하고 호출하는 기능이 없기 때문에 중간에 중개해 주는 무엇이 필요합니다.
WSGI는 pep 333을 기반으로 만들어진 웹 서버와 파이썬 애플리케이션을 하나의 체인으로 연결해 통신하게 하는 인터페이스입니다.
먼저 클라이언트에서 온 요청이 웹 서버가 받고, 그 요청을 WSGI에 전달합니다. 서버단에서 작업이 필요한 경우에는 WSGI가 애플리케이션에 요청을 전송하고 애플리케이션에서 로직이 처리된 후에 WSGI middleware을 통해 응답됩니다.
2. WSGI middleware
WSGI middleware은 WSGI를 사용한 구현체입니다.
미들웨어가 직접적으로 웹 서버와 애플리케이션을 연결해 주는 역할을 하며 그 종류에는 Gunicorn, uWSGI 등등 여러 가지 있습니다.
nginx에 WSGI module이 바인드 되고 application이 WSGI process 위에 올라가는 구조를 갖고 있습니다.
WSGI module, process를 함께 WSGI middleware라고 부르고 보라색으로 표시된 부분 즉 WSGI process까지 WAS라고 부릅니다.
WSGI middleware은 로드밸런싱등 여러 기능들을 기본으로 탑재되어 있습니다.
3. Django wsgi.py
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings')
application = get_wsgi_application()
Django 애플리케이션은 wsgi 혹은 asgi 위에서 동작합니다. wsgi.py는 애플리케이션과 웹 서버를 연결해 주는 역할을 하며 runserver(로컬 개발 환경)과 프로덕션 서버에서 모두 사용됩니다.
코드를 간단하게 설명해 보면 DJANGO_SETTINGS_MODULE라는 환경변수에 settings.py의 위치를 넣어 기본 설정파일을 지정해 줍니다.
application 에는 get_wsgi_application()이 담깁니다.
import django
from django.core.handlers.wsgi import WSGIHandler
def get_wsgi_application():
django.setup(set_prefix=False)
return WSGIHandler()
get_wsgi_application 내부에서는 장고를 셋업하고 WSGIHandler를 반환합니다.
4. WSGIHandler()
class WSGIHandler(base.BaseHandler):
request_class = WSGIRequest
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.load_middleware()
def __call__(self, environ, start_response):
set_script_prefix(get_script_name(environ))
signals.request_started.send(sender=self.__class__, environ=environ)
request = self.request_class(environ)
response = self.get_response(request)
response._handler_class = self.__class__
status = "%d %s" % (response.status_code, response.reason_phrase)
response_headers = [
*response.items(),
*(("Set-Cookie", c.output(header="")) for c in response.cookies.values()),
]
start_response(status, response_headers)
if getattr(response, "file_to_stream", None) is not None and environ.get(
"wsgi.file_wrapper"
):
response.file_to_stream.close = response.close
response = environ["wsgi.file_wrapper"](
response.file_to_stream, response.block_size
)
return response
4-1. __init__
BaseHandler를 초기화하고 middleware를 로드합니다. 부모클래스인 BaseHandler는 장고 settings 파일에서 넣어준 middleware들을 실행합니다.
4-2. __call__
call 매직메서드는 요청을 처리할 때 사용됩니다.
주요 로직을 살펴보면
request_class()
자신 클래스의 WSGIRequest 객체를 생성해서 요청 객체를 생성합니다.
WSGIHandler에 get_request_class를 호출할 때 WSGIRequest가 초기화됩니다. HTTP Request 패킷 자체를 직접 사용할 수 없기에 WSGIRequest라는 객체에 담고 Django의 View 계층으로 전송하면서 마치 orm처럼 HTTP 요청을 파이썬 객체로 쉽게 사용할 수 있게 도와줍니다. Django Rest Framework에서는 Django에 HTTPRequest를 감싸는 Request 객체를 새로 만들어 사용합니다. 이 객체는 다음 메서드인 get_response 메서드에 request로 인자에 들어갑니다.
get_response()
요청 객체를 전달하고 요청에 대한 응답을 생성합니다. 이때 라우팅, view 로직 등이 실행됩니다.
response
status와 cookie를 설정하고 WSGI에 status code와 cookie를 설정하며 응답을 시작합니다. 파일 스트리밍인 경우에는 wsgi.file_wrapper를 따로 사용하고 아닌 경우에는 WSGI에 응답 객체를 반환하며 클라이언트에게 전송되며 응답이 종료됩니다.
'django' 카테고리의 다른 글
Django - Trailing Slash (1) | 2024.12.02 |
---|---|
Django - DB Connection (0) | 2024.10.27 |
DRF Serializer (2) | 2024.09.18 |
Django ORM - Transaction (0) | 2024.08.06 |
Django - Nginx + Gunicorn으로 배포하기 (1) | 2024.06.21 |