Nari

LevelUp Piano — MIDI 피아노 연습 앱 · 블로그

보이게 만들고, 안전하게 배포하기 — 옵저버빌리티와 무중단 배포

블로그 목록
기능 소개2026-06-27
운영옵저버빌리티배포인프라
3신호 (지표·로그·트레이스)
4겹배포 안전망
자동smoke 실패 → 롤백
무중단롤링 배포

안 보이면 못 고친다

작게 시작한 앱이라도, 실제 사용자가 붙는 순간 "지금 서버가 괜찮은가?"라는 질문에 답할 수 있어야 합니다. 문제가 생겼을 때 로그를 뒤늦게 뒤지는 대신, 평소에 보이게 만들어 두는 것이 옵저버빌리티입니다.

지표·로그·트레이스 한 곳으로

백엔드에 관측 에이전트를 붙여 지표(metrics)·로그(logs)·트레이스(traces) 를 수집하고, 이를 대시보드로 모읍니다(Grafana 계열 + OpenTelemetry). 대시보드에서는 API p95 지연, 5xx 비율, 요청량, DB 연결 상태, 메모리를 봅니다. 트레이스는 점수 제출처럼 DB 쓰기와 외부 저장소 접근이 섞인 요청에서 병목 구간을 찾는 데 씁니다. 앱에서 일어나는 사용자 행동 이벤트도 배치로 백엔드에 보내, 제품 판단의 근거로 씁니다.

헬스 체크 엔드포인트도 공개해 두어, 배포 자동화와 외부 모니터링이 "지금 살아 있나"를 언제든 물어볼 수 있게 했습니다.

배포는 무섭다 — 그래서 4겹 안전망

1 · Preflightcompile · test · image2 · Rolling deployzero-downtime3 · Smoke testhit core flows✓ pass — live✗ fail → rollback이전 릴리스로 자동 복귀
배포 파이프라인 — preflight로 미리 걸러내고, 롤링 배포 후 smoke, 실패하면 이전 릴리스로 자동 복귀

혼자 운영하는 서버에 배포하는 건 늘 조마조마합니다. 그래서 배포를 한 줄 명령이 아니라 여러 겹의 게이트를 지나는 파이프라인으로 만들었습니다.

  1. Preflight — 컴파일·테스트·커버리지·이미지 빌드·필수 설정 존재 여부를 배포 전에 검증합니다. 하나라도 실패하면 프로덕션을 건드리기 전에 멈춥니다.
  2. 현재 버전 기억 — 문제 시 되돌아갈 지점을 저장합니다.
  3. 롤링 배포 — 새 인스턴스가 헬스 체크를 통과한 뒤에야 기존 인스턴스를 내려, 무중단으로 교체합니다.
  4. Smoke 테스트 — 배포 직후 핵심 흐름을 실제로 호출합니다: 헬스 체크, 인증(토큰 갱신), 카탈로그 조회, 점수 제출, 파일 업로드 presign 발급.
  5. 실패 시 자동 롤백 — smoke가 실패하거나 헬스 체크가 타임아웃되면, 2번에서 저장한 이전 릴리스로 자동 복귀합니다.

핵심은 "실패를 사람이 발견하기 전에, 자동으로 되돌린다"입니다.

💡 Insight

1인 운영의 안전망은 영웅적 대응이 아니라 자동화다 — 실패를 사람이 발견하기 전에 파이프라인이 스스로 되돌린다.

예컨대 컴파일은 되지만 점수 제출 경로를 깨뜨리는 변경이 나갔다고 해봅시다. 사용자가 항의하기 전에 smoke의 점수 제출 호출이 실패하고, 파이프라인이 곧바로 이전 버전으로 되돌립니다 — 이게 이 안전망이 막도록 설계된 종류의 사고입니다.

DB 스키마도 안전하게

데이터베이스 변경은 특히 되돌리기 어렵습니다. 그래서 마이그레이션 도구로 스키마 변경을 버전 관리하고, 앱이 뜰 때 자동 적용되도록 했습니다. 컬럼 추가 같은 변경은 기존 코드와 호환되게(덧붙이는 방향으로) 설계해, 배포 순서에 따른 사고를 줄였습니다.

리소스는 넉넉하되 낭비 없이

관측 스택은 공짜가 아닙니다. 에이전트도 메모리를 먹습니다. 그래서 앱과 관측 도구가 함께 도는 환경의 리소스를 실제 사용량에 맞춰 잡되, 여유(헤드룸)를 두어 급증에도 견디게 했습니다. "보이게 만드는 도구가 서비스를 방해하지 않게" 하는 균형입니다.

마치며

옵저버빌리티와 안전한 배포는 화려한 기능은 아닙니다. 사용자는 이걸 직접 보지 못합니다. 하지만 밤에 두 다리 뻗고 자게 해주는 건 이 부분입니다. 보이게 만들고, 자동으로 검증하고, 실패하면 스스로 되돌리게 — 1인 개발일수록 이 자동화가 곧 안심이자 지속 가능성이었습니다.