티스토리 뷰

Python

WSGI

song 2021. 3. 10. 10:39

Web Server 와 Web Application

우선 Web Server 의 개념과 간단한 히스토리를 알아야 한다.

Web Server 는 Client 의 정적인 리소스(File, Image, HTML page, ...) 요청을 처리하는 프로그램이며, 대표적으로 Apache 와 Nginx 가 있다.

그리고 동적인 요청이 들어오면 비즈니스 로직을 수행하기 위해 Web Application(혹은, WAS, AS) 에게 요청을 위임하고, Web Application 은 Web Server 에게 로직을 수행한 결과를 다시 돌려준다.

그럼 Web Server 가 Web Application 과 대화할 수 있는 인터페이스가 필요할 것이다.

특히, 다양한 종류의 Web Server 와 Web Application 을 Interchangable 하게 사용하기 위해서는 잘 정의된 인터페이스가 필수다.

 

CGI

2003년까지 Python Web Framework 는 주로 CGI 와 같은 방식으로 Web Server 와 대화했다.

CGI(Common Gateway Interface) 는 다음과 같이 동작한다.

  • 먼저 Web Server 가 Client 로 부터 HTTP Request 를 받는다.
  • Web Server 는 Request 에 대한 정보(Method, Url, Parameters, ...)를 Environment Variable 과 Standard Input 을 통해 전달하면서 Script 를 실행한다.
  • Script 는 비즈니스 로직을 수행하고 Standard Output 으로 결과를 Web Server 에게 전달한다.
  • Web Server 는 이를 다시 Client 에게 전달한다.

문제는 매번 다시 스크립트를 실행하여 메모리에 적재하는 과정에서 발생하는 추가적인 시간 소요 등이었다.

이 때 2003년에 Python 표준(PEP333)인 WSGI 가 등장하게 된다.

 

WSGI

WSGI(Web Server Gateway Interface)(위스키라고 읽는다) 는 Callable Object 라는 녀석을 통해 Web Server 가 요청에 대한 정보를 Application 에 전달한다.

Callable Object 는 Function 이나 Object 의 형태가 될 수 있으며, Web Server 는 Callable Object 를 통해 2가지 정보를 전해주어야 한다.

  • HTTP Request 에 대한 정보(Method, URL, Data, ...)
  • Callback 함수
def application(environ, start_response):
    body = b'Hello world!\n'
    status = '200 OK'
    headers = [('Content-type', 'text/plain')]
    start_response(status, headers)
    return [body]

Web Application 는 HTTP Request 에 대한 정보를 가지고 Business Logic 을 수행한 뒤에 Callback Function 을 통해 결과를 웹서버에 반환한다.

이러한 WSGI Interface 를 구현하는 Web Server 나 Application 을 WSGI compatible 하다고 하며,

WSGI compatible 한 Application 을 WSGI Application 이라고 부르기도 한다.

또한, 이 WSGI 인터페이스를 구현하기만 한다면 누구나 Python Web Server 나 Python Framework 를 만들어서 기존에 WSGI 를 지원하던 웹서버나 프레임워크와 함께 동작하게 할 수 있다.

 

WSGI Middleware

Web Service 를 개발하다 보면 공통적으로 필요한 기능들이 있는데, Authentication, Routing, Session, Cookie, Error Page 보여주기, ... 와 같은 기능들이다.

WSGI Middleware 는 Middleware 라는 이름처럼 WSGI Application 의 실행 전과 후에 이러한 기능들을 추가해주는 녀석이며, 그 자체로도 WSGI Application 이다.

Design Pattern 의 Decorator Pattern 을 생각하면 이해가 쉽다.

 

uWSGI, Gunicorn, Werkzeug

글 맨 처음에 언급한 uWSGI, Gunicorn, Werkzeug 과 같은 라이브러리들이 바로 위에서 이야기한 WSGI Middleware 의 기능을 가진 라이브러리들이다.

WSGI Middleware 역할 외에도 uWSGI, Gunicorn, Werkzeug 은 자체적으로 Web Server 의 역할(WSGI Server, java의 경우 WAS(Web Application Server 라고 함)을 할 수도 있다. 그래서 WSGI Server 나 Stand alone WSGI Container 라고 불리기도 한다.

Flask 에서 기본적으로 사용하는 WSGI Middleware 가 Werkzeug 인데, 별다른 설정없이 Flask 앱을 실행 해보면

Production 에서는 사용하지 말라는 경고 문구가 나올 정도로 단순한 개발용 서버를 내장하고 있다.

Production Level 에서는 Nginx, Gunicorn, Django 와 같은 식의 구성을 많이 사용하기도 한다.

Nginx 는 주로 Buffering, Reverse Proxying, Load Balancing 등의 기능을 위해 Gunicorn 앞단에 배치하고,

Gunicorn 은 Django 로 작성한 Web Application 에 HTTP 요청을 전달해주는 역할의 WSGI HTTP Server 로서 사용하는 것이다.

Gunicorn 을 사용할 땐 worker process 의 개수와 worker class(async 방식인 Gevent, Tornado, ...)를 설정하여 요청 처리 성능을 높일 수 있다.

 

* 참고로 gunicorn, uwsgi모두 앞단에 nginx를 쓰는케이스가 많이 있습니다. 이는
DDos 공격방지, static file전송 효율성등때문이라고 합니다. 그리고 gunicorn document에서도 말하고 있는 nginx buffering기능때문입니다.

nginx에도 설명이 잘나와있지만 nginx buffering에 대해 좀더 설명하자면,

client - nginx - app servers

이 구조에서 client에 response를 전송하는데 nginx buffer가 없고 클라이언트가 response 패킷을 천천히 받으면 그 영향이 app server한테까지 끼쳐서 그 process는 블락이되어 다른 패킷을 처리 못하게 됩니다. 

하지만 nginx buffer가 있다면 nginx는 app server에게 response패킷을 모두 받을때까지 client에게 응답하지 않고 app server에게 다 받은후 client에게 응답을 보냅니다. 따라서 slow client를 만나더라도 app server는 블락이 되지않을 수 있는것이죠.

 

 

Web Server + WSGI Server

WSGI Server도 자체적으로 서버를 포함하는데 굳이 apache나 nginx같은 정통 web server와 함께 사용할 필요가 있을까? 결론은 그러면 더 좋다는 것이다. 오랜동안 검증된 안정성, static resource 처리의 성능, DOS 공격에 대한 방어 등의 이점이 있지만 많은 traffic이 발생하지 않는 작은 사이트의 경우에는 WSGI Server만으로도 큰 상관이 없다.

 

 

 

'Python' 카테고리의 다른 글

os.path vs pathlib  (0) 2021.08.11
PROPAGATE_EXCEPTIONS  (0) 2021.04.19
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함