FastAPI + Next.js 1

0. 전체 시리즈 목차 (예고)

  1. 현재 진단 & 기준선 만들기 → 오늘
  2. FastAPI 프로덕션 튜닝(성능/연결/동시성)
  3. 데이터 레이어(Postgres/Redis/Search)와 캐싱 전략
  4. 비동기·이벤트 처리(큐/스트림/워크플로: SQS·Kafka·Celery·Outbox)
  5. 인증/인가(OAuth2/OIDC, JWT/세션, RBAC/ABAC, 토큰 로테이션)
  6. API 게이트웨이·레이트리밋·엣지(CloudFront/Vercel/WAF/BFF 패턴)
  7. Next.js at Scale(SSR/ISR/RSC/Route Handlers, 이미지 최적화, CDN)
  8. 가시성(Observability): OpenTelemetry/로그/메트릭/트레이싱 & SLO
  9. CI/CD & IaC: GitHub Actions, Docker, Terraform, Helm, GitOps
  10. 쿠버네티스 운영: 오토스케일링, 롤아웃, KEDA, PDB, Mesh
  11. 보안·컴플라이언스: 비밀/키 관리, 암호화, PII, ISMS-P/개인정보보호법
  12. 신뢰성·DR: 백업/복구, RTO/RPO, 멀티AZ/리전, 카오스 테스트, 비용관리

1편. 현재 진단 & 기준선 만들기 (Baseline First)

1) 목표 정의: “성능·안정성·비용” 3축

  • 성능: API p95 < 200ms(핵심 읽기), p95 < 350ms(쓰기), 웹 p95 TTFB < 300ms(SSR 기준)
  • 안정성: 가용성 99.9% 이상, 에러율 < 0.1%
  • 비용: 월 이용자·요청당 비용(¥/req, ₩/MAU) 목표선 수립

위 수치는 서비스 특성에 맞게 조정하지만, “측정 가능한 수치”로 박아두는 게 핵심.

2) 현황 스냅샷: 지금 상태를 수치로 “고정”

아래 체크리스트로 현재 수치를 기록해 두세요. 앞으로 모든 개선은 이 기준선과 비교합니다.

  • 트래픽: 초당 요청(RPS), 피크 시간대, 엔드포인트 TOP 10
  • 지연: p50/p95/p99(엔드포인트별), TTFB/CLS/LCP(웹)
  • 에러: 4xx/5xx 비율, 상위 에러 유형(타임아웃/DB Deadlock 등)
  • DB: QPS, 느린 쿼리 Top 20, 연결 수/사용률, 캐시 히트율
  • 인프라: CPU/메모리/네트워크 사용률, 오토스케일 동작 여부
  • 배포: 리드타임, 실패율, 롤백 평균 시간
  • 비용: 월 총비용, 리소스별 분해(컴퓨트/DB/스토리지/네트워크)

k6로 10분만에 벤치 기준선 잡기(샘플)

// save as baseline.js
import http from 'k6/http';
import { sleep, check } from 'k6';
export const options = { vus: 50, duration: '2m' };

export default function () {
  const res = http.get(`${__ENV.API_URL}/healthz`);
  check(res, { 'status 200': (r) => r.status === 200 });
  sleep(1);
}
API_URL=https://api.example.com k6 run baseline.js

→ p95, 에러율 기록 후 저장(“2025-10-09 기준선” 같은 이름)

3) 최소 운영 아키텍처(MVP→프로덕션) 제안

베이스 아키텍처(단계 1)

[Client] 
   ↓
[CDN/Edge (CloudFront/Vercel)] — [WAF]
   ↓
[Next.js SSR/ISR (Vercel or Node pool)]
   ↓           ↘
[BFF/API Gateway]  [Static/S3, Image Opt]
   ↓
[FastAPI (Gunicorn+Uvicorn, ASGI)]
   ↓       ↘
[PgBouncer] [Redis(Cache/Rate limit)]
   ↓
[Postgres (RDS/Aurora)]
   ↘
[Queue( SQS/Rabbit/Kafka )] ← [Workers(Celery/KEDA)]
  • Next.js: ISR로 캐시 가능한 페이지는 엣지/CDN에 최대한 밀어넣기
  • FastAPI: 동시성 친화(비동기 I/O), 커넥션 풀, 타임아웃·리트라이·Circuit Breaker
  • Redis: 캐시·세션·분산락·레이트리밋 토대
  • PgBouncer: DB 연결 수 관리(트래픽 급등 방지)
  • Queue + Worker: 쓰기/대용량/외부연동은 비동기로 털어주기
  • 관측성: OTEL 수집→Collector→Grafana/Tempo/Loki 등

성장 단계(단계 2~3)에서 추가

  • 읽기 리플리카, CQRS(읽기 전용 API 라우팅)
  • 서치(OpenSearch/ES) 분리, 보고/분석 DB 분리
  • 서킷브레이커/리밸런싱(service mesh 또는 게이트웨이)
  • 블루/그린·카나리 배포, KEDA로 워커 자동 확장
  • 멀티AZ→멀티리전(액티브/패시브 → 액티브/액티브)

4) 리포지토리 & 설정 표준화

모노레포 추천(공유 타입 안전성↑)

repo/
  apps/
    api/        # FastAPI
    web/        # Next.js
  packages/
    shared/     # 공통 DTO/스키마/유틸(예: zod schema + pydantic 매핑)
  infra/
    terraform/  # VPC/RDS/Redis/Queues/… IaC
    helm/       # k8s 차트

설정 관리(12-Factor)

  • FastAPI: pydantic-settings로 환경변수 중심, .env는 로컬 전용
  • Next.js: NEXT_PUBLIC_*만 클라이언트로 노출, 나머지는 서버 전용
  • 비밀값은 SSM/Vault/KMS 등에서 주입, Git 저장 금지

5) 헬스체크 & Readiness(실전용 스니펫)

FastAPI

# app/main.py
from fastapi import FastAPI
import asyncpg, aioredis, os

app = FastAPI()
@app.get("/healthz")   # liveness
async def healthz():
    return {"ok": True}

@app.get("/readyz")    # readiness
async def readyz():
    # DB & Redis 간단 점검(타임아웃 필수)
    # 실제론 커넥션 풀 ping, 쿼리/명령 시간 제한 권장
    return {"db": "ok", "cache": "ok"}

Next.js (Route Handler)

// app/api/healthz/route.ts
import { NextResponse } from 'next/server';
export async function GET() { return NextResponse.json({ ok: true }); }

쿠버네티스일 경우:

  • livenessProbe: /healthz
  • readinessProbe: /readyz (DB/Redis 체크 포함)
  • startupProbe: 마이그/워밍업 시간 고려

6) 로깅·트레이싱·메트릭 최소 구성

FastAPI OpenTelemetry 셋업 예

# app/telemetry.py
import os
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
from opentelemetry import trace
from opentelemetry.sdk.resources import Resource
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor

def setup_tracing(app):
    provider = TracerProvider(resource=Resource.create({"service.name":"api"}))
    exporter = OTLPSpanExporter(endpoint=os.getenv("OTLP_ENDPOINT","http://otel-collector:4317"), insecure=True)
    provider.add_span_processor(BatchSpanProcessor(exporter))
    trace.set_tracer_provider(provider)
    FastAPIInstrumentor.instrument_app(app)
  • 로그는 반드시 JSON 구조화(요청ID/사용자ID/트레이스ID 포함)
  • 메트릭: 요청수, 지연(p50/p95/p99), 에러율, DB풀 사용률, 캐시 히트율

7) Docker & CI/CD 스켈레톤

FastAPI Dockerfile(간단형)

FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt && pip install gunicorn uvicorn
COPY . .
ENV PORT=8000
CMD ["gunicorn","-k","uvicorn.workers.UvicornWorker","-w","4","-b","0.0.0.0:8000","app.main:app"]

Next.js Dockerfile(standalone 빌드)

FROM node:20-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci

FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build

FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
# standalone 출력 가정
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public
EXPOSE 3000
CMD ["node","server.js"]

GitHub Actions(요지)

  • lint/test → build → sbom 생성 → 이미지 푸시 → 배포(ArgoCD 트리거)
  • PR단 품질 게이트: 유닛/통합 테스트, 타입체크, 슬랙 알림

8) 빠른 체감 성과(48시간 내) 체크리스트

  • /healthz//readyz 구현 & 모니터링 대시보드 연결
  • API 타임아웃(클라이언트/서버/DB) 상향평준화, 재시도 정책 정의
  • PgBouncer 도입, DB 커넥션 수 절반으로 절감 테스트
  • Redis 캐시 레이어(핵심 읽기 1~2개 엔드포인트) 적용
  • 정적 자산/이미지 최적화 & CDN 헤더 점검(Next.js Image 최적화도)
  • k6로 p95/에러율 재측정 → 기준선 대비 개선폭 기록

9) 안티 패턴(초기 확장 단계에서 많이 겪는 것)

  • API에서 모든 것 동기 처리(이메일/서드파티/영상처리 등)
  • DB 커넥션 폭주(풀 미사용·ORM 세션 누수)
  • SSR 페이지를 매 요청 렌더(ISR/캐시 미활용)
  • 구조화 로그 부재로 원인 추적 불가
  • 엔드포인트별 SLO 없음(무엇이 중요한지 모름)
  • 스키마/인덱스 관리 부재로 느린 쿼리 누적

10) 오늘의 산출물 템플릿(복붙용)

A. 기준선 리포트 (YYYY-MM-DD)

  • 트래픽:
  • 지연 p50/p95/p99:
  • 에러율:
  • DB/캐시 상태:
  • 인프라 사용률:
  • 비용(추정):

B. 2주 액션 플랜

  1. PgBouncer 도입, 커넥션 튜닝
  2. Redis 캐시(핵심 조회 2개)
  3. ISR 도입(트래픽 상위 페이지 3개)
  4. OTEL + 대시보드(지연/에러율 가시화)
  5. 릴리즈 파이프라인에 롤백 버튼 & 카나리 10% 적용

다음 편(2편)은 “FastAPI 프로덕션 튜닝”:
ASGI 서버 선택, 워커 수 결정, 커넥션 풀/타임아웃, N+1 방지, Pydantic v2/Python 3.12 최적화, 레이트리밋/백프레셔, 아이템포턴시 키, 트랜잭션·아웃박스까지 실전 스니펫 위주로 갑니다.

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다