Web-Network 실전 가이드북

이 문서의 목적

이 문서는 Web-Network 아래의 85개 문서를 실제 개발/운영 상황에서 다시 찾아가게 만드는 안내서다. 네트워크 개념을 다시 요약하려는 문서가 아니라, 장애 알림을 받았거나 API 계약을 설계하거나 인프라 팀과 변경을 맞춰야 할 때 “무엇을 보고, 어떤 질문을 하고, 어느 문서로 돌아갈지”를 빠르게 잡기 위한 지도다.

  • 먼저 상황을 읽는다.
  • 증거를 어떤 계층으로 나눌지 생각한다.
  • 찾아볼 문서로 돌아가 상세 원리와 명령을 확인한다.
  • 마지막에는 한 문장 판단 기준만 가져간다.

먼저 보는 빠른 길찾기

지금 마주친 상황먼저 볼 Case핵심 관찰
간헐적 504, timeout, 느린 APICase 1, Case 5, Case 16curl -w, p95/p99, pool pending, upstream time
배포 후 일부 사용자만 이전 화면을 봄Case 2, Case 14, Case 19DNS TTL, CDN Age, cache key, purge timeline
브라우저에서만 로그인/요청 실패Case 3, Case 18Set-Cookie, Cookie, Origin, preflight, DevTools
모바일/파트너만 HTTPS 실패Case 4, Case 15SNI, chain, truststore, ALPN, TLS policy
외부 API 장애가 전체 장애로 번짐Case 5, Case 12timeout 정렬, retry budget, idempotency, breaker
업로드/다운로드/장기 연결이 자주 깨짐Case 6, Case 7body limit, buffering, idle timeout, draining
LB 502/503/504와 app log 부재Case 8, Case 16응답 주체, target health, proxy/LB access log
이벤트 전 capacity와 병목이 걱정됨Case 9, Case 10headroom, load test, shared resource, rare limit
도메인, 인증서, 관리자 경계를 설계함Case 11, Case 17DNS, cookie scope, TLS termination, 운영 기준
인프라 팀과 변경/장애를 맞춰야 함Case 13, Case 16, Case 20요청 정보, owner, rollback, postmortem action
세부 HTTP 계약이 실제 코드에서 흔들림보충 Case 1, 보충 Case 2, 보충 Case 7Accept, Content-Type, ETag, If-Match, 민감 header
고급 운영 선택을 인프라와 맞춰야 함보충 Case 3, 보충 Case 4, 보충 Case 5, 보충 Case 6, 보충 Case 8HTTP/3, mTLS, WebClient timeout, WAF/LB, rare limit runbook

실전 Case

Case 1. 주문 API가 가끔 504를 내고, 서버 CPU는 낮다

상황

  • 주문 API에서 사용자는 가끔 timeout을 본다.
  • app CPU는 낮고, 평균 응답 시간은 괜찮아 보인다.
  • NGINX나 LB에는 504가 찍히지만 application log에는 일부 요청만 남는다.

관찰할 증거 또는 확인할 단서

  • curl -w로 DNS/TCP/TLS/first byte/total time을 분리한다.
  • LB/proxy의 upstream_response_time, upstream_status, app trace의 DB acquire time을 본다.
  • DB pool active/pending, HTTP client pool pending, retry count, p95/p99를 함께 본다.

먼저 생각해보기

  • 요청은 앱까지 도달했는가, 아니면 proxy/LB에서 timeout이 났는가?
  • 느린 구간은 query 실행인가, pool acquire인가, 외부 API 호출인가?
  • timeout 값은 client, LB, proxy, app, downstream 순서로 정렬되어 있는가?

찾아볼 문서

실전 행동

  • 504가 생성된 계층을 먼저 찾는다.
  • trace에서 DB acquire, query, external call, serialization 시간을 분리한다.
  • timeout을 늘리기 전에 pool pending과 retry 증가가 있는지 확인한다.

정리

  • CPU가 낮은 장애는 “아무 일도 안 하는 서버”가 아니라 “어딘가에서 기다리는 서버”일 수 있다.

가져갈 한 문장

  • 느린 요청은 CPU보다 먼저 queue와 timeout의 위치를 찾는다.

Case 2. 배포했는데 일부 사용자만 이전 화면을 계속 본다

상황

  • 배포는 성공했고 origin 서버는 새 버전을 응답한다.
  • 일부 사용자는 예전 HTML이나 JS를 계속 받는다.
  • 새 API와 오래된 asset 조합 때문에 프론트 오류가 난다.

관찰할 증거 또는 확인할 단서

  • Cache-Control, Age, ETag, Last-Modified, CDN cache status를 본다.
  • CDN 응답과 origin 응답을 같은 URL로 비교한다.
  • 배포 시각, purge 요청 시각, edge별 반영 시각을 timeline으로 둔다.

먼저 생각해보기

  • 브라우저 cache, CDN edge, origin, application cache 중 어디의 응답인가?
  • HTML과 asset의 TTL 전략이 서로 맞는가?
  • purge로 해결할 문제인가, versioned URL로 피해야 할 문제인가?

찾아볼 문서

실전 행동

  • 사용자가 받은 응답의 cache header를 먼저 확보한다.
  • CDN과 origin을 분리해 비교한다.
  • asset은 fingerprint로, HTML은 짧은 TTL 또는 재검증으로 가는지 점검한다.

정리

  • 캐시 장애는 “안 바뀐다”가 아니라 “어느 cache key의 어떤 응답이 재사용되는가”로 바꿔야 좁혀진다.

가져갈 한 문장

  • 배포와 cache는 purge 버튼이 아니라 version, TTL, compatibility의 조합으로 안전해진다.

Case 3. API는 200인데 브라우저에서는 로그인된 상태가 아니다

상황

  • 로그인 응답은 200이고 Set-Cookie도 내려간 것처럼 보인다.
  • 다음 요청에 cookie가 붙지 않거나, preflight에서 막힌다.
  • 서버 간 curl은 성공하지만 브라우저 fetch는 실패한다.

관찰할 증거 또는 확인할 단서

  • DevTools에서 cookie rejected reason을 본다.
  • 실제 요청의 Cookie, Origin, Access-Control-*, Set-Cookie를 확인한다.
  • OPTIONS preflight와 실제 요청을 분리해서 본다.

먼저 생각해보기

  • 쿠키가 저장되지 않았는가, 저장됐지만 전송되지 않았는가?
  • CORS가 응답 노출을 막는가, preflight가 본 요청을 막는가?
  • SameSite, Secure, Domain, Path, credential fetch 설정이 서로 맞는가?

찾아볼 문서

실전 행동

  • Set-Cookie 수신, cookie 저장, cookie 전송, CORS 노출을 각각 다른 단계로 본다.
  • credential CORS는 allowlist, Allow-Credentials, Vary: Origin, SameSite를 세트로 점검한다.
  • Spring Security filter 이전에 CORS 처리가 되는지 확인한다.

정리

  • 브라우저 보안 문제는 서버가 200을 냈는지만 봐서는 풀리지 않는다.

가져갈 한 문장

  • 브라우저 인증 장애는 Set-CookieCookie 사이의 빈칸을 증거로 채우는 작업이다.

Case 4. 모바일 앱이나 파트너사만 HTTPS 호출에 실패한다

상황

  • 최신 브라우저에서는 정상 접속된다.
  • 특정 모바일 버전, 오래된 Java client, 파트너사 환경에서만 TLS 오류가 난다.
  • 앱 서버에는 요청 로그가 없다.

관찰할 증거 또는 확인할 단서

  • openssl s_client -servername ... -showcerts로 SNI와 chain을 본다.
  • curl -v --http2time_appconnect로 TLS 구간을 분리한다.
  • Java client의 PKIX path building failed, hostname mismatch, ALPN 협상 실패를 확인한다.

먼저 생각해보기

  • TLS가 어느 구간에서 종료되는가?
  • 실패 client의 truststore, TLS version, cipher, SNI 지원은 무엇인가?
  • 인증서 발급 성공과 LB/CDN/proxy 반영 성공을 혼동하고 있지 않은가?

찾아볼 문서

실전 행동

  • SNI 포함/미포함 결과를 비교한다.
  • chain, SAN, issuer, 만료일, ALPN 결과를 기록한다.
  • 인프라 팀에는 hostname, client runtime, 발생 시각, openssl 결과를 같이 보낸다.

정리

  • TLS 장애는 “사이트가 안 열린다”가 아니라 client 종류와 termination 구간에 따라 달라지는 검증 실패다.

가져갈 한 문장

  • HTTPS 실패에서 앱 로그가 없으면 TLS handshake 이전의 증거부터 모은다.

Case 5. 외부 API 장애가 우리 서비스 전체 장애로 번진다

상황

  • 추천 API나 결제 API가 느려진 뒤 우리 서비스의 전체 p99가 같이 무너진다.
  • retry가 늘고 thread나 connection이 오래 붙잡힌다.
  • 일부 기능 장애가 핵심 API 장애로 번진다.

관찰할 증거 또는 확인할 단서

  • external call latency, timeout, retry attempt, circuit breaker open count를 본다.
  • HTTP client pool active/idle/pending을 본다.
  • retry 대상 method가 멱등인지, idempotency key가 있는지 확인한다.

먼저 생각해보기

  • timeout은 dependency별로 분리되어 있는가?
  • retry가 recovery를 돕는가, traffic을 증폭하는가?
  • fallback은 정확성을 해치지 않는가?

찾아볼 문서

실전 행동

  • 외부 API별 timeout, retry, breaker, bulkhead를 분리한다.
  • non-idempotent 요청은 자동 retry 전에 중복 처리 계약을 확인한다.
  • 부가 기능은 degraded response나 fallback으로 핵심 기능과 분리한다.

정리

  • resilience 설정은 장애를 없애는 장식이 아니라 장애가 퍼지는 길을 좁히는 설계다.

가져갈 한 문장

  • 외부 API 호출은 timeout, retry, pool, breaker를 하나의 계약으로 본다.

Case 6. 파일 업로드가 413, 502, 504를 오가며 실패한다

상황

  • 작은 파일은 성공하지만 큰 파일은 proxy에서 413이 나거나 중간에 끊긴다.
  • app log에는 요청이 없거나, body를 읽다가 timeout이 난다.
  • 사용자에게는 그냥 업로드 실패로 보인다.

관찰할 증거 또는 확인할 단서

  • Content-Length, Transfer-Encoding, multipart boundary를 확인한다.
  • NGINX client_max_body_size, proxy buffering, read timeout을 확인한다.
  • LB/proxy/app 중 어느 계층이 응답을 만들었는지 본다.

먼저 생각해보기

  • body size 제한은 CDN, LB, proxy, app 중 어디에 있는가?
  • streaming이 필요한 요청을 proxy가 buffering하고 있지 않은가?
  • 긴 업로드를 동기 요청으로 유지해야 하는가, 비동기 처리로 바꿔야 하는가?

찾아볼 문서

실전 행동

  • 413이면 body limit부터 찾고, 504면 upstream 처리 시간과 timeout 정렬을 본다.
  • 업로드 endpoint는 일반 API와 timeout/buffer 정책을 분리한다.
  • 큰 파일은 pre-signed URL이나 비동기 처리 전환도 검토한다.

정리

  • 업로드 장애는 애플리케이션 로직보다 HTTP body와 proxy 경계에서 먼저 갈라지는 경우가 많다.

가져갈 한 문장

  • 큰 body는 API 로직 전에 framing, buffering, size limit을 통과해야 한다.

Case 7. SSE나 WebSocket이 1분쯤 지나면 조용히 끊긴다

상황

  • 로컬에서는 괜찮은데 운영에서는 SSE나 WebSocket이 일정 시간 뒤 끊긴다.
  • 서버는 에러를 크게 남기지 않는다.
  • 사용자는 알림이 가끔 사라진다고 말한다.

관찰할 증거 또는 확인할 단서

  • LB, proxy, app, client idle timeout 값을 나열한다.
  • WebSocket upgrade header, SSE buffering, heartbeat 주기를 본다.
  • draining 중 장기 연결이 어떻게 종료되는지 확인한다.

먼저 생각해보기

  • 연결이 idle로 판단되는 계층은 어디인가?
  • heartbeat가 proxy/LB idle timeout보다 짧은가?
  • 배포 중 연결을 어떻게 끊고 재연결하게 할 것인가?

찾아볼 문서

실전 행동

  • 연결 유형별로 timeout chain을 표로 만든다.
  • SSE는 buffering off와 heartbeat를, WebSocket은 upgrade와 reconnect/backoff를 확인한다.
  • 배포 시 draining과 client reconnect 동작을 함께 테스트한다.

정리

  • 장기 연결은 연결 유지보다 연결이 끊긴 뒤 회복하는 계약이 더 중요할 때가 많다.

가져갈 한 문장

  • 장기 연결 장애는 idle timeout, buffering, draining, reconnect를 한 줄로 세워서 본다.

Case 8. Cloud LB가 502를 반환하는데 app log에는 아무것도 없다

상황

  • 사용자는 502를 보고, app log에는 해당 request id가 없다.
  • LB target health가 흔들리거나 특정 target group만 실패한다.
  • proxy access log에는 upstream 관련 값이 남는다.

관찰할 증거 또는 확인할 단서

  • LB access log의 status, target status, target response time을 본다.
  • NGINX upstream_status, upstream_connect_time, upstream_response_time을 확인한다.
  • target health reason, readiness, security group, path rewrite를 같이 본다.

먼저 생각해보기

  • 502는 app이 만든 응답인가, LB/proxy가 만든 응답인가?
  • 요청이 target까지 갔는가, target 선택 전 실패했는가?
  • 최근 배포, health check 변경, upstream path rewrite 변경이 있었는가?

찾아볼 문서

실전 행동

  • response header와 access log로 응답 주체를 먼저 찾는다.
  • target health와 readiness 전환 시각을 배포 timeline에 겹친다.
  • app log가 없다는 사실을 “앱 문제가 아님”이 아니라 “앱 전 단계 증거 필요”로 다룬다.

정리

  • 502는 한 단어가 아니라 proxy/LB가 본 upstream 실패의 여러 얼굴이다.

가져갈 한 문장

  • app log가 없을 때는 마지막으로 요청을 본 계층의 log가 출발점이다.

Case 9. 이벤트 트래픽 전에 capacity가 충분한지 말해야 한다

상황

  • 마케팅 이벤트 전 예상 traffic이 공유된다.
  • “서버 몇 대 더 늘리면 되죠?”라는 질문을 받는다.
  • DB, cache, NAT, DNS, external API quota는 아직 확인되지 않았다.

관찰할 증거 또는 확인할 단서

  • peak RPS, burst, payload 크기, fan-out, retry 정책을 모은다.
  • p95/p99, error rate, queue length, pool pending, external quota를 본다.
  • load test의 traffic mix와 client generator 병목을 확인한다.

먼저 생각해보기

  • app instance 증가가 shared resource 부하를 얼마나 늘리는가?
  • SLO를 깨는 saturation point는 어디인가?
  • overload 때 거절할 요청과 보호할 요청은 무엇인가?

찾아볼 문서

실전 행동

  • capacity inventory를 먼저 만들고, app/DB/cache/NAT/external API 한계를 나란히 적는다.
  • 부하 테스트는 평균 RPS보다 실패 직전 metric snapshot을 남긴다.
  • rate limit, queue limit, traffic shedding 기준을 이벤트 전 합의한다.

정리

  • capacity planning은 서버 대수 계산이 아니라 SLO를 지키는 traffic 범위를 아는 일이다.

가져갈 한 문장

  • scale out 전에 shared resource와 backpressure부터 계산한다.

Case 10. scale out 후에도 장애가 더 빨리 난다

상황

  • app instance를 늘렸는데 DB connection, NAT, DNS, external API timeout이 늘었다.
  • CPU는 넉넉한데 outbound connect timeout과 socket 상태가 이상하다.
  • “서버를 늘렸는데 왜 더 나빠졌지?”라는 질문이 나온다.

관찰할 증거 또는 확인할 단서

  • app instance 수와 pool size 합계를 계산한다.
  • ss -s, file descriptor, TIME_WAIT, conntrack, NAT metric을 본다.
  • DNS resolver QPS, external API quota, DB max connection을 확인한다.

먼저 생각해보기

  • 늘린 것은 app capacity인가, 전체 system capacity인가?
  • shared resource가 scale out의 새 병목이 되었는가?
  • rare limit이 평소에는 숨어 있다가 traffic에서 드러난 것인가?

찾아볼 문서

실전 행동

  • instance 수 증가 전후의 connection 총량을 계산한다.
  • OS/cloud network 한계를 runbook에 있는 명령과 provider metric으로 확인한다.
  • DB/cache/external API owner와 quota 증설 또는 pool 조정을 협의한다.

정리

  • app을 늘리는 일은 downstream과 네트워크 공유 테이블에 더 많은 일을 보내는 일이기도 하다.

가져갈 한 문장

  • scale out은 병목을 없애기보다 다음 병목을 더 잘 보이게 만든다.

Case 11. 새 도메인과 관리자 경계를 설계한다

상황

  • www, api, admin, static 도메인을 어떻게 나눌지 정해야 한다.
  • cookie scope, CORS, TLS 인증서, OAuth callback, WAF 정책이 함께 얽힌다.
  • 개인 프로젝트라도 운영 서비스처럼 보이고 싶다.

관찰할 증거 또는 확인할 단서

  • URL의 scheme/host/path/query가 어느 계층에서 쓰이는지 본다.
  • DNS record, CNAME, CAA, wildcard 인증서 범위를 확인한다.
  • admin 도메인의 cookie, CORS, IP allowlist, auth policy를 분리한다.

먼저 생각해보기

  • 도메인 경계가 인증 경계와 cache 경계를 같이 표현하는가?
  • wildcard나 shared cookie domain이 편하지만 위험하지 않은가?
  • redirect URL과 callback URL은 allowlist로 관리되는가?

찾아볼 문서

실전 행동

  • 도메인별 역할과 인증/캐시/CORS 정책을 한 표로 만든다.
  • admin은 public API와 도메인, cookie, WAF 정책을 분리한다.
  • DNS와 인증서 변경은 rollback record와 검증 명령까지 같이 적는다.

정리

  • 도메인은 예쁜 주소가 아니라 브라우저와 인프라가 공유하는 보안 경계다.

가져갈 한 문장

  • 도메인 설계는 URL, cookie, CORS, TLS, WAF를 함께 결정한다.

Case 12. 결제 요청 재시도와 중복 결제를 막아야 한다

상황

  • 결제 API에서 client timeout이 발생했다.
  • 사용자는 다시 시도했고, 서버는 첫 요청을 이미 처리했을 수도 있다.
  • gateway retry와 client retry가 동시에 켜져 있다.

관찰할 증거 또는 확인할 단서

  • HTTP method와 idempotency key 유무를 확인한다.
  • timeout 후 서버 작업이 계속됐는지 transaction log를 본다.
  • error response에 retry 가능 여부와 Retry-After가 있는지 본다.

먼저 생각해보기

  • 이 요청은 자동 retry해도 안전한가?
  • idempotency key 저장소가 processing/succeeded/failed 상태를 구분하는가?
  • status code와 응답 body가 client 행동을 안내하는가?

찾아볼 문서

실전 행동

  • POST retry는 idempotency key와 결과 재조회 API를 함께 설계한다.
  • 409, 202, 429, 503 같은 응답이 client의 다음 행동을 분명히 하게 한다.
  • gateway retry와 app retry가 곱해지지 않도록 소유권을 정한다.

정리

  • 결제 같은 상태 변경 API에서 네트워크 timeout은 성공/실패가 아니라 “결과를 모르는 상태”다.

가져갈 한 문장

  • 자동 retry보다 먼저 중복 처리 계약을 설계한다.

Case 13. 파트너 API가 WAF나 Gateway에서 막힌다

상황

  • 특정 파트너사 요청만 403, 429, 413으로 실패한다.
  • app log에는 요청이 없거나, gateway log에 rule id가 남는다.
  • 파트너사는 “어제까지 됐다”고 말한다.

관찰할 증거 또는 확인할 단서

  • gateway/WAF rule id, rate limit key, request id, client IP, header size를 본다.
  • X-Forwarded-For chain과 trusted proxy 정책을 확인한다.
  • 차단 응답의 body와 header가 파트너가 이해할 수 있는지 본다.

먼저 생각해보기

  • 차단은 보안 정책인가, quota 초과인가, 잘못된 header/path rewrite인가?
  • IP 기준 제한이 NAT나 proxy 때문에 과도하게 적용됐는가?
  • CORS 문제와 gateway 차단 문제를 섞어 보고 있지 않은가?

찾아볼 문서

실전 행동

  • 차단된 요청의 raw method/path/header/body size와 rule id를 확보한다.
  • gateway에서 처리할 정책과 app에서 처리할 정책을 분리한다.
  • 파트너에게는 재현 가능한 request id와 다음 행동을 주는 응답 계약을 제공한다.

정리

  • gateway/WAF 장애는 앱 코드보다 정책, 신뢰 경계, 관측 위치를 먼저 맞춰야 한다.

가져갈 한 문장

  • 403과 429는 “안 됨”이 아니라 어떤 정책이 어떤 key에 적용됐는지 묻는 신호다.

Case 14. DNS 전환과 Blue-Green 배포를 함께 진행한다

상황

  • 새 인프라로 traffic을 옮기기 위해 DNS, LB target, CDN cache를 함께 바꿔야 한다.
  • 일부 사용자는 old로, 일부 사용자는 new로 들어올 수 있다.
  • rollback도 가능해야 한다.

관찰할 증거 또는 확인할 단서

  • authoritative DNS와 public resolver cache를 비교한다.
  • old/new endpoint health, TLS certificate, CDN cache status를 모두 확인한다.
  • weighted routing, canary, draining, TTL 복구 시점을 기록한다.

먼저 생각해보기

  • old와 new가 동시에 살아 있어도 API와 asset이 호환되는가?
  • DNS TTL을 낮추는 시점과 실제 전환 시점이 분리되어 있는가?
  • LB target draining과 DNS rollback이 충돌하지 않는가?

찾아볼 문서

실전 행동

  • lower TTL, dual-run, switch, observe, restore 단계를 나눈다.
  • old/new 둘 다 smoke test하고 request id와 version header를 남긴다.
  • rollback은 DNS만 되돌리는지, LB target과 CDN cache도 같이 되돌리는지 정한다.

정리

  • 전환 작업은 한 번에 바꾸는 일이 아니라 old와 new가 동시에 맞는 시간을 운영하는 일이다.

가져갈 한 문장

  • DNS 전환은 record 변경보다 dual-run과 rollback 증거가 중요하다.

Case 15. gRPC나 HTTP/2가 운영에서만 이상하게 느리다

상황

  • 로컬에서는 gRPC가 빠른데 운영에서는 HTTP/1.1처럼 동작하거나 연결이 불안정하다.
  • proxy를 지나면 protocol이 바뀌거나 ALPN 협상이 다르게 나온다.
  • HTTP/3를 켰더니 일부 네트워크에서만 실패한다.

관찰할 증거 또는 확인할 단서

  • curl --http2, curl --http3, openssl s_client -alpn 결과를 본다.
  • CDN/LB/proxy/origin 사이 protocol을 각각 확인한다.
  • UDP 443 차단, h3 fallback, gRPC timeout/idle timeout을 본다.

먼저 생각해보기

  • client-edge, edge-origin, origin-app 구간 protocol이 같은가?
  • HTTP/2 multiplexing이나 flow control이 proxy에서 깨지는가?
  • UDP/QUIC은 fallback이 정상인가?

찾아볼 문서

실전 행동

  • protocol 협상 결과를 구간별로 나눈다.
  • gRPC는 h2, ALPN, proxy timeout, max stream 설정을 함께 본다.
  • HTTP/3는 UDP 경로와 h2 fallback을 운영 smoke test에 넣는다.

정리

  • HTTP 버전 문제는 기능 차이보다 연결 모델과 proxy 변환 차이로 나타난다.

가져갈 한 문장

  • “HTTPS 성공”은 HTTP/2, gRPC, HTTP/3 성공을 보장하지 않는다.

Case 16. 장애 첫 10분에 무엇을 모아야 할지 막막하다

상황

  • Slack에 “네트워크 문제 같습니다”라는 말이 올라온다.
  • 상태코드, request id, 영향 범위, 최근 변경이 아직 없다.
  • 여러 팀이 각자 다른 dashboard를 보고 있다.

관찰할 증거 또는 확인할 단서

  • 영향 범위, 첫 발생 시각, request id, status code, response header, 마지막 log 위치를 모은다.
  • DNS/TCP/TLS/HTTP/proxy/app/DB 계층 중 어디까지 도달했는지 표시한다.
  • 최근 배포, DNS/TLS/LB/WAF/CDN 변경을 확인한다.

먼저 생각해보기

  • “왜”보다 “어디까지 갔는가”를 먼저 말할 수 있는가?
  • 응답을 만든 계층과 요청을 마지막으로 본 계층이 같은가?
  • 지금 필요한 것은 원인 단정인가, 완화인가, 영향 범위 축소인가?

찾아볼 문서

실전 행동

  • incident message를 “증상, 영향, 증거, 다음 확인” 네 줄로 바꾼다.
  • request id로 LB/proxy/app log를 연결한다.
  • 원인 후보를 줄이면서 동시에 완화 가능한 경로를 찾는다.

정리

  • 장애 초반에는 정답보다 모두가 같은 증거를 보게 만드는 것이 빠르다.

가져갈 한 문장

  • 네트워크 장애 대응은 추측을 계층별 증거로 바꾸는 작업이다.

Case 17. 개인 프로젝트를 운영 서비스처럼 보이게 만들고 싶다

상황

  • 개인 프로젝트를 공개했고, 이제 포트 하나 연 서버가 아니라 운영 가능한 백엔드처럼 만들고 싶다.
  • 도메인, HTTPS, reverse proxy, health check, access log, 배포 smoke test가 필요하다.
  • 비용은 작게 유지하고 싶다.

관찰할 증거 또는 확인할 단서

  • public URL, DNS record, TLS certificate, NGINX access log, app health endpoint를 확인한다.
  • app port가 인터넷에 직접 열려 있는지 본다.
  • 배포 후 smoke test script가 있는지 확인한다.

먼저 생각해보기

  • 사용자가 들어오는 실제 request path를 설명할 수 있는가?
  • 장애가 났을 때 최소한 request id, status, response time을 볼 수 있는가?
  • 직접 운영과 managed service 사이의 비용/학습 trade-off는 무엇인가?

찾아볼 문서

실전 행동

  • domain, HTTPS, reverse proxy, /healthz, access log, smoke test를 먼저 갖춘다.
  • app port는 private으로 두고 proxy만 public entry로 둔다.
  • 장애 노트와 간단한 post-deploy check를 남긴다.

정리

  • 개인 프로젝트의 수준은 기능 수보다 장애를 좁힐 수 있는 증거에서 드러난다.

가져갈 한 문장

  • 작은 서비스도 request path와 운영 증거를 갖추면 갑자기 단단해진다.

Case 18. 캐시를 붙였더니 다른 사용자 데이터가 보일까 걱정된다

상황

  • CDN을 붙이고 나니 응답이 빨라졌다.
  • 하지만 사용자별 API, CORS 응답, 압축 응답이 섞일 가능성이 걱정된다.
  • 보안 리뷰에서 cache policy를 설명해야 한다.

관찰할 증거 또는 확인할 단서

  • Cache-Control, Vary, Authorization, cookie, CDN cache key를 확인한다.
  • 개인화 endpoint가 public으로 저장되는지 본다.
  • web cache poisoning/deception 가능성이 있는 path와 extension rule을 확인한다.

먼저 생각해보기

  • 이 응답은 공유 cache에 저장되어도 되는가?
  • 같은 URL이라도 origin, user, language, encoding에 따라 응답이 달라지는가?
  • cache HIT율보다 정보 노출 위험이 더 중요한 endpoint는 무엇인가?

찾아볼 문서

실전 행동

  • /assets/*/api/* cache 정책을 분리한다.
  • 인증 응답은 private/no-store 기준으로 보수적으로 시작한다.
  • CDN rule 변경은 보안 리뷰와 smoke test를 함께 둔다.

정리

  • 캐시 성능은 좋은데, 공유 cache에 무엇을 저장할지 정하지 않으면 보안 문제가 된다.

가져갈 한 문장

  • cache key는 성능 키이면서 데이터 격리 키다.

Case 19. 권한을 뺐는데 사용자는 여전히 화면을 본다

상황

  • 관리자가 멤버십이나 권한을 회수했다.
  • DB에는 반영됐지만 사용자 화면은 몇 분 동안 그대로다.
  • CDN, 브라우저 cache, application cache, search index 중 어디가 늦는지 모른다.

관찰할 증거 또는 확인할 단서

  • 권한 변경 DB commit, event 발행, cache purge, edge 반영 시각을 timeline으로 만든다.
  • 같은 URL을 사용자 token으로, cache bypass header와 함께 비교한다.
  • 304, ETag, private/no-store 정책을 확인한다.

먼저 생각해보기

  • 권한 데이터는 stale을 몇 초까지 허용할 수 있는가?
  • cache key가 user/tenant/role 차이를 반영하는가?
  • 권한 회수는 purge로 충분한가, 아예 저장 금지가 맞는가?

찾아볼 문서

실전 행동

  • 권한 변경 데이터는 cache 허용 시간을 제품/보안과 합의한다.
  • 공유 cache 저장 여부와 cache key를 먼저 확인한다.
  • cache 문제를 DB 문제와 분리하기 위해 origin 직접 응답과 edge 응답을 비교한다.

정리

  • 권한 정합성은 성능 최적화보다 사용자 데이터 보호 쪽으로 판단해야 한다.

가져갈 한 문장

  • 권한 데이터의 cache는 HIT율보다 회수 지연 위험을 먼저 본다.

Case 20. 장애가 끝났고, 다음에는 더 빨라지고 싶다

상황

  • 502/504 장애는 완화됐다.
  • 회고에서 “다음에는 더 빨리 알자”가 반복된다.
  • 하지만 action item이 사람의 주의에만 의존한다.

관찰할 증거 또는 확인할 단서

  • timeline, detection time, mitigation time, customer impact, owner를 정리한다.
  • 누락된 log, metric, request id, runbook, alert를 찾는다.
  • 같은 유형이 반복되지 않도록 action item의 완료 조건을 정의한다.

먼저 생각해보기

  • 원인보다 늦어진 이유가 무엇인가?
  • 어떤 증거가 없어서 팀 간 추측이 길어졌는가?
  • action item은 알람, 자동화, runbook, 테스트 중 무엇으로 남길 것인가?

찾아볼 문서

실전 행동

  • 회고 문서에는 “없어서 늦어진 증거”를 반드시 적는다.
  • action item은 owner, 검증 방법, 완료 기준을 가진다.
  • 다음 장애 때 첫 10분에 볼 dashboard와 log query를 runbook으로 남긴다.

정리

  • 좋은 회고는 비난 없이도 다음 장애의 시간을 줄이는 시스템 변경으로 끝난다.

가져갈 한 문장

  • 장애 회고의 성과는 멋진 원인 분석이 아니라 다음 대응 시간을 줄이는 증거 개선이다.

보충 실전 Case

기본 Case 1~20은 전체 문서를 한 번씩 실전 상황으로 다시 찾아가게 만드는 지도다. 보충 Case는 그중에서도 백엔드 개발자가 운영 중 자주 놓치거나, 인프라 팀과 맞추지 않으면 나중에 크게 터질 수 있는 세부 판단을 따로 훈련하기 위한 섹션이다.

보충 Case 1. AcceptContent-Type은 맞아 보이는데 415/406이 난다

상황

  • 파트너는 “JSON으로 보냈다”고 말하지만 API는 415 Unsupported Media Type을 낸다.
  • 또는 서버는 정상 응답을 만들었는데 client가 406 Not Acceptable을 받는다.
  • local curl은 성공하지만 gateway를 지나면 header가 달라진다.

관찰할 증거 또는 확인할 단서

  • 실제 wire에 나간 Content-Type, Accept, Content-Encoding, Accept-Encoding을 본다.
  • Spring MVC의 consumes, produces, HttpMessageConverter, gateway header rewrite 여부를 나눈다.
  • 실패 요청과 성공 요청의 raw header를 HAR, access log, request dump로 비교한다.

먼저 생각해보기

  • Content-Type 문제인가, Accept 문제인가?
  • body는 JSON처럼 보여도 charset, boundary, compression, vendor media type이 다른가?
  • Spring controller가 좁은 media type만 받도록 선언되어 있는가?

찾아볼 문서

실전 행동

  • controller의 media type 계약을 코드에 명시하고, 문서와 테스트가 같은 값을 쓰게 한다.
@PostMapping(
    value = "/orders",
    consumes = MediaType.APPLICATION_JSON_VALUE,
    produces = MediaType.APPLICATION_JSON_VALUE
)
public ResponseEntity<OrderResponse> create(@RequestBody @Valid OrderRequest request) {
    Order order = orderService.create(request);
    return ResponseEntity.ok(OrderResponse.from(order));
}
  • 실패 요청은 client SDK가 아니라 curl로 다시 만들어 header 차이를 줄인다.
curl -i 'https://api.example.com/orders' \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  --data '{"sku":"BOOK-1","quantity":1}'
  • gateway나 WAF가 Content-Type을 제거하거나 normalize하는지 access log와 config를 함께 확인한다.

정리

  • 415는 “내가 보낸 body를 서버가 해석할 수 없음”이고, 406은 “client가 받을 수 있다고 한 표현으로 서버가 응답할 수 없음”이다.

가져갈 한 문장

  • media type 장애는 JSON 여부가 아니라 요청과 응답 표현 계약이 실제 경로에서 보존됐는지의 문제다.

보충 Case 2. ETagIf-Match로 동시 수정 충돌을 막아야 한다

상황

  • 관리자 화면에서 두 사람이 같은 상품 가격을 수정한다.
  • 마지막 저장이 이기면서 앞선 사용자의 변경이 조용히 사라진다.
  • DB optimistic lock은 있지만 HTTP API 계약에는 충돌 표현이 없다.

관찰할 증거 또는 확인할 단서

  • 조회 응답에 ETag가 있는지 확인한다.
  • 수정 요청에 If-Match가 들어오는지 확인한다.
  • 충돌 시 409 Conflict412 Precondition Failed 중 어떤 의미가 맞는지 나눈다.

먼저 생각해보기

  • 이 API는 “마지막 쓰기 승리”를 허용해도 되는가?
  • client가 보고 있던 버전과 서버의 현재 버전이 다를 때 어떤 상태코드와 body를 줄 것인가?
  • CDN/cache와 API 조건부 요청을 같은 용어로 설명하고 있는가?

찾아볼 문서

실전 행동

  • 조회 응답은 현재 버전을 ETag로 돌려주고, 수정 요청은 If-Match를 요구한다.
@GetMapping("/products/{id}")
public ResponseEntity<ProductResponse> get(@PathVariable long id) {
    Product product = productService.get(id);
    return ResponseEntity.ok()
        .eTag("\"" + product.version() + "\"")
        .body(ProductResponse.from(product));
}
 
@PutMapping("/products/{id}")
public ResponseEntity<ProductResponse> update(
    @PathVariable long id,
    @RequestHeader("If-Match") String ifMatch,
    @RequestBody ProductUpdateRequest request
) {
    Product updated = productService.updateIfVersionMatches(id, ifMatch, request);
    return ResponseEntity.ok()
        .eTag("\"" + updated.version() + "\"")
        .body(ProductResponse.from(updated));
}
  • 버전 불일치는 조용한 overwrite가 아니라 412 Precondition Failed와 재조회 안내로 표현한다.
  • ETag가 cache 최적화용인지, write precondition용인지 API 문서에서 분리해 설명한다.

정리

  • 조건부 요청은 cache 절약 기능으로만 볼 수 없고, 쓰기 API의 동시성 계약으로도 쓸 수 있다.

가져갈 한 문장

  • 동시 수정 충돌은 DB만의 문제가 아니라 HTTP 요청 조건을 client와 공유해야 줄어든다.

보충 Case 3. HTTP/3를 켰는데 일부 회사망과 모바일망에서만 느리다

상황

  • CDN에서 HTTP/3를 활성화했다.
  • 대부분은 빨라졌지만 일부 회사망, VPN, 구형 단말, 특정 통신사에서만 접속이 느리거나 간헐 실패한다.
  • 서버 지표만 보면 오류가 거의 없다.

관찰할 증거 또는 확인할 단서

  • ALPN 결과가 h3, h2, http/1.1 중 무엇인지 확인한다.
  • UDP/443 차단, middlebox, QUIC fallback 지연을 의심한다.
  • 같은 endpoint를 HTTP/3, HTTP/2로 각각 호출해 차이를 비교한다.

먼저 생각해보기

  • 문제는 HTTP/3 자체인가, HTTP/3 실패 뒤 fallback 경로가 느린 것인가?
  • CDN, LB, origin 중 어디까지 HTTP/3가 적용되는가?
  • 장애 알림은 protocol별로 분리되어 있는가?

찾아볼 문서

실전 행동

  • 같은 URL을 protocol별로 확인한다.
curl -I --http3 https://api.example.com/health
curl -I --http2 https://api.example.com/health
curl -w 'namelookup=%{time_namelookup} connect=%{time_connect} appconnect=%{time_appconnect} starttransfer=%{time_starttransfer} total=%{time_total}\n' \
  -o /dev/null -s https://api.example.com/health
  • CDN log에서 protocol, region, ASN, user agent, error reason을 나눠 본다.
  • HTTP/3 rollout은 전체 on/off보다 비율, region, host 단위로 되돌릴 수 있게 둔다.

정리

  • HTTP/3는 더 빠른 길을 열어주지만, UDP 차단 환경에서는 fallback 품질이 사용자 경험을 결정한다.

가져갈 한 문장

  • protocol upgrade는 평균 속도보다 fallback 실패와 특정 네트워크 구간의 꼬리 지연을 같이 봐야 한다.

보충 Case 4. 내부 API에 mTLS를 도입할지 결정해야 한다

상황

  • 사내 서비스 간 호출에 mTLS를 도입하자는 제안이 나왔다.
  • 보안팀은 강한 인증을 원하고, 개발팀은 인증서 운영 부담과 장애 가능성을 걱정한다.
  • 일부 legacy client는 인증서 배포와 갱신 자동화가 준비되어 있지 않다.

관찰할 증거 또는 확인할 단서

  • TLS termination 위치와 app이 실제 client identity를 어디서 얻는지 확인한다.
  • 인증서 발급, 배포, rotation, 폐기, 만료 알림 owner가 정해져 있는지 본다.
  • mesh, gateway, NGINX, app 중 어느 계층에서 mTLS를 끝낼지 결정한다.

먼저 생각해보기

  • mTLS가 필요한 경계는 internet edge인가, service-to-service인가, 관리자 API인가?
  • app은 인증서를 직접 검증해야 하는가, trusted proxy가 검증한 결과만 받아도 되는가?
  • header로 client identity를 넘긴다면 그 header를 누가 만들고 누가 지울 수 있는가?

찾아볼 문서

실전 행동

  • proxy에서 client certificate를 검증한다면 app으로 전달되는 identity header의 신뢰 경계를 문서화한다.
server {
    listen 443 ssl;
    ssl_certificate /etc/nginx/tls/server.crt;
    ssl_certificate_key /etc/nginx/tls/server.key;
 
    ssl_client_certificate /etc/nginx/pki/client-ca.pem;
    ssl_verify_client on;
 
    proxy_set_header X-Client-Verify $ssl_client_verify;
    proxy_set_header X-Client-DN $ssl_client_s_dn;
    proxy_pass http://internal-api;
}
  • app은 public internet에서 들어온 동일 header를 신뢰하지 않도록 trusted proxy 경계를 둔다.
  • 도입 전에는 certificate rotation drill과 만료 알림을 smoke test 수준으로 검증한다.

정리

  • mTLS는 “보안을 켠다”가 아니라 인증서 수명주기와 신뢰 경계를 운영 계약으로 만드는 일이다.

가져갈 한 문장

  • mTLS의 난이도는 handshake가 아니라 인증서 배포, 갱신, 폐기, 신뢰 header 통제에 있다.

보충 Case 5. Spring WebClient timeout과 retry를 실제 장애 기준으로 조정한다

상황

  • 외부 결제 API가 가끔 느려진다.
  • 개발자는 WebClient timeout을 늘리자고 하고, 운영자는 thread와 connection pool 고갈을 걱정한다.
  • retry를 넣었더니 장애 때 외부 API 호출량이 더 늘었다.

관찰할 증거 또는 확인할 단서

  • connect timeout, response timeout, read/write timeout, pool acquire timeout을 분리한다.
  • retry 횟수와 backoff가 전체 timeout budget 안에 들어오는지 계산한다.
  • idempotency key와 retry 가능한 method/status가 정의되어 있는지 확인한다.

먼저 생각해보기

  • timeout을 늘리면 사용자가 기다릴 가치가 있는 요청인가?
  • retry는 사용자 성공률을 높이는가, downstream을 더 때리는가?
  • breaker와 bulkhead가 없으면 장애가 어떤 pool까지 번지는가?

찾아볼 문서

실전 행동

  • client 설정은 한 곳에서 만들고, API별 timeout budget을 명시한다.
@Bean
WebClient paymentWebClient(WebClient.Builder builder) {
    HttpClient httpClient = HttpClient.create()
        .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 1_000)
        .responseTimeout(Duration.ofSeconds(2));
 
    return builder
        .clientConnector(new ReactorClientHttpConnector(httpClient))
        .baseUrl("https://payment.example.com")
        .build();
}
  • retry는 “몇 번 더”가 아니라 전체 예산 안에서 backoff와 함께 제한한다.
resilience4j:
  retry:
    instances:
      payment:
        max-attempts: 2
        wait-duration: 200ms
        retry-exceptions:
          - java.io.IOException
  timelimiter:
    instances:
      payment:
        timeout-duration: 2500ms
  • payment처럼 side effect가 있는 요청은 idempotency key 없이 자동 retry하지 않는다.

정리

  • timeout과 retry는 안정성 기능이지만, budget 없이 켜면 장애 증폭 장치가 된다.

가져갈 한 문장

  • Spring client 설정은 “느리면 더 기다리기”가 아니라 제한된 시간 안에서 실패를 격리하는 계약이다.

보충 Case 6. WAF, LB, DNS 변경 요청서를 써야 한다

상황

  • 신규 관리자 API를 열기 위해 WAF rule, LB listener, DNS record 변경이 필요하다.
  • 백엔드 팀은 “이 경로만 열어주세요”라고 말하고 싶지만, 인프라 팀은 impact, rollback, 검증 방법이 필요하다.
  • 개인 프로젝트에서는 클릭 몇 번이면 끝났던 변경이 회사에서는 change window와 승인 절차를 거친다.

관찰할 증거 또는 확인할 단서

  • 변경 대상 host, path, method, source, target, expected status, rollback 방법을 적는다.
  • WAF allow rule이 필요한지, rate limit과 body size limit도 함께 바뀌는지 확인한다.
  • DNS TTL, LB health check, certificate, logging, alert owner를 같이 본다.

먼저 생각해보기

  • 이 변경은 외부 노출면을 넓히는가?
  • 실패하면 사용자는 어떤 오류를 보고, 어느 지표가 먼저 움직이는가?
  • rollback은 DNS 되돌리기인가, LB target 제외인가, WAF rule disable인가?

찾아볼 문서

실전 행동

  • 변경 요청은 설정값 나열보다 검증 가능한 기대 결과를 중심으로 쓴다.
change_request:
  service: admin-api
  host: admin.example.com
  path: /v1/reports/*
  methods: [GET, POST]
  source: office-vpn
  target: admin-api-prod-8080
  expected:
    success_status: 200
    blocked_status_from_public: 403
    health_check: /actuator/health/readiness
  risks:
    - WAF false positive on large report filter body
    - DNS propagation delay during rollback
  validation:
    - curl from office VPN
    - curl from public network must be blocked
    - LB target health all healthy
  rollback:
    - disable WAF allow rule
    - detach new target group
  • 인프라 팀에는 “무엇을 바꿔주세요”와 함께 “어떻게 성공을 확인할지”를 준다.
  • 개인 프로젝트에서도 이 템플릿을 줄여서 쓰면 배포 사고를 훨씬 빨리 되돌릴 수 있다.

정리

  • 좋은 변경 요청은 인프라 담당자가 추측하지 않아도 되는 요청이다.

가져갈 한 문장

  • 인프라 협업의 품질은 요청 문장보다 검증 조건과 rollback 조건에서 드러난다.

보충 Case 7. Header가 너무 크거나 민감정보가 로그에 남을 위험이 있다

상황

  • 인증 관련 header와 cookie가 늘어나면서 일부 요청이 431 Request Header Fields Too Large를 낸다.
  • gateway access log에 Authorization, Cookie, Set-Cookie, X-Api-Key가 그대로 남을 수 있다.
  • observability를 위해 header를 더 남기자는 요구와 보안 요구가 충돌한다.

관찰할 증거 또는 확인할 단서

  • client가 보내는 header 총 크기와 cookie 개수를 본다.
  • proxy, LB, app server의 header size limit을 확인한다.
  • log pipeline에서 민감 header가 redaction되는지 샘플 로그로 검증한다.

먼저 생각해보기

  • 이 header는 routing, auth, tracing, debugging 중 무엇을 위해 필요한가?
  • request id와 trace id만으로 충분한데 전체 header를 남기고 있지는 않은가?
  • cookie에 넣은 상태가 session store나 token introspection으로 옮겨갈 수 있는가?

찾아볼 문서

실전 행동

  • 애플리케이션 로그에서는 allowlist 방식으로 남길 header를 고른다.
private static final Set<String> SAFE_HEADERS = Set.of(
    "x-request-id",
    "traceparent",
    "user-agent",
    "x-forwarded-for"
);
 
String printableHeader(String name, String value) {
    if (!SAFE_HEADERS.contains(name.toLowerCase(Locale.ROOT))) {
        return "[redacted]";
    }
    return value;
}
  • Authorization, Cookie, Set-Cookie, API key류는 기본적으로 남기지 않는다.
  • header size 문제는 limit을 키우기 전에 cookie scope, token 크기, 중복 header, proxy 추가 header를 줄인다.

정리

  • header는 관측에도 필요하지만 인증 상태와 개인정보가 지나가는 통로이기도 하다.

가져갈 한 문장

  • header 로그는 많이 남길수록 좋은 것이 아니라, 장애 판단에 필요한 것만 안전하게 남겨야 한다.

보충 Case 8. NAT, DNS, TLS 희귀 한계를 장애 전 runbook에 넣는다

상황

  • 지금은 잘 동작하지만 이벤트, 대량 배치, 트래픽 급증 때 희귀한 한계가 터질까 걱정된다.
  • ephemeral port, NAT table, conntrack, DNS resolver quota, file descriptor, certificate expiry 같은 항목은 평소 알림에서 잘 보이지 않는다.
  • 장애가 나면 백엔드와 인프라가 서로 “우리 쪽은 정상”이라고 말할 가능성이 있다.

관찰할 증거 또는 확인할 단서

  • outbound 연결 수와 destination 분포를 본다.
  • NAT gateway, firewall, node conntrack, DNS resolver, TLS certificate 만료 알림을 확인한다.
  • 장애 전후에 바로 실행할 명령과 cloud metric 이름을 runbook에 적는다.

먼저 생각해보기

  • 이 서비스는 inbound보다 outbound가 병목이 될 수 있는가?
  • 같은 destination으로 짧은 연결을 너무 많이 만들고 있지는 않은가?
  • DNS cache, connection pool, keep-alive가 실제로 효과를 내고 있는가?

찾아볼 문서

실전 행동

  • runbook에는 “나중에 보면 됨”이 아니라 장애 첫 10분에 볼 명령을 넣는다.
ss -s
ss -tan state time-wait | wc -l
cat /proc/sys/net/ipv4/ip_local_port_range
cat /proc/sys/net/netfilter/nf_conntrack_max
dig api.partner.example.com
openssl s_client -connect api.partner.example.com:443 -servername api.partner.example.com </dev/null
  • cloud 환경에서는 NAT gateway port allocation, connection count, DNS resolver error, LB rejected connection, TLS certificate expiry metric을 dashboard에 올린다.
  • 개인 프로젝트에서도 최소한 certificate expiry, uptime check, DNS record, reverse proxy access log는 확인 가능하게 둔다.

정리

  • 희귀 한계는 자주 일어나지 않아서 희귀한 것이 아니라, 터지기 전까지 보통 dashboard에 없어서 희귀해 보인다.

가져갈 한 문장

  • 고급 운영 역량은 자주 보이는 오류보다 평소 보이지 않는 한계를 미리 관측 가능하게 만드는 데서 나온다.

개발 단계별 활용법

단계이때 볼 Case활용 방식
설계 전Case 9, Case 11, Case 12, Case 17, 보충 Case 4, 보충 Case 6, 보충 Case 8도메인, 인증, retry, capacity, 운영 증거를 설계 입력으로 넣는다.
구현 중Case 3, Case 5, Case 6, Case 12, Case 18, 보충 Case 1, 보충 Case 2, 보충 Case 5, 보충 Case 7header, body, timeout, idempotency, cache policy를 코드 계약으로 명시한다.
배포 전Case 2, Case 4, Case 7, Case 14, Case 15, 보충 Case 3, 보충 Case 4, 보충 Case 6TLS, DNS, CDN, LB, draining, protocol fallback을 smoke test에 넣는다.
장애 대응 중Case 1, Case 8, Case 10, Case 13, Case 16, 보충 Case 1, 보충 Case 3, 보충 Case 5, 보충 Case 7, 보충 Case 8응답 주체, 마지막 관측 계층, queue 위치, 정책 차단 여부를 빠르게 나눈다.
회고/개선 시Case 17, Case 18, Case 19, Case 20, 보충 Case 6, 보충 Case 8누락된 log/metric/runbook/action item을 다음 운영 기준으로 바꾼다.

커버리지 지도

기존 문서연결된 Case이 문서가 필요한 이유
웹 요청 흐름 전체 지도 압축 정리16전체 장애 대응의 첫 지도 역할
전체 요청 경로 상세1, 16요청이 어느 계층까지 갔는지 분리
계층별 관찰 지점 상세1, 16계층별 log/metric 관찰 포인트
브라우저와 서버 경계 상세3브라우저 보안 정책과 서버 응답 분리
로그와 Trace ID로 따라가기 상세1, 16, 보충 7request id로 계층별 로그 연결과 header redaction 판단
장애 가설 세우기 상세16, 20추측을 검증 가능한 가설로 전환
URL URI DNS 압축 정리11, 14URL/DNS/도메인 변경의 빠른 지도
URI와 URL 구조 상세11redirect, path, query, origin 판단
DNS 조회와 레코드 상세11, 14DNS record와 resolver 증거 확인
DNS TTL과 배포 전파 상세2, 14, 보충 6DNS 전환, 변경 요청, rollback 판단
도메인 설계와 보안 상세11cookie/CORS/TLS/OAuth 보안 경계 설계
IP TCP UDP 기본 압축 정리10, 17IP/port/TCP/UDP 운영 비용의 빠른 지도
IP와 포트 라우팅 상세10, 17bind address, firewall, target port 판단
TCP Handshake와 상태 상세8, 10TCP 상태와 연결 실패 증거 확인
UDP와 QUIC 기본 상세15, 보충 3HTTP/3, QUIC, UDP fallback 판단
OS 네트워크 관찰 상세10, 보충 8socket, FD, port, conntrack 관찰
TCP 연결 Keep-Alive Connection Pool 압축 정리5, 7, 10연결 재사용과 pool 장애의 빠른 지도
Keep-Alive 동작 상세7, 15연결 재사용, idle socket, protocol 영향
HTTP Client Connection Pool 상세1, 5, 12, 보충 5external call pool pending과 timeout 판단
서버 Socket Thread Backlog 상세10backlog, worker thread, accept queue 판단
Idle Timeout 불일치 상세7stale connection과 장기 연결 끊김 판단
Pool 고갈 장애 상세5, 10DB/HTTP/thread pool 고갈 판단
HTTP 기본 구조 압축 정리6, 12HTTP 메시지 계약의 빠른 지도
요청과 응답 메시지 상세12, 16, 보충 1, 보충 7request/response 구조와 request id 판단
Message Framing과 Body 상세6upload/body/chunked/framing 판단
HTTP 버전별 차이 상세15, 보충 3HTTP/1.1, HTTP/2, HTTP/3 차이 판단
Content Negotiation과 Encoding 상세18, 보충 1Vary, compression, content negotiation 판단
HTTP Method Status Code Header 압축 정리12, 16method/status/header 운영 해석의 빠른 지도
Method와 멱등성 상세12, 보충 2retry 가능성과 method 의미 판단
Status Code 운영 해석 상세6, 8, 19, 보충 2status code를 응답 주체와 다음 확인으로 연결
Header 설계와 관찰 상세13, 18, 보충 1, 보충 7header 신뢰 경계와 관측 기준
API 응답 계약 상세12, 13, 보충 1client 행동을 안내하는 response contract
HTTPS TLS 인증서 압축 정리4, 15TLS/인증서 전체 빠른 지도
TLS Handshake 상세4, 15, 보충 3handshake timing, ALPN, TLS policy 판단
인증서 Chain과 SNI 상세4, 11, 보충 4chain, SAN, SNI, truststore 판단
TLS Termination과 mTLS 상세4, 17, 보충 4termination 위치, mTLS, forwarded proto 판단
TLS 디버깅 상세4, 16, 보충 8TLS 장애 재현 명령과 report evidence
Cookie Session SameSite CORS 압축 정리3, 18브라우저 인증 경계의 빠른 지도
Cookie 속성 상세3, 11Set-Cookie, Domain, Path, Secure 판단
Session과 인증 상태 상세3, 19session scale out과 인증 상태 판단
SameSite와 CSRF 상세3SameSite, CSRF, OAuth redirect 판단
CORS와 Preflight 상세3, 13preflight, credential CORS, gateway 소유권
브라우저 보안 디버깅 상세3DevTools, HAR, browser-only failure 판단
Cache CDN Conditional Request 압축 정리2, 18, 19cache/CDN/조건부 요청 빠른 지도
HTTP Cache 기본 상세2, 18Cache-Control, Vary, shared cache 판단
ETag와 Conditional Request 상세2, 19, 보충 2ETag, 304, conditional request 판단
CDN Origin과 Purge 상세2, 14CDN cache key, purge, origin 비교
Cache 정합성 장애 상세2, 19, 보충 2stale data, purge event, 권한/가격 정합성
Cache 성능과 보안 상세18cache poisoning, private data, safe headers
Proxy Reverse Proxy Gateway 압축 정리8, 13proxy/gateway/WAF 빠른 지도
Proxy와 Reverse Proxy 역할 상세8, 17, 보충 7응답 주체와 reverse proxy 역할 판단
NGINX Timeout과 Buffer 상세6, 7, 15, 보충 3timeout, buffer, upload, long connection 판단
Forwarded Header와 Client IP 상세4, 13, 17client IP, trusted proxy, forwarded proto 판단
API Gateway와 WAF 상세13, 보충 6WAF, rate limit, gateway policy 판단
Path Rewrite와 Upstream 상세8path rewrite, upstream DNS, normalization 판단
Load Balancer Health Check Traffic Routing 압축 정리8, 14LB/health/routing 빠른 지도
LB 알고리즘과 Routing 상세9, 14, 보충 6canary, weighted routing, target group 판단
Health Check와 Readiness 상세8, 9liveness/readiness/probe 판단
Idle Timeout과 장기 연결 상세7LB idle timeout과 장기 연결 판단
배포와 Draining 상세14, 17draining, graceful shutdown, rollback 판단
Cloud LB 디버깅 상세8cloud LB access log와 target health 판단
Timeout Retry Idempotency Circuit Breaker 압축 정리5, 12timeout/retry/idempotency 빠른 지도
Timeout 종류와 정렬 상세1, 5, 보충 5timeout chain과 정렬 판단
Retry와 장애 증폭 상세5, 12, 13, 보충 5retry storm, Retry-After, budget 판단
Idempotency Key 상세12중복 결제/중복 처리 방지
Circuit Breaker Bulkhead Fallback 상세5장애 격리, fallback, breaker 판단
Spring과 Resilience 설정 상세5, 보충 5Spring client timeout과 Resilience4j 설정
대용량 트래픽과 네트워크 병목 압축 정리9, 10대용량 병목 빠른 지도
Capacity Planning 상세9, 보충 8SLO, headroom, shared resource 계산
병목 구분 상세1, 9, 10queue 위치와 metric 기반 병목 분리
부하 테스트와 관측 상세9load/stress/spike 테스트와 관측
Backpressure와 Rate Limit 상세9, 13rate limit, load shedding, retry storm 방지
희귀하지만 중요한 한계 상세10, 보충 8ephemeral port, NAT, DNS, FD, conntrack 한계
네트워크 장애 대응과 트러블슈팅 압축 정리16, 20장애 대응 전체 빠른 지도
장애를 계층별로 의심하는 방법 상세16장애 초반 계층별 분리
타임아웃과 지연 장애 분석 상세1, 16tail latency와 timeout 분석
HTTP 상태코드별 병목 구간 상세8, 164xx/5xx/status별 다음 확인
요청 유형별 네트워크 판단 상세6, 7업로드, 장기 연결, 모바일 요청 판단
실제 502 사례와 장애 보고 상세8, 16, 20502 보고와 장애 증거 전달
백엔드 개발자와 인프라 협업 압축 정리17, 20협업과 운영 기준 빠른 지도
개인 프로젝트에서 챙길 네트워크 기준 상세17개인 프로젝트 운영 품질 기준
팀 서비스 운영에서 챙길 네트워크 기준 상세16, 17, 보충 8팀 공통 운영 계약과 runbook
기업 운영 환경에서 챙길 네트워크 기준 상세14, 17, 보충 4, 보충 6변경 관리, SLO, 보안, multi-AZ 판단
인프라 팀과 소통하는 방법 상세13, 16, 20, 보충 4, 보충 6인프라 요청 정보와 증거 전달
장애 회고에서 네트워크를 다루는 방법 상세20postmortem과 action item 설계

가져갈 판단 기준

  • 상태코드는 결론이 아니라 응답 주체와 다음 확인 계층을 좁히는 단서다.
  • app log가 없다는 말은 app 이전 계층의 증거가 더 필요하다는 뜻일 수 있다.
  • timeout을 늘리기 전에 queue, pool, retry, downstream quota를 본다.
  • cache는 성능 기능이 아니라 데이터 정합성과 보안 경계를 바꾸는 응답 계약이다.
  • 브라우저 문제는 서버 응답, 브라우저 저장, 브라우저 전송, JavaScript 노출을 나눠야 보인다.
  • TLS와 DNS 변경은 “설정 완료”보다 실제 endpoint 검증과 rollback 가능성이 중요하다.
  • scale out은 app capacity만 늘리는 것이 아니라 shared resource 부하도 함께 늘린다.
  • 인프라 협업은 요청을 던지는 일이 아니라 증거, 기대 결과, owner, rollback을 맞추는 일이다.