Chapter 7

마이크로서비스, 투명성, 릴리스

  • 7.1 12-Factor App
  • 7.2 컨테이너와 불변 인프라
  • 7.3 마이크로서비스의 빛과 그림자
  • 7.4 클라우드 네이티브 설계
  • 7.5 투명성이 중요한 이유
  • 7.6 로깅 전략
  • 7.7 메트릭과 모니터링
  • 7.8 알림과 대시보드
  • 7.9 지속적 배포와 릴리스 파이프라인
  • 7.10 카나리 릴리스와 점진적 롤아웃
  • 7.11 기능 플래그와 실험
  • 7.12 적응형 시스템과 카오스 엔지니어링

현대 프로덕션은 마이크로서비스, 투명성, 지속적 릴리스가 하나로 엮여 돌아가. 코드를 넘어 시스템 전체의 생애주기를 설계하는 이야기야.

클라우드 환경에서 잘 돌아가는 앱의 특성은 12-Factor App이 정확히 설명해. 무상태 프로세스, 설정 외부화, 의존성 명시적 선언, 빌드/릴리스/실행 분리, 로그를 이벤트 스트림으로 취급 — 이것들이 컨테이너와 클라우드에서 잘 돌아가는 앱의 조건이거든. 컨테이너는 "내 로컬에서는 되는데?" 문제를 해결하고, 초 단위로 시작해서 스케일 아웃에 유리하고, 프로세스와 파일 시스템을 격리해줘. 여기에 **불변 인프라(Immutable Infrastructure)**까지 더하면 — 서버에 SSH로 접속해서 설정을 고치는 게 아니라, 새 이미지를 빌드하고 기존 서버를 교체하는 방식이야. 수동 변경은 추적이 어렵고 서버 간 불일치(configuration drift)를 만들거든.

마이크로서비스는 독립 배포, 기술 선택의 자유, 장애 격리, 팀 자율성 같은 장점이 있어. 근데 그 뒤에는 분산 시스템의 복잡성이 따라와. 네트워크 호출, 지연, 부분 장애, 데이터 일관성 — 모노리스에서는 없던 문제들이야. 서비스가 50개면 모니터링, 로깅, 배포, 장애 대응도 50배 복잡해지고, 서비스 간 통합 테스트는 극도로 어려워. 저자의 조언은 명확해 — 모노리스에서 감당 못 하는 규모가 됐을 때 전환하는 거지, 처음부터 마이크로서비스로 시작하는 건 대부분 오버엔지니어링이라고.

클라우드 네이티브 설계는 클라우드의 특성을 적극 활용하는 거야. 인스턴스는 언제든 죽을 수 있으니 상태를 서버에 저장하면 안 되고, 수평 확장이 기본이고, API로 모든 걸 자동화하고, 비용은 사용량에 비례하니 필요할 때 늘리고 줄이면 돼. 자동 스케일링, 서비스 디스커버리, 헬스체크 기반 자가 치유, Infrastructure as Code — 이런 것들이 현대 프로덕션의 기본이 됐어.

이렇게 분산된 시스템을 운영하려면 **투명성(Transparency)**이 필수야. 프로덕션에서 뭔가 잘못되고 있을 때, 그걸 아는 게 첫 번째 단계잖아. 근데 현실에서는 모니터링이 없어서 장애가 터지고 나서야 아는 경우가 허다해. 투명성은 장애 조기 감지, 추세 파악, 사후 분석, 정상 상태 파악을 가능하게 해줘. 특히 정상이 뭔지 알아야 비정상을 감지할 수 있다는 게 핵심이야 — 베이스라인 없이는 아무것도 판단할 수 없거든.

로깅은 투명성의 기본인데, "그냥 많이 남기면 되지"는 틀린 접근이야. **구조화된 로그(Structured Logging)**로 파싱과 검색을 쉽게 하고, 하나의 요청이 여러 서비스를 거칠 때 **상관 ID(Correlation ID)**로 흐름을 추적하고, 로그 레벨을 구분해서 프로덕션에서는 INFO 이상만 남기되 필요할 때 동적으로 DEBUG를 켤 수 있게 해야 해. 로그 메시지도 "Error code 47293"이 아니라 "Failed to connect to payment service at 10.0.1.5:8080 after 3 retries" 같이 사람이 읽을 수 있게 써야 하고. 너무 많은 로그는 디스크를 채우고, 민감 정보가 찍히면 보안 사고고, 로그 로테이션 안 하면 서버가 죽어.

**메트릭(Metrics)**은 "지금 상태가 어떤가"를 말해줘. 비즈니스 메트릭(분당 주문 수)이 가장 중요하고, 애플리케이션 메트릭(응답 시간, 에러율), 인프라 메트릭(CPU, 메모리), 미들웨어 메트릭(커넥션 풀 사용률, 캐시 히트율)이 뒤따라. **RED(Rate, Errors, Duration)**는 서비스 모니터링의, **USE(Utilization, Saturation, Errors)**는 인프라 모니터링의 기본 프레임워크야. 메트릭을 수집하는 것만으로는 부족하고 거기에 반응해야 하는데, 알림은 행동 가능한(actionable) 것만 보내야 해. 알림 피로(alert fatigue)가 진짜 장애를 놓치게 만드는 실질적 위험이거든. 모니터링은 사후 대응이 아니라 사전 예방 도구야 — "지금은 괜찮지만 이 추세면 2주 후에 디스크가 찬다" 같은 통찰을 주는 게 좋은 모니터링이야.

투명성을 확보했으면 이제 릴리스를 이야기하자. 역설적으로 들리지만 — 릴리스가 아프면, 더 자주 해. 배포를 자주 하면 각 배포의 변경 범위가 작아지고, 문제가 생겨도 원인 파악이 쉬워지고, 롤백 비용이 낮아져. 3개월치 변경을 롤백하는 것과 어제 변경을 롤백하는 건 완전히 다르잖아. 배포가 일상이 되면 두려움도 줄어들어 — 팀의 배포 근육이 단련되는 거지.

**카나리 릴리스(Canary Release)**는 위험을 제한하는 핵심 전략이야. 전체 서버 중 5%에 신버전을 먼저 배포하고, 에러율, 응답 시간, 비즈니스 메트릭을 모니터링하면서 이상 없으면 25%, 50%, 100%로 확대해. 심각한 버그가 있어도 5%만 영향받고, 즉시 롤백할 수 있어. 내부 직원부터, 베타 사용자, 트래픽 적은 지역부터 — 이런 점진적 롤아웃은 카나리를 더 정교하게 한 거야. **다크 런칭(Dark Launching)**도 강력한 기법이야. 새 검색 엔진을 배포하되 사용자에게는 기존 결과를 보여주면서, 내부적으로 새 엔진도 돌려서 성능과 정확도를 비교하는 거지. 사용자 영향 없이 검증할 수 있어.

마지막은 적응형 시스템(Adaptive System) — 환경 변화에 자동으로 대응하는 시스템이야. 자동 스케일링, 헬스체크 기반 자가 치유, 런타임에 타임아웃이나 서킷 브레이커 임계치를 바꿀 수 있는 동적 설정, 에러율이 올라가면 트래픽을 줄이는 피드백 루프 — 이것들을 갖추면 시스템이 스스로 적응해. 그리고 **카오스 엔지니어링(Chaos Engineering)**으로 이게 정말 동작하는지 검증해야 해. Netflix의 Chaos Monkey가 프로덕션에서 랜덤하게 인스턴스를 죽이는 이유가 뭐냐면, 서킷 브레이커가 정말 동작하는지, 페일오버가 정말 되는지는 실제로 해봐야 알기 때문이야. 소프트웨어는 한 번 만들고 끝이 아니야. 모니터링하고, 실험하고, 개선하고, 다시 배포하는 순환 — 프로덕션은 시작이지 끝이 아니거든.


정리

7장 읽고 기억할 거 세 가지:

  1. 마이크로서비스는 문제를 해결하는 게 아니라 옮겨 — 코드 복잡성이 운영 복잡성으로 변하니까, 투명성(로깅, 메트릭, 모니터링)이 필수야.
  2. 릴리스가 아프면 더 자주 해 — 카나리 릴리스로 위험을 제한하고, 점진적 롤아웃으로 검증한 후 확대해.
  3. 카오스 엔지니어링으로 복원력을 검증해 — 서킷 브레이커, 페일오버, 자동 스케일링이 정말 동작하는지는 실제로 장애를 주입해봐야 알아.