Files
tasteby/docs/design/277-backend-health/README.md
joungmin 80b553ec19 docs: 현행화 17개 설계서 Approved + 후속 이슈 백로그 등록
Reviewer 결과 17 PASS / 1 REJECT (#267 admin 권한 critical).
- 17개 설계서를 Draft → Approved로 갱신
- #267(backend-user)은 critical 결함으로 06-Reviewer 유지
- 후속 17개 개선 이슈(#289~#305) 자동 등록 — 결함 124건 백로그 반영
  (critical 3 / major 46 / minor 75)
- docs/README.md에 18개 설계서 인덱스 추가
- CHANGELOG.md 2026-06-15 섹션 추가

Refs: #266 #268-#283 (현행화 완료) #267 (대기) #289-#305 (백로그)
2026-06-15 11:08:18 +09:00

6.9 KiB

설계서: 백엔드 - Health/모니터링 (#277)

상태: Approved 작성: [AI] Architect · 최종수정: 2026-06-15 추적성 — Redmine: #277 · 관련 ADR: 없음 · 구현 파일: backend-java/src/main/java/com/tasteby/controller/HealthController.java · 테스트: TBD (현재 없음)

1. 목적 (Why)

PM2(dev) / Kubernetes (OKE prod) / Nginx Ingress 가 백엔드 프로세스가 살아있는지 판단할 수 있는 경량 HTTP 엔드포인트를 제공해, 장애 시 재기동·트래픽 차단을 자동화한다.

2. 범위 (Scope)

  • 포함:
    • GET /api/health — 항상 200 OK{"status":"ok"} 를 반환하는 liveness 체크 엔드포인트.
    • 인증 없이 호출 가능(공개).
  • 제외 (out of scope):
    • DB/Redis/외부 API 의존성 상태를 포함하는 deep health(readiness) 체크.
    • Spring Boot Actuator (/actuator/health) 활성화.
    • 메트릭(Micrometer/Prometheus) 노출.
    • 분산 트레이싱·로그 수집.
    • 알림(Slack/Email/PagerDuty) 통합.

3. 인수조건 (Acceptance Criteria)

  • GET /api/health 호출 시 HTTP 200 과 본문 {"status":"ok"} 를 반환한다.
  • 인증 없이 누구나 호출 가능하다(WebConfig CORS 허용 범위 내).
  • 응답 본문은 Content-Type: application/json 으로 직렬화된다(Spring 기본).
  • 외부 의존성(DB/Redis/LLM)이 다운되어도 본 엔드포인트는 영향을 받지 않는다(순수 인메모리 응답).

4. 컨텍스트 & 제약

  • 의존성:
    • Spring Web (@RestController, @GetMapping).
    • 외부 의존성 없음 — 컨트롤러 자체가 무상태 상수 응답.
    • 호출자: PM2 헬스(현재는 미사용), Kubernetes liveness/readiness probe(향후), Nginx upstream check(현재는 미사용), Uptime 모니터링.
  • 제약:
    • 응답 시간 < 50ms 가정. 어떤 비용 있는 작업도 포함하지 않아야 함.
    • 본 엔드포인트가 200 을 반환한다고 해서 "서비스 정상" 을 의미하지 않음(프로세스 생존만 보장).
  • 가정:
    • 프로세스가 응답할 수 있으면 JVM/Tomcat 이 살아있다는 신호로 충분.
    • 인증 미들웨어(Spring Security/필터)는 /api/health 를 통과시킨다(현재 인증 강제 없음).

5. 아키텍처 개요

  • 모듈:
    • HealthController — 단일 @RestController 클래스, 메서드 1개.
  • 경계:
    • I/O: HTTP 입출력만. DB/Redis/LLM 호출 없음.
    • 순수 로직: 상수 Map 반환 — 테스트 자체가 거의 불필요한 수준.
   Probe/Monitor  ──HTTP GET /api/health──▶  Spring DispatcherServlet
                                                     │
                                                     ▼
                                            HealthController.health()
                                                     │
                                                     ▼
                                          Map.of("status","ok")  → JSON 200

6. 데이터 모델

  • 단순 응답 객체: Map<String, String> 의 불변 단일 엔트리.
{ "status": "ok" }
  • 입력 파라미터/바디 없음.
  • 상태 코드: 항상 200. 다른 코드 없음.
  • 경계 검증: 해당 없음.

7. 함수 명세 (Function Specs)

함수 책임(1줄) 시그니처(잠정) 입력 출력 에러/실패 복잡?
HealthController.health liveness 응답 반환 Map<String,String> health() 없음 {"status":"ok"} 이론상 없음(JVM/Tomcat 죽으면 연결 실패) 단순

8. 흐름 / 알고리즘

  1. 클라이언트(K8s probe / 모니터)가 GET /api/health 호출.
  2. Spring DispatcherServlet 라우팅 → HealthController.health() 호출.
  3. 메서드는 Map.of("status","ok") 상수 반환.
  4. Jackson 이 JSON 직렬화 → HTTP 200 응답.

cron 표현/주기: 본 컨트롤러 자체는 스케줄러가 아님(외부 probe 가 주기적으로 호출). 운영 권장 주기: K8s liveness 10s, readiness 5s.

9. 엣지케이스 & 에러 처리

  • JVM 데드락/OOM: 응답 없음 → probe 가 타임아웃 → 비정상 판정 → 재기동(외부 메커니즘이 처리, 본 엔드포인트가 의도한 시나리오).
  • 요청 폭주(DDoS): 본 메서드는 매우 가볍지만 인증/레이트리밋이 없음. Nginx Ingress 단에서 처리 가정.
  • DB/Redis 다운: 본 엔드포인트는 영향 없음(의도된 동작). 단, 운영자가 "서비스 정상"으로 오인할 수 있는 한계 — 별도 readiness 필요(11장 참조).
  • 잘못된 HTTP 메서드: POST /api/health 등은 405 (Spring 기본).
  • CORS: WebConfig 의 허용 origin 에 따라 브라우저 접근 제한될 수 있음(서버-서버 probe 에는 영향 없음).

10. 테스트 계획

현재 자동 테스트 없음(TBD). 권장 케이스:

  • Unit/Slice (@WebMvcTest(HealthController.class)):
    • GET /api/health → 200 + 본문 {"status":"ok"}.
    • POST /api/health → 405.
  • Smoke:
    • 운영/dev 배포 후 curl -sf https://www.tasteby.net/api/health 가 0 종료 코드.
  • 모킹: 불필요 — 의존성 없음.

11. 리스크 & 대안 검토

  • 선택: 자체 컨트롤러 1개 + 상수 응답.
    • 장점: 의존성 0, 인증/필터 우회 명확, K8s probe 와 1:1 매핑 쉬움.
    • 단점: deep health(DB/Redis 연결 확인) 부재 → "프로세스는 살아있지만 서비스 불가" 상황 감지 못 함.
  • 대안:
    • Spring Boot Actuator (/actuator/health) — DB/Redis HealthIndicator 자동 구성, 표준화. 보안 노출 범위 제어 필요. → readiness 용도로 향후 도입 후보.
    • K8s readinessProbe 별도 엔드포인트 (/api/health/ready) — DB ping, Redis ping 결과 합산. 본 설계의 자연스러운 확장.
    • 외부 모니터링(UptimeRobot/Healthchecks.io) — HTTP 200 만으로 충분히 활용 가능.
  • 트레이드오프: 현재는 운영자 1인 / 트래픽 적음 → 최소 구현이 합리적. Prod 안정화 단계에서 Actuator + readiness 분리 권장.
  • 되돌리기 어려운 결정 없음.

12. 미해결 질문 (Open Questions)

  • DB/Redis 연결을 검사하는 readiness 엔드포인트(/api/health/ready)를 언제 도입할 것인가?
  • Spring Boot Actuator 를 켜고 노출 범위(어떤 엔드포인트, 어떤 인증)를 어떻게 제어할 것인가?
  • Prometheus 메트릭/Grafana 대시보드를 운영할 것인가(현재는 PM2/kubectl 로그 의존)?
  • K8s probe 구성(initialDelay, periodSeconds, failureThreshold) 표준값은?
  • 헬스 응답에 빌드 버전/커밋 SHA를 포함할 것인가(/api/version 분리 vs 통합)?
  • 본 엔드포인트도 인증/IP 제한 대상으로 둘 필요가 있는가(공개 권장)?