CS

CGI, WGSI, ASGI 알아보기

haong_ 2024. 9. 4. 21:26

웹 애플리케이션을 배포할때 파이썬에서는 주로 두가지 표준 인터페이스인 WSGI와 ASGI 를 사용한다. 두 인터페이스는 각각 동기적, 비동기적 웹 애플리케이션을 지원하며 이를 기반으로 여러 웹서버와 프레임워크가 작동한다. 회사에서 FastAPI를 사용하는데, uvicorn 실행 명령어만 쳤지 자세한 내용을 모르는 것 같아서 정리해보려고 한다.

웹 서버와 웹 애플리케이션 서버

  • 웹 서버 (Web Server)
    • 클라이언트로부터 HTTP 요청을 받아 정적 콘텐츠(HTML, 이미지, CSS 등)를 제공하는 서버
    • 대표적인 웹 서버 - Apache, Nginx
  • 웹 애플리케이션 서버 (Web Application Server)
    • 클라이언트 요청을 처리하기 위해 동적 콘텐츠를 생성하는 서버
    • 데이터베이스와 상호작용하거나, 비즈니스 로직을 수행하여 요청에 맞는 데이터를 생성해 웹 서버나 클라이언트에 반환
    • REST API, GraphQL 등 API 제공

이러한 웹 서버와 웹 애플리케이션 서버간의 데이터를 주고받는 방식을 표준화한 인터페이스가 CGI, WSGI 같은 기술이다. 웹 서버와 웹 애플리케이션 서버가 통신할 때의 중재자 역할을 하여 서로 효율적으로 데이터 교환할 수 있도록 돕는 역할이다.

CGI(Common Gateway Interface)

  • 웹 서버와 애플리케이션 간에 통신 방식을 정의한 초기 표준 인터페이스

동작 방식

  • 클라이언트가 웹 서버에 HTTP 요청을 보내면 웹 서버는 새로운 프로세스를 생성하여 CGI 스크립트를 실행하여 요청을 처리하고 HTML 응답을 웹 서버로 반환하는 방식
  • 웹 서버는 클라이언트 요청을 처리하기 위해 환경변수나 표준입력(STDIN)을 통해 요청 정보를 CGI 스크립트로 전달함

단점: 각 요청마다 새로운 프로세스를 생성하기 때문에 성능이 매우 낮은 문제가 있음

WSGI(Web Server Gateway Interface)

  • CGI의 성능 문제를 해결하기 위해 나온 파이썬 웹 애플리케이션 동기적 표준 인터페이스
  • Django, Flask 같은 동기적 웹 프레임워크가 WSGI를 따름

동작 방식

  • 웹 서버는 Callable Object로 정의된 WSGI 애플리케이션을 호출하여 데이터를 처리
def simple_wsgi_app(environ, start_response):
    status = '200 OK'
    headers = [('Content-Type', 'text/plain')]
    start_response(status, headers)
    return [b"Hello, WSGI!"]
  • 데이터를 환경변수나 표준입력을 통해 전달하지 않고 파이썬 객체(environ 딕셔너리)로 처리
  • 콜백 함수인 start_response를 호출해 응답 상태 코드와 헤더를 설정한 후 응답 본문을 웹 서버로 반환
  • 하나의 프로세스에서 파이썬의 callable 객체를 사용하여 요청을 처리하므로 시간이 단축되고 프로세스 생성 비용이 절감되는 효과가 있다

단점: WSGI는 요청을 받아 순차적으로 처리하며 한 요청이 끝나기 전에 다른 요청을 처리 할 수 없음

Gunicorn?

  • Gunicorn은 WSGI 서버로 동기적 애플리케이션을 구동할 때 사용
  • but, 비동기 작업을 지원하기 위해 uvicorn 과 함께 사용가능
  • 멀티프로세서 구조로 애플리케이션을 여러 워커에서 동시에 실행 할 수 있게 해주어 성능과 확장성 제공

ASGI(Asynchronous Server Gateway Interface)

  • ASGI는 WSGI의 비동기처리 불가능을 해결하기 위해 등장한 비동기 인터페이스
  • WSGI에서는 하나의 동기적인 callable 객체가 요청을 받아 응답을 리턴하는는 방식이어서 길게 유지되어야 하는 연결이나 웹 소켓에는 적합하지 않은 반면, ASGI에서는 웹소켓 같은 실시간 통신을 지원하기 때문에 실시간 채팅, 스트리밍 서비스에 적합

동작 방식

ASGI에서는 비동기 함수(async)를 통해 이벤트 루프에서 비동기 작업을 관리

이벤트 루프

  • 비동기 작업을 이벤트 큐(queue)에 쌓아두고 작업이 준비되면 이를 하나씩 처리하는 방식
  • 비동기 함수는 async로 선언되고 await 키워드를 통해 I/O 작업을 처리하는 동안 각 작업이 완료될 때까지 기다리지 않고 다른 작업을 병렬로 처리 할 수 있음

async & await

  • 비동기 작업을 선언하고 제어하는데 사용
  • async로 선언된 함수는 비동기 함수가 되어 이벤트 루프에서 실행 될 수 있음
  • await는 해당 작업이 완료될때 까지 기다리는 동안, 이벤트 루프가 다른 작업을 처리할 수 있게 함
  • 즉, await가 없는 작업은 이벤트 루프에서 비동기적 처리 대상이 되지 않고, 순차적으로 처리. 반대로 await가 사용된 작업은 이벤트 루프가 I/O 대기 상태로 인식해 그동안 다른 작업 처리할 수 있게 해줌

WebSocket

  • 웹소켓은 클라이언트와 서버 간에 양방향 통신이 가능한 실시간 프로토콜
  • 기존 HTTP 처럼 요청-응답 패턴에 국한되지 않고 클라이언트와 서버가 연결이 살아있는 동안 데이터를 주고 받을 수 있는 지속적인 통신을 허용함

WebSocket 통신과 비동기 처리

  • 서버는 클라이언트의 메세지를 기다리면서도 다른 작업을 동시에 처리 할 수 있어야 하는데 이를 위해 비동기 처리가 필수적
  • await 키워드로 서버가 메세지를 기다리는 동안 서버가 블로킹되지 않고 다른 작업도 동시에 처리 할 수 있음
  • 실시간 통신에서는 대기 시간이 중요한데 이러한 비동기 처리를 통해 I/O 대기시간을 최적화하고 동시성을 지원하므로 여러 클라이언트와 실시간으로 데이터를 주고받을 수 있게 됨
  • 결론적으로 비동기 처리 덕분에 웹소켓 같은 실시간 통신이 가능해진것

FastAPI와 Uvicorn

  • FastAPI는 이런 비동기 처리를 지원하는 프레임워크로 ASGI 표준을 따름
  • 이러한 FastAPI 애플리케이션을 실행하기 위해서 필요한 서버가 바로 Uvicorn

Uvicorn?

  • ASGI 서버로 FastAPI 같은 비동기 애플리케이션을 구동할 때 사용
  • Uvicorn으로 비동기 요청을 처리하고 이벤트 루프를 사용해 동시에 여러 요청을 관리하는 역할