FastAPI 설정 패턴
백엔드FastAPI 설정 패턴 — 실전 적용 구조와 코드 예시
언제 쓰나 · FastAPI 프로젝트 초기 구성 시 · Settings + Lifespan + 미들웨어 구조가 필요할 때
#backend#FastAPI
# FastAPI 설정 패턴
## 언제 쓰는가
- FastAPI 프로젝트 초기 구성 시
- Settings + Lifespan + 미들웨어 구조가 필요할 때
## 핵심 구조
- Pydantic Settings (.env 자동 로드)
- Lifespan (startup/shutdown)
- CORS + 인증 미들웨어
- 예외 핸들러
## 코드 예시
### Settings (Pydantic)
```python
class Settings(BaseModel):
host: str = "0.0.0.0"
port: int = 8000
debug: bool = False
database_url: str = "sqlite:///./api.db"
allowed_origins: list[str] = ["http://localhost:8000"]
rate_limit_per_minute: int = 100
settings = Settings() # .env / .env.local 자동 로드
```
### Lifespan (startup/shutdown)
```python
@asynccontextmanager
async def lifespan(app: FastAPI):
# Startup
await init_database()
yield
# Shutdown
await cleanup()
app = FastAPI(lifespan=lifespan)
```
### 미들웨어 (CORS + 인증)
```python
app.add_middleware(CORSMiddleware,
allow_origins=settings.allowed_origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"])
@app.middleware("http")
async def auth_middleware(request: Request, call_next):
if request.url.path in PUBLIC_PATHS:
return await call_next(request)
api_key = request.headers.get("Authorization", "").removeprefix("Bearer ")
if not api_key:
api_key = request.headers.get("X-API-Key", "")
if not validate(api_key):
return JSONResponse(status_code=401, content={"error": "Unauthorized"})
return await call_next(request)
```
### 예외 핸들러
```python
@app.exception_handler(HTTPException)
async def http_exception_handler(request, exc):
return JSONResponse(status_code=exc.status_code,
content={"error": {"message": exc.detail, "code": exc.status_code}})
@app.exception_handler(Exception)
async def general_exception_handler(request, exc):
return JSONResponse(status_code=500,
content={"error": {"message": "Internal server error"}})
```
## 주의사항
- `@app.on_event("startup")` 대신 `lifespan` 사용 (공식 권장)
- API Key는 쿼리스트링이 아닌 헤더에서만 추출 (로그 노출 방지)
- 인메모리 Rate Limiter는 단일 인스턴스만 유효
- 에러 응답에 내부 스택트레이스 노출 금지
## 재사용 방법
- Settings + Lifespan + 미들웨어 구조 그대로 복사
- Settings 필드만 프로젝트에 맞게 추가/변경
- 라우터는 `app.include_router()`로 분리 등록jt · v1 · CC0-1.0 · 복사 0