Published on

FastAPI에서 APIRouter로 확장성을 고려해 엔드포인트 설계하기

Authors

슬랙봇을 구축하면서, 데이터/이벤트를 수신받기 위해 FastAPI 서버를 배포했습니다.

가볍고 빠르기로 유명한 프레임워크를 사용하면서 확장성을 고려한 애플리케이션을 설계하고자 했습니다.

RestfulAPI 에 있어서 endpoint 설계는 무척 중요하다고 생각하며, APIRouter를 사용하여 어떻게 확장성 있는 엔드포인트 구조를 설계할 수 있는지 기록합니다.

1. APIRouter 란?

쉽게말하면 APIRouter는 FastAPI에서 엔드포인트를 모듈화 할 수 있게 도와주는 기능입니다.

  • 모듈화 된다는 의미: 라우터를 각 기능(인증 처리, 유저 관리 로직, 관리자 기능에 따른 로직)으로 나눠서 관리가 가능하다는 것 입니다. 엔드포인트 묶음을 Python 으로 작성된 한 주제의 기능으로 여긴다..정도로 생각하면 될 것 같습니다.
  • 동일한 라우터를 여러 경로에 적용하여 코드를 재사용할 수 있습니다. 라우팅과 관련된 코드를 분리하게 되고, 코드의 이해도나 가독성이 높아집니다.

2. APIRouter Basic 사용법

우선, FastAPI에서 APIRouter를 사용하는 기본적인 구조를 살펴보겠습니다. 각 기능을 담당하는 라우터 파일을 분리하여, 여러 모듈에서 라우터를 쉽게 추가할 수 있습니다.


# admin_router.py
from fastapi import APIRouter

router = APIRouter(
    prefix="/admin",
    tags=["Admin"]
)

@router.post("/create")
async def create_admin():
    return {"message": "Admin created"}

@router.get("/list")
async def list_admins():
    return {"admins": []}

이제 main.py에서 이 admin_router를 앱에 포함시킵니다.

# main.py
from fastapi import FastAPI
from app.api.admin_router import router as admin_router

app = FastAPI()

app.include_router(admin_router)

3. 확장성을 고려한 APIRouter 설계

APIRouter를 활용하면 기능별로 라우터를 분리하여 확장성 있는 구조로 설계할 수 있습니다.

예를 들어, 유저 관련 API와 관리자 관련 API를 각각 별도의 파일에 정의할 수 있습니다.

이렇게 하면 각 기능이 독립적으로 관리되며, 프로젝트의 복잡성이 증가하더라도 어느 주제인지에 따라 분류하고 추가할 수 있게되니 그나마 쉽게 유지보수할 수 있을 것 같습니다.

구조 예시


프로젝트root/
├── app/
│   ├── api/
│   │   ├── admin_router.py      # 관리자 관련 라우터
│   │   ├── user_router.py       # 유저 관련 라우터
│   ├── core/
│   │   ├── config.py            # 설정 파일
│   └── main.py                  # FastAPI app Call 지점
├── models/
│   └── user.py                  # 모델 관련
└── services/
    └── ex)user_service.py          # 비즈니스 로직 등등을 이렇게 설정 or utils(네이밍은 자유롭게..)

위와 같은 구조는 각 기능별로 모듈을 분리하여 프로젝트가 커져도 쉽게 확장할 수 있도록 해줍니다. 예를 들어, 새로운 기능이 추가될 때 새로운 라우터 파일을 만들어 메인 앱에 추가하기만 하면 됩니다.

4. APIRouter Prameters

Prefix

라우터의 앞단에 prefix를 지정할 수 있습니다.

엔드포인트를 (큰 묶음으로) 관리자와 유저 기능을 각각 /admin/user 처럼 나눌 수 있게 됩니다.

router = APIRouter(
    prefix="/admin",
    tags=["Admin"],
    responses={404: {"description": "Not found"}}
)

tag

tags 파라미터를 사용하면 FastAPI 에서 제공하는 docs(Swagger UI)에서 각 엔드포인트를 그룹화하여 더 쉽게 관리할 수 있습니다.


router = APIRouter(
    tags=["Users"]
)

Dependencies

Dependencies 를 통해 의존성 주입을 할 수있고, 이를 통해 APIRouter에서 인증, 데이터베이스 연결 등 공통적인 기능을 재사용할 수 있습니다.

from fastapi import Depends

def get_current_user():
    """인증 로직 생략"""
    return {"username": "admin"}

@router.get("/me")
async def read_users_me(current_user: dict = Depends(get_current_user)):
    return current_user

APIRouter는 엔드포인트를 관리한다는 측면에서 보면, DRF(Django Rest Framework)의 urls.py 와 유사하지만, 의존성 주입에 대한 부분 까지 관리를 한다는 면에서 처리하는 단계가 다릅니다.

백엔드(애플리케이션 프레임워크)에서 앱의 구조를 잘 설계하는 것이 곧 엔드포인트를 잘 설계하는 것과 같다고 생각합니다. 어떤 로직을 갖고있던 라우팅을 잘 관리하는 것이 먼저이고, 어떤 기능과 비즈니스 로직을 엮어서 설계하는지도 잘 고려해야겠죠.

기능별로 모듈화된 라우터를 사용함으로써, 대규모 프로젝트에서도 효율적으로 엔드포인트를 관리할 수 있고 공식문서에서도 이를 지향하는 것 처럼 보입니다.

참고 링크

FastAPI문서

hongreat 블로그의 글을 봐주셔서 감사합니다!