본문으로 건너뛰기
02 수립 방향 분기

02 · 수립 방향이라는 분기점

  • “연결을 누가 거느냐"와 “데이터가 어디로 흐르느냐"는 별개입니다. 중앙 → 단말 일방 푸시라는 요구는 두 분기가 모두 만족합니다. SSE·WebSocket·long-polling이 존재하는 이유 자체가 클라이언트가 건 연결 위에서 서버가 일방적으로 미는 것이기 때문입니다.
  • 현행 구성이 이미 답을 알고 있습니다. API Gateway WebSocket API에는 클라이언트 개시 외의 모드가 없습니다. 지금 돌아간다면 POS가 outbound로 걸고 있다는 뜻입니다 — 서비스 제약이 그것 말고는 허용하지 않습니다.
  • 판정은 액세스 로그 한 줄이면 끝납니다. $context.identity.sourceIp가 매장 회선의 NAT 공인 IP로 찍히면 분기 A가 확정됩니다.
  • 분기는 링의 유무 말고도 여럿을 바꿉니다. 전송 프로토콜(SSE가 맞는가), k8s 워크로드 종류(Deployment냐 StatefulSet이냐), 장애 감지 주체가 전부 뒤집힙니다.
  • 분기 B가 네트워크상 가능해도 보통은 A를 택합니다. 5만 대의 주소 인벤토리, 단말별 TLS 서버 인증서와 그 갱신, 매장 방화벽 인바운드 규칙이 전부 새 운영 비용으로 붙기 때문입니다. B는 “가능한가"가 아니라 “그 값을 치를 만한가"로 판정해야 합니다.
  • 혼재는 A로 수렴시킵니다. 일부 매장이 전용망이라 해서 두 경로를 함께 유지하면 장애 모드가 두 배가 됩니다. 전용망 매장도 outbound로 걸게 하면 A 하나로 끝납니다.

왜 이 문서인가. 이 질문 하나가 0405 중 어느 쪽을 읽어야 하는지를 정합니다. 그런데 실무에서는 이 질문이 “중앙에서 단말로 밀어야 하니 중앙이 연결을 걸어야 하는 것 아닌가” 라는 형태로 자주 뒤섞입니다. 여기서는 두 방향을 분리하고 판정을 코드 한 줄 짜지 않고 끝내는 절차를 남깁니다.

1. 두 개의 방향

정의이 워크로드의 값
흐름 방향애플리케이션 데이터가 어디로 가는가중앙 → POS 일방 (확정)
수립 방향TCP 연결의 SYN을 누가 보내는가미결

둘은 독립입니다. 웹의 푸시 기술 전체가 “수립은 클라이언트, 흐름은 서버"라는 조합을 만들려고 존재합니다 — 클라이언트가 NAT 뒤에 있어서 서버가 먼저 닿을 수 없다는 전제 위에 서 있기 때문입니다. SSE는 그 조합의 가장 얇은 구현입니다. 클라이언트가 GET을 보내고 서버가 응답을 닫지 않은 채 계속 씁니다. 그게 전부입니다.

2. 현행 구성이 이미 내놓은 증거

API Gateway WebSocket API에는 서버 개시 모드가 없습니다. 라우트 모델 자체가 $connect / $disconnect / $default로 되어 있고 $connect클라이언트가 핸드셰이크를 보내야 발화합니다. 서버 쪽에서 임의의 단말에 연결을 새로 만드는 API는 존재하지 않습니다 — @connections이미 맺어진 연결에 데이터를 밀어넣는 것뿐입니다. 지금 POS가 붙어 있다면 거는 쪽은 POS이고 이건 네트워크 구성을 조사하기 전에 이미 확정된 사실입니다.

뒤집을 수 있는 경우는 하나뿐입니다 — 전환하면서 수립 방향까지 바꾸겠다고 새로 결정하는 경우. 그렇다면 그건 발견이 아니라 설계 선택이고 §5의 값을 치를 각오가 필요합니다.

3. 판정 체크리스트

순서대로 하나만 확인되면 멈춥니다.

① API Gateway 액세스 로그의 소스 IP — 가장 빠릅니다.

$context.identity.sourceIp

이 값이 매장 회선 ISP 대역의 공인 IP로 찍히면 분기 A 확정입니다. POS가 NAT를 거쳐 인터넷으로 나온다는 뜻이고 중앙에서 그 단말로 인바운드를 꽂을 주소는 존재하지 않습니다. 반대로 사설 대역(10.0.0.0/8 등)으로 찍힌다면 전용망/VPN 경유이므로 ②로 갑니다.

② 클러스터 VPC의 라우팅 테이블에 매장 대역이 있는가 — 없으면 B는 불가능합니다. 있어도 그것만으로는 부족하고 ③이 필요합니다.

③ POS 단말이 리슨할 수 있는가 — 단말 벤더 스펙에서 확인할 것:

  • 상시 동작하는 HTTP/TCP 서버를 띄울 수 있는가
  • 안정적인 주소(고정 IP 또는 등록형 DNS)가 있는가
  • TLS 서버 인증서를 배포·갱신할 수단이 있는가

④ 매장 방화벽이 인바운드를 허용하는가 — 5만 매장이면 정책 하나로 끝나지 않고 5만 건의 변경이 됩니다.

⑤ 단말 IP 변동 주기 — DHCP 임대 갱신마다 주소가 바뀐다면 중앙이 인벤토리를 실시간으로 따라가야 합니다. 그 인벤토리를 누가 어떻게 갱신하는가가 곧 새 컴포넌트입니다.

①에서 공인 IP가 나오면 ②~⑤는 볼 필요가 없습니다.

4. 분기가 강제하는 것

A — POS가 건다B — pod가 건다
커넥션 소유권 결정자로드밸런서파드들 스스로
소유권 분배 문제존재하지 않음링·샤딩·lease가 여기서 필요해짐
파드 사망 감지POS가 즉시 감지, 재접속생존 파드들이 감지하고 인수해야
중복 방지불필요필수 (두 파드가 같은 단말에 걸면 안 됨)
단말 장애 감지재접속이 안 오면 = 장애다이얼 실패로 감지 — 재시도 정책 필요
확장 시새 파드가 새 연결을 받음. 기존 연결 무영향재배정 발생 → 기존 연결 강제 이동
전송 프로토콜SSE 그대로SSE는 방향 불일치 — §5.1
k8s 워크로드DeploymentStatefulSet 검토 대상
주소 인벤토리불필요5만 건 필요, 실시간 갱신
TLS서버 인증서 1장(게이트웨이)단말마다 서버 인증서
닮은 선례Loki ingester · API Gatewayvmagent 스크랩 샤딩 · Thanos compactor

세 번째 줄이 결정적입니다. 분기 A에서는 “죽은 파드의 몫을 누가 줍나"라는 문제 자체가 존재하지 않습니다. 파드가 죽으면 그 파드에 붙어 있던 POS들이 각자 재접속하고 로드밸런서가 생존 파드들에 알아서 흩어놓습니다. 링으로 풀려던 문제를 TCP와 로드밸런서가 이미 해결해준 상태입니다.

5. 분기 B는 “가능한가"가 아니라 “값을 치를 만한가”

전용망이 깔려 있어서 B가 기술적으로 가능하다고 해도 얻는 것과 잃는 것을 나란히 놓으면 대개 답이 나옵니다.

B가 주는 것

  • 단말별 연결을 중앙이 능동적으로 통제합니다 (원하는 시점에 열고 닫음)
  • 로드밸런서가 필요 없습니다
  • 어느 파드가 어느 단말을 맡는지 결정론적으로 알 수 있습니다

B가 가져가는 것

  • 5만 건의 주소 인벤토리와 그 실시간 갱신 파이프라인
  • 단말마다 TLS 서버 인증서 발급·배포·갱신 (매장 5만 개의 인증서 만료 관리)
  • 매장 방화벽 인바운드 정책 5만 건
  • 배정 링, 멤버십 발견, 중복 다이얼 방지 lease — 05 전체
  • 리밸런싱마다 발생하는 연결 강제 이동 — A에서는 배포할 때만 생기는 일이 B에서는 스케일 변경마다 생깁니다

세 번째 줄에서 대개 끝납니다. 매장 방화벽은 우리가 관리하는 물건이 아닙니다.

5.1 B를 택하면 SSE는 방향이 안 맞는다

pod가 걸고 POS가 SSE를 서빙하면 데이터는 POS → pod로 흐릅니다. 우리가 원하는 방향의 반대입니다.

B에서 중앙 → 단말 푸시를 하려면 단말이 HTTP 서버가 되어 중앙의 POST를 받거나(요청-응답, 장수명 연결이 아님), 양방향 프로토콜(gRPC 스트림·WebSocket 클라이언트 역할 반전)을 쓰거나, pod가 연 연결 위에서 커스텀 프레이밍을 해야 합니다. 어느 쪽이든 “SSE로 전환한다"는 원안은 폐기됩니다. 이 분기는 링 유무를 넘어 전환 계획서의 제목까지 바꿉니다.

6. 혼재 — 두 경로를 동시에 두지 않는다

“일부 매장은 전용망, 일부는 일반 인터넷"인 경우가 실제로 흔합니다. 그래도 두 수립 방향을 나란히 유지하는 설계는 피합니다.

  • 장애 모드가 두 벌이 됩니다 (재접속 실패 vs 다이얼 실패)
  • 코드 경로가 두 벌, 관측 지표가 두 벌, 런북이 두 벌
  • 링이 필요한 쪽 하나 때문에 시스템 전체가 링을 지게 됩니다

전용망 매장도 outbound로 걸게 하면 A 하나로 수렴합니다. 전용망은 연결 방향을 뒤집는 근거가 못 됩니다. 경로 품질과 보안 경계의 이야기로 남겨두는 편이 낫습니다.

7. 판정이 나기 전에 할 수 있는 것

수립 방향이 정해지지 않아도 분기와 무관하게 확정된 설계 결정이 이미 여럿 있습니다.

  • 이벤트 로그를 파드 밖에 두는 것 — 재개 보장을 선택한 시점에 확정 (04 §2)
  • 이벤트 ID 체계와 재개 창 계약 — 두 분기 모두 필요
  • 하트비트와 idle timeout 설계 — 두 분기 모두 필요
  • graceful shutdown과 재접속 폭풍 억제 — B에서는 “리밸런싱 폭풍"으로 이름만 바뀜

판정을 기다리는 동안 멈출 필요는 없습니다. 막히는 것은 링과 워크로드 종류뿐입니다.

마지막 수정 일자