728x90

FastAPI 문서화 기능 개요
FastAPI는 OpenAPI Specification(구 Swagger)을 중심으로 다음을 자동 생성합니다.
| 구성요소 | 기본 경로 | 역할 |
|---|---|---|
| OpenAPI JSON | /openapi.json |
API 명세 원본 |
| Swagger UI | /docs |
대화형 API 테스트 UI |
| ReDoc | /redoc |
읽기 중심의 API 문서 |
| OAuth2 지원 | /docs 내부 |
인증 포함 API 테스트 |
| Schema 자동 생성 | - | Request/Response 검증 |
| 예제 자동 노출 | - | Payload 예시 |
👉 코드 → 스키마 → 문서 → 테스트가 한 번에 연결되는 구조입니다.
OpenAPI (/openapi.json)
🔹 역할
- FastAPI가 모든 라우트, 파라미터, 요청/응답 모델을 JSON 스펙으로 자동 변환
- Swagger, ReDoc, 외부 도구(Postman, Stoplight, API Gateway)가 모두 이 파일을 사용
🔹 주요 구성
{
"openapi": "3.1.0",
"info": {
"title": "My API",
"version": "1.0.0"
},
"paths": {},
"components": {
"schemas": {},
"securitySchemes": {}
}
}
🔹 내부 동작
- Python type hint + Pydantic 모델 기반
- 런타임에 동적 생성 (static 파일 아님)
🔹 활용 사례
- API Gateway 연동
- 사내 API 표준 문서
- SDK 자동 생성 (openapi-generator)
Swagger UI (/docs)
🔹 특징
- 대화형 API 테스트
- Authorization 헤더 설정 가능
- 요청/응답 예제 자동 표시
🔹 제공 기능
- Try it out
- Request Body Schema
- Response Code별 예시
- OAuth2 로그인 버튼
🔹 OAuth2 연동 예시
from fastapi.security import OAuth2PasswordBearer
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
Swagger UI에서
- 🔐 Authorize 버튼 자동 생성
- Bearer Token 주입 가능
🔹 실무 활용
- 프론트엔드/QA 협업
- 테스트용 Mock API
- 내부 운영 API 점검
ReDoc (/redoc)
🔹 특징
- 읽기 중심 문서
- 계층 구조 정리 우수
- 비개발자/기획자 친화적
🔹 Swagger 대비 차이
| 항목 | Swagger | ReDoc |
|---|---|---|
| 테스트 | 가능 | 불가 |
| 가독성 | 중간 | 높음 |
| 대규모 API | 복잡 | 구조적 |
| 보안 노출 위험 | 높음 | 상대적으로 낮음 |
🔹 활용 사례
- 외부 파트너 API 문서
- 사내 API 포털
- PDF 변환 문서
Pydantic Schema 자동 문서화
🔹 Request/Response 자동 노출
from pydantic import BaseModel
class User(BaseModel):
id: int
name: str
is_active: bool = True
Swagger/ReDoc에 자동 표시
- 필드 타입
- 기본값
- 필수 여부
🔹 예제 추가
class User(BaseModel):
id: int
name: str
class Config:
json_schema_extra = {
"example": {
"id": 1,
"name": "admin"
}
}
API 메타데이터 커스터마이징
🔹 FastAPI 앱 설정
app = FastAPI(
title="Internal Security API",
description="보안 이벤트 수집 및 분석 API",
version="2.1.0",
contact={
"name": "Security Team",
"email": "sec@company.com"
}
)
🔹 태그 기반 그룹화
@app.get("/alerts", tags=["Security"])
Docs/Schema 비활성화 및 경로 변경 (보안 핵심)
🔹 비활성화
app = FastAPI(
docs_url=None,
redoc_url=None,
openapi_url=None
)
🔹 내부망 전용 경로 변경
app = FastAPI(
docs_url="/_internal/docs",
openapi_url="/_internal/openapi.json"
)
보안 관점 핵심 가이드
왜 위험한가?
- API 전체 구조 노출
- 인증 방식, 파라미터 구조 노출
- 공격자에게 완벽한 공격 명세 제공
점검 포인트 체크리스트
✔ 운영 환경에서 /docs, /redoc 노출 여부
✔ /openapi.json 외부 접근 가능 여부
✔ 인증 없는 Try-it-out 가능 여부
✔ 민감 필드(example 포함) 노출 여부
✔ OAuth 토큰 발급 API 노출 여부
300x250
권장 보안 정책 예시
| 환경 | 정책 |
|---|---|
| DEV | 전부 활성화 |
| STG | VPN + 인증 |
| PROD | 완전 비활성화 or IP 제한 |
인증 기반 Docs 접근 제어 예시
from fastapi import Depends, HTTPException, status
def docs_auth(token: str = Depends(oauth2_scheme)):
if token != "internal-token":
raise HTTPException(status_code=403)
@app.get("/_docs", dependencies=[Depends(docs_auth)])
def secured_docs():
return get_swagger_ui_html(openapi_url="/openapi.json")
확장 활용 사례
- API SDK 자동 생성
- 테스트 자동화 (Postman/Newman)
- AI API 분석 학습 데이터
- 보안 점검 자동화 (OpenAPI Lint)
- API 사용 정책 문서화
FastAPI의 docs/redoc/openapi는 “개발 생산성의 끝판왕”이지만,
운영 환경에서는 “가장 먼저 통제해야 할 공격 표면”입니다.
가장 권장: 네트워크 레벨 차단 (L7/L4)
방법
- 내부망(VPC)에서만 접근
- VPN/ZTNA 통해서만 접근
- WAF / API Gateway / Ingress에서
/docs,/redoc,/openapi.json경로를 차단 또는 allowlist - IP Allowlist 적용 (사내 공인IP, VPN 대역 등)
장점
- 앱 코드 수정 최소화
- 가장 강력하고 단순
- 실수로 코드가 바뀌어도 외부 노출 방지
점검 포인트
/openapi.json도 동일하게 막혀 있는지 (문서만 막고 스펙은 열려 있는 실수 흔함)- 프록시 뒤에서 real ip 처리(
X-Forwarded-For) 신뢰 설정이 안전한지
(예시) Nginx에서 경로 차단/허용
location ~ ^/(docs|redoc|openapi\.json)$ {
allow 10.0.0.0/8; # 내부망/VPN 대역
allow 203.0.113.10; # 특정 공인IP
deny all;
proxy_pass http://fastapi_upstream;
}
문서 기능 자체를 운영에서 끄기 (가장 확실)
운영에서는 아예 생성/제공을 비활성화하는 방식입니다.
app = FastAPI(
docs_url=None,
redoc_url=None,
openapi_url=None
)
장점
- 노출면(attack surface) 자체 제거
- 설정 실수 가능성 감소
단점
- 운영에서 문서가 필요하면 별도 대책 필요(스테이징에서만 제공 등)
경로 변경 + 비공개 네임스페이스로 숨기기 (보조책)
app = FastAPI(
docs_url="/_internal/docs",
redoc_url="/_internal/redoc",
openapi_url="/_internal/openapi.json"
)
주의
- “숨김”은 보안이 아닙니다.
반드시 네트워크 제한 또는 인증과 함께 쓰는 보조책으로만 사용하세요.
인증 기반 접근제어 (앱 레벨)
HTTP Basic Auth (간단/효과적)
- 내부 운영자가 빠르게 접근해야 할 때 현실적으로 많이 씁니다.
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import HTTPBasic, HTTPBasicCredentials
from fastapi.openapi.docs import get_swagger_ui_html, get_redoc_html
import secrets, os
security = HTTPBasic()
DOC_USER = os.getenv("DOC_USER", "admin")
DOC_PASS = os.getenv("DOC_PASS", "change-me")
def basic_auth(credentials: HTTPBasicCredentials = Depends(security)):
ok_user = secrets.compare_digest(credentials.username, DOC_USER)
ok_pass = secrets.compare_digest(credentials.password, DOC_PASS)
if not (ok_user and ok_pass):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
headers={"WWW-Authenticate": "Basic"},
)
app = FastAPI(docs_url=None, redoc_url=None, openapi_url=None)
@app.get("/docs", dependencies=[Depends(basic_auth)], include_in_schema=False)
def docs():
return get_swagger_ui_html(openapi_url="/openapi.json", title="Docs")
@app.get("/redoc", dependencies=[Depends(basic_auth)], include_in_schema=False)
def redoc():
return get_redoc_html(openapi_url="/openapi.json", title="ReDoc")
@app.get("/openapi.json", dependencies=[Depends(basic_auth)], include_in_schema=False)
def openapi():
return app.openapi()
포인트
docs_url=None로 기본 문서 라우트는 끄고, 내가 만든 라우트에 인증을 붙여 제공include_in_schema=False로 이 라우트가 다시 문서에 노출되지 않게
JWT/OAuth2 기반 (조직 표준 SSO에 맞추기)
- 사내 인증(SSO, OIDC) 붙여서 “관리자/개발자” 롤만 허용
핵심 원리
/docs,/redoc,/openapi.json요청에 대해Depends(verify_jwt_and_role)같은 디펜던시로 검사- 역할(Role) 기반 접근제어(RBAC)
점검 포인트
- 토큰이 브라우저에 저장될 경우(로컬스토리지 등) 탈취 위험
- 문서 UI에서 “Try it out”이 가능한 경우 권한/감사로그(누가 어떤 호출 했는지) 고려
환경변수/배포환경 분리 (DEV/STG/PROD 정책)
운영에서 실수로 켜지는 사고를 막는 “조직 운영 정책”입니다.
import os
env = os.getenv("APP_ENV", "dev")
if env == "prod":
app = FastAPI(docs_url=None, redoc_url=None, openapi_url=None)
else:
app = FastAPI()
권장 운영정책(현실적인 베스트)
- DEV: 전부 ON
- STG: VPN/IP 제한 + 인증(권장)
- PROD: 기본 OFF (정말 필요하면 내부망+인증으로 제한 제공)
“Try it out” 자체를 제한/통제하고 싶을 때
Swagger UI는 기본적으로 호출이 가능해서, 문서 접근권한이 곧 API 호출 인터페이스 제공이 됩니다.
통제 방법
- 문서 접근은 허용하되, API 자체는
- 운영망에서만 호출 가능
- 또는 “읽기 전용 토큰”만 발급
- 또는 문서용 계정은 특정 scope만 허용
점검 포인트
- 문서 접근권한과 API 권한이 과도하게 묶이지 않게(최소권한)
실무 베스트 프랙티스
제일 추천(운영 안정/보안 강함)
- PROD: docs/redoc/openapi 모두 OFF
- STG: ON + VPN/IP allowlist + Basic Auth 또는 SSO
- 필요 시 OpenAPI JSON은 CI에서 추출해 별도 문서포털로 배포
“운영에서도 꼭 봐야 한다”면
- 경로 변경(
/_internal/...) - + 네트워크 제한(IP/VPN)
- + 앱 레벨 인증(Basic/SSO)
➡️ 3중으로 겹치기
보안 관점 체크리스트
- 외부에서
/openapi.json접근 가능한가? /docs막았는데/redoc은 열려 있지 않은가?- 프록시/Ingress에서 우회 경로가 없는가? (rewrite)
- 인증정보가 코드에 하드코딩되지 않았는가? (ENV/Secret)
- 내부 접근 로그(누가 문서 접근/호출 했는지)가 남는가?
- 문서에 예제로 토큰/키/내부 URL이 노출되지 않는가?
728x90
그리드형(광고전용)
댓글