TIL - 20261006

juni·2일 전

TIL

목록 보기
472/473

1006 운영 자동화/AI 워크플로우 심화 (30/N): Health Check, Readiness/Liveness, Graceful Shutdown과 Drain


✅ 1. 프로세스가 살아 있다는 것과 서비스를 할 수 있다는 것은 다르다

예를 들어 NestJS 프로세스가:

PID 존재

Node.js Event Loop 동작

HTTP Port 열림

상태라고 하자.

겉으로 보면 서버는 살아 있다.

하지만 실제로:

DB 연결 실패

필수 Config 없음

Queue 연결 실패

Migration 미적용

Worker 초기화 실패

상태일 수 있다.

이 서버에 고객 요청을 보내면 실패한다.


✅ 2. 그래서 Health Check는 단순 200 OK가 아니다

가장 단순한 Health Endpoint:

@Get('/health')
health() {
  return { status: 'ok' };
}

는:

NestJS Controller가 응답했다

정도만 알려준다.

실제 서비스 가능 여부까지 보장하지 않는다.


✅ 3. Health Check에는 서로 다른 질문이 있다

대표적으로 세 가지를 구분한다.

Liveness
=
이 프로세스가 살아 있는가?

Readiness
=
지금 요청을 받아도 되는가?

Startup
=
초기화가 끝났는가?

이다.


✅ 4. Liveness

Liveness는:

프로세스를 재시작해야 할 정도로 죽어 있는가?

를 판단한다.

정상 예:

Event Loop 정상

프로세스 정상

치명적 Deadlock 없음

이다.


✅ 5. Liveness에 모든 Dependency를 넣으면 안 된다

예를 들어 DB가 잠깐 장애라고 하자.

Liveness가 DB를 검사해서:

DB DOWN
→ Liveness FAIL

로 판단하면 인프라가 서버를 계속 재시작할 수 있다.

하지만 서버 재시작으로 DB 장애가 해결되는 것은 아니다.


✅ 6. 오히려 Restart Loop가 발생할 수 있다

DB 장애

↓

App Liveness FAIL

↓

App Restart

↓

DB 여전히 장애

↓

Liveness FAIL

↓

Restart

가 반복된다.


✅ 7. 그래서 Liveness는 최소한으로 유지한다

일반적으로:

프로세스 자체가 정상적으로 동작 가능한가?

정도만 확인한다.


✅ 8. Readiness

Readiness는:

이 Instance가 현재 실제 Traffic을 받아도 되는가?

를 판단한다.

여기에는 Dependency가 더 중요하다.

예:

DB 연결 가능

필수 Config 로드 완료

Application Initialization 완료

등이다.


✅ 9. Readiness가 FAIL이면 서버를 죽이지 않는다

대신:

Load Balancer에서 Traffic 제외

하는 것이 핵심이다.

즉:

프로세스는 살아 있음

하지만 새 요청은 받지 않음

상태가 가능하다.


✅ 10. 이 구분이 배포에서도 중요하다

신규 Instance가 실행됐다.

Node Process 시작

했다고 바로 Traffic을 보내면 안 된다.

아직:

Config Loading

DB 연결

Module Initialization

Cache 준비

가 끝나지 않았을 수 있다.


✅ 11. Startup Check

Startup은:

애플리케이션 초기 준비가 완료됐는가?

를 본다.

예:

필수 Env/SSM 값 로딩

DB 연결 확인

Module 초기화

중요 Schema Version 검증

이다.


✅ 12. 전체 흐름

Process Start
↓
STARTING
↓
초기화
↓
READY
↓
Traffic 수신

처럼 보는 것이 좋다.


✅ 13. 서비스 상태 모델

예:

STARTING

READY

NOT_READY

DRAINING

STOPPING

STOPPED

정도로 볼 수 있다.


✅ 14. /health/live

예:

GET /health/live

는 Liveness용이다.

응답:

{
  "status": "ok"
}

정도면 충분할 수 있다.


✅ 15. /health/ready

예:

GET /health/ready

는 실제 Traffic 가능 여부를 본다.

예:

{
  "status": "ready"
}

또는:

{
  "status": "not_ready"
}

이다.


✅ 16. 내부 상세 Health와 외부 Health를 분리할 수 있다

외부 Health:

status만

내부 운영용 Health:

DB

Queue

Config

Version

Worker

상태를 더 자세히 보여준다.


✅ 17. Public Health Endpoint에서 내부 구조를 너무 많이 노출하지 않는다

나쁜 예:

{
  "dbHost": "prod-rds-xxx",
  "redisHost": "...",
  "awsRegion": "...",
  "secretVersion": "..."
}

같은 정보는 불필요하다.


✅ 18. 외부에서는 단순 상태만

예:

{
  "status": "ok"
}

정도로 충분하다.


✅ 19. 내부 운영 Endpoint

인증된 내부 경로에서는:

{
  "status": "degraded",
  "checks": {
    "database": "ok",
    "queue": "degraded"
  }
}

정도로 볼 수 있다.


✅ 20. Dependency Health Check

예:

PostgreSQL

Redis / Queue

S3

SSM

External Notification Provider

Notion

LLM Provider

등이 있다.

하지만 전부 Readiness에 넣으면 안 된다.


✅ 21. Dependency를 Critical / Optional로 구분한다

예:

Critical

PostgreSQL

없으면 주문/관리 기능 대부분이 동작하지 않는다.

Optional

Notion

AI Analysis Provider

Recommendation API

없어도 핵심 서비스는 동작할 수 있다.


✅ 22. Optional Dependency 장애 때문에 서버 전체 Readiness를 FAIL시키지 않는다

예:

Notion DOWN

이라고 홈페이지 주문까지 Load Balancer에서 빼버리는 것은 과하다.


✅ 23. Health Criticality

예:

type DependencyCriticality =
  | 'CRITICAL'
  | 'IMPORTANT'
  | 'OPTIONAL';

정도로 나눌 수 있다.


✅ 24. Critical Dependency FAIL

예:

DB DOWN

이라면:

Readiness
NOT_READY

가 합리적일 수 있다.


✅ 25. Optional Dependency FAIL

예:

AI Provider DOWN

이면:

Readiness
READY

Service State
DEGRADED

로 둘 수 있다.


✅ 26. Health와 Degraded Mode 연결

1005에서:

NORMAL

DEGRADED

OVERLOADED

상태를 다뤘다.

Health 시스템과 연결하면:

Optional Dependency FAIL

↓

DEGRADED

로 볼 수 있다.


✅ 27. Health Check가 실제 업무를 수행하면 안 된다

예를 들어:

Health Check마다
DB에 INSERT

하거나:

실제 알림톡 발송

하면 안 된다.


✅ 28. Health Check는 가볍게

DB는 예:

SELECT 1;

정도면 충분하다.


✅ 29. 하지만 SELECT 1만으로 모든 DB 문제를 찾을 수 있는 것은 아니다

예:

DB 연결은 됨

하지만 Connection Pool 포화

중요 Table Lock

Migration 불일치

는 못 잡을 수 있다.


✅ 30. Health와 Observability를 구분한다

Health:

지금 요청 받을 수 있는가?

Observability:

왜 느린가?

어디가 포화됐는가?

이다.

Health Endpoint 하나에 모든 진단을 넣지 않는다.


✅ 31. DB Health

초기에는:

Connection 가능 여부

짧은 Query 성공 여부

면 충분하다.


✅ 32. DB Pool 상태는 Metric으로 본다

예:

active connections

idle

waiting

등이다.


✅ 33. Queue Health

Queue 시스템 자체 연결 상태를 확인할 수 있다.

하지만:

Queue Depth = 1000

이라고 바로 Health FAIL로 볼 필요는 없다.


✅ 34. Queue Depth는 Capacity/Backpressure Metric

1005에서 다룬:

queue_depth

oldest_job_age

가 더 적합하다.


✅ 35. Queue 자체가 완전히 사용할 수 없다면

예:

Redis Queue Connection FAIL

이고 해당 Queue가 핵심 기능에 필수라면 Readiness에 영향을 줄 수 있다.


✅ 36. 예: 주문 저장 후 후속 Job이 반드시 필요한 구조

Queue가 없으면 업무 누락 위험이 크다면:

Readiness NOT_READY

를 고려한다.


✅ 37. 하지만 Outbox가 있다면 판단이 달라질 수 있다

1001의 Outbox가 있으면:

DB Transaction

↓

Outbox 저장

까지는 가능하다.

Queue가 잠시 내려가도 Event가 DB에 보존된다.


✅ 38. 따라서 Queue 장애 시에도 핵심 Write를 계속 받을 수 있을 수 있다

이게 Outbox의 운영 장점 중 하나다.

다만:

Outbox Backlog

가 너무 커지면 결국 Admission Control이 필요하다.


✅ 39. 외부 Provider Health

예:

알림톡 Provider

가 DOWN이라고 매 Health Check마다 Provider API를 호출하는 것도 문제다.


✅ 40. Health Check가 Provider 부하를 만들 수 있다

서버 10대가:

5초마다 Provider Health 호출

하면 그 자체가 불필요한 Traffic이다.


✅ 41. Provider Health는 최근 실제 요청 결과를 활용할 수도 있다

예:

최근 1분
Error Rate 80%

이면:

UNHEALTHY

로 판단한다.


✅ 42. 직접 Probe와 Passive Health를 구분한다

Active Probe

직접 Ping / API 호출

Passive Health

실제 요청 Error/Latency 기반

이다.


✅ 43. 둘을 적절히 조합한다

DB는 Active Probe.

External Provider는 Passive Health 중심.

같은 방식이 가능하다.


✅ 44. Health Check Timeout

Health Check 자체가 오래 걸리면 안 된다.

예:

DB Probe 5초 대기

하면 Load Balancer Health 판단도 느려진다.


✅ 45. Health Probe에는 짧은 Timeout

예:

500ms

1s

등 보수적으로 둔다.

정확한 값은 환경에 맞춘다.


✅ 46. Health 결과 Cache

Dependency마다 매 Request 시 Health를 직접 검사하지 않는다.

예:

5초마다 Health 계산

현재 상태 Memory 저장

할 수 있다.


✅ 47. /health/ready는 현재 계산된 상태를 빠르게 반환

Load Balancer Probe가 잦아도 DB에 매번 Query를 던지지 않게 할 수 있다.


✅ 48. 단 Health Cache가 너무 오래되면 안 된다

예:

10분 Cache

는 장애 감지가 너무 느리다.


✅ 49. Health State는 짧은 주기로 갱신한다

예:

5초

10초

정도다.

환경에 맞춘다.


✅ 50. Graceful Shutdown

서버를 종료할 때:

Process Kill

해버리는 것이 아니라:

새 일을 받는 것을 중단하고, 현재 진행 중인 일을 가능한 안전하게 마무리한 뒤 종료하는 것

이다.


✅ 51. 배포할 때도 Shutdown은 발생한다

예:

새 Version 배포

↓

Old Instance 종료

이다.

Old Instance가 요청 처리 중이라면 종료 전략이 필요하다.


✅ 52. 나쁜 종료

SIGTERM

↓

즉시 process.exit()

하면:

HTTP 요청 중단

DB Transaction 중단

파일 생성 중단

Queue Job 중간 종료

될 수 있다.


✅ 53. 좋은 종료 흐름

SIGTERM 수신

↓

Readiness OFF

↓

새 요청 차단

↓

현재 HTTP 요청 Drain

↓

Worker 신규 Job Claim 중단

↓

진행 중 Job 완료/Checkpoint

↓

DB/Queue Connection 종료

↓

Process 종료

이다.


✅ 54. 가장 먼저 Readiness를 내린다

예:

READY
→
DRAINING

한다.

그러면 Load Balancer가 새 Traffic을 다른 Instance로 보낸다.


✅ 55. Readiness OFF 직후 바로 서버를 죽이면 안 된다

Load Balancer가 변경을 감지하는 데 시간이 걸릴 수 있다.


✅ 56. Drain Delay

예:

Readiness OFF

↓

몇 초 대기

↓

HTTP Server Close 시작

같은 짧은 Drain Window를 둘 수 있다.


✅ 57. 정확한 시간은 Infrastructure에 맞춘다

Load Balancer Health Check 주기와 Deregistration Delay 등을 확인해야 한다.


✅ 58. HTTP Server close

Node.js HTTP Server는 새 Connection을 받지 않고 기존 Connection이 끝나길 기다리는 방식으로 종료할 수 있다.


✅ 59. 하지만 Keep-Alive가 있으면 종료가 오래 걸릴 수 있다

Client가 연결을 오래 유지할 수 있다.

따라서 최대 Shutdown Deadline이 필요하다.


✅ 60. Graceful Shutdown Timeout

예:

최대 30초

동안 기다리고 이후 강제 종료.

정확한 값은 업무 특성에 맞춘다.


✅ 61. 종료는 무한정 기다릴 수 없다

Job 하나가 Bug로:

2시간

걸린다고 Deployment가 2시간 멈춰서는 안 된다.


✅ 62. Shutdown Deadline

예:

SIGTERM
T0

Graceful Deadline
T0 + 30s

처럼 둔다.


✅ 63. Deadline 전에 완료하면 정상 종료

Deadline을 넘기면:

현재 상태 저장

Lease 만료 가능 상태

강제 종료

가 필요하다.


✅ 64. Worker Shutdown은 HTTP보다 더 어렵다

HTTP 요청은 보통 짧지만 Worker Job은:

Export

AI Report

대량 알림

Backfill

처럼 오래 걸릴 수 있다.


✅ 65. Worker 종료 시 가장 먼저 새 Job Claim을 중단한다

PAUSE CLAIM

한다.


✅ 66. 이미 실행 중인 Job은 업무 특성에 따라 처리한다

선택:

완료까지 기다림

Checkpoint 후 중단

Lease 만료 후 다른 Worker가 Resume

즉시 Cancel

이다.


✅ 67. 짧은 Job

예:

Notification 한 건
1~2초

이면 완료까지 기다릴 수 있다.


✅ 68. 긴 Job

예:

AI 분석
15분

이면 배포마다 15분 기다리는 것은 어렵다.

Checkpoint/Resume 구조가 필요하다.

0930과 연결된다.


✅ 69. Durable Workflow의 장점

Process는 죽어도 된다.

Workflow State는 DB에 남는다.

원칙이 Graceful Shutdown에서도 중요하다.


✅ 70. Worker가 중간에 죽어도 Resume 가능해야 한다

예:

COLLECT_GIT
SUCCESS

GENERATE_REPORT
SUCCESS

UPLOAD_NOTION
RUNNING

이었다면 다음 Worker가 상태를 복구한다.


✅ 71. Lease 기반 Job Claim

예:

lockedBy
worker_123

leaseUntil
10:30

을 가진다.


✅ 72. Worker 정상 종료 시 Lease를 Release할 수 있다

예:

RUNNING
→
PENDING

또는:

RETRY_PENDING

으로 되돌린다.


✅ 73. 하지만 외부 Side Effect 중간이라면 단순 Release가 위험하다

예:

알림톡 API 호출

요청을 보낸 직후 Shutdown.

응답을 아직 못 받았다.


✅ 74. 결과가 UNKNOWN일 수 있다

이 경우:

PENDING으로 되돌리고 다시 실행

하면 중복 발송 가능성이 있다.


✅ 75. 따라서:

RUNNING
→
UNKNOWN

또는 Reconciliation 대상 상태가 필요하다.

0916/0917과 연결된다.


✅ 76. Shutdown이 발생했다고 Blind Retry하지 않는다

외부 Side Effect는:

실제 실행 여부 확인

후 재시도한다.


✅ 77. Worker 종료 Hook

예:

process.on('SIGTERM', async () => {
  await worker.pause();
  await worker.drain();
  await shutdown();
});

같은 개념이다.


✅ 78. NestJS Shutdown Hook

NestJS에서는 Application Shutdown Hook을 사용할 수 있다.

예:

app.enableShutdownHooks();

를 통해 종료 이벤트를 연결할 수 있다.


✅ 79. 하지만 Hook을 켜는 것만으로 Graceful Shutdown이 완성되지는 않는다

각 Resource가:

HTTP

DB

Queue

Worker

Scheduler

에서 어떻게 종료되는지 설계해야 한다.


✅ 80. Shutdown 순서가 중요하다

좋은 예:

1. Readiness OFF

2. Scheduler Trigger 중단

3. 신규 Queue Claim 중단

4. HTTP 신규 요청 중단

5. 진행 중 작업 Drain

6. Resource Close

7. Process Exit

이다.


✅ 81. Scheduler부터 중단

Shutdown 중인데 새 Job을 계속 만들면 안 된다.


✅ 82. Cron/Scheduler Lock Release

Leader 역할을 수행하고 있었다면:

Scheduler Lease

를 안전하게 넘겨야 한다.


✅ 83. 다음 Instance가 Scheduler를 이어받을 수 있어야 한다

Single Scheduler 구조라면 특히 중요하다.


✅ 84. HTTP 요청 Drain

현재 처리 중인 요청 수를 추적할 수 있다.

예:

activeRequests

Counter를 둔다.


✅ 85. 새 요청이 시작되면 +1

끝나면 -1.

Shutdown 시:

activeRequests == 0

을 기다린다.


✅ 86. 하지만 Health Check 요청은 별도로 처리한다

DRAINING 상태에서도:

/health/live

는 응답 가능해야 한다.


✅ 87. /health/ready는 DRAINING이면 실패

예:

{
  "status": "not_ready",
  "reason": "draining"
}

정도다.


✅ 88. Liveness는 DRAINING 동안 정상일 수 있다

Process 자체는 살아 있기 때문이다.


✅ 89. 이 차이가 중요하다

Liveness
OK

Readiness
FAIL

상태가 정상적으로 존재할 수 있다.


✅ 90. 배포 중 Old Instance가 딱 이런 상태가 된다

살아 있지만

새 Traffic은 받지 않음

이다.


✅ 91. Grace Period

Load Balancer에서 Instance가 제외된 후에도 기존 Connection이 남아 있을 수 있다.


✅ 92. Deregistration Delay

Infrastructure Load Balancer가 기존 Request를 처리하도록 시간을 주는 설정이 있을 수 있다.

App Shutdown Timeout과 맞춰야 한다.


✅ 93. App 5초, LB 30초처럼 어긋나면

App이 먼저 죽어 기존 Request가 끊길 수 있다.


✅ 94. 반대로 App 5분, Deployment Timeout 30초도 문제다

배포 시스템이 강제로 Kill할 수 있다.


✅ 95. Shutdown Timing을 전체 시스템 기준으로 본다

Load Balancer

Deployment System

Container/EC2 Process

Application

Worker

설정을 맞춘다.


✅ 96. SIGTERM과 SIGKILL

일반적으로:

SIGTERM
=
정상 종료 요청
SIGKILL
=
즉시 강제 종료

로 생각하면 된다.


✅ 97. SIGKILL에는 Cleanup 기회가 없다

따라서 SIGTERM 단계에서 최대한 상태를 안전하게 만든다.


✅ 98. SIGINT도 로컬 개발에서는 고려할 수 있다

예:

Ctrl + C

이다.


✅ 99. Shutdown Handler는 Idempotent해야 한다

여러 Signal이 들어와도:

cleanup
두 번 실행

되어 문제 생기지 않게 한다.


✅ 100. 예

if (isShuttingDown) {
  return;
}

isShuttingDown = true;

같은 Guard를 둔다.


✅ 101. Shutdown 중 새 Workflow 시작 차단

예:

POST /automation/run

요청이 Drain 시작 후 들어오면:

503

등으로 거절할 수 있다.


✅ 102. 진행 중 Workflow는 계속 상태를 기록한다

Worker 종료 Deadline이 오기 전에 Checkpoint를 남긴다.


✅ 103. AI Worker Shutdown

예:

Ollama Generation

이 10분 걸리는 상황.

선택:

Generation 완료 기다림

Generation Cancel

Artifact Checkpoint 후 Retry

가 있다.


✅ 104. Local LLM은 Resume 구조가 중요하다

LLM 생성 자체를 중간 Token부터 Resume하기는 어렵다.

따라서:

LLM Step

자체는 다시 실행될 수 있다.


✅ 105. 하지만 이전 Step은 재사용한다

예:

Git Context 수집
SUCCESS

Context Artifact
저장

↓

LLM Step만 재실행

한다.


✅ 106. AI Run Shutdown 상태

예:

RUNNING
→
INTERRUPTED

또는:

RETRY_PENDING

을 사용할 수 있다.


✅ 107. 모델 호출이 외부 API라면 UNKNOWN도 고려

Request 전송 후 응답을 못 받고 종료됐다면 Provider 비용은 이미 발생했을 수 있다.


✅ 108. Token/Cost Budget도 Attempt에 반영

Retry 시 중복 비용 가능성을 기록한다.


✅ 109. Export Worker Shutdown

대형 Excel 파일 생성 중이라면:

임시 파일

이 남을 수 있다.


✅ 110. Temporary Artifact 상태

예:

BUILDING

COMPLETE

ABORTED

를 둘 수 있다.


✅ 111. ABORTED 파일은 Cleanup 대상

1003의 Retention/Cleanup과 연결된다.


✅ 112. S3 Multipart Upload 중 종료됐다면

미완료 Upload가 남을 수 있다.

이런 Temporary Resource Cleanup도 고려한다.


✅ 113. DB Transaction 중 Shutdown

보통 Process가 종료되면 Connection이 끊기고 Transaction은 Rollback될 수 있다.

하지만 이것만 믿지 않는다.


✅ 114. 긴 Transaction을 피하는 것이 우선

Shutdown과 무관하게:

짧은 Transaction

이 운영에 유리하다.


✅ 115. Migration 중 Shutdown

Schema Migration 도중 Process가 죽으면 특히 위험하다.


✅ 116. Migration과 Application Lifecycle을 분리

Production Application 시작할 때:

매번 자동 Migration 실행

하는 구조는 신중해야 한다.


✅ 117. 여러 Instance가 동시에 Migration을 실행하면 안 된다

Migration Runner를 별도로 관리하거나 Lock이 필요하다.


✅ 118. Migration 완료 전 신버전 Readiness를 열지 않는다

1002의 Compatibility와 연결된다.


✅ 119. Version Compatibility Check

예:

Application requiredSchemaVersion
2026100601

DB가 아직:

2026100503

이면 Readiness를 열지 않는다.


✅ 120. 하지만 Migration을 자동 Rollback하려 하지 않는다

DB Migration은 Roll Forward가 더 안전한 경우가 많다.


✅ 121. Startup Dependency Initialization

예:

Config

Logger

DB

Queue

Cache

Scheduler

순서로 초기화할 수 있다.


✅ 122. Optional Dependency는 늦게 붙어도 된다

예:

Notion

연결 실패 때문에 전체 Application Startup을 막지 않는다.


✅ 123. Lazy Initialization도 가능

실제로 기능이 호출될 때 외부 Client를 초기화한다.


✅ 124. 하지만 첫 요청 Latency가 커질 수 있다

Trade-off다.


✅ 125. Critical Client는 Startup에서 검증

예:

PostgreSQL

은 미리 확인하는 편이 좋다.


✅ 126. Cache는 Startup 필수일까?

1004 원칙대로 Cache가 없어도 DB fallback 가능하다면:

Redis Cache DOWN

이 전체 Readiness FAIL 이유가 아닐 수 있다.


✅ 127. Queue Redis라면 다를 수 있다

같은 Redis가 핵심 Queue를 담당한다면 영향이 더 크다.


✅ 128. 같은 Redis라도 역할별 Criticality가 다르다

Cache

Queue

Session

중 무엇을 담당하는지 봐야 한다.


✅ 129. 단순 “Redis DOWN” Health만으로는 부족

실제 역할 기준으로 판단한다.


✅ 130. Health Aggregation

예:

database
CRITICAL
OK

queue
IMPORTANT
OK

cache
OPTIONAL
DOWN

notion
OPTIONAL
DOWN

이면 전체:

DEGRADED

지만 Readiness는 READY일 수 있다.


✅ 131. Health Status

예:

HEALTHY

DEGRADED

UNHEALTHY

로 나눌 수 있다.


✅ 132. Readiness와 Health Status는 별개

Health
DEGRADED

Readiness
READY

가 가능하다.


✅ 133. 관리자 Dashboard에는 이 구분이 유용하다

예:

서비스
DEGRADED

고객 주문
정상

AI Report
장애

처럼 표현한다.


✅ 134. Health 상태가 자주 튀면 문제다

예:

READY

NOT_READY

READY

NOT_READY

가 초 단위로 반복되면 Load Balancer가 Traffic을 계속 넣고 뺄 수 있다.


✅ 135. Flapping

이런 상태를 Health Flapping이라고 볼 수 있다.


✅ 136. 실패 Threshold

한 번 Probe 실패했다고 바로 NOT_READY로 바꾸지 않을 수 있다.

예:

연속 3회 실패
→ NOT_READY

이다.


✅ 137. 복구 Threshold

정상 Probe도:

연속 2회 성공
→ READY

처럼 둘 수 있다.


✅ 138. Hysteresis와 같은 원리

1005에서 Overload 상태 전환과 비슷하다.


✅ 139. Critical DB 장애는 너무 늦게 반응해서도 안 된다

Threshold는 Dependency 특성에 맞춘다.


✅ 140. Health 상태에 Timestamp

예:

lastSuccessAt

lastFailureAt

consecutiveFailures

을 관리하면 좋다.


✅ 141. 하지만 Public Endpoint에 상세 시각을 노출할 필요는 없다

내부 Monitoring에서 사용한다.


✅ 142. Health Check Metrics

예:

health_check_total

health_check_failure_total

readiness_state

dependency_health_state

등이다.


✅ 143. Readiness 전환 Metric

ready → not_ready

횟수가 갑자기 늘면 문제를 알 수 있다.


✅ 144. Shutdown Metrics

예:

shutdown_started_total

graceful_shutdown_success_total

forced_shutdown_total

shutdown_duration

정도다.


✅ 145. Forced Shutdown이 자주 발생하면 구조 문제다

예:

Worker Job이 너무 오래 걸림

Shutdown Deadline 부족

Drain 실패

일 수 있다.


✅ 146. Active Request Metric

http_active_requests

를 보면 Drain 진행 상태를 알 수 있다.


✅ 147. Active Job Metric

worker_active_jobs

도 중요하다.


✅ 148. Shutdown Progress

예:

DRAINING

HTTP Active
3

Worker Active
1

Deadline Remaining
12s

같은 내부 상태를 볼 수 있다.


✅ 149. 새 요청 거절 기준

DRAINING 상태에서는:

일반 API
503

로 거절하거나 Load Balancer에서 애초에 전달되지 않게 한다.


✅ 150. 이미 들어온 요청은 가능하면 완료

이게 Graceful Drain의 기본이다.


✅ 151. Streaming/WebSocket은 더 까다롭다

연결이 오래 지속될 수 있기 때문이다.


✅ 152. WebSocket 서버가 있다면 종료 전에 Client에 종료 신호를 보낼 수 있다

예:

server_maintenance

Event를 보내고 Client가 Reconnect하도록 한다.


✅ 153. 현재 실시간 Queue 현황 페이지 같은 기능을 WebSocket으로 확장하면 고려할 부분이다

단 지금 실제 WebSocket이 없다면 미리 과도하게 구현할 필요는 없다.


✅ 154. SSE도 장기 Connection이다

Shutdown 시 Reconnect 전략이 필요하다.


✅ 155. Client Reconnect에는 Backoff/Jitter

모든 Client가 동시에 재연결하면 Restart 직후 Traffic Spike가 생긴다.


✅ 156. Connection Draining

Load Balancer/Server가 기존 Connection은 유지하되 신규 Connection을 다른 Instance로 보내는 구조다.


✅ 157. 무중단 배포의 핵심 요소

New Instance READY

↓

Traffic Shift

↓

Old Instance DRAINING

↓

Old Instance STOP

이다.


✅ 158. 배포 순서

예:

1. New Version 시작

2. Startup 완료

3. Readiness PASS

4. Traffic 일부 전환

5. Health/SLI 확인

6. Old Version Readiness OFF

7. Old Version Drain

8. Old Version 종료

이다.


✅ 159. 이게 Canary/Blue-Green과도 연결된다

0927 Release Safety에서 다룬 배포 구조의 기반이다.


✅ 160. 새 Instance Readiness가 잘못되면 배포가 실패한다

예:

Process 시작
→ READY

를 너무 빨리 내면 초기화 중 Traffic을 받는다.


✅ 161. 반대로 Readiness가 너무 엄격하면

Optional Dependency 하나 때문에 신규 Instance가 영원히 Traffic을 못 받을 수 있다.


✅ 162. 그래서 Critical Dependency를 명확히 정해야 한다


✅ 163. Readiness Gate 예

App Initialized
AND
DB Healthy
AND
Required Config Loaded
AND
Schema Compatible

이면 READY.


✅ 164. Optional Check는 별도 Health 상태

Cache
Notion
AI

등이다.


✅ 165. Config Readiness

필수 Config가 없는 서버가 시작되는 것을 막는다.

예:

JWT Secret

DB URL

필수 AWS Parameter

등이다.


✅ 166. 단 Health Endpoint에 Secret 값을 노출하지 않는다

configured: true

정도만 본다.


✅ 167. Config Validation은 Startup에서 수행

예:

필수 값 없음
→ Process Start 실패

가 더 낫다.


✅ 168. 시작은 됐는데 요청할 때마다 Env Missing Error가 나는 것보다 낫다

Fail Fast 원칙이다.


✅ 169. Startup Failure와 Runtime Failure를 구분한다

Startup:

필수 설정 없음

Runtime:

외부 Provider 잠시 장애

이다.


✅ 170. Startup Failure는 바로 실패시켜도 된다

Deployment가 문제를 감지한다.


✅ 171. Runtime Optional Failure는 Degraded로 운영

전체 서버를 계속 재시작하지 않는다.


✅ 172. Health Endpoint에 DB Migration 실행 넣지 않는다

Health는 확인만 한다.

변경 작업을 하지 않는다.


✅ 173. Health Check는 Side Effect Free

이 원칙이 중요하다.

읽기

검증

상태 확인

만 한다.


✅ 174. Health Check 자체가 Incident를 만들면 안 된다


✅ 175. Graceful Shutdown과 Idempotency

Shutdown 중 Request가 끊겨 Client가 Retry할 수 있다.

예:

POST /orders

응답 직전에 서버 종료.


✅ 176. DB에는 주문이 생성됐는데 Client는 Timeout을 봄

Client가 재시도하면 중복 주문 위험이 있다.


✅ 177. 그래서 중요한 POST에는 Idempotency가 필요하다

0916과 직접 연결된다.


✅ 178. Graceful Shutdown으로 모든 불확실 상태를 없앨 수는 없다

Network는 언제든 끊길 수 있다.


✅ 179. 결국:

Graceful Shutdown
+
Idempotency
+
Reconciliation

이 함께 필요하다.


✅ 180. Worker도 동일

Shutdown을 아무리 잘 해도 서버 전원 장애는 발생할 수 있다.

따라서:

Lease

Checkpoint

Idempotency

가 최종 안전장치다.


✅ 181. Graceful Shutdown은 복구 설계를 대체하지 않는다

중요 원칙이다.


✅ 182. Maintenance Mode

대규모 Migration 등으로 일부 기능을 잠시 막아야 할 수 있다.


✅ 183. 전체 Maintenance와 Partial Maintenance를 구분

예:

전체 고객 주문
OFF

보다:

관리자 Export
OFF

만 필요한 경우가 많다.


✅ 184. 기능별 Maintenance Flag

예:

order_write_enabled

export_enabled

ai_enabled

같은 Feature Flag와 연결한다.


✅ 185. Read-only Mode

DB Maintenance 때:

조회 가능

수정 불가

모드가 유용할 수 있다.


✅ 186. 예

Product Read
OK

Order Create
503 / Maintenance

형태다.


✅ 187. Read-only Mode도 Source of Truth를 명확히

Frontend 버튼만 숨기면 안 된다.

Backend에서 Write를 거절해야 한다.


✅ 188. Maintenance Response

예:

503 Service Unavailable

와 명확한 Error Code:

SERVICE_MAINTENANCE

를 사용할 수 있다.


✅ 189. Retry-After

예정된 Maintenance라면 Retry-After나 메시지를 제공할 수 있다.


✅ 190. 하지만 정확한 복구 시간을 모르면 거짓 ETA를 제공하지 않는다


✅ 191. Scheduled Maintenance와 Scheduler

Maintenance 동안:

Cron Job

이 계속 실행되면 문제일 수 있다.


✅ 192. 일부 Scheduler를 Pause

예:

Report

Cleanup

Backfill

등 Low Priority Job을 일시 중지한다.


✅ 193. 핵심 Reconciliation Job은 계속 필요할 수도 있다

모든 Scheduler를 무조건 끄지 않는다.


✅ 194. Shutdown과 Cleanup Job

1003 Cleanup이 실행 중인데 Deployment가 시작되면:

현재 Batch 완료

Checkpoint

중단

정도로 처리할 수 있다.


✅ 195. 다음 Instance가 Resume

CutoffAt과 Cursor가 고정되어 있으므로 이어갈 수 있다.


✅ 196. Backfill Job도 동일

1002 Migration Backfill:

lastCursor

processedCount

를 저장하면 Resume 가능하다.


✅ 197. 배포와 장기 Job을 같은 Process에 둘지 생각해야 한다

장기 Worker가 Web API와 같은 Process에 있으면:

API Deploy
→ Worker도 종료

된다.


✅ 198. Worker Process 분리 장점

예:

api

worker

scheduler

를 별도 Process로 운영하면 배포 영향 범위를 줄일 수 있다.


✅ 199. 하지만 현재 규모에서는 과할 수도 있다

먼저 같은 코드베이스라도:

PROCESS_ROLE=api

PROCESS_ROLE=worker

정도로 분리할 수 있다.


✅ 200. 실제 필요성이 생긴 뒤 Infrastructure까지 분리한다


✅ 201. Process Role

예:

API

WORKER

SCHEDULER

로 나눈다.


✅ 202. Role별 Readiness도 다르다

API:

DB ready?
HTTP ready?

Worker:

Queue ready?
DB ready?

Scheduler:

DB?
Leader Lock?

등이다.


✅ 203. Worker에는 HTTP Readiness가 필요 없을 수도 있다

운영 Probe용 작은 Health Server만 열 수 있다.


✅ 204. Scheduler Health

단순 Process가 살아 있는 것뿐 아니라:

lastTickAt

lastSuccessfulRun

등을 확인할 수 있다.


✅ 205. Scheduler가 살아 있지만 Job을 하나도 생성하지 않는 Silent Failure를 잡아야 한다


✅ 206. Worker Health도 마찬가지

Process는 살아 있는데:

lastJobProcessedAt
3시간 전

일 수 있다.


✅ 207. 이건 Liveness보다는 Operational Health다

자동 재시작보다는 Alert가 적합할 수 있다.


✅ 208. Last Activity Metric

예:

worker_last_success_timestamp

scheduler_last_tick_timestamp

를 둔다.


✅ 209. 기대 Activity가 없는 시간대도 고려

새벽에 Job이 없을 수 있으므로 단순:

10분 Job 처리 없음
→ 장애

라고 판단하면 안 된다.


✅ 210. Queue에 Pending이 있는데 처리 없음

이 조합이 더 의미 있다.

queue_depth > 0

AND

worker_active = 0

AND

lastProcessed 오래됨

이면 문제 가능성이 높다.


✅ 211. Health는 Context 기반으로 본다

단일 Metric 하나로 판단하지 않는다.


✅ 212. Graceful Shutdown 실패 원인

예:

HTTP Keep-Alive

무한 Retry Job

External API Hang

DB Query Hang

Worker Cancel 미지원

등이다.


✅ 213. 그래서 모든 외부 작업에 Timeout이 필요하다

0924/1005와 연결된다.

Shutdown Deadline보다 긴 Network Timeout이 있으면 종료가 늦어진다.


✅ 214. 예

Shutdown Deadline
30s

External API Timeout
120s

는 좋지 않다.


✅ 215. Shutdown 정책과 Timeout 정책을 맞춘다


✅ 216. Request Cancellation

Client가 연결을 끊었을 때 Backend가 불필요한 작업을 계속할 수 있다.


✅ 217. AbortSignal 등을 활용할 수 있다

지원 가능한 작업에서는:

Client disconnected

↓

External request cancel

할 수 있다.


✅ 218. 하지만 DB Transaction처럼 이미 중요한 Write가 시작됐다면 함부로 Cancel하면 안 된다

업무 특성에 따라 다르다.


✅ 219. Read Query는 취소하기 쉬운 편

Write는 상태 일관성이 더 중요하다.


✅ 220. Graceful Shutdown에서도 Cancel 가능/불가능 Action을 구분한다


✅ 221. Shutdown Priority

예:

Critical Write
완료 우선

Read Request
종료 가능

Low Priority AI
Checkpoint 후 중단

처럼 나눌 수 있다.


✅ 222. 모든 작업을 똑같이 기다릴 필요 없다


✅ 223. Draining 중 Retry를 새로 시작하지 않는다

예:

현재 Job 실패

shutdown 진행 중

이라면 같은 Process에서 새 Retry Attempt를 시작하지 않고 Queue로 넘긴다.


✅ 224. Shutdown 중 신규 Child Job 생성도 신중

Parent가 끝나기 전에 Process가 죽을 수 있다.

Outbox나 Transactional Job 생성 구조를 활용한다.


✅ 225. Drain State를 공통 Context로 제공

예:

shutdownService.isDraining()

으로 여러 Module이 확인할 수 있다.


✅ 226. 단 Business Logic 곳곳에서 직접 분기하지 않는다

Middleware/Worker/Scheduler Entry Point에서 처리하는 편이 낫다.


✅ 227. Shutdown Coordinator

예:

ShutdownCoordinator

├─ HTTP
├─ Scheduler
├─ Worker
├─ Queue
├─ DB
└─ Cache

순서대로 종료를 조정한다.


✅ 228. Resource마다 Lifecycle Interface

예:

interface ManagedResource {
  stopAcceptingWork(): Promise<void>;
  drain(): Promise<void>;
  close(): Promise<void>;
}

정도로 추상화할 수 있다.


✅ 229. 하지만 범용 Framework를 너무 크게 만들 필요는 없다

처음에는 명시적 Shutdown Service 하나면 충분하다.


✅ 230. Shutdown 로그

예:

shutdown.started

readiness.disabled

scheduler.paused

worker.claim.paused

http.draining

worker.drained

db.closed

shutdown.completed

를 남긴다.


✅ 231. Correlation ID는 Shutdown 전체에 꼭 필요하지 않을 수 있다

대신:

instanceId

releaseId

가 중요하다.


✅ 232. Release ID 연결

예:

{
  "event": "shutdown.started",
  "instanceId": "api-2",
  "releaseId": "release_20261006_01"
}

정도다.


✅ 233. 왜 종료됐는지도 기록

예:

DEPLOYMENT

MANUAL

CRASH

AUTOSCALING

HEALTH_RESTART

등이다.


✅ 234. 정상 종료와 Crash를 구분한다

Crash에는 Graceful Hook이 실행되지 않을 수 있다.


✅ 235. Startup에서 이전 비정상 종료 흔적을 찾을 수도 있다

예:

stale lease

RUNNING job

unfinished workflow

를 Reconciler가 복구한다.


✅ 236. Instance Heartbeat

Worker Instance가:

lastHeartbeatAt

을 기록하면 죽은 Worker가 잡고 있던 Job을 찾기 쉽다.


✅ 237. 하지만 Heartbeat를 너무 자주 DB에 쓰면 부하

예:

1초마다 모든 Worker DB UPDATE

는 과할 수 있다.


✅ 238. 몇 초~수십 초 단위로 충분할 수 있다

업무 SLA에 맞춘다.


✅ 239. Worker Registration

예:

workerId

startedAt

lastHeartbeatAt

status

를 저장할 수도 있다.


✅ 240. 현재 규모에서는 Queue 자체 Worker 상태로 충분하면 별도 Table이 필요 없을 수도 있다


✅ 241. Dependency Health와 Circuit Breaker 연결

Provider Circuit이 OPEN이면:

provider health
UNHEALTHY

로 볼 수 있다.


✅ 242. 하지만 App Readiness는 계속 READY

Optional Provider라면 전체 Traffic을 막지 않는다.


✅ 243. 관리자 Dashboard에 Circuit State 표시

예:

Kakao Provider
CIRCUIT OPEN

AI Provider
HEALTHY

같이 본다.


✅ 244. Health Check와 Rate Limit 연결

Health Probe가 일반 API Rate Limit에 걸리면 안 된다.


✅ 245. Health Endpoint는 별도 정책

하지만 Public 인터넷에 무제한 노출할 필요도 없다.


✅ 246. Health Probe IP/Infrastructure 경로를 구분할 수 있다

환경에 맞춘다.


✅ 247. Health Endpoint에 인증을 붙이면 Load Balancer 지원 여부를 확인해야 한다

외부 Probe는 보통 단순 Endpoint가 필요할 수 있다.


✅ 248. Public Liveness는 최소 정보

Detailed Diagnostics는 인증된 Internal Endpoint.

이 분리가 현실적이다.


✅ 249. Health Response Cache-Control

Health Response가 CDN/Browser에 Cache되면 안 된다.


✅ 250. 오래된 Health 상태를 받으면 의미가 없다

따라서:

Cache-Control: no-store

같은 정책을 고려한다.


✅ 251. Health Probe에 DB Query가 폭증하지 않게 한다

앞서 말한 내부 상태 Cache를 이용할 수 있다.


✅ 252. N개의 Instance가 각각 매초 DB Probe를 하면 DB에 불필요한 Traffic

현재 작은 규모에서는 큰 문제는 아니지만 확장 시 고려한다.


✅ 253. Synthetic Health

실제 사용자 흐름을 가볍게 테스트하는 Synthetic Check도 있다.

예:

상품 목록 API

로그인 없이 조회

를 외부 Monitoring이 주기적으로 요청한다.


✅ 254. Liveness/Readiness와 Synthetic Check는 역할이 다르다

Liveness:

프로세스 살았나?

Readiness:

Traffic 받아도 되나?

Synthetic:

사용자 관점 기능이 실제 동작하나?

이다.


✅ 255. 주문 생성 Synthetic은 위험할 수 있다

실제 주문 데이터가 생길 수 있다.

Test 전용 경로나 Staging에서 수행한다.


✅ 256. Production Synthetic은 Side Effect 없는 Read Journey부터 시작

예:

메인 페이지

상품 목록

상품 상세

이다.


✅ 257. Health Check가 녹색이어도 Synthetic이 실패할 수 있다

예:

DB 연결 OK

App READY

하지만 Product Query Bug
500

이다.


✅ 258. 그래서 여러 수준의 Health가 필요하다

Process

Dependency

User Journey

다.


✅ 259. Graceful Restart 테스트

실제로 배포 전에 테스트해보는 것이 좋다.

시나리오:

요청 처리 중 SIGTERM

이다.


✅ 260. Expected

신규 요청 차단

기존 요청 완료

응답 유실 없음

Process 정상 종료

이다.


✅ 261. Worker Shutdown Test

Job 실행 중 SIGTERM

Expected:

새 Job Claim 중단

진행 중 Job 처리 정책 준수

Lease/상태 정상

다른 Worker Resume 가능

이다.


✅ 262. External Call 중 Shutdown Test

예:

Provider 응답 대기 중 SIGTERM

Expected:

중복 Side Effect 없음

UNKNOWN/Reconciliation 처리

이다.


✅ 263. Shutdown Timeout Test

일부 Job을 의도적으로 Hang시킨다.

Expected:

Deadline 이후 강제 종료

stale lease 복구 가능

이다.


✅ 264. Health Flapping Test

DB Probe를 간헐적으로 실패시킨다.

Expected:

1회 실패로 Traffic 계속 출렁이지 않음

이다.


✅ 265. Optional Dependency Failure Test

예:

Notion DOWN

Expected:

App READY

AI/Report 기능만 DEGRADED

이다.


✅ 266. Critical Dependency Failure Test

DB DOWN

Expected:

Readiness FAIL

Liveness는 상황에 따라 OK

이다.


✅ 267. DB Recovery

Expected:

연속 Health 성공
→ READY 복귀

이다.


✅ 268. Deployment Test

Staging에서:

Traffic 지속

↓

New Release 배포

중 Error Rate를 본다.


✅ 269. Zero-Downtime 성공 기준

예:

5xx Spike 없음

Connection Reset 없음

중복 주문 없음

Queue Job 유실 없음

이다.


✅ 270. Worker 배포 성공 기준

stuck jobs 없음

duplicate side effect 없음

lease recovery 정상

이다.


✅ 271. Health Admin UI

예:

Application
HEALTHY

DB
HEALTHY

Queue
HEALTHY

Cache
DEGRADED

Notification Provider
HEALTHY

AI
DOWN

처럼 볼 수 있다.


✅ 272. 상세 페이지

예:

Dependency

Status

Last Checked

Last Success

Error Code

Criticality

정도다.


✅ 273. Raw Error Stack을 모든 관리자에게 보여줄 필요는 없다

운영자용 메시지와 개발자 Detail을 나눌 수 있다.


✅ 274. Status 이유는 Error Code 중심

예:

DB_TIMEOUT

QUEUE_UNAVAILABLE

CACHE_DEGRADED

PROVIDER_CIRCUIT_OPEN

이다.


✅ 275. Health History

최근:

READY → NOT_READY

전환 이력을 남길 수 있다.

Incident 분석에 도움된다.


✅ 276. 모든 Probe 결과를 DB에 저장할 필요는 없다

Metric/Monitoring 시스템에 남기는 편이 낫다.

상태 전환만 Event로 기록할 수 있다.


✅ 277. Health State Changed Event

예:

application.readiness.changed

dependency.health.changed

를 남길 수 있다.


✅ 278. 같은 상태를 매 5초 DB에 쓰지 않는다

상태 변화 시점만 기록한다.


✅ 279. Incident와 연결

예:

DB NOT_READY
5분 지속

이면 Incident Candidate가 될 수 있다.


✅ 280. Optional Provider DOWN은 바로 P1일 필요 없다

실제 고객 영향에 따라 Severity를 결정한다.

0923과 연결된다.


✅ 281. Health Check는 Incident Detection의 한 입력일 뿐

단독으로 Incident를 결정하지 않는다.


✅ 282. AI가 Health를 분석할 수 있다

예:

최근 30분 Dependency Health

Readiness 전환

Queue Lag

Error Rate

를 요약해:

DB Connection 문제 가능성

후보를 제안할 수 있다.


✅ 283. AI가 서버를 재시작하게 바로 두지는 않는다

Health Failure 원인이 외부 DB인데 App Restart는 효과가 없을 수 있다.


✅ 284. Auto Restart는 Liveness 문제에 제한

예:

Process Hang

Event Loop 완전 정지

같은 상황이다.


✅ 285. Readiness Failure는 Traffic 격리

이 차이를 다시 기억한다.

Liveness FAIL
→ Restart 후보

Readiness FAIL
→ Traffic 제외

이다.


✅ 286. Optional Health FAIL

Degraded Mode

후 해당 기능만 제한한다.


✅ 287. 이 세 단계가 깔끔하다

PROCESS DEAD
→ Restart

INSTANCE NOT READY
→ Remove From Traffic

OPTIONAL FEATURE DOWN
→ Degrade Feature

이다.


✅ 288. 현재 프로젝트에 먼저 적용할 항목

1단계

/health/live

/health/ready

분리.


✅ 289. 2단계

Readiness 조건:

Application Initialized

DB Connected

Required Config Valid

정도다.


✅ 290. 3단계

SIGTERM Handler

Readiness OFF

HTTP Drain

을 구현한다.


✅ 291. 4단계

Queue Worker:

Pause Claim

Active Job Drain

Shutdown Deadline

을 구현한다.


✅ 292. 5단계

긴 Workflow에:

Checkpoint

Lease

Resume

를 적용한다.


✅ 293. 6단계

Optional Dependency:

Cache

AI

Notion

Notification Provider

를 Degraded 상태로 분리한다.


✅ 294. 7단계

Staging에서:

SIGTERM

DB Failure

Redis Failure

Provider Failure

Reliability Test를 수행한다.


✅ 295. 현재 당장 과한 것

Service Mesh Health Routing

복잡한 Multi-region Failover

다중 Cluster Drain Controller

Custom Orchestrator

매 Dependency마다 별도 Health DB

까지 필요 없다.


✅ 296. API/Worker Process가 하나라면 우선 한 Process에서 Lifecycle을 정리한다

실제 장기 Job 때문에 배포 영향이 커질 때 Worker Process를 분리한다.


✅ 297. NestJS 구조 예

src/
├─ health/
│  ├─ health.controller.ts
│  ├─ health.service.ts
│  ├─ readiness.service.ts
│  ├─ dependency-health.service.ts
│  └─ health.types.ts
│
├─ lifecycle/
│  ├─ shutdown.service.ts
│  ├─ drain.service.ts
│  └─ process-signal.service.ts
│
├─ workers/
└─ scheduler/

✅ 298. Readiness Service

예:

type ReadinessState =
  | 'STARTING'
  | 'READY'
  | 'DRAINING'
  | 'NOT_READY';

이다.


✅ 299. 단순 구현

class ReadinessService {
  private state:
    ReadinessState = 'STARTING';

  markReady() {
    this.state = 'READY';
  }

  markDraining() {
    this.state = 'DRAINING';
  }

  isReady() {
    return this.state === 'READY';
  }
}

정도로 시작할 수 있다.


✅ 300. Dependency Health

interface DependencyHealth {
  name: string;

  status:
    | 'HEALTHY'
    | 'DEGRADED'
    | 'UNHEALTHY';

  criticality:
    | 'CRITICAL'
    | 'IMPORTANT'
    | 'OPTIONAL';

  checkedAt: Date;
}

✅ 301. Overall Status 계산

예:

CRITICAL Dependency
UNHEALTHY
→ NOT_READY

OPTIONAL Dependency
UNHEALTHY
→ DEGRADED

이다.


✅ 302. Shutdown Service

class ShutdownService {
  private shuttingDown = false;

  async beginShutdown() {
    if (this.shuttingDown) {
      return;
    }

    this.shuttingDown = true;

    // readiness off
    // scheduler pause
    // workers pause
    // drain
    // close resources
  }
}

정도로 볼 수 있다.


✅ 303. Graceful Shutdown Error 처리

Cleanup 하나가 실패했다고:

Shutdown 전체 무한 대기

하지 않는다.


✅ 304. 예

Cache Close 실패

는 Log 남기고 다음 단계로 진행할 수 있다.


✅ 305. DB Connection Close 실패도 Deadline 내에서 처리

결국 Process는 종료돼야 한다.


✅ 306. Shutdown Step별 Timeout

예:

Scheduler Pause
2s

Worker Drain
20s

DB Close
5s

같이 둘 수 있다.


✅ 307. 전체 Deadline도 존재

Step Timeout 합이 전체 Deadline을 넘지 않게 한다.


✅ 308. Shutdown 단계 순서를 Audit보다는 Structured Log로 남긴다

Shutdown은 운영 로그 성격이 강하다.


✅ 309. 사용자 행위가 아니므로 일반 Business Audit와 구분한다


✅ 310. Readiness Error Code

예:

APP_STARTING

APP_DRAINING

DATABASE_UNAVAILABLE

SCHEMA_INCOMPATIBLE

CONFIG_INVALID

등이다.


✅ 311. Public Response에는 Reason을 감출 수 있다

Internal Diagnostics에서만 상세 Error Code를 본다.


✅ 312. Health Probe Fail Response

예:

503

을 사용할 수 있다.


✅ 313. Liveness는 정상:

200

Readiness FAIL:

503

형태가 흔하다.


✅ 314. Health Check Status Code를 명확히 한다

항상 200 안에서 JSON status만 바꾸면 Load Balancer가 실패를 감지하지 못할 수 있다.


✅ 315. Graceful Shutdown과 CDN

CloudFront 같은 앞단 Cache는 정적 응답을 계속 제공할 수 있다.

Backend Drain과 별개다.


✅ 316. API Origin Health

Backend Instance들이 모두 NOT_READY라면 Load Balancer는 503을 반환할 수 있다.


✅ 317. Deployment는 최소 하나 이상의 READY Instance를 유지

이게 무중단 배포 기본이다.


✅ 318. 단일 Instance 환경에서는 완전 무중단이 더 어렵다

Old Process를 내리기 전에 New Process를 병렬로 띄워야 한다.


✅ 319. 단일 EC2라도 Blue/Green Process 전략이 가능할 수 있다

예:

Port 3000
Old

Port 3001
New

Nginx Upstream을 전환하는 방식이다.


✅ 320. 하지만 현재 배포 구조가 단순하면 먼저 Graceful Restart부터 적용한다

Infrastructure를 크게 바꾸지 않는다.


✅ 321. Nginx 사용 시 Upstream Drain

Nginx가 새 요청을 Old Process로 보내지 않도록 설정하는 방식도 고려할 수 있다.


✅ 322. 실제 배포 시스템에 맞춰야 한다

PM2, systemd, Docker, ECS 등 방식에 따라 다르다.


✅ 323. 특정 Process Manager를 가정하지 않고 Application Lifecycle부터 정리한다


✅ 324. Health Check와 Deployment Gate

신규 Release 후:

Readiness PASS

만 보고 바로 100% Traffic을 보내지 않을 수 있다.


✅ 325. 초기 SLI 확인

예:

Error Rate

p95

DB Error

Queue Error

를 잠깐 확인하고 Traffic을 확대한다.


✅ 326. Canary와 연결

Readiness
= 요청 받을 기본 자격

Canary Metric
= 실제 새 Release 품질

이다.


✅ 327. Readiness PASS가 Release 품질 보증은 아니다

코드 Bug는 실제 요청에서만 나타날 수 있다.


✅ 328. Startup Time Metric

예:

app_startup_duration

을 측정할 수 있다.


✅ 329. Startup이 점점 느려지면

의존성 증가

초기 대량 Query

잘못된 Cache Warm-up

등을 의심할 수 있다.


✅ 330. Startup에서 대량 Cache Warm-up을 무리하게 하지 않는다

1004와 연결된다.


✅ 331. Warm-up 때문에 Readiness가 5분 걸리면 배포가 느려진다

핵심 데이터만 준비하거나 Lazy Load한다.


✅ 332. Startup 작업을 Critical / Background로 구분

Critical:

Config

DB

Schema Compatibility

Background:

일부 Cache Warm-up

AI Model Metadata

Report Preload

이다.


✅ 333. Background Initialization 실패는 READY를 막지 않을 수도 있다

해당 기능만 Degraded.


✅ 334. Health Check와 Security

Health Endpoint에서:

DB Connection String

Version 상세 Secret

Token

등은 절대 반환하지 않는다.


✅ 335. Release ID/Commit SHA 공개 여부도 판단

Internal Endpoint에서는 유용하지만 Public Endpoint에는 최소화할 수 있다.


✅ 336. 내부 운영 화면에 Version 표시

예:

Release
20261006-01

Commit
abc1234

는 Incident 분석에 유용하다.


✅ 337. Instance ID

여러 서버면:

api-1

api-2

처럼 Instance별 Health를 본다.


✅ 338. 한 Instance만 장애일 수 있기 때문이다

전체 서비스 Health와 Instance Health를 구분한다.


✅ 339. Dependency별 Failover

예:

AI Provider A
DOWN

Provider B
available

라면 Fallback이 가능할 수 있다.


✅ 340. 하지만 Health System이 자동 Provider Switching까지 모두 담당하지 않는다

Provider Adapter/Resilience Layer 역할이다.


✅ 341. Health는 상태 제공

Resilience Layer가:

Retry

Fallback

Circuit Breaker

를 결정한다.


✅ 342. 책임 분리가 중요하다

Health
관찰

Resilience
대응

Lifecycle
종료/시작

이다.


✅ 343. Local LLM Health

예:

Ollama Process

Model Availability

를 확인할 수 있다.


✅ 344. Local LLM이 내려가도 전체 Web Service Health에는 영향 없음

AI Workflow만:

DEGRADED

로 본다.


✅ 345. Model Health Probe도 너무 무겁게 하지 않는다

매 Health Check마다 실제 긴 LLM Generation을 하지 않는다.


✅ 346. 예:

Ollama API reachable

Model listed

정도면 충분하다.


✅ 347. 실제 Generation 품질/속도는 별도 Synthetic Job으로 확인할 수 있다


✅ 348. AI Worker Readiness

예:

Ollama available

Required model available

Work directory accessible

등이다.


✅ 349. Git Repository Lock 등도 고려할 수 있다

AI Worker가 특정 Repository 작업 전용이라면:

repo accessible

정도다.


✅ 350. 하지만 특정 프로젝트 하나가 없다고 Worker Process 전체를 NOT_READY로 만들지는 않는다

지원 범위를 봐야 한다.


✅ 351. Shutdown 전 AI 신규 Task 수신 중단

Queue Consumer를 Pause한다.


✅ 352. 진행 중 Tool Command가 있다면

짧은 명령은 완료.

장시간 명령은 Timeout/Cancel 정책을 따른다.


✅ 353. Git Write 중 강제 종료는 특히 주의

예:

commit

checkout

rebase

중간 종료는 Repository 상태를 꼬이게 할 수 있다.


✅ 354. 위험한 Git Action은 Atomic 경계가 명확한 Tool로 감싼다

완료 여부를 확인한 뒤 Step을 SUCCESS 처리한다.


✅ 355. Shutdown 후 Repository Reconciliation

다음 Run에서:

git status

HEAD

lock file

working tree

를 확인한다.


✅ 356. Health / Lifecycle Reliability Test용 Codex 프롬프트

현재 NestJS + Prisma + PostgreSQL + Queue/Worker 구조를 기준으로
Health Check, Readiness/Liveness, Graceful Shutdown 구조를 추가해줘.

목표는 Kubernetes 수준의 복잡한 플랫폼을 만드는 것이 아니라,

- 신규 Instance가 준비되기 전에 Traffic을 받지 않게 하고
- 배포/재시작 시 신규 요청과 Job을 먼저 차단하고
- 진행 중 작업을 가능한 안전하게 Drain한 뒤
- Process가 죽더라도 Job/Workflow를 복구할 수 있게 만드는 것이다.

현재 배포 방식, Process Manager, Queue Library,
NestJS Bootstrap 구조를 먼저 분석한다.

특정 Infrastructure를 추정해서 구현하지 말고
현재 프로젝트에 맞춘다.

1. Health Endpoint를 최소 두 개로 분리한다.

GET /health/live

목적:
프로세스 자체가 살아 있는지 확인.

GET /health/ready

목적:
현재 Instance가 실제 Traffic을 받을 준비가 됐는지 확인.

2. Liveness에는
DB/외부 Provider의 일시 장애를 과도하게 포함하지 않는다.

외부 Dependency 장애 때문에
Application이 무한 Restart Loop에 빠지지 않게 한다.

3. Readiness에는 우선 다음을 고려한다.

- application initialization 완료
- PostgreSQL 연결 가능
- required config validation 완료
- 필요한 경우 DB schema compatibility 확인

4. Optional Dependency를 분리한다.

예:
- Cache
- AI Provider / Ollama
- Notion
- Notification Provider

Optional Dependency 장애 때문에
핵심 웹 서비스 전체 Readiness를
무조건 FAIL시키지 않는다.

5. Dependency마다 Criticality를 둘 수 있는
간단한 구조를 만든다.

- CRITICAL
- IMPORTANT
- OPTIONAL

6. 전체 Service Health는 다음 정도로 표현할 수 있게 한다.

- HEALTHY
- DEGRADED
- UNHEALTHY

Readiness와 Health Status를 동일 개념으로 만들지 않는다.

예:
AI DOWN
→ service DEGRADED
→ readiness READY

7. Health Check에는 Side Effect를 넣지 않는다.

금지:
- DB INSERT
- 실제 알림 발송
- Production Write
- Migration 실행

8. DB Probe는 가벼운 방식으로 구현한다.

9. Health Check 자체에 짧은 Timeout을 둔다.

Health Probe 때문에 Application Resource가 오래 묶이지 않게 한다.

10. Public Health Response에는
민감한 Infrastructure 정보를 노출하지 않는다.

11. 상세 Dependency 상태가 필요하다면
인증된 Internal Health Endpoint 또는
운영 Dashboard용 Service로 분리한다.

12. Readiness 상태를 Application Lifecycle과 연결한다.

예:
- STARTING
- READY
- DRAINING
- NOT_READY

13. Application Startup 완료 전에
READY가 되지 않게 한다.

14. Graceful Shutdown을 구현한다.

SIGTERM 수신 시 최소 순서:

1) 중복 Shutdown 방지
2) Readiness → DRAINING
3) Scheduler 신규 Trigger 중단
4) Worker 신규 Job Claim 중단
5) HTTP 신규 요청 Drain
6) 진행 중 Job 처리
7) Queue/DB/기타 Resource Close
8) Process 종료

15. process.exit()를 Signal 직후 바로 호출하지 않는다.

16. Shutdown 전체에 Deadline을 둔다.

Deadline 이후에는
무한 대기하지 않고 강제 종료가 가능해야 한다.

정확한 시간은 Config로 조정 가능하게 한다.

17. 각 Resource Close 작업도
무한 대기하지 않게 한다.

18. HTTP Active Request 수를
추적할 수 있는 간단한 구조를 고려한다.

Shutdown 시 가능한 경우
현재 요청이 완료될 때까지 기다린다.

19. DRAINING 상태에서는
/health/ready가 실패하도록 한다.

/health/live는 Process가 살아 있는 동안
정상일 수 있다.

20. Worker는 Shutdown 시작 후
새 Job을 Claim하지 않는다.

21. 짧은 Job은 완료까지 기다릴 수 있게 한다.

22. 장시간 Job은
기존 Checkpoint / WorkflowRun / Lease 구조가 있다면
이를 이용해 Resume 가능하게 한다.

새로운 중복 Workflow Engine을 만들지 않는다.

23. External Side Effect 요청 중 Shutdown이 발생해
결과가 불확실하다면
무조건 PENDING으로 되돌려 Blind Retry하지 않는다.

UNKNOWN / Reconciliation 흐름과 연결한다.

24. Worker Claim에 Lease/Heartbeat 구조가 있다면
Shutdown 시 안전하게 Release하거나
Lease 만료 후 다른 Worker가 복구할 수 있게 한다.

25. Scheduler가 있다면
Shutdown 시 신규 ScheduleRun 생성을 중지한다.

Leader Lock/Lease 구조가 있다면
다른 Instance가 이어받을 수 있게 한다.

26. Queue / Redis가 Cache와 Worker에
서로 다른 역할을 한다면
Health Criticality를 역할별로 판단한다.

27. Cache 장애 시 DB fallback이 가능한 경우
Cache 장애만으로 전체 Readiness를 FAIL시키지 않는다.

28. Outbox 구조가 있다면
Queue 일시 장애 상황에서
핵심 DB Write를 계속 받을 수 있는지 현재 구조를 분석한다.

무조건 허용하지 말고
Outbox backlog 한도와 업무 위험을 같이 고려한다.

29. Optional Provider Health는
매 Health Probe마다 실제 외부 API를 호출하지 않는다.

기존 실제 호출 Error Rate / Circuit Breaker 상태 /
주기적 경량 Probe를 활용할 수 있게 한다.

30. Health Flapping을 줄일 수 있게 한다.

필요하면:
- consecutive failure count
- consecutive success count

를 이용한다.

31. Dependency Health에 다음 Metadata를
내부적으로 유지할 수 있게 한다.

- status
- lastCheckedAt
- lastSuccessAt
- lastFailureAt
- errorCode

32. Structured Log Event를 추가한다.

예:
- application.starting
- application.ready
- readiness.disabled
- shutdown.started
- worker.claim.paused
- worker.draining
- shutdown.completed
- shutdown.forced
- dependency.health.changed

33. Log에는 가능하면:
- instanceId
- releaseId
- processRole
을 연결한다.

34. Health Probe 결과를 매번 DB에 저장하지 않는다.

Metric 또는 상태 변화 Event 중심으로 기록한다.

35. 다음 Metric을 고려한다.

- readiness_state
- dependency_health_state
- http_active_requests
- worker_active_jobs
- shutdown_duration
- forced_shutdown_total

36. API / Worker / Scheduler를 현재 하나의 Process가 담당하고 있다면
바로 Infrastructure를 세 개로 분리하지 않는다.

다만 코드에서 Process Role을
향후 분리하기 쉬운 구조로 만드는 것은 고려한다.

37. 다음 Reliability Test를 작성한다.

- 정상 Startup → READY
- 필수 Config 누락
- DB unavailable
- Optional Notion unavailable
- Cache unavailable
- Readiness DRAINING 상태
- HTTP 요청 처리 중 SIGTERM
- Worker Job 실행 중 SIGTERM
- External API 호출 중 SIGTERM
- Shutdown Deadline 초과
- Health Probe 간헐적 실패
- DB 복구 후 Readiness 회복
- 동일 Shutdown Signal 여러 번 수신

38. 테스트에서 확인한다.

- 신규 요청 차단
- 진행 중 요청 완료 여부
- 중복 Side Effect 여부
- Worker Job 유실 여부
- Lease/Checkpoint 복구
- Readiness 상태
- Structured Log

39. 실제 Production Process를 강제 종료하지 말고
Integration/Staging 환경에서 재현한다.

40. 현재 프로젝트 규모에 맞게
최소 구조로 구현하고,

Service Mesh, Kubernetes Operator,
복잡한 Custom Orchestrator 같은
불필요한 구조는 추가하지 않는다.

✅ 357. Graceful Shutdown 검증용 Codex 프롬프트

현재 서버의 Graceful Shutdown 구현을 분석해줘.

코드를 바로 수정하지 말고 먼저 다음을 확인한다.

1. SIGTERM 처리 여부
2. SIGINT 처리 여부
3. NestJS enableShutdownHooks 사용 여부
4. HTTP Server Close 여부
5. Prisma Connection 종료 여부
6. Queue Worker Pause 여부
7. Scheduler Pause 여부
8. 실행 중 Job 처리 방식
9. Shutdown Timeout 여부
10. process.exit 직접 호출 위치

그 후 다음 위험을 찾아줘.

P0:
- Signal 직후 즉시 process.exit
- DB Write 중 강제 종료 가능
- 동일 Job 중복 실행 가능
- External Side Effect Blind Retry 가능

P1:
- Worker 신규 Job Claim 계속됨
- Scheduler가 종료 중 신규 Job 생성
- Readiness가 Drain 시작 후에도 READY
- Shutdown Timeout 없음

P2:
- Structured Log 부족
- Shutdown Metric 없음
- Optional Resource Close 순서 개선 가능

마지막에 현재 구조를 최대한 유지하면서
수정 범위를 최소화한 개선안을 제시해줘.

✅ 358. Health Check 분석용 Codex 프롬프트

현재 프로젝트의 Health Check와 Dependency를 분석해서
Liveness / Readiness / Optional Health를 구분해줘.

코드는 수정하지 않는다.

검토 Dependency:

- PostgreSQL
- Redis / Queue
- Cache
- AWS 관련 필수 Resource
- Notification Provider
- Notion
- AI / Ollama
- Scheduler
- Worker

각 Dependency에 대해:

## Dependency

## 현재 사용 용도

## Criticality

- CRITICAL
- IMPORTANT
- OPTIONAL

## Liveness 포함 여부

## Readiness 포함 여부

## Degraded Mode 가능 여부

## 권장 Probe

- Active
- Passive
- Metric 기반

## Probe 비용

## Timeout 필요 여부

## 장애 시 전체 서비스 영향

를 정리한다.

특히 Optional Dependency 하나가 장애라고
전체 Application Restart를 유발하지 않게 한다.

마지막에:

1. /health/live에 포함할 것
2. /health/ready에 포함할 것
3. Dashboard만 표시할 것

세 그룹으로 나눠줘.

✅ 359. 무중단 배포 검증 시나리오

현재 배포 구조에서
Zero-Downtime 관점의 검증 계획을 작성해줘.

목표:

새 Release 배포 중에도

- 진행 중 Request 유실 없음
- 신규 Request 5xx 최소화
- Worker Job 유실 없음
- 중복 Side Effect 없음

을 확인한다.

Scenario:

1. 평상시 Traffic 발생

2. New Instance/Process 시작

3. Startup 완료 전 Traffic 유입 여부 확인

4. Readiness PASS

5. Traffic 전환

6. Old Instance DRAINING

7. 진행 중 HTTP Request 완료

8. Worker 신규 Claim 중지

9. Worker 진행 중 Job 처리

10. Old Instance 종료

관찰 Metric:

- HTTP 5xx
- connection reset
- p95 latency
- active requests
- queue depth
- active jobs
- duplicate job execution
- shutdown duration

실제 Production Traffic이 아니라
Staging/Test Traffic으로 검증한다.

✅ 360. 실무 체크리스트

Liveness

  • 프로세스 자체 상태만 주로 확인하는가?
  • DB 장애 때문에 Restart Loop가 생기지 않는가?
  • Probe가 가벼운가?
  • Side Effect가 없는가?

Readiness

  • Application 초기화 전 READY가 되지 않는가?
  • 필수 DB/Config를 확인하는가?
  • Optional Provider 장애가 전체 Readiness를 막지 않는가?
  • DRAINING 상태에서 READY가 해제되는가?

Dependency

  • CRITICAL / OPTIONAL을 구분하는가?
  • Cache 장애 시 DB Fallback 가능 여부를 반영하는가?
  • Provider Health를 과도하게 Probe하지 않는가?
  • Circuit Breaker/실제 Error Rate를 활용할 수 있는가?

Startup

  • 필수 Config Validation을 하는가?
  • DB Schema Compatibility를 확인하는가?
  • 무거운 Cache Warm-up이 Startup을 막지 않는가?
  • Background Initialization과 Critical Initialization을 구분하는가?

Shutdown

  • SIGTERM을 처리하는가?
  • Signal 직후 process.exit하지 않는가?
  • Shutdown Handler가 Idempotent한가?
  • Readiness를 가장 먼저 내리는가?
  • 전체 Shutdown Deadline이 있는가?

HTTP Drain

  • 새 요청을 중단하는가?
  • 기존 요청을 가능한 완료하는가?
  • Active Request를 확인할 수 있는가?
  • Keep-Alive 때문에 무한 대기하지 않는가?

Worker

  • 신규 Job Claim을 중지하는가?
  • 짧은 Job은 완료 가능한가?
  • 긴 Job은 Checkpoint/Resume 가능한가?
  • Side Effect 결과 불명확 시 Blind Retry하지 않는가?
  • Lease/Stale Recovery가 있는가?

Scheduler

  • Shutdown 중 신규 ScheduleRun을 만들지 않는가?
  • Scheduler Lease를 다음 Instance가 이어받을 수 있는가?
  • Missed Job 정책과 연결되는가?

Deployment

  • New Instance READY 후 Traffic을 보내는가?
  • Old Instance를 Drain한 뒤 종료하는가?
  • 최소 하나의 READY Instance가 유지되는가?
  • LB Drain 시간과 App Shutdown 시간이 맞는가?

Observability

  • Readiness 상태를 Metric으로 보는가?
  • Dependency 상태를 보는가?
  • Forced Shutdown 횟수를 보는가?
  • Shutdown Duration을 보는가?
  • Worker Active Job을 보는가?

AI Workflow

  • Ollama 장애가 전체 웹 서비스를 막지 않는가?
  • AI 신규 Task를 Shutdown 중 받지 않는가?
  • Prompt/Artifact Checkpoint가 있는가?
  • Git 작업 후 상태를 Reconcile하는가?
  • 장시간 AI 작업에 Shutdown/Resume 정책이 있는가?

📌 요약

1005에서는:

시스템이 얼마나 많은 일을 받을 것인가?

를 다뤘다.

1006에서는 그 다음 질문인:

이 서버가 지금
새 일을 받을 준비가 되어 있는가?

를 다뤘다.

가장 먼저:

Liveness

Readiness

Startup

을 구분해야 한다.

Liveness는:

이 Process를 재시작해야 하는가?

를 본다.

Readiness는:

이 Instance에 지금 Traffic을 보내도 되는가?

를 본다.

그래서:

Liveness OK

Readiness FAIL

상태는 이상한 것이 아니다.

배포 중 Old Instance가 Drain될 때 오히려 정상적인 상태다.

또 모든 Dependency 장애를 같은 수준으로 처리해서는 안 된다.

예를 들어:

PostgreSQL DOWN

은 핵심 기능을 막을 수 있지만:

Notion DOWN

AI DOWN

은 핵심 주문 서비스 전체를 죽일 필요가 없을 수 있다.

따라서:

CRITICAL

IMPORTANT

OPTIONAL

으로 Dependency를 분류하고,

Optional 장애
→ DEGRADED

Critical 장애
→ NOT_READY

처럼 처리한다.

Graceful Shutdown의 핵심 흐름은:

SIGTERM
↓
Readiness OFF
↓
Scheduler Pause
↓
Worker Claim Pause
↓
HTTP Drain
↓
진행 중 Job 처리
↓
Resource Close
↓
Process Exit

이다.

중요한 점은:

종료 요청을 받았다고 바로 Process를 죽이지 않는 것

이다.

하지만 Graceful Shutdown도 완벽한 방어는 아니다.

서버 전원 장애나 SIGKILL처럼 Cleanup 기회조차 없는 상황이 존재한다.

그래서 Worker에는 여전히:

Idempotency

Lease

Heartbeat

Checkpoint

Reconciliation

이 필요하다.

즉:

Graceful Shutdown

은 복구 구조를 대체하는 것이 아니라,

복구가 필요한 상황 자체를 줄여주는 추가 안전장치

다.

장시간 Workflow에서는 특히:

Process는 죽어도 된다.

Workflow State는 살아 있어야 한다.

원칙이 중요하다.

API 배포와 연결하면:

New Process STARTING
↓
Initialization
↓
READY
↓
Traffic 전환
↓
Old Process DRAINING
↓
기존 요청 완료
↓
STOP

이 된다.

이 구조가 제대로 되어 있어야:

Deployment
=
서비스 중단

이라는 공식에서 벗어날 수 있다.

현재 프로젝트에서는 처음부터 복잡한 Container Orchestrator를 만드는 것보다:

/health/live

/health/ready

DB Readiness

Optional Dependency 분리

SIGTERM Handler

Readiness OFF

HTTP Drain

Worker Pause

Shutdown Deadline

정도부터 적용하는 것이 가장 현실적이다.

전체 운영 흐름을 연결하면:

Startup
↓
Health Check
↓
Readiness
↓
Traffic
↓
Work Processing
↓
Drain
↓
Graceful Shutdown
↓
Checkpoint / Lease
↓
Restart
↓
Reconciliation
↓
Ready

가 된다.

결국 Health Check와 Graceful Shutdown의 핵심은

“프로세스가 켜져 있느냐”가 아니라, 지금 이 인스턴스가 일을 받아도 되는 상태인지 명확히 판단하고, 내려가야 할 때는 새 일을 먼저 차단한 뒤 이미 맡은 일을 가능한 안전하게 넘겨주고 종료할 수 있게 만드는 것

이다.

0개의 댓글