개발 이모저모

파이썬 비동기 웹 애플리케이션 기본 개념부터 FastAPI까지

발짜개 2024. 11. 9. 07:39

이번 글은 사실 FastAPI를 언제 어떻게 쓰면 좋을까, 최고의 usecase에는 어떤 게 있을까 하는 고민으로부터 시작하게 되었습니다. 그런데 공부를 하다 보니 기본 개념을 한번 더 짚고 넘어가면 좋을 것 같다는 생각에 비동기 웹 애플리케이션 개념부터 WSGI, ASGI가 뭔지 FastAPI가 어떻게 등장하게 되었는지 등을 다뤄보려고 합니다.

동기/비동기 웹 애플리케이션

1. 동기 웹 애플리케이션

동기 웹 애플리케이션에서는 클라이언트가 요청을 보내면 서버가 해당 요청을 처리할 때까지 클라이언트는 대기해야 합니다. 서버가 응답을 보내기 전까지, 다른 작업은 실행되지 않습니다. 동기 애플리케이션은 구현이 간단하지만, 서버가 오래 걸리는 작업을 처리할 때 클라이언트가 응답을 기다려야 한다는 단점이 있습니다.

2. 비동기 웹 애플리케이션

비동기 웹 애플리케이션은 클라이언트가 요청을 보내면 서버는 해당 요청을 처리하는 동안 클라이언트가 다른 작업을 계속할 수 있도록 합니다. 서버는 작업이 완료되면 클라이언트에게 응답을 보내, 필요한 부분만 업데이트합니다. 예를 들면 AJAX를 이용해 특정 데이터만 가져오거나, 채팅 애플리케이션에서 실시간 메시지를 주고받는 방식입니다. 비동기 애플리케이션은 서버의 응답을 기다리지 않고 동시에 여러 요청을 처리할 수 있어, 더 나은 사용자 경험을 제공합니다. 그러나 동기 방식에 비해 구현이 복잡하며, 데이터 동기화를 위한 처리가 필요합니다.

 

WSGI란?

일반적으로 웹 애플리케이션에서 메시지의 흐름은 다음과 같습니다.

이때 WSGI(Web Server Gateway Interface)는 Web Server와 Python Web Application가 서로 통신할 수 있는 통로 역할을 합니다. 즉, Python 웹 애플리케이션을 다양한 웹 서버와 호환될 수 있도록 하기 위해 만들어진 표준 인터페이스입니다. 쉽게 설명하자면 클라이언트가 보내는 Request Message가 Python이 이해할 수 있는 형태로 바꾸어주는 역할을 한다고 할 수 있습니다.

WSGI 서버로는 Gunicorn, uWSGI, Waitress 등이 존재하며, WSGI 웹 프레임워크로는 Flast, Django, Pyramid 등이 있습니다. Flask의 경우 자체적으로 WSGI가 구현되어 있어서 `python run.py` 형태로 애플리케이션을 실행할 수 있습니다.

1. 주요 역할과 특징

  • 애플리케이션과 서버 간의 통신 표준 제공: WSGI는 애플리케이션과 서버가 데이터를 주고받는 방법을 정의하여 두 시스템 간의 호환성을 높입니다. 애플리케이션 개발자는 WSGI 표준을 따르기만 하면 특정 웹 서버에 종속되지 않고 다양한 서버에서 애플리케이션을 운영할 수 있습니다.
  • 애플리케이션의 유연성 향상: WSGI는 웹 서버와 애플리케이션의 결합을 느슨하게 만들어, 웹 애플리케이션을 쉽게 다른 환경이나 서버로 옮길 수 있도록 돕습니다. 예를 들어, Django나 Flask와 같은 WSGI 호환 웹 프레임워크로 작성된 애플리케이션은 WSGI를 지원하는 서버에서 문제없이 동작할 수 있습니다.

2. 장점과 한계

WSGI를 사용하면 웹 애플리케이션이 특정 웹 서버에 의존하지 않기 때문에, 다양한 WSGI 호환 서버에서 작동할 수 있어 서버 독립성을 가질 수 있습니다. 또한 WSGI 표준 덕분에 Python 웹 애플리케이션과 웹 서버의 호환성이 높아집니다.

 

그러나 WSGI는 동기식 요청 처리를 기반으로 설계되어, 고성능 비동기 애플리케이션에는 적합하지 않습니다. 따라서 WebSocket과 같은 실시간 양방향 통신을 지원하지 않습니다. 이러한 비동기 한계를 극복하기 위해 ASGI(Asynchronous Server Gateway Interface)라는 비동기 표준이 만들어졌으며, 이는 FastAPI와 같은 비동기 프레임워크에서 사용됩니다.

 

ASGI란?

ASGI(Asynchronous Server Gateway Interface)는 Python에서 비동기 웹 애플리케이션과 웹 서버가 상호작용할 수 있도록 설계된 표준 인터페이스입니다. WSGI가 동기 방식의 웹 애플리케이션을 위한 표준이었다면, ASGI는 비동기 및 동기 애플리케이션 모두를 지원할 수 있도록 만들어졌습니다. 특히, 동시에 많은 요청을 효율적으로 처리해야 하는 현대적인 웹 애플리케이션을 위해 등장했습니다.

ASGI 서버로는 Uvicorn, Daphne 등이 있으며, ASGI 웹 프레임워크로는 Starlette, FastAPI, aiohttp, Django Channels, Quart, Sanic, Starlite 등이 있습니다.

FastAPI는 실행 환경을 제공하지 않으므로, 이를 실행하려면 ASGI 서버가 필요합니다. Uvicorn은 ASGI 표준을 구현한 서버 중 하나로, FastAPI 애플리케이션을 실행하기 위해 흔히 사용됩니다. 예를 들어 `uvicorn app:app` 명령어로 FastAPI 애플리케이션을 실행할 수 있습니다. Uvicorn은 Python의 asyncio와 uvloop을 사용해 이벤트 루프 기반 비동기 처리를 제공합니다. 이 방식은 비동기 작업을 효율적으로 처리할 수 있게 하여 요청을 동시에 여러 개 처리하는 데 뛰어납니다. 네트워크 대기 시간과 I/O 작업이 많은 경우 성능이 크게 향상됩니다. 또한 HTTP/2 네트워크 프로토콜을 지원합니다. HTTP/2는 멀티플렉싱과 헤더 압축을 통해 대역폭 효율성을 높여 Uvicorn을 빠르고 유연하게 사용할 수 있습니다.

Daphne는 Django Channels를 위해 설계된 ASGI 서버로, Django 애플리케이션에서 WebSocket을 지원합니다.

1. 주요 역할과 특징

  • 비동기 및 동기 요청 모두 지원: ASGI는 WSGI의 한계를 극복하고, 비동기 요청을 처리할 수 있도록 설계되었습니다. 이를 통해 Python 애플리케이션이 실시간 데이터 전송 및 높은 동시성 처리가 필요한 환경에서 효율적으로 작동할 수 있습니다.
  • WebSocket과 같은 양방향 통신 지원: WSGI는 HTTP 통신만 지원하지만, ASGI는 WebSocket을 포함한 다양한 프로토콜을 지원합니다. 이를 통해 실시간 통신이 필요한 채팅, 알림, 실시간 대시보드와 같은 애플리케이션 개발이 가능해졌습니다.
  • 범용성: ASGI는 비동기 및 동기 웹 애플리케이션 모두에서 작동할 수 있도록 설계되었기 때문에, 기존 WSGI 애플리케이션도 어느 정도 호환할 수 있습니다.

2. 장점과 한계

ASGI는 비동기 처리가 가능하여 고성능의 동시성 처리 요구에 적합합니다. 또한 WebSocket을 통한 실시간 양방향 통신을 지원하므로, 실시간 애플리케이션에 유리합니다. 다양한 프로토콜을 처리할 수 있도록 설계되어 향후 확장이 용이합니다.

 

하지만 비동기 코드는 `async`, `await`등의 사용 등으로 동기 코드보다 이해하기 어렵고, 디버깅과 에러 처리가 더 복잡할 수 있습니다. 그리고 ASGI는 기존 WSGI와 완전히 호환되지 않으므로, 기존의 WSGI 애플리케이션을 ASGI로 마이그레이션 하는 과정을 거쳐야 합니다. 또한 비동기 애플리케이션에서는 데이터베이스 접근도 비동기적으로 처리할 수 있습니다. 예를 들어, SQLAlchemy의 비동기 버전인 Databases 라이브러리 또는 Tortoise ORM과 같은 비동기 지원 ORM을 사용할 수 있습니다.

 

FastAPI란?

FastAPI는 Python 기반의 비동기 웹 프레임워크로, 높은 성능과 간편한 사용성 덕분에 최근 인기를 끌고 있습니다. ASGI 표준을 따르며, 비동기 처리와 높은 성능이 요구되는 RESTful API나 실시간 통신을 위한 웹 애플리케이션 개발에 적합합니다.

1. Starlette 기반

Starlette 역시 Python기반 경량 ASGI 프레임워크로, 비동기 요청 처리를 지원하여 높은 동시성을 필요로 하는 웹 애플리케이션이나 API에 최적화되어 있어 Node.js나 Go와 같은 비동기 기반의 다른 언어 프레임워크와 비교할 수 있는 성능을 제공합니다.

또한 간결하고 유연한 코드 구조로 필요한 기능만을 추가해 코드를 간결하게 유지할 수 있으며, 다양한 기능을 쉽게 확장할 수 있습니다. 그 외에도 URL 경로 설정 및 미들웨어 구성을 간단하게 할 수 있도록 설계되어 있어, 요청과 응답을 효과적으로 관리할 수 있습니다. ASGI 애플리케이션 테스트도 HTTPX와 통합된 테스트 클라이언트로 쉽게 수행할 수 있습니다.

FastAPI는 Starlette의 기능을 확장하여 사용자가 더욱 편리하게 REST API와 웹 애플리케이션을 만들 수 있도록 설계된 프레임워크입니다. Starlette은 라우팅, 미들웨어, 세션 관리와 같은 웹 애플리케이션의 기본 기능을 제공하고, FastAPI는 이에 더해 데이터 검증, 자동 문서화, 타입 힌트를 사용하는 추가 기능을 더했습니다.

2. Pydantic과 SQLModel

Pydantic은 Python 데이터 모델링 및 데이터 검증 라이브러리로, 데이터 유효성 검사직렬화를 간편하게 수행할 수 있게 해 줍니다. Python의 타입 힌트를 사용하여 데이터 구조를 명확히 정의하고, 입력된 데이터가 사전에 정의된 형식에 부합하는지 자동으로 검사할 수 있습니다. 즉, 데이터베이스와의 직접적인 상호작용을 목적으로 하지 않으며, 데이터베이스와 상호작용하는 모델과 유효성을 검사하는 모델을 분리해 데이터의 무결성을 관리할 수 있습니다.

SQLModel은 Pydantic과 SQLAlchemy의 기능을 결합하여 데이터 유효성 검사와 동시에 SQLAlchemy ORM을 사용하여 데이터베이스와 직접 상호 작용할 수 있게 해주는 Python 라이브러리입니다. SQLModel의 모델은 SQLAlchemy ORM 클래스처럼 사용할 수 있습니다. 따라서 데이터베이스 모델링과 데이터 유효성 검사를 동시에 수행하고 싶을 때 SQLModel을 사용하는 것이 좋습니다.

 

2.1 SQLModel이 ORM인가?

 

SQLModel은 자체 ORM이라기보다는 SQLAlchemy ORM을 확장하고 보완하는 역할을 합니다. SQLModel 클래스는 기본적으로 SQLAlchemy의 Declarative Base를 상속받아 SQL 테이블과 상호 작용할 수 있습니다. 따라서 SQLModel을 사용할 때는 SQLAlchemy ORM과 함께 사용한다고 생각하면 됩니다.

 

2.2 Pydantic과 SQLModel 사용법

 

SQLModel을 사용할 때 별도로 Pydantic을 사용할 필요는 없습니다. SQLModel이 Pydantic과 SQLAlchemy를 결합한 형태이기 때문에, SQLModel의 모델 클래스는 이미 Pydantic 모델 SQLAlchemy 모델로 동작합니다.

하지만, 특정 상황에서는 Pydantic 모델을 추가로 사용하는 것이 유리할 때도 있습니다. 예를 들어:

  1. 데이터베이스 스키마와 다른 API 요청/응답 스키마가 필요할 때: 데이터베이스 모델과 약간 다른 구조의 API 스키마가 필요할 때는 Pydantic을 별도로 사용할 수 있습니다.
  2. 고급 데이터 유효성 검사를 수행할 때: SQLModel 모델이 제공하는 기본 유효성 검사 외에, Pydantic의 고급 유효성 검사 기능을 활용하고 싶을 때도 있습니다.

이런 특수한 경우가 아니라면 SQLModel을 단독으로 사용하는 것으로 충분합니다.

3. FastAPI의 주요 장점

위에 언급한 비동기 환경에서의 고성능 외에도 다음과 같은 장점들이 있습니다.

  • 타입 힌트와 자동 검증: 요청과 응답의 데이터를 자동으로 검증하여 타입 안정성이 향상되며, 타입 에러를 줄일 수 있습니다. 오류 메시지를 자동으로 생성해 클라이언트에게 반환합니다.
  • 자동 문서화: FastAPI는 OpenAPI와 JSON Schema를 자동으로 생성하여 API 문서를 자동으로 제공합니다. 개발자는 /docs 또는 /redoc 경로에서 Swagger UI 또는 Redoc을 통해 API 문서를 시각화할 수 있어, 빠르게 문서를 확인하고 테스트할 수 있습니다.
  • 간결하고 직관적인 코드: FastAPI는 코드가 간결하고 직관적이어서 학습 곡선이 낮습니다. RESTful API를 구축할 때, 엔드포인트 설정, 파라미터 검증, 응답 형식 정의 등이 빠르고 쉽게 이루어집니다.
  • 비동기 및 동기 함수 모두 지원: FastAPI는 비동기 함수뿐만 아니라 동기 함수도 지원합니다. 이를 통해, 기존의 동기 코드를 쉽게 통합할 수 있으며, 필요에 따라 비동기로 전환할 수도 있습니다.

FastAPI를 선택하기 좋은 상황

  • 고성능 API: FastAPI는 특히 RESTful API 또는 비동기 작업을 많이 필요로 하는 서비스에서 뛰어난 성능을 발휘하므로, 빠르고 효율적인 API가 필요한 서비스에 적합합니다.
  • 대규모 또는 실시간 데이터 통신: WebSocket과 같은 실시간 데이터 통신이나 많은 동시 요청 처리가 필요한 환경에서는 비동기 지원 덕분에 FastAPI가 유리합니다.
  • 타입 안정성이 중요한 프로젝트: 타입 힌트를 통한 자동 검증 및 문서화가 필요하거나, 데이터 모델이 복잡하여 검증이 중요한 프로젝트에서 FastAPI는 Pydantic과의 통합을 통해 강력한 데이터 유효성 검사를 제공합니다.
  • 자동화된 문서화와 빠른 개발 속도: 클라이언트와 협력하는 프로젝트나 빠른 프로토타입 개발이 필요한 경우, 자동화된 문서화는 API 설계 및 테스트 효율성을 높여줍니다.