Backend Architecture
개요
Backend는 브라우저에 Cognito 토큰을 노출하지 않는 BFF(Backend for Frontend) 구조입니다.
Browser
-> Cloudflare Pages /api/*
-> API Gateway HTTP API
-> API Lambda (Express)
-> Cognito / DynamoDB / Secrets Manager
Frontend는 Cloudflare Pages에서 제공됩니다. Pages Function이 동일 오리진의 /api/* 요청을 API Gateway로 전달하므로 OAuth callback과 HttpOnly 인증 쿠키가 동일한 Frontend 도메인을 사용합니다.
AWS 리소스
API Lambda
- Runtime: Node.js 22
- Architecture: ARM64
- Memory: 512MB
- Timeout: 29초
- Reserved concurrency: 50
- X-Ray tracing: 활성화
- Entry point:
src/lambda.ts
reservedConcurrentExecutions는 최대 동시 실행 제한이며 Provisioned Concurrency가 아닙니다. 유휴 상태에서 고정 Lambda 실행 비용을 만들지 않습니다.
API Gateway
- HTTP API
$defaultstage- 모든 경로와 HTTP method를 API Lambda로 proxy
- Steady-state rate: 초당 50 요청
- Burst limit: 100 요청
- CloudWatch access log 보관: 1개월
- Route-level detailed metrics 활성화
Cognito
- 이메일 기반 가입 및 로그인
- 이메일 확인과 비밀번호 복구
- Google OAuth authorization code + PKCE
- TOTP MFA
- Access/ID token 유효 기간: 15분
- Refresh token 유효 기간: 30일
- GitHub 전용 비밀 app client와 Custom Auth Lambda trigger
GitHub는 Cognito의 기본 소셜 IdP가 아니므로 GitHub OAuth API로 검증된 이메일을 확인한 후 Admin Custom Auth를 수행합니다.
DynamoDB
단일 테이블은 pk, sk 복합 키를 사용합니다.
| PK | SK | 용도 |
|---|---|---|
USER#{userId} | PROFILE | 이름, 이메일, 소개, locale, timezone |
USER#{userId} | ACCESS | 구독 상태와 권한 |
AUTH_SESSION#{id} | AUTH_SESSION | MFA challenge 단기 세션 |
OAUTH_STATE#{state} | OAUTH_STATE | OAuth CSRF state와 PKCE verifier |
AUDIT#{userId} | {timestamp}#{id} | 권한 변경 감사 기록 |
테이블은 on-demand billing, AWS 관리형 암호화, PITR, TTL을 사용합니다. OAuth state는 원자적 삭제 후 반환하여 재사용을 막습니다.
Secrets Manager
GitHub OAuth client secret을 저장합니다. Lambda execution role만 읽을 수 있습니다.
인증 쿠키
efk_access: Cognito access tokenefk_id: Cognito ID tokenefk_refresh: Cognito refresh tokenefk_auth_source: 일반 또는 GitHub 로그인 구분efk_auth_username: GitHub refresh에 필요한 Cognito username
모든 쿠키는 HttpOnly, SameSite=Lax, 운영 환경 Secure로 설정됩니다.
권한 모델
MODULE_UPLOADMODULE_VERIFYMODULE_DELETEMODULE_HIDEPERMISSION_MANAGE
권한은 DynamoDB에서 조회하며 API route에서 별도로 검사합니다. Cognito group만으로 권한을 결정하지 않기 때문에 구독 정보와 세부 권한을 같은 사용자 access record에서 관리할 수 있습니다.