백엔드

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