기술과 산업/언어 및 프레임워크

FastAPI 시리즈 8화 - 의존성 주입 시스템(Depends) 실전 활용법

B컷개발자 2025. 5. 9. 14:40
728x90

FastAPI의 Depends를 활용한 의존성 주입 시스템을 설명합니다. 공통 로직 재사용, 인증 처리, DB 연결 관리 등 실전 API 개발에서의 활용 패턴을 예제로 정리합니다.


왜 의존성 주입(Dependency Injection)이 중요한가?

전통적인 함수 호출 방식에서는 모든 기능을 하나의 엔드포인트 함수에서 직접 처리합니다.
하지만 실제 서비스에서는 다음과 같은 공통 로직이 필요합니다:

  • 로그인 인증
  • DB 커넥션 핸들링
  • 공통 파라미터 처리
  • 권한 체크, API 사용량 제한

이 로직들을 매번 복사해서 쓰는 것은 유지보수와 테스트 모두에게 지옥입니다.

FastAPI의 Depends는 이런 문제를 한 줄로 해결합니다.


1. Depends 기본 구조

from fastapi import Depends, FastAPI

app = FastAPI()

def get_token_header():
    print("의존성 함수 실행됨")
    return "token123"

@app.get("/items/", dependencies=[Depends(get_token_header)])
def read_items():
    return {"message": "token 검증 완료"}
  • get_token_header()는 호출되지만 결과를 사용하지 않음
  • 주로 로그, 인증, 트래킹 목적으로 사용
  • Swagger 문서에선 표시되지 않지만 내부적으로 실행됨

2. 값을 실제로 사용하는 방식

def get_user_agent(user_agent: str = Header(...)):
    return user_agent

@app.get("/user-agent")
def show_agent(agent: str = Depends(get_user_agent)):
    return {"User-Agent": agent}
  • Depends(get_user_agent)를 통해 agent 값 자동 전달
  • 공통 파라미터 추출 및 재사용이 쉬워짐

3. 인증 처리 예제 – 인증 토큰 검사

from fastapi import HTTPException, status, Header

def verify_token(token: str = Header(...)):
    if token != "secure-token":
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid Token"
        )
    return token

@app.get("/secure-data")
def secure_endpoint(token: str = Depends(verify_token)):
    return {"data": "비공개 데이터", "token": token}
  • verify_token()에서 인증 실패 시 HTTP 예외 발생
  • 성공 시 토큰 값이 라우터 함수에 전달됨

4. 의존성 계층 구조 (Nested Dependencies)

def get_db():
    print("DB 연결 생성")
    return "db_conn"

def get_user(db=Depends(get_db)):
    print(f"{db}에서 사용자 조회")
    return {"username": "alice"}

@app.get("/profile")
def profile(user=Depends(get_user)):
    return user
  • get_user()는 get_db()에 의존
  • FastAPI는 자동으로 계층 구조를 추론하고 순차 실행함
  • 복잡한 로직도 모듈화하고 테스트 가능

5. 클래스 기반 의존성 주입

class CommonQueryParams:
    def __init__(self, q: str = "", page: int = 1):
        self.q = q
        self.page = page

@app.get("/search")
def search(params: CommonQueryParams = Depends()):
    return {"query": params.q, "page": params.page}
  • 의존성 객체를 클래스로 선언하면 상태 + 파라미터 처리를 함께 다룰 수 있음
  • 내부 로직을 메서드화하면 훨씬 강력한 서비스 객체 패턴 구현 가능

6. 고급 기능 – dependency_overrides

테스트 환경에서 실제 인증 대신 mock 함수를 주입할 수도 있습니다.

def override_token():
    return "test-token"

app.dependency_overrides[verify_token] = override_token
  • 테스트 환경에서만 인증 우회 처리
  • 유닛 테스트, 통합 테스트 시 매우 유용

정리 – Depends는 FastAPI의 확장성과 품질의 핵심 축

기능 활용 예

공통 인증 처리 로그인 토큰 검증
파라미터 재사용 헤더, 쿠키, 쿼리 스트링 추출
로깅 및 감사 미들웨어 대체용
DB 관리 커넥션 생성 및 반환 구조화
테스트 유연성 mock 주입을 통한 테스트

FastAPI에서 Depends는 단순 헬퍼가 아닌 아키텍처 설계 도구입니다.
적절히만 사용한다면, 유지보수 가능한 API 백엔드를 구성하는 데 큰 힘이 됩니다.


다음 글 예고

FastAPI 시리즈 9화 - Background Tasks: 비동기 작업을 우아하게 처리하는 방법
에서는 사용자의 요청과 동시에 백그라운드에서 실행할 수 있는 작업(알림 전송, 로그 기록 등)을
어떻게 BackgroundTasks로 처리할 수 있는지를 다룹니다.

728x90