junglast
Published on

FastAPI에서 동일한 쿼리 파라미터 재사용하기

FastAPI에서 한 라우트에 쿼리 파라미터를 지정하는 방법은 아래와 같이 라우트를 정의하는 함수(Path Operation Function)의 정의 부분에 사용하고자 하는 쿼리 파라미터의 이름과 타입을 정의하는 것입니다.

@app.get("/products")
def get_products(product_id: str, product_type: str):
    ...

하지만 같은 쿼리 파라미터가 여러 라우트에 걸쳐 필요한 경우 일반적으로는 동일한 쿼리 파라미터를 여러 번 반복해서 정의해야 합니다. 특히, 타입 정의, 파라미터 제약 조건(길이, 초기값) 등이 상세하게 추가되어야 한다면 이와 같은 방식은 한계가 있을 수 있습니다.

@app.get("/products")
def get_products(product_id: str, product_type: str):
    ...

@app.delete("/products")
def delete_products(product_id: str, product_type: str):
    ...

@app.get("/products/packages")
def get_products_packages(product_id: str, product_type: str):
    ...

또한 라우트에 Body 파라미터를 정의할 때는 Pydantic의 Model로 정의된 객체를 반복해서 재사용할 수 있지만 쿼리 파라미터에서는 이러한 재사용이 불가능합니다.

이 경우, FastAPI에서 제공하는 dependency를 이용해 문제를 해결할 수 있습니다.

라우트 정의에서 반복되는 쿼리 파라미터를 다음과 같이 별도의 dependency로 정의해 줍니다.

def product_query_parameters(product_id: str, product_type: str):
    return {"product_id": product_id, "product_type": product_type}

그 다음, 정의된 dependency를 Path Operation Function의 정의 부분에 Depends를 이용하여 주입합니다.

from fastapi import Depends

@app.get("/products")
def get_products(query_parameters: dict = Depends(product_query_parameters)):
    ...

@app.delete("/products")
def delete_products(query_parameters: dict = Depends(product_query_parameters)):
    ...

@app.get("/products/packages")
def get_products_packages(query_parameters: dict = Depends(product_query_parameters)):
    ...

이제 모든 라우트는 product_query_parameters dependency에 의해 product_idproduct_type를 쿼리 파라미터로 가지게 됩니다.

한편, FastAPI의 dependency는 callable한 형태로 정의되어야 합니다. 따라서, 함수를 사용해 정의한 위 예제와 달리 클래스로도 dependency를 정의할 수 있습니다.

class ProductQueryParameters:
    def __init__(product_id: str, product_type: str):
        self.product_id = product_id
        self.product_type = product_type

사용은 함수 형태의 dependency와 동일합니다. 다만, IDE에서 타입 힌트를 얻기 위해서는 아래처럼 쿼리 파라미터의 타입을 dict 타입이 아닌 dependency가 정의된 클래스의 이름으로 지정해주어야 합니다.

from fastapi import Depends

@app.get("/products")
def get_products(query_parameters: ProductQueryParameters = Depends(ProductQueryParameters)):
    ...

이 경우 Depends에서 파라미터인 ProductQueryParameters를 생략해 다음과 같이 적을 수도 있습니다.

from fastapi import Depends

@app.get("/products")
def get_products(query_parameters: ProductQueryParameters = Depends()):
    ...