테스팅과 배포
- 17.1 Scope
- 17.2 Size
- 17.3 Practical considerations
- 17.4 Formal verification
- 17.5 Review and build
- 17.6 Pre-production
- 17.7 Production
- 17.8 Rollbacks
릴리스 과정은 결국 두 단계야 — 확인하고, 보내는 것. 테스팅이 "이거 괜찮아?"를 묻는 거고, 배포가 "그럼 내보내자"를 실행하는 거지. 버그는 빨리 발견할수록 고치기 싸지만, 테스팅은 만능이 아니야 — 개발자가 상상할 수 있는 장애만 커버하고, 프로덕션의 복잡한 **창발적 행동(emergent behavior)**은 커버 못 하거든.
테스트의 **범위(scope)**는 실제로 테스트하는 코드 경로에 따라 결정돼. 유닛 테스트는 작은 컴포넌트, 통합 테스트는 서비스와 외부 의존성 간 상호작용, E2E 테스트는 전체 사용자 시나리오를 검증하지. 범위와 별개로 크기(size) 개념도 있어. Small 테스트는 단일 프로세스 내에서 빠르고 안정적이고, Medium은 단일 노드에서 로컬 I/O를 포함하고, Large는 여러 노드가 필요해서 느리고 flaky해. 크기를 줄이면서 범위를 유지하려면 테스트 더블을 쓰는데, 우선순위가 명확해 — 실제 구현 > fake > stub > mock. Fake(예: 인메모리 DB)가 가장 유용한 타협안이고, mock은 최후의 수단이야.
코드를 한 줄도 쓰기 전에 **정형 검증(formal verification)**으로 설계의 정확성을 검증하는 접근법도 있어. TLA+ 같은 도구로 분산 알고리즘의 속성을 수학적으로 증명하는 거야. 구현은 아니지만 설계 수준의 버그를 조기에 발견할 수 있지.
테스트를 통과했으면 이제 보내야 해. 여정은 풀 리퀘스트에서 시작돼. 컴파일, 정적 분석, 빠른 테스트를 통과하고, 리뷰어가 확인한 후 메인에 머지하지. 빌드 아티팩트를 합성 프리 프로덕션 환경에 배포해서 초기 검증을 하고, 프로덕션 롤아웃은 여러 전략이 있어. **카나리 배포(canary)**는 소수 사용자에게 먼저 릴리스, **롤링 배포(rolling)**는 인스턴스를 점진적으로 교체, **피처 플래그(feature flags)**는 배포와 릴리스를 분리해 — 코드를 배포하되 기능은 꺼둔 상태로, 나중에 플래그로 활성화하는 거야.
문제가 발견되면 파이프라인이 자동으로 롤백하거나 엔지니어에게 알려. 빠른 롤백 능력이 핵심이야 — 배포 실패의 영향을 최소화하려면 롤백이 빠르고 안정적이어야 하거든. 결국 테스팅에서 확신을 쌓고, 배포에서 안전하게 전달하는 거야. 둘 중 하나만으로는 부족해.
정리
17장 읽고 기억할 거 세 가지:
- 테스트의 범위(scope)와 크기(size)는 별개야 — fake로 크기를 줄이면서 범위를 유지하는 게 핵심이고, 테스트 더블 우선순위는 실제 구현 > fake > stub > mock이야.
- 카나리 배포 + 피처 플래그로 배포와 릴리스를 분리해 — 코드를 안전하게 배포하고, 기능을 점진적으로 활성화하는 거지.
- 빠른 롤백이 안전망이야 — 테스팅이 모든 걸 잡을 수 없으니까, 문제 감지 시 즉시 되돌릴 수 있어야 해.