
누락된 계층: AI 네이티브 시스템에 실행 상태 연속성 (Execution-State Continuity)이 필요한 이유
요약
AI 에이전트가 장기적인 목표를 수행할 때, 메모리는 유지되지만 실행 중인 런타임 상태(서버, DB 연결, 셸 등)가 유실되는 문제를 지적합니다. 이를 해결하기 위해 AI 네이티브 시스템에 '실행 상태 연속성(Execution-State Continuity)' 계층이 필수적임을 강조합니다.
핵심 포인트
- 에이전트의 메모리와 워크플로우는 존재하지만 라이브 런타임 계층이 부재함
- 연결 끊김이나 호스트 마이그레이션 시 실행 중인 프로세스 유실 발생
- 단순한 메모리 저장을 넘어 실행 상태의 연속성 확보가 핵심 과제임
- AI 네이티브 시스템을 위한 세 번째 필수 계층으로서의 실행 계층 제안
우리는 영구 메모리 (Persistent memory)를 구축했습니다. 워크플로우 오케스트레이션 (Workflow orchestration)도 구축했습니다. 하지만 라이브 런타임 (Live runtime)을 살아있는 상태로 유지하는 계층은 구축하지 못했습니다. 그리고 모든 장기적 목표를 가진 에이전트 (Long-horizon agent)들은 이제 자신이 남긴 벽에 부딪히고 있습니다.
원문은 docs.cmdop.com/blog/execution-state-continuity-01-missing-layer에서 처음 게시되었습니다 — The Command-Operator Execution Layer 시리즈의 일부입니다.
에이전트가 한 시간 동안 작업하고 있습니다. 저장소 (Repo)를 클론하고, 툴체인 (Toolchain)을 설치하고, 개발 서버 (Dev server)를 시작하고, 데이터베이스 (Database) 연결을 열었으며, 이제 10단계 마이그레이션 중 9단계까지 진행했습니다. 그런데 노트북 덮개가 닫힙니다. 혹은 데스크톱 앱이 자동 업데이트를 배포하고 재시작합니다. 또는 기차가 터널로 진입하여 WebSocket 연결이 40초 동안 끊어집니다.
다시 돌아왔을 때, 에이전트의 _메모리 (Memory)_는 깨끗합니다. 에이전트는 모든 결정, 자신이 건드린 모든 파일, 계획의 요약, 7단계의 예외 상황(Edge case)에 대해 스스로 작성한 메모리까지 모두 기억하고 있습니다. 하지만 에이전트에게 없는 것은 개발 서버, 데이터베이스 연결, 절반만 적용된 마이그레이션, 또는 sudo 프롬프트를 기다리던 셸 (Shell)입니다. 자서전은 살아남았지만, 런타임 (Runtime)은 살아남지 못했습니다.
그 닫힌 노트북 덮개는 모든 사람이 직접 경험해 본 버전의 벽입니다. 작업이 바로 그곳에 있었는데, 순식간에 사라져 버린 것이죠. 이는 가장 공감하기 쉬운 버전일 뿐, 가장 깊은 문제는 아닙니다. 에이전트를 클라우드 (Cloud)로 옮겨서 — 모든 진지한 런타임이 이미 실행되고 있는 서버 측에서 실행하더라도 — 두 명의 운영자, 두 개의 장치, 또는 호스트 마이그레이션 (Host migration)이 등장하는 순간 동일한 벽이 다시 나타납니다. 자신의 연결 끊김에서 살아남는 것은 쉬운 절반입니다. 진짜 어려운 절반은 _해당 프로세스를 시작한 주체 이외의 누군가_가 실행 상태에 접근할 수 있어야 할 때 나타납니다.
이것은 특정 제품의 버그가 아닙니다. 스택 전체에서 누락된 계층입니다. 지난 몇 년 동안 업계는 AI 네이티브 (AI-native) 시스템에 필요한 세 가지 계층 중 두 가지를 구축했으며, 이를 매우 잘 만들어냈습니다. 하지만 아직 세 번째 계층은 구축하지 못했습니다. 이 글에서는 그 세 번째 계층의 이름을 명시하고, 왜 이것이 누락되었는지 추적하며, 현재 전체 분야가 서로 다른 방향에서 동시에 이 계층으로 수렴하고 있다는 증거를 보여줍니다.
우리가 제대로 구축한 두 가지 계층
한 걸음 물러나서 모든 진지한 에이전트 (agent) 시스템이 수렴한 아키텍처 (architecture)를 살펴보십시오. 현재 거의 모든 사람이 동의하는 두 가지 계층이 있습니다.
첫 번째는 **메모리 (memory)**입니다. 이것은 발생한 일에 대한 영구적인 기록입니다: 대화 스크립트 (conversation transcripts), 벡터 임베딩 (vector embeddings), 순환 요약 (rolling summaries), 프로필 및 규칙 파일, 에피소드 및 의미론적 저장소 (episodic and semantic stores)에 대한 검색 파이프라인 (retrieval pipelines) 등이 이에 해당합니다. 이곳에는 엄청난 양의 훌륭한 엔지니어링이 투입되었습니다. 메모리는 디스크에 깔끔하게 직렬화 (serialize)되고, 간단하게 복제 (replicate)되며, 단일 세션보다 오래 지속되도록 명시적으로 설계되었습니다. 사람들이 에이전트가 "장기 기억을 가지고 있다"라고 말할 때, 그들이 의미하는 것이 바로 이 계층입니다. 이제 메모리는 범용 인프라 (commodity infrastructure)가 존재할 정도로 충분히 해결된 문제입니다.
두 번째는 **오케스트레이션 (orchestration)**입니다. 이것은 다음에 무엇을 할지 결정하는 로직 (logic)입니다: 에이전트 루프 (agent loop), 플래너 (planner), 태스크 그래프 (task graph), 도구 호출 계층 (tool-dispatch layer), 서브 에이전트 팬아웃 (subagent fan-out), 그리고 재시작 시에도 다단계 프로세스의 완료를 보장하는 내구적 워크플로 엔진 (durable-workflow engine) 등이 포함됩니다. 이 계층 또한 성숙해 있습니다. Temporal, Orleans, Dapr, 그리고 내구적 실행 (durable-execution) 계보의 기술들은 결정론적 재생 (deterministic replay)을 통해 논리적 (logical) 워크플로가 장애 상황에서도 생존하게 만드는 어려운 문제를 해결했습니다. 에이전트 프레임워크 (agent frameworks)는 그 위에 계획 (planning)과 도구 호출 (tool-calling)을 계층화했습니다. 사람들이 에이전트가 "긴 작업을 안정적으로 수행할 수 있다"라고 말할 때, 그들은 이 계층을 의미합니다.
Memory(메모리)는 내가 무엇을 배우고 결정했는가에 답합니다. Orchestration(오케스트레이션)은 다음에 무엇을 해야 하며, 계획이 완료되도록 어떻게 보장할 것인가에 답합니다. 이 둘 사이에서 놀라울 정도로 방대한 영역을 다룹니다. 하지만 서두에서 언급한 시나리오 — 노트북이 닫히거나, 소켓이 끊기거나, 프로세스가 회수되는 상황 — 은 이 중 어느 것에도 영향을 받지 않습니다. Memory는 계획을 기억했습니다. Orchestration은 기꺼이 다음 단계를 다시 실행할 것입니다. 하지만 그 어느 것도 **실행 중인 런타임 (live runtime)**을 유지하지 못했습니다.
우리가 건너뛴 계층
시스템에는 메모리도 오케스트레이션도 아닌 세 번째 객체가 존재합니다. 그것은 바로 **실행 중인 상태 (live execution state)**입니다. 즉, 실행 중인 프로세스 트리 (process tree), 스크롤백과 라인 디시플린 (line discipline)을 포함한 가상 터미널 (pseudo-terminal, PTY), 오프셋 (offset)과 잠금 (lock)을 가진 열린 파일 디스크립터 (file descriptors), 바인딩된 리스닝 소켓 (listening socket), 프로세스의 사용자 공간 주소 공간 (user-space address space)에 상주하는 실시간 변수들입니다. 이것은 무엇이 일어났는가도 아니고, 다음에 무엇을 할 것인가도 아닙니다. 이것은 지금 이 순간, 실제 머신 위에서 일어나고 있는 일입니다. (이 튜플에 속할 것처럼 보이지만 속하지 않는 한 가지는 외부 데이터베이스나 거래소로 향하는 진행 중인 TCP 연결입니다. 해당 연결의 절반은 원격 피어(remote peer)의 커널에 존재하며, 이는 로컬 계층이 보유할 수 없습니다. 이는 실행 상태 계층이 아니라 애플리케이션 프로토콜에 속합니다. 아래의 경계 단락에서 이를 정확히 설명합니다.)
그리고 오늘날 출시되는 거의 모든 시스템에서, 그 객체는 독립적인 존재성을 갖지 못합니다. 그것은 우연히 그것을 생성한 클라이언트의 구현 세부 사항일 뿐입니다. 프로세스 트리는 클라이언트가 연결을 끊을 때 종료되는 세션에 부모를 두고 있습니다. PTY는 그것을 연 터미널에 속해 있습니다. 소켓은 그것을 만든 연결과 함께 생성되고 소멸합니다. 전송(transport)이 끊기면 — 연결 해제, 재시작, 충돌, 장치 전환 — 실행 상태는 구조적으로 소리 없이 소멸됩니다. 그것을 유지하는 것이 임무인 계층은 존재하지 않습니다.
그것이 바로 누락된 계층입니다. 이를 커맨드-오퍼레이터 실행 계층 (command-operator execution layer), 즉 기술적으로는 **실행 상태 연속성 계층 (execution-state continuity layer)**이라 부를 수 있습니다. 이 계층은 라이브 런타임(live runtime) — 프로세스 트리(process tree), PTY, 파일 디스크립터(file descriptors), 로컬 소켓(local sockets) — 을 고유한 정체성을 가진 일급(first-class), 단일 홈(single-homed), 소유자 없는(ownerless) 객체로 만듭니다. 이를 통해 인간, AI 에이전트, 장치 및 서비스는 각 클라이언트가 연결이 끊기면 소멸하는 런타임을 소유하는 대신, 하나의 실행 중인 실행(execution)에 **오퍼레이터 (operators)**로서 부착(attach)됩니다 (클라이언트, 전송 계층 및 장치 간에 분리 및 재부착 가능). 실행은 단일 홈(single-homed) 방식이며, 분산되는 것은 여기에 부착되는 오퍼레이터들의 집합입니다. 이는 연결을 유지하는 클라이언트가 곧 런타임의 보유자가 되는 **컨트롤러 모델 (controller model)**에서, 런타임이 지속적인 실체이며 이를 생성한 클라이언트를 포함한 모든 클라이언트가 교체 가능한 부착 참조(attached reference)가 되는 **오퍼레이터 모델 (operator model)**로의 전환을 의미합니다. (여기서 "오퍼레이터"는 시스템 내부에서 라이브 시스템을 운용하는 행위자라는 인간 공학적 의미로 사용되었습니다. 이는 상위에서 원하는 상태를 조정하는 _컨트롤러 (controller)_인 Kubernetes Operator 패턴과는 다르며, 두 개념은 거의 정반대에 가깝습니다.)
본격적인 논의에 앞서 한 가지 솔직하게 명확히 짚고 넘어가겠습니다. 위에서 언급한 튜플(tuple)은 난이도가 매우 다른 요소들을 혼합하고 있기 때문입니다. 해당 시나리오에는 세 가지 뚜렷한 연속성 영역(continuity regimes)이 숨어 있으며, 진정한 연속성 계층(continuity layer)은 자신이 담당하는 영역이 무엇인지 정확히 규정해야 합니다. (1) 호스트는 살아있으나 클라이언트가 분리되는 경우 — 노트북 덮개를 닫거나, 소켓(socket) 연결이 끊기거나, 앱이 재시작되는 상황입니다. 런타임(runtime)은 계속 실행 중이며, 나중에 클라이언트가 다시 연결됩니다. 이것이 바로 계층이 온전히 책임지는 영역이며, 본 시리즈가 다루고자 하는 핵심입니다. (2) 호스트 자체가 종료되거나 마이그레이션(migration)되는 경우. 이제 여러분은 체크포인트/복구(checkpoint/restore)의 영역(pause/resume 샌드박스로 제품화된 CRIU 계보)에 들어서게 됩니다. 이는 메모리와 프로세스 상태에 대해 해결 가능하지만, 실제 비용과 한계가 따릅니다. 실제로 이 영역은 스펙트럼 상에서 접근됩니다. 즉, 재시작 시 세션 상태(session state)를 유지하고 복구하는 수준(현재 사용 가능)에서부터, 완전한 라이브 메모리 체크포인트/복구(동일 축의 더 어려운 끝단)에 이르기까지 다양합니다. (3) 호스트 마이그레이션 중에도 라이브 외부 연결이 유지되는 경우 — 데이터베이스나 거래소로 향하는 인플라이트(in-flight) 소켓과 같은 경우입니다. 이것은 계층의 문제가 전혀 아닙니다. 반대편의 피어(peer)가 자신의 커널에 연결의 절반을 유지하고 있으므로, 그 어떤 로컬 연속성으로도 원격 서버의 소켓 상태를 재작성할 수는 없습니다. 해당 영역은 런타임이 아니라 애플리케이션 프로토콜(application protocol) — 재연결(reconnect), 시퀀스 번호에 의한 동기화(resync), 멱등성 연산(idempotent operations) — 이 담당해야 합니다. 만약 연속성 계층이 그렇지 않다고 주장한다면, 그것은 물리 법칙에 대해 거짓말을 하는 것입니다. 따라서 본 시리즈에서 계층이 라이브 실행을 유지한다고 말할 때, 이는 (1)번 영역을 핵심으로 하여 (2)번 영역까지 확장하되, (3)번 영역은 의도적으로 프로토콜에 넘겨준다는 것을 의미합니다. 이 경계를 명확히 하는 것은 해당 카테고리의 약점이 아니라, 정직하게 정의된 그 카테고리 자체입니다. (Part 6에서 이 경계를 명시적으로 다루며, Part 7에서 각 장애 모드(failure mode)를 살펴봅니다.)
여기 전체 멘탈 모델(mental model)을 하나의 그림으로 나타냈습니다.
그림을 보기 전에 기하학적 구조(geometry)에 대해 명확히 짚고 넘어가겠습니다. 이 세 가지는 엄격한 수직 스택(vertical stack)이라기보다 세 가지의 _독립적인 관심사(independent concerns)_로 이해하는 것이 가장 좋습니다. 메모리(memory)와 실행 상태(execution state)는 서로 직교하는 축이며(Part 2에서 이를 정확히 다룹니다), 오케스트레이션(orchestration)은 또 다른 세 번째 축입니다. 연속성(continuity)을 _최하단(bottom)_에 그린 이유는 다른 요소들이 연속성으로부터 바이트 단위로 구축되었기 때문이 아니라, 나머지 두 요소가 조용히 활성 런타임(live runtime)이 존재한다고 가정하기 때문입니다. 메모리는 자신의 트랜스크립트(transcript)를 런타임과 연관시키고
tmate는 이를 네트워크 전체로 확장하여, 릴레이(relay)로 향하는 아웃바운드 터널(outbound tunnel)을 열고 세션 토큰(session token)을 발행함으로써, *여러 원격 클라이언트(multiple remote clients)*가 NAT 및 방화벽을 통해 하나의 라이브 PTY(live PTY)에 접속할 수 있도록 했습니다. 이는 릴레이를 매개로 한 다중 클라이언트 터미널 공유 문제를 해결했지만, 근본적으로는 여전히 터미널이었습니다.
**Jupyter 커널 (Jupyter kernel)**은 이 개념을 터미널을 완전히 넘어 일반화했습니다. 독립적인 커널 프로세스가 메모리에 변수, 임포트(imports), 연결(connections)을 유지하는 동안, 노트북 클라이언트들은 연산을 잃지 않고 ZeroMQ를 통해 연결을 끊었다가 다시 연결할 수 있습니다. 이는 라이브 *힙 (heap)*을 UI로부터 분리하는 문제를 해결했지만, 해당 힙을 단일 커널 프로세스에 종속시켰으며, 일반적인 런타임이 아닌 대화형 노트북을 위한 것이었습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기