FastAPI 통합

junyul-kr[fastapi] extra는 Starlette 기반 미들웨어 ComplyMiddleware를 포함합니다. HTML 응답에 자동으로 컴플라이언스 배너를 주입하고, 렌더링 시점에 transparency.notice_shown 이벤트를 기록합니다.

설치

# 공개 PyPI 릴리스 또는 고객 전용 패키지 채널 연결 후
pip install "junyul-kr[fastapi]"

앱 초기화 + 미들웨어

from fastapi import FastAPI
import junyul
from junyul.disclosure.fastapi import ComplyMiddleware

junyul.init(
    api_key=os.environ["JUNYUL_API_KEY"],
    tenant_secret=os.environ["JUNYUL_TENANT_SECRET"],  # HMAC user anonymization
    environment="production",
)

app = FastAPI()

# Auto-inject a compliance banner into every HTML response + record
# transparency.notice_shown event on each render.
app.add_middleware(
    ComplyMiddleware,
    default_asset_id="chatbot_v1",
    locale="ko",
    position="top",
)

@app.post("/chat")
@junyul.track(asset_id="chatbot_v1")
async def chat(req: ChatRequest):
    return await call_llm(req.message)

요청별 이벤트 기록

@app.post("/loan-decision")
async def decide(req: LoanRequest):
    decision = await credit_model.score(req.features)

    junyul.events.record_decision(
        asset_id="loan_v3",
        action="automated_decision_made",
        legal_bases=["ai_basic_law_kr", "credit_info_36_2_kr", "pipa_37_2_kr"],
        risk_tier="high",
        subject_id=req.applicant_id,    # HMAC'd locally via tenant_secret
        outcome_hash=junyul.utils.canonical_hash({
            "decision": decision.category,
            "confidence": round(decision.confidence, 2),
        }),
        correlation_id=req.request_id,
    )

    return decision

비동기 handler의 성능 영향

SDK는 이벤트를 메모리 큐에 O(1)로 넣고 즉시 반환합니다. 네트워크 전송은 백그라운드 태스크. 벤치마크 기준 record_* 호출의 p99 latency는 ~50μs입니다. 고영향 결정 앞에서도 응답 지연에 사실상 영향이 없습니다.

OpenTelemetry 연동

opentelemetry-api가 설치되어 있고 JUNYUL_OTEL_ENABLED=true인 경우, SDK가 현재 active span의 trace_idspan_id를 자동으로 이벤트에 부착합니다. FastAPI를 otelcollector와 연결하셨다면 별도 작업 없이 감사 로그에 분산 추적 컨텍스트가 보존됩니다.

테스트

JUNYUL_ENVIRONMENT=test로 초기화하면 이벤트는 서버로 전송되지 않고junyul.testing.get_captured_events()로 assert 가능합니다. 기존 FastAPI TestClient 테스트를 수정 없이 재사용할 수 있습니다.