상태 저장 오케스트레이션의 숨겨진 비용
SchemaBridge Team · 2026-02-02 · Distributed Systems, Immutable Infrastructure, Orchestration, Anti-Patterns, Reliability
'단순해' 보이는 사내 도구가 어떻게 가장 큰 안정성 리스크가 될 수 있는지, 그리고 불변 인프라(Immutable Infrastructure) 패턴을 애플리케이션 로직에 적용하면 어떻게 이를 해결할 수 있는지 살펴봅니다.
마이크로서비스의 세계에서 우리는 디커플링에 집착합니다. 큐를 사용하고, 이벤트 기반 아키텍처를 채택하며, 모놀리스를 잘게 쪼갭니다. 그럼에도 불구하고 오케스트레이션 엔진 내부에서는 분산 시스템의 중대한 죄악을 저지르곤 합니다. 우리는 상태를 가진(stateful) 루프를 작성합니다.
SchemaBridge에서는 최근 핵심 시스템 워크플로를 전면 개편했습니다. 그 과정에서 우리는 많은 엔지니어링 조직을 괴롭히는 것과 동일한 안티패턴과 마주하게 되었습니다. 이 글은 단순한 릴리스 노트 이야기가 아니라, 불변 인프라(Immutable Infrastructure) 원칙을 애플리케이션 계층에 적용한 사례 연구입니다.
"루프" 안티패턴
고전적인 "폴러(Poller)"를 생각해봅시다.
while not deployment.is_ready():
sleep(60)
check_status()
이 코드는 안정된 우주를 가정합니다. 폴링 프로세스가 영원히 살아있을 것이라고 가정하는 것이죠. 실제로 이것은 분산 모놀리스(Distributed Monolith)의 산물입니다. [AWS Builders' Library]에서도 언급하듯, 장기 실행되는 동기적 상태에 의존하면 "좀비" 프로세스와 예측 불가능한 장애 모드가 만들어집니다.
해결책: 재귀적 체이닝(Recursive Chaining)
우리는 내부의 while 루프에서 재귀적 실행 모델(Recursive Execution Model)로 전환했습니다. 이는 함수형 프로그래밍에서 사용되는 연속 전달 스타일(Continuation Passing Style)이나 분산 트랜잭션의 사가 패턴(Saga Pattern)과 유사합니다.
- 패턴: 스텝 A는 스텝 B를 "기다리지" 않습니다. 스텝 A는 스텝 B를 새롭고 독립적인 워크플로로 생성(spawn)합니다.
- 결과: "보류" 상태가 전혀 없습니다. 오케스트레이터가 죽더라도 데이터베이스 상태(스텝 B가 큐에 있다는 사실)가 진실의 원천으로 남습니다.
불변 로직: "콘텐츠 주소 지정 가능한(content-addressable)" 아이덴티티를 활용한 버전 관리
버전 관리는 악명 높게 어려운 문제입니다. 워크플로 정의를 업데이트하면, 이미 실행 중일 수 있는 실행(execution)들에는 어떤 일이 벌어질까요?
- 안티패턴: "제자리(in-place) 업데이트." 새 코드를 배포하면 기존 실행들이 갑자기 다르게 동작하기 시작합니다.
- 업계 표준: 불변 인프라(Immutable Infrastructure). 서버에 SSH로 접속해 패치하지 않고 아예 교체하는 것처럼, 실행 중인 워크플로 정의도 패치해서는 안 됩니다.
우리는 정규화된 DSL 해싱(Canonical DSL Hashing)을 구현했습니다.
워크플로 로직의 추상 구문 트리(Abstract Syntax Tree, AST)를 해싱함으로써, 우리는 모든 버전을 고유하고 콘텐츠 주소 지정이 가능한(content-addressable) 엔티티로 취급합니다. 이는 temporal.io를 비롯한 다른 현대적 엔진들이 사용하는 전략과 일치합니다. 실행의 아이덴티티는 코드의 아이덴티티에 종속됩니다.
"갓 모드(God Mode)" 잠그기
마지막으로 우리는 내부 도구의 보안 문제를 다뤘습니다. 내부 "정리(cleanup)" 스크립트에 루트 권한을 부여하는 것은 흔한 일입니다. 이는 최소 권한 원칙(Principle of Least Privilege)을 위반합니다.
우리는 자체 내부 "점진적 롤아웃(Gradual Rollout)" 도구가 중요한 시스템 ID를 덮어쓸 수 있는 권한을 가지고 있다는 사실을 발견했습니다. 우리는 암호학적으로 검증된 시스템 행위자만 특정 논리적 ID를 요청할 수 있는 "Sudo" 패턴을 사용해 이를 잠갔습니다.
결론
오케스트레이션이 sleep()에 의존한다면, 당신은 클라우드와 싸우고 있는 것입니다.
재귀(Recursion), 불변성(Immutability), 엄격한 아이덴티티(Strict Identity)를 받아들임으로써, 우리는 "희망 기반" 오케스트레이션에서 "증명 기반" 오케스트레이션으로 나아갑니다.
더 읽어보기: