FastAPI 비동기 / 미들웨어 / 라우팅

예찬예찬·2024년 6월 10일

FastAPI

목록 보기
7/10
post-thumbnail

비동기 프로그래밍

컴퓨터 프로그램에서 특정 코드의 실행이 완료되지 않고 다른 작업을 동시에 진행할 수 있게 하는 것!

asyncio

비동기 프로그래밍을 위한 라이브러리

  • 비동기 I/O, 이벤트 루프, 코루틴
    • 이벤트 루프 - 코루틴을 실행시키기 위한 여러 방법 중 하나
  • 네트워크 I/O와 같이 시간이 많이 소요되는 작업들을 효율적으로 처리해줌

Async/Await 키워드

파이썬에서 비동기 프로그래밍을 구현할 때 사용하는 키워드

→ 위 키워드를 통해 비동기 프로그래밍을 할 수 있다. 이를 실행하기 위해 asyncI/O가 필요하다.

async

  • 비동기 함수는 ‘코루틴’이라 하며, await를 사용하여 호출될 수 있음.
  • await는 비동기 실행을 “일시 정지”하고 코루틴의 실행이 완료될 때까지 기다린다.
  • 블로킹 연상을 대기하는 동안 다른 코루틴이 실행될 수 있게 효율성을 증가시킨다.

FastAPI의 비동기 프로그래밍

  • API 경로 연산 함수에서 사용됩니다.
  • async def로 정의되며, 필요에 따라 await로 비동기 작업을 호출

비동기 프로그래밍의 장점

  • 성능 향상
    • 동시에 여러 I/O 바운드 작업을 처리할 수 있다.
  • 리소스 효율성
    • 쓰레드 기반의 동시성 모델에 비해 적은 메모리를 사용
  • 주의사항
    • 블로킹 코드의 사용: 비동기 함수 내에서 블로킹 코드(예: 일반 동기 데이터베이스 드라이브)를 사용하면 전체 애플리케이션의 성능 저하가 될 수 있음.
    • 에러 핸들링: 비옫기 프로그래밍에서는 에러 핸들링이 다소 복잡해질 수 있으며, 적절한 예외 처리가 필요함.

ASGI

  • ASGI - (Asynchronous Server Gateway Interface)
    • WSGI (Web Server Gateway Interface)의 한계를 극복하기 위해 계발
    • WSGI는 하나의 요청을 처리하는 동안 다른 요청이 대기 상태에 머물게 되는 동기 방식
    • 이에 비해 ASGI는 비동기 방식으로 여러 요청을 동시에 처리할 수 있음.
  • ASGI의 주요 특징
    • 비동기 지원: ASGI는 비동기 요청 처리를 지원하여, 높은 동시성과 성능을 제공
    • 웹소켓 지원: 웹소켓과 같은 비동기적 통신 프로토콜을 지원하여, 실시간 양방향 통신이 가능
    • 확장성: ASGI는 다양한 이벤트 기반 아키텍처와 함께 사용될 수 있어, 웹 애플리케이션의 확장성을 향상
    • 호환성: 다양한 ASGI 호환 웹 프레임워크와 서버가 있어, 선택의 폭이 넓음

FastAPI와 ASGI 서버 정리

FastAPI

  • ASGI 인터페이스를 구현하는 Python 웹 프레임 워크
  • 비동기 프로그래밍을 통해 높은 성능의 API 쉽게 구축
  • 요철을 처리하고 응답을 구성하는 데 사용되는 로직과 도구를 제공

ASGI 서버 (예: Uvicorn)

  • FastAPI 애플리케이션과 같은 ASGI 호환 애플리케이션을 호스팅하는 데 사용
  • 네트워크 요청을 수신하고, FastAPI 애플리케이션으로 전달 후, 애플리케이션의 응답을 클라이언트에게 반환하는 역할을 한다.

FastAPI를 사용한다는 것은 FastAPI 프레임워크를 사용하여 애플리케이션을 개발한다는 것을 의미

하지만 실제로 웹 요청을 받고 처리하려면 Uvicorn과 같은 ASGI 서버가 필요함.


미들웨어

FastAPI 미들웨어

  • 클라이언트로부터의 요청이 처리되기 전과 후에 실행되는 함수
  • FastAPI의 모든 요청은 설정된 미들웨어를 거치게 되며, 이를 통해 요청을 로깅하거나, 요청/응답을 수정하거나, 보안 체크를 수행할 수 있다.

미들웨어 추가

  • FastAPI에서 미들웨어는 app.middleware(”http”) 데코레이터를 사용해 추가할 수 있다.

예시 코드

  • http 요청에 대한 실행 시간 로그를 찍게 하는 미들웨어
from fastapi import FastAPI, Request
import time
from starlette.middleware.base import BaseHTTPMiddleware

app = FastAPI()

class CustomMiddleware(BaseHTTPMiddleware):
    async def dispatch(self,request, call_next):
        print("Hello It's Me")
        response = await call_next(request)
        return response
    
app.add_middleware(CustomMiddleware)

# 미들웨어 정의
@app.middleware("http")
async def log_requests(request: Request, call_next):
    start_time = time.time()
    # 요청처리
    response = await call_next(request)
    # 처리 시가 계산
    process_time = time.time() - start_time
    # 로그 출력
    print(f"Request: {request.method} {request.url} - Completed in {process_time} secs")
    return response

# 예시 경로
@app.get("/")
async def read_root():
    return {"Hello": "World"}

@app.get("/items/{item_id}")
async def read_item(item_id: int):
    return {"item_id": item_id}

라우터

FastAPI 라우팅

  • 라우팅은 URL 경로와 해당 경로에 매핑되는 처리 함수 (경로 연산 함수)를 정의하는 과정
  • FastAPI에서는 다양한 HTTP 메서드(GET, POST, PUT, DELETE)에 대한 경로 연산을 쉽게 설정할 수 있음
  • 라우터는 이걸 처리해주는 객체!

라우터 분리와 재사용성

분리

  • 큰 애플리케이션에서는 라우터를 분리하여 기능별로 구분할 수 있음
  • 코드의 재사용성 증가!

APIRouter 사용

  • APIRouter 클래스를 사용하여 라우터를 별도의 모듈로 분리 가능

미들웨어를 라우터 별로 따로 지정은 불가능! 미들웨어는 일반적으로 애플리케이션 전체에 적용되기 때문

  • 라우터별로 특정 미들웨어의 동작을 구현하고 싶은 경우는 Depend라는 것을 사용
  • 라우터 그룹을 특정 그룹에 대해서만 사용자 인증을 요구하고 싶다면 디펜드로 구현 가능
profile
나는 오예찬

0개의 댓글