Spring Boot Graceful Shutdown: 요청을 흘리지 않고 죽는 법
server.shutdown=graceful 한 줄로는 부족하다. SmartLifecycle phase로 못 박힌 종료 순서, 임베디드 서버별 drain 방식, 버전별 기본값 함정, 쿠버네티스 preStop까지 Spring Boot 소스로 직접 확인한 graceful shutdown의 내부.
애플리케이션의 기반. Boot, 관측성, 생태계 통합.
서버를 표준으로 정리했으면 클라이언트와 테스트도 따라와야 반쪽이 아니다. RestTemplate의 공식 deprecation, @HttpExchange 선언적 클라이언트와 HTTP Interface Groups, 그리고 라이브 서버와 단일 컨트롤러를 한 API로 테스트하는 RestTestClient로 시리즈를 닫는다.
HTTP 상태 코드와 헤더는 다 아는 영역 같지만 RFC는 계속 갱신된다. Framework 7이 RFC 9110에 맞춰 HttpStatus 상수 이름을 바꾸고(숫자는 그대로), RFC 7239 ForwardedHeaderFilter로 프록시 뒤 정보를 복원하고, trailing slash 매칭을 보안 이유로 걷어낸 자리를 본다.
에러 응답 포맷이 서비스마다 다른 문제를 RFC 9457이 표준 바디로 푼다. Spring의 ProblemDetail과 ErrorResponse가 어떻게 맞물리는지, 내장 예외까지 표준 형식으로 내보내는 법, properties Map으로 검증 에러를 확장하는 법을 코드로 따라간다.
버전을 끊기 전에 클라이언트에게 "이건 곧 죽는다"를 어떻게 알리나. Spring 7의 StandardApiVersionDeprecationHandler가 RFC 9745 Deprecation·RFC 8594 Sunset·RFC 8288 Link 헤더를 자동 발급한다. 두 헤더의 날짜 형식이 다른 이유까지 RFC 원문으로 따라간다.
Spring MVC·WebFlux가 API 버저닝을 1급으로 지원한다. URL이냐 헤더냐 하는 "어떻게"를 ApiVersionStrategy로 추상화하고, 매핑은 version 속성만 선언한다. baseline 버전 1.2+가 풀어주는 메서드 중복 문제, 클라이언트 ApiVersionInserter까지 코드로 따라간다.