이 문서를 통해 아래 질문들에 답할 수 있게 됩니다.

  • 팀 서비스에서 timeout, retry, health, trace, metric을 왜 공통 운영 계약으로 관리해야 하는가?
  • 장애 때 어느 계층 로그부터 볼지 팀이 미리 정하려면 어떤 문서와 dashboard가 필요한가?
  • 배포 전후 네트워크 관점의 검증 기준은 무엇인가?

개요

팀 서비스는 개인의 기억으로 운영하면 안 된다. 한 명은 NGINX timeout을 알고, 한 명은 Spring timeout을 알고, 한 명은 외부 API retry를 알고 있으면 장애 때 지식이 흩어진다. 팀 운영 기준은 이 지식을 한 곳에 모아 “누구나 같은 순서로 확인할 수 있게” 만드는 것이다.

팀 수준에서 가장 중요한 것은 공통 계약이다. timeout, retry, health, request id, metric, 배포 검증, rollback 기준이 문서화되어 있으면 장애 대응 속도와 품질이 달라진다.

왜 백엔드 개발자가 알아야 하는가

팀 서비스에서 백엔드 개발자는 코드 기능뿐 아니라 운영 신호도 제공해야 한다.

  • 앱이 request id를 만들지 않으면 proxy/LB 로그와 연결이 어렵다.
  • readiness가 부정확하면 인프라가 traffic을 보내도 되는 target을 판단할 수 없다.
  • timeout이 문서화되지 않으면 504가 났을 때 누가 먼저 끊었는지 모른다.
  • retry 정책이 흩어지면 외부 API 장애 때 전체 서비스가 흔들린다.
  • 배포 후 smoke test가 없으면 장애를 사용자가 먼저 발견한다.

팀 협업은 “서로 잘하자”가 아니라 관찰 가능한 계약을 만드는 일이다.

요청 흐름에서의 위치

팀 운영 기준은 요청 경로 전체를 가로지른다.

Client
→ CDN / WAF
→ LB / Gateway
→ Proxy
→ Application
→ DB / Cache / External API
→ Logs / Metrics / Traces

각 계층의 owner는 다를 수 있지만, 장애는 계층 사이에서 발생한다. 그래서 공통 식별자와 공통 시간대, 공통 dashboard가 필요하다.

원리

팀이 합의할 운영 계약은 다음과 같다.

영역팀 합의 내용없을 때 생기는 문제
Timeoutclient/proxy/LB/app/DB/API 값과 순서누가 먼저 끊었는지 모름
Retry대상 exception/status, 횟수, backoff, idempotencyretry storm, 중복 처리
Healthliveness/readiness 의미와 dependency 포함 범위배포 직후 502/503
Request ID생성 위치, 헤더명, 로그 필드명로그 연결 실패
MetricsRED/USE, p95/p99, saturation, dependency평균만 보고 장애 누락
Deploycanary, draining, smoke test, rollback사용자 선발견
Runbook장애 유형별 첫 확인 순서담당자 경험 의존

운영 계약은 한 번 쓰고 끝나는 문서가 아니라 배포와 장애를 거치며 업데이트되는 팀의 기억이다.

팀 서비스 체크리스트

최소한 아래 항목은 서비스별로 있어야 한다.

Ingress:
  domain:
  CDN/WAF:
  LB/Gateway:
  proxy:
Application:
  health endpoint:
  readiness criteria:
  request id header:
  access log fields:
Timeout:
  proxy:
  app request:
  HTTP client:
  DB query:
Retry:
  allowed methods/status:
  idempotency:
  backoff:
Observability:
  dashboard:
  alert:
  trace search:
Deploy:
  smoke test:
  rollback:

이 템플릿이 있으면 신규 팀원이 와도 장애 대응의 출발선이 맞춰진다.

실무에서 자주 만나는 문제

  • 팀마다 timeout 기본값이 다르다.
    • 하나의 요청이 여러 팀 서비스와 proxy를 지나면 timeout 순서가 깨진다.
    • service catalog나 runbook에 timeout inventory를 둔다.
  • request id가 계층 사이에서 끊긴다.
    • CDN, LB, proxy, app 로그를 같은 요청으로 묶지 못한다.
    • 헤더 이름과 overwrite 정책을 합의한다.
  • readiness와 liveness가 같은 의미로 쓰인다.
    • 살아 있지만 준비되지 않은 pod에 traffic이 들어간다.
    • readiness는 traffic 수신 가능성을 의미하도록 설계한다.
  • 장애 보고 형식이 없다.
    • 매번 발생 시각, URL, status, request id를 다시 물어본다.
    • 보고 템플릿을 고정한다.

디버깅 방법

팀 서비스의 장애 확인은 runbook으로 시작한다.

1. alert 이름과 dashboard 확인
2. 영향 범위와 endpoint 확인
3. edge/LB/proxy/app 중 마지막 로그 위치 확인
4. request id로 trace 검색
5. 최근 배포와 config 변경 확인
6. dependency latency와 pool 상태 확인
7. 완화 조치와 rollback 여부 결정

배포 전후에는 smoke test와 dashboard를 같이 본다.

BASE_URL=https://api.example.com
curl -fsS "$BASE_URL/health" >/dev/null
curl -sS -o /dev/null -w "code=%{http_code} first_byte=%{time_starttransfer} total=%{time_total}\n" "$BASE_URL/api/orders"

smoke test는 단순 200 확인이 아니라 핵심 route, auth, dependency, latency를 대표해야 한다.

코드로 확인하기

장애 보고 템플릿은 팀의 공통 인터페이스다.

증상:
발생 시각:
영향 범위:
URL / Method:
Status / Response Header:
Request ID / Trace ID:
curl timing:
마지막으로 확인된 로그 위치:
최근 배포 / 설정 변경:
완화 후보:
필요한 확인 요청:

팀 서비스에서는 이 템플릿이 Slack, Jira, Notion, incident tool 어디에 있든 쉽게 꺼낼 수 있어야 한다.

주니어가 자주 하는 오해

  • 운영 기준은 인프라 팀 문서라고 생각한다.
    • app의 health, timeout, request id, graceful shutdown은 백엔드가 제공해야 하는 계약이다.
  • dashboard는 SRE만 보는 것이라고 생각한다.
    • 백엔드 개발자도 자기 서비스 p99, 5xx, dependency latency, pool pending을 읽을 수 있어야 한다.
  • retry는 코드에서만 보면 된다고 생각한다.
    • gateway/service mesh/client retry가 함께 있을 수 있다.
  • 배포 성공은 CI green이라고 생각한다.
    • 사용자 경로 smoke test와 dashboard 안정까지 봐야 한다.

시니어의 설계 판단 기준

  • 서비스 onboarding 문서에는 요청 경로와 운영 계약이 포함되어야 한다.
  • runbook은 장애 후 업데이트되어야 하며 owner가 있어야 한다.
  • alert는 action 가능해야 한다. “뭔가 느림”보다 “payment API p99와 pool pending 증가”가 낫다.
  • canary와 rollback 기준은 배포 전에 정해져 있어야 한다.
  • retry, timeout, pool, breaker는 dependency별로 리뷰한다.

인프라 협업 포인트

  • 인프라 팀과 request id 헤더명, proxy overwrite 정책, log retention을 맞춘다.
  • 배포 전략은 readiness, graceful shutdown, connection draining과 함께 설계한다.
  • WAF/rate limit 변경은 정상 사용자 burst와 공격 traffic 구분 기준을 공유한다.
  • 장애 시 escalation 기준과 연락 채널을 정한다.

실전 팁

  • timeout inventory는 표 하나로 시작해도 충분하다.
  • 장애방 pinned message에 보고 템플릿과 dashboard 링크를 둔다.
  • 배포 체크리스트에는 curl smoke test 결과를 붙인다.
  • 팀 회고에서 “다음에 5분 빨리 알 수 있는 지표”를 하나씩 추가한다.

위험 신호!

  • request id가 app log에만 있고 proxy/LB에는 없다.
  • timeout 값이 코드, config, proxy에 흩어져 있고 owner가 없다.
  • readiness가 항상 200이다.
  • 배포 후 사용자가 먼저 장애를 발견한다.
  • runbook이 오래되어 현재 인프라 구조와 다르다.

확인 질문

확인 질문

  • 팀 서비스에서 timeout inventory가 필요한 이유는 무엇인가?
    • 여러 계층 timeout의 순서를 알아야 누가 먼저 끊었고 어떤 자원이 계속 점유되는지 판단할 수 있기 때문이다.
  • request id 전파가 중요한 이유는 무엇인가?
    • CDN/LB/proxy/app/trace 로그를 같은 요청으로 연결해야 장애 위치를 좁힐 수 있기 때문이다.
  • readiness와 liveness를 구분해야 하는 이유는 무엇인가?
    • process 생존 여부와 traffic을 받아도 되는 준비 상태는 다르기 때문이다.

참고 문서