의존성 주입 (Dependency Injection) 개념과 활용
개념
의존성 (Dependency)
A 함수 또는 클래스에서 B 기능 사용할 때, A는 B에 의존 (Dependency)한다고 이야기할 수 있다. 하나의 컴포넌트 (함수, 클래스)가 다른 컴포넌트에 의존하는 경우 해당 의존성을 해결하는 것이 중요하다.
- send_email (A) 함수는 email_service (B) 객체에 의존
- 만약 email_service가 없다면, send_email() 함수는 동작할 수 없음
def send_email(email_service):
email_service.send("Hello!") # send_email()은 email_service에 의존
의존성 주입 (Dependency Injection, DI)
의존성 주입이란 의존성을 함수 내부에서 생성하는 것이 아닌 외부에서 주입하는 방식을 의미한다. 이를 통해 코드의 재사용성을 높일 수 있다. FastAPI에서는 Depends()를 제공하므로 의존성 주입을 쉽게 구현이 가능하다.
- email_service()를 직접 호출하는 것이 아니라 Depends(email_service)를 통해 주입
- 이 방식을 활용해 email_service()를 다른 함수, 클래스에서 재사용 가능
from fastapi import Depends
def email_service():
return "Email Service Activated"
def send_email(service=Depends(email_service)):
return {"message": service}
의존성 주입 X vs 의존성 주입 O
의존성 주입 X
- get_message()가 앱이 실행될 때 한 번 호출
- 이후 모든 요성에서 message는 항상 같은 값 (캐싱된 값)을 사용
- get_message()가 고정된 값이므로, 동적으로 값이 바뀌어야 할 경우 적용 불가능
- 데이터베이스에 적용한다면, 동일한 데이터베이스 세션을 사용해 세션 충돌 발생 가능
from fastapi import FastAPI
app = FastAPI()
def get_message():
return "Hello, Dependency Injection!"
@app.get("/")
def read_root(message: str = get_message()): # 함수 직접 호출
return {"message": message}
의존성 주입 O
- Depends(get_message)를 사용하면 요청이 들어올 때마다 get_message() 실행
- 동적으로 실행되고, 요청마다 새로운 값을 반환 가능
- FastAPI 내부적으로 get_message() 실행 후 반환 값을 message에 주입
- 데이터베이스에 적용한다면, 독립적인 데이터베이스 세션이 생성돼 세션 충돌 방지
from fastapi import FastAPI, Depends
app = FastAPI()
def get_message():
return "Hello, Dependency Injection!"
@app.get("/")
def read_root(message: str = Depends(get_message)): # Depends 사용
return {"message": message}
FastAPI에서 의존성 주입 활용법
Depends 사용 with 함수
- message: str = Depends(get_message)
- get_message()의 반환 값은 str 형태 (Type Hint)이며, 해당 값을 message에 대입
from fastapi import FastAPI, Depends
app = FastAPI()
def get_message():
return "Hello, Dependency Injection!"
@app.get("/")
def read_root(message: str = Depends(get_message)):
return {"message": message}
Depends 사용 with 클래스
- FastAPI에서는 클래스도 의존성으로 주입 가능
- UserManager 객체가 경로 함수의 매개변수로 자동 생성되어 주입 가능
class UserManager:
def __init__(self):
self.users = ["Alice", "Bob"]
def get_users(self):
return self.users
@app.get("/users")
def read_users(manager: UserManager = Depends(UserManager)):
return manager.get_users()
Annotated 사용 (Python 3.9 이상)
- Python 3.9 이상에서는 Annotated를 활용해 의존성 타입을 더 명확히 지정 가능
- MessageType = Annotated[str, Depends(get_message)]
- get_message()의 반환 값은 str 형태 (Type Hint)이며, 해당 값을 MessageType에 대입
- 각 경로 함수의 MessageType으로 주입이 가능하므로 재사용성 향상
from fastapi import Depends
from typing import Annotated
def get_message():
return "Hello, Annotated!"
MessageType = Annotated[str, Depends(get_message)]
@app.get("/")
def read_root(message: MessageType):
return {"message": message}
'Web' 카테고리의 다른 글
[FastAPI] OAuth2와 JWT를 활용한 인증 구현 (0) | 2025.02.22 |
---|---|
[FastAPI] DB Migration을 위한 alembic 개념과 활용 (0) | 2025.02.17 |
[FastAPI] 데이터베이스 Session 생성을 위한 get_db() 이해 (0) | 2025.02.01 |
[Web] 웹 크롤링을 위한 Fiddler와 Postman 설치 및 사용법 (1) | 2024.09.25 |
[Web] 데이터 수집을 위한 웹 크롤링 3가지 방법 (정적 vs 동적) (1) | 2024.09.13 |