[FastAPI] Uvicorn (CGI, WSGI, ASGI)

이홍준·2023년 8월 17일
0

FastAPI

목록 보기
1/4
post-thumbnail

우연히 FastAPI를 통해 웹 서버를 구축하는 프로젝트를 수행하게 되었다. 공부하던 중에 이해가 안되는 부분이 있었다. Spring 밖에 서버를 구축하는 데에 동적 페이지 부분에 있어서 꼭 필요한 Tomcat과 같은 WAS가 있어야 하는데 공식 문서 대로 보니 FastAPI는 그런 부분은 없고 Uvicorn이라는 것이 있었다. 이게 WAS인가 싶어서 찾아보니 아니었고 내가 알고 있던 것과 괴리감을 느낀 나머지 궁금증을 해결하고자 한번 정리해 보았다.

WAS vs Gateway Interface

  • WAS는 웹 애플리케이션의 실행 환경 및 관련 기능들을 제공하는 반면에, Gateway Interface는 웹 서버와 웹 애플리케이션 사이의 프로토콜을 정의한다.
  • WAS는 웹 애플리케이션을 직접 실행하는 반면에, Gateway Interface는 애플리케이션과 웹 서버간의 메시지 전달 역할 만을 한다.

Gateway Interface를 쓰게 된 배경

  • 파이썬 웹 개발은 단순함과 유연성을 중요시 하기 때문에 웹 애플리케이션과 웹 서버를 독립적이고 간단하게 하고자 함
  • 사실상 Nginx, Apache와 같은 리벅스 프록시와 같이 사용하면서 사실상 WAS의 역할 들을 수행해줌

Common Gateway Interface(CGI)

웹 서버와 외부 애플리케이션 사이의 인터페이스 규격이다. 초기 웹 개발 때 많이 사용되던 방식이다.

Python CGI, Perl CGI등의 라이브러리에 사용된다.

  1. 장점: 언어에 독립적이다. 즉 다양한 언어로 작성할 수 있다.
  2. 단점: 요청마다 새로운 프로세스를 생성하기 때문에 프로젝트의 규모가 큰 경우에는 적합하지 않다.
  3. 동작 과정
    • 웹서버가 웹브라우저 같은 클라이언트로부터 요청을 받음
    • 그 요청이 특정 프로그램이 실행될 필요가 있다고 웹 서버에 설정 되어 있으면, 프로그램을 실행시킨다.
    • CGI 규약에 따라서 데이터를 프로그램에 넘김
    • 프로그램 실행이 끝나고 결과가 나오면 프로그램은 CGI대로 결과를 웹 서버에 넘겨줌
#!/usr/bin/python3
import cgi
form = cgi.FieldStorage()

a = form.getvalue('a')
b = form.getvalue('b')

result = int(a) * int(b)

print('Content-type: text/plain')
print()
print(f'Result:{result}')

Web Server Gateway Interface(WSGI)

python 웹 어플리케이션과 웹 서버 사이의 표준 인터페이스를 정의한다. 웹 서버가 클라이언트로 부터 받은 요청을 파이썬 애플리케이션 전달하여 실행하고 그 실행 결과를 돌려받기 위한 약속이다.

Flask, Django에서 채택하고 있는 기술이다.

  1. 특징

    • 간단한 인터페이스: WSGI 애플리케이션은 두개의 인자(environ, start_response)를 받는 호출 가능한 객체
    • Middleware: 요청과 응답을 조작하거나 추가적인 기능을 제공하기 위해 사용된다.
    • Server와 Application의 분리: 웹 서버와 웹 애플리케이션은 WSGI 명세에 따라 완전히 분리될 수 있다. 그래서 서버와 애플리케이션의 독립성을 보장한다.
    # environ은 웹 서버가 제공한 환경변수와 현재 요청에 대한 정보가 포함된 딕셔너리
    # start_response: 클라이언트로 HTTP 응답을 보내는 작업을 시작하는 데 사용되는 함수
    def simple_wsgi_app(environ, start_response):
        status = '200 OK'
        headers = [('Content-type', 'text/plain')]
        start_response(status, headers)
        return [b"Hello WSGI World!"]
  2. 기존 CGI와의 차이점

    • 프로세스: CGI는 각 요청마다 새로운 프로세스를 실행하는 것과 다르게 WSGI는 프로세스를 한 번만 시작하고, 여러 요청들을 동일한 프로세스 내에 처리함으로써 성능을 개선시킨다.
    • 언어 독립성: CGI는 언어에 구애받지 않는 대신에 WSGI는 Python 전용이다.
    • 미들웨어: 중간에서 request, response를 수정하거나 추가적인 처리를 수행하는 레이어를 쉽게 추가할 수 있다.
    • 배포: WSGI는 해당하는 호환 웹 서버나 애플리케이션 서버가 필요하다 .설정과 관리가 좀 더 복잡하다.

Asynchronous Server Gateway Interface (ASGI)

WSGI와 비슷한 구조를 가지면서 기본적으로 요청을 비동기로 처리하는 방식이다. WSGI의 상위 버전이라고 할 수 있다. 요즘 출시된 FastAPI, Starlette에서 Uvicorn에서 사용되는 기술이다. (요즘 Django의 3.0 이상부터 지원한다고 한다)

  1. vs WSGI
    • 비동기 처리로 인해 트래픽 처리를 유연하게 할 수 있다.
    • 표준화 된 웹 소켓을 지원 해줌
  2. 구성
    1. scope: 현재 요청에 대한 정보가 포함된 딕셔너리로, WSGI의 environ과 비슷하지만 세부적인 명명 규칙이 조금 다름.
    2. send: 애플리케이션이 클라이언트로 메시지를 돌려보낼 수 있게 해주는 async callable(함수)
    3. receive: 애플리케이션이 클라이언트로 부터 메시지를 수신할 수 있게 해주는 async callable이다.
async def application(scope, receive, send):
    await send({
        'type': 'http.response.start',
        'status': 200,
        'headers': [
            [b'content-type', b'text/plain'],
        ],
    })

    await send({
        'type': 'http.response.body',
        'body': b'Hello, world!',
    })

Uvicorn

uvicorn은 파이썬 용 ASGI 기반 웹서버 구현체이다. 기존 방식들과는 다르게 low-level의 비동기 프레임워크들을 지원 해준다. ( HTTP/1.1 & 웹소켓)

$ pip install uvicorn # 기본 설치
$ pip install 'uvicorn[standard]' # 최소한의 의존성 설치
$ uvicorn main:app # 실행
import uvicorn

async def app(scope, receive, send):
    ...

if __name__ == "__main__":
    uvicorn.run("main:app", port=5000, log_level="info")

References

profile
I'm a web developer.

2개의 댓글

comment-user-thumbnail
2023년 8월 17일

정리가 잘 된 글이네요. 도움이 됐습니다.

1개의 답글

관련 채용 정보