오래전부터 파이썬 웹 애플리케이션은 웹 서버와 통신할 때 웹 서버 게이트웨이 인터페이스(WSGI) 표준을 따랐다. WSGI는 2003년에 처음 도입돼 2010년에 업데이트됐으며 파이썬 버전 2.2에서는 네이티브 기능을 이용해 쉽게 구현할 수 있게 됐다. 결과적으로 WSGI는 모든 주요 파이썬 웹 프레임워크에 빠르게 도입돼 파이썬을 사용한 웹 개발의 초석이 됐다.

ⓒ Getty Images Bank
시계를 다시 현재로 돌려보자. 파이썬 2는 폐기됐고(한참 늦었지만), 파이썬에는 이제 네트워크 호출과 같은 비동기 작업을 처리하기 위한 기본 구문이 있다. WSGI 및 기타 기본적으로 동기 동작을 전제하는 표준은 비동기의 성능이나 효율성이 떨어진다. 이는 곧 WSGI가 웹소켓과 같은 고급 프로토콜을 효과적으로 처리하지 못한다는 것을 의미한다.
그래서 나온 것인 ASGI, 즉 비동기 서버 게이트웨이 인터페이스다. ASGI는 WSGI와 마찬가지로 파이썬 웹 애플리케이션과 웹 서버 간의 공통적인 인터페이스를 기술한다. WSGI와 다른 점은 애플리케이션당 여러 개의 비동기 이벤트를 허용한다는 것이다. 또한 ASGI는 동기 앱과 비동기 앱을 모두 지원한다. ASGI를 사용해 새로운 비동기 웹 앱을 구축하는 것뿐만 아니라 오래된 동기 WSGI 웹 앱을 ASGI로 마이그레이션할 수도 있다.
WSGI는 보통 application 또는 app이라는 이름의 파이썬 함수를 웹 서버에 드러낸다. 이 함수는 다음의 두 매개변수를 받는다.
함수가 반환하는 데이터가 응답 본문을 구성한다. 간단한 application 함수는 다음과 같은 형태다.
def application(environ, start_response): start_response('200 OK', [('Content-Type', 'text/plain')]) return [b'Greetings universe']
플라스크(Flask)와 같은 WSGI 호환 웹 프레임워크를 사용하는 경우 프레임워크 자체가 application 함수를 제공하며 이 함수의 모든 구성요소가 자동으로 연결된다.
WSGI의 단점은 2가지다. 첫째, WSGI는 한 번에 하나의 요청과 응답만 처리하며 응답이 즉시 반환된다고 전제한다. 웹소켓 또는 롱 폴링 HTTP 연결과 같이 장시간 지속되는 연결을 처리할 방법이 없다. 둘째, WSGI는 동기 전용이다. 멀티스레드 연결 풀을 사용하더라도 응답이 반환될 때까지 각 연결이 차단된다. 많은 WSGI 설정에 스레드와 프로세스 풀을 처리할 수 있는 기능이 있지만 WSGI 인터페이스 자체가 동기적이라는 점에 의해 제한된다.
ASGI는 표면적으로는 WSGI와 비슷하다. WSGI와 마찬가지로 application 함수 객체를 정의한다. 다른 점은 async 함수이며 매개변수가 2개가 아닌 3개라는 것이다.
간단한 application 함수는 다음과 같은 형태다.
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!', })