크라우니 게이트웨이 한선씨화 — P4 스트랭글러-피그 컷오버 계획
개요
레거시 JS 게이트웨이(bin/cli.js → lib/gateway.js 785줄 + lib/ssl.js 753줄, 라이브 :8080/:8443)를
한선씨 게이트웨이(P1 설정/프록시 + P2 TLS_SNI + P3 헬스)로 무중단 교체한다.
스트랭글러-피그(Strangler-Fig) 패턴: 새 구현을 그림자 포트(8081/8444)에서 먼저 돌리고, 헬스가 통과(Ti)하면 라이브 포트(8080/8443)로 승격한 뒤 레거시를 종료한다. 실패 시 즉시 롤백.
- 오케스트레이션 스크립트:
/Users/ef/crowny-gateway/한선게이트웨이/컷오버.한선(hanseonc_high 컴파일 통과, 드라이런 검증 완료) - 산출은 라이브 파일과 분리된
한선게이트웨이/하위에 둠.
전제조건 (P1~P3 통합 완료)
| 단계 | 모듈 | 인터페이스 | 상태 |
|---|---|---|---|
| P1 | 설정.한선 | 설정로드(경로)→라우트맵, 호스트매칭(라우트맵,호스트)→upstream | 통합 필요 |
| P1 | 프록시.한선 | 프록시처리(요청텍스트,호스트,upstream)→응답텍스트 (HTTP 8081 수신→upstream TCP 포워드) | 통합 필요 |
| P2 | TLS_SNI.한선 | 인증서선택(도메인)→[cert경로,key경로] (certbot live SAN 우선, 자체서명 폴백) | 통합 필요 |
| P3 | 헬스.한선 | 헬스체크(upstream)→Ti/Om/Ta, 인증서리로드()→Ti | 통합 필요 |
그림자기동.한선 → 그림자기동.toau)로 합쳐
8081(HTTP)/8444(HTTPS)에서 listen 시켜야 컷오버 단계1이 의미를 가진다.단계별 체크리스트
단계0 — 그림자 좀비 정리
- 8081/8444에 남은 이전 그림자 프로세스를
한선게이트웨이패턴 매칭으로만 TERM - 라이브(8080/8443/9100/9878/9907)는 절대 미접촉
-
sleep 1
단계1 — 그림자 기동 (8081/8444)
-
./crownyc run 그림자기동.toau백그라운드 기동, 로그/tmp/그림자게이트웨이.log -
sleep 2안정화
단계2 — 그림자 헬스 검증 (Ti/Om/Ta 게이트)
-
curl /health→ 200 (Ti) 확인 - 백엔드 tiomta 127.0.0.1:9878 → 200
- 백엔드 mpti 127.0.0.1:9907 → 200
- 모두 Ti(+1)일 때만 단계3 진행. 하나라도 Ta(-1)면 → 롤백
단계3 — 포트 승격 (8081/8444 → 8080/8443)
-
GW_HTTP=8080 GW_HTTPS=8443로 그림자 인스턴스 라이브 포트 재바인딩 - 승격 직후
curl 127.0.0.1:8080/health재확인 → Ti - 레거시는 아직 살아있음 (무중단 핵심)
단계4 — 레거시 종료
- 8080/8443에서
bin/cli.js start패턴 매칭 프로세스만 TERM -
sleep 1종료 확인 - 한선씨 게이트웨이 8080/8443 단독 서빙 확인
무중단 보장 원리
[그림자 검증] [승격] [정리]
8081/8444 한선씨 기동 → 헬스 Ti → 8080/8443 재바인딩 → 레거시 cli.js TERM
레거시 cli.js 계속 라이브 (8080/8443 응답 유지) ─────────────┘ (이 시점에만 종료)
- 헬스가 통과하기 전까지 레거시는 절대 종료되지 않는다.
- 승격은 그림자가 라이브 포트에 추가로 바인딩 → 헬스 재확인 → 그 다음에 레거시 종료.
- 따라서 어느 순간에도 8080/8443에 응답하는 인스턴스가 최소 1개 존재한다.
롤백 절차
발동 조건: 단계2 헬스 Ta(-1) 또는 단계3 승격 후 헬스 실패.
- 그림자 8081/8444 프로세스 종료 (
한선게이트웨이패턴) - 라이브 포트에 올라온 그림자 인스턴스가 있으면 종료 (
한선게이트웨이패턴 한정 — cli.js는 미접촉) - 레거시
bin/cli.js start는 계속 라이브 → 운영 영향 0 -
컷오버실행()이-1반환 시 자동으로롤백()분기
회귀 테스트 도메인 목록
승격 후 다음 도메인이 정상 라우팅되는지 확인 (HTTP 200 + 올바른 upstream):
| 도메인 | upstream | 비고 |
|---|---|---|
| tiomta.com | 127.0.0.1:9878 | 메인 검증 백엔드, certbot-ext SAN |
| mpti. | 127.0.0.1:9907 | 검증 백엔드, certbot-ext SAN |
| tube. | (gateway.yaml) | 정적/SPA 라우팅 |
| tok.* | (gateway.yaml) | 라우팅 |
| crowny.org | (gateway.yaml 코어) | 코어 라우팅 |
| docs.crowny.org | 127.0.0.1:4100 | 문서 |
| pkg.crowny.org | 127.0.0.1:4873 | Verdaccio |
- TLS: tiomta/mpti는 certbot live
crownybus.com-extSAN으로 인증서 선택되는지 확인. - 그 외 도메인은 도메인별 자체서명
<도메인>.crt/.key폴백 동작 확인.
리스크
| 리스크 | 영향 | 완화 |
|---|---|---|
| 그림자 헬스 false-positive | 깨진 인스턴스 승격 | 백엔드 tiomta/mpti 실측 + 승격 후 재확인 2중 게이트 |
| 포트 재바인딩 충돌(EADDRINUSE) | 승격 실패 | 레거시 미종료 상태라 8080 점유 가능 → SO_REUSEPORT 또는 레거시 먼저 SIGHUP graceful 필요(검토) |
bin/cli.js start 패턴 오매칭 | 무관 프로세스 종료 | grep 패턴을 bin/cli.js start로 엄격 한정, 그림자는 한선게이트웨이로 분리 |
| 인증서 핫리로드 누락 | TLS 핸드셰이크 실패 | P3 인증서리로드()→Ti 호출을 승격 직전 삽입 |
| 한선씨 HTTP Content-Length 한글 바이트 불일치 | 한글 본문 잘림 | Connection:close + Content-Length 생략 (메모리 규칙 준수) |
주의: 포트 재바인딩 충돌은 미해결 설계 이슈. 실제 컷오버 전, 레거시를 먼저 graceful(SIGHUP)
시킨 뒤 그림자를 라이브 포트로 올리는 변형(단계3↔4 순서 교환)을 SO_REUSEPORT 가용 여부에 따라 결정해야 한다.
현재 컷오버.한선은 안전한 드라이런(미실행)이며, 실제 실행 전 이 결정이 선행되어야 한다.관련 파일
/Users/ef/crowny-gateway/한선게이트웨이/컷오버.한선— 오케스트레이션 (드라이런)/Users/ef/crowny-gateway/한선게이트웨이/설정.한선— P1/Users/ef/crowny-gateway/한선게이트웨이/TLS_SNI.한선— P2/Users/ef/crowny-gateway/start.한선— 좀비정리 패턴 참고 원본/Users/ef/crowny-gateway/gateway.yaml— SSOT 라우팅
잔여 이슈
- P1
프록시.한선, P3헬스.한선이한선게이트웨이/에 아직 미배치 (병렬 세션 진행 중). 그림자기동.한선(4모듈 통합 엔트리) 미작성 — 컷오버 단계1이 참조하는.toau산출 필요.- 포트 재바인딩 무중단 전략(SO_REUSEPORT vs 순서교환) 미확정.
- 실제 컷오버 실행 트리거(드라이런→실행 전환 플래그)는 의도적으로 미구현 (라이브 보호).