
에이전트 기반은 왜 「OS」에 가까워지는가──기술 스택을 밑바닥부터 읽기 (제0회)
요약
에이전트가 단순한 함수 호출을 넘어 장시간 실행되는 프로세스로 진화함에 따라, 이를 관리하기 위한 운영체제(OS)와 같은 계층 구조의 필요성을 다룹니다. 자원 관리, 상태 유지, 권한 제어 등 에이전트 시스템의 규모화와 상용화를 위한 핵심 과제를 분석합니다.
핵심 포인트
- 에이전트는 단순 호출을 넘어 상태와 자원을 소비하는 프로세스로 진화 중
- 장기 실행 에이전트를 위해 OS와 유사한 관리 계층이 필수적임
- 자원 스케줄링, 메모리(기억) 격리, 권한 관리 등의 문제 해결 필요
- 신뢰할 수 있는 에이전트 시스템 구축을 위한 구조적 접근 강조
지난 1년 동안, 「에이전트 (Agent)」라는 단어의 무게중심이 바뀌었다.
조금 전까지만 해도 에이전트라고 하면, 대체로 다음과 같은 것을 가리켰다. 대규모 언어 모델 (LLM)에 한 번 질의한다. 그 전후로 검색, 파일 조작, 코드 실행, 브라우저 조작과 같은 도구를 연결한다. 모델이 「다음에 무엇을 할지」를 문장으로 결정한다. 필요하면 도구를 호출한다. 결과를 보고, 다시 한번 생각한다.
이것은 확실히 편리했다. 단순한 채팅보다 한 단계 진보해 있었다. 모델이 외부 세계와 접촉하기 때문이다.
하지만, 이 단계의 에이전트는 아직 「한 번의 호출을 조금 더 똑똑하게 만든 것」에 가까웠다. 고장 나더라도 다시 실행하면 된다. 중간 상태가 손실되어도 이용자가 다시 설명하면 된다. 권한이 조금 허술해도 실험이라면 허용된다. 동작 시간도 짧고, 동시에 실행되는 수도 적다.
문제는, 그것을 멈추지 않고 실전(Production)에서 구동하려고 한 순간 시작된다.
에이전트가 몇 분이 아니라 몇 시간 동안 실행된다. 도중에 파일을 읽고, 외부 API를 호출하고, 브라우저를 열고, 코드를 작성하고, 결과를 저장한다. 어제의 판단을 오늘도 기억하고 있을 필요가 있다. 여러 에이전트가 동시에 움직이며 서로 의존한다. 어떤 에이전트의 출력이 다른 에이전트의 입력이 된다. 실패했을 때는 어디까지 되돌릴지를 결정해야 한다. 어떤 도구는 사용하게 하고 싶지만, 어떤 조작은 허용하고 싶지 않다. 어떤 기억은 공유하고 싶지만, 어떤 기억은 격리하고 싶다.
여기까지 오면, 에이전트는 「똑똑한 함수 호출 (Function Calling)」이 아니게 된다.
그것은 상태를 가지고, 자원을 소비하며, 권한을 가지며, 실패하고, 재개되고, 관측되며, 다른 실행 단위와 협조하는 존재가 된다. 즉, 프로세스 (Process)가 된다.
그리고 프로세스가 늘어나면, 반드시 관리하는 계층이 필요하다.
누가 언제 실행되는가. 어떤 자원을 사용해도 되는가. 어떤 기억에 접근해도 되는가. 외부 도구를 호출하는 권한은 어디까지인가. 도중에 중단되었을 때 어떤 상태부터 재개할 것인가. 여러 실행이 같은 데이터를 수정하려고 할 때 어느 쪽을 우선할 것인가. 이용자에게 보여줘야 할 로그와 내부적으로만 보유해야 할 로그를 어떻게 나눌 것인가.
이것은 새로운 문제처럼 보이지만, 구조적으로는 오래된 것이다.
컴퓨터가 단일 프로그램을 하나씩 실행하던 시대에는 실행 관리가 단순했다. 하지만 여러 프로그램을 동시에 실행하고, 메모리를 나누고, 파일을 보호하며, 디바이스를 공유하고, 실패로부터 복구하려고 했을 때, 운영체제 (OS)가 필요해졌다.
지금 에이전트 기반에서 일어나고 있는 일은 그것과 상당히 유사하다.
물론, 에이전트 기반은 기존의 OS 그 자체는 아니다. CPU의 명령을 직접 스케줄링하는 것도 아니고, 메모리 주소를 페이지 단위로 할당하는 것도 아니다. 하지만 풀고 있는 문제의 형태는 닮아 있다. 실행 단위가 있고, 자원이 있으며, 상태가 있고, 권한이 있고, 실패가 있으며, 관측이 있다. 그 전체를 이용자나 개발자가 매번 수동으로 관리할 수는 없다.
따라서 신뢰할 수 있고, 규모화(Scale)할 수 있으며, 상용화할 수 있는 에이전트 기반을 진지하게 만들려고 하면, 그것은 비유가 아니라 OS와 같은 계층 구조를 갖기 시작한다.
이 연재는 그 구조를 밑바닥부터 읽어 내려간다.
단발적인 모델 호출에서는 관리해야 할 것이 적다.
입력을 전달한다. 출력을 받는다. 필요하면 재시도한다. 실패해도 이용자가 다시 던지면 그만이다. 대화 이력(Conversation History)은 있을지 모르지만, 그것도 기본적으로는 「다음 입력에 덧붙이는 문맥 (Context)」일 뿐이다.
그런데, 에이전트가 길게 실행되기 시작하면 사정이 달라진다.
예를 들어, 어떤 조사 에이전트가 아침부터 작동하고 있다고 가정하자. 여러 사이트를 순회하며 기사를 읽고, 요약하고, 중요도를 판정하며, 나중에 사용하기 위해 메모를 남긴다. 도중에 API 제한에 걸린다. 어떤 페이지는 로딩에 실패한다. 다른 페이지는 로그인이 필요해진다. 요약 도중에 모델 호출이 실패한다. 게다가 같은 시간대에 다른 에이전트도 같은 데이터베이스에 쓰려고 하고 있다.
이때 필요한 것은 좋은 프롬프트 (Prompt)만이 아니다.
어떤 작업이 완료되었고 어떤 작업이 미완료 상태인가. 실패한 처리는 재시도해도 되는가. 재시도하면 중복으로 기록되지 않는가. 중간까지 읽은 기사의 상태는 어디에 저장하는가. 어떤 에이전트가 어떤 인증 정보를 사용할 수 있는가. 외부 사이트에 대한 액세스 횟수를 어떻게 제어할 것인가. 처리 전체의 로그를 어떻게 추적할 것인가.
이것들은 모델의 똑똑함과는 별개의 문제이다.
모델이 아무리 똑똑해도 실행 상태가 사라지면 다음 단계로 진행할 수 없다. 모델이 아무리 도구를 잘 사용해도 권한 경계 (Permission Boundary)가 없다면 위험해진다. 모델이 아무리 추론을 잘해도 여러 작업이 같은 자원을 두고 다투면 망가진다. 모델이 아무리 자연스러운 문장을 써도 어디서 실패했는지 보이지 않으면 운용할 수 없다.
따라서 에이전트를 실전에서 구동하기 위해서는 모델의 외측에 관리 계층이 필요하다.
이 관리 계층이 담당하는 업무는 기존의 OS (Operating System)가 맡아온 업무와 대응된다. OS는 CPU 시간을 배분한다. 메모리를 분할한다. 프로세스를 기동하고, 정지시키며, 격리한다. 파일이나 디바이스에 대한 액세스를 제어한다. 시스템 콜 (System Call)이라는 형태로, 프로그램이 외부 세계와 접하는 입구를 결정한다.
에이전트 기반에서도 비슷한 일이 일어난다. 모델 호출, 도구 호출, 메모리 참조, 외부 API, 파일, 브라우저, 코드 실행을 누구에게 어디까지 허용할지 결정해야 한다. 길게 이어지는 작업을 어떤 단위로 저장하고, 재개하며, 모니터링할지 결정해야 한다. 여러 에이전트를 어떻게 배치하고, 어떻게 대기시키며, 어떻게 정지시킬지 결정해야 한다.
여기서 중요한 것은 'OS 같다'는 분위기가 아니다.
문제의 인과관계가 OS를 요구하고 있다는 것이다.
실행이 길어진다. 그러면 상태 (State)가 필요해진다. 상태가 있으면 저장과 복구가 필요해진다. 여러 실행이 병렬로 이루어진다. 그러면 스케줄링 (Scheduling)이 필요해진다. 도구를 호출한다. 그러면 권한이 필요해진다. 외부 세계를 수정한다. 그러면 감사 (Audit)가 필요해진다. 실패가 발생한다. 그러면 재시도와 롤백 (Rollback)이 필요해진다.
이 연쇄의 끝에 자연스럽게 계층이 생겨난다.
하단에는 계산 자원이 있다. 그 위에 추론 서비스가 있다. 그 위에 모델이 있다. 그 위에 에이전트의 실행 환경이 있다. 더 위에는 여러 에이전트의 편성 (Orchestration)이 있다. 안전은 그 옆을 관통한다. 평가와 개발 메커니즘이 전체를 제품으로서 성립시킨다. 마지막으로 금융, 교육, 콘텐츠 안전과 같은 용도가 올라간다.
이것이 이 연재에서 말하는 Agentic OS 기술 스택이다.
이전의 핵심 과제는 모델 그 자체에 가까웠다.
어떻게 프롬프트 (Prompt)를 작성할 것인가. 어떤 모델을 사용할 것인가. 어떤 도구를 건네줄 것인가. 어떤 순서로 생각하게 할 것인가. 모델에게 계획을 세우게 할 것인가, 외부 코드(External Code)로 제어할 것인가. 이것들은 지금도 중요하지만, 주전장은 조금 위로 옮겨갔다.
지금 질문되고 있는 것은 '에이전트라는 실행 단위를 어떻게 관리할 것인가'이다.
이는 애플리케이션 개발로 치면, 함수의 내용만을 보던 단계에서 서비스 운용을 보는 단계로 넘어온 것과 같다. 함수 단독이라면 입력과 출력만 보면 된다. 하지만 서비스는 요청을 받고, 상태를 가지며, 타 서비스를 호출하고, 장애에 견디며, 로그를 남기고, 권한을 지키고, 배포되며, 모니터링된다. 내부 로직만으로는 설명할 수 없다.
에이전트도 마찬가지다.
하나의 모델 호출이 올바른 답을 낼 수 있는지 여부만으로는 부족하다. 그 답이 긴 작업의 어느 위치에서 나왔는가. 전제가 되는 기억은 무엇인가. 어떤 도구를 사용하여 얻은 결과인가. 누구의 권한으로 실행되었는가. 실패 시 재실행해도 안전한가. 다른 에이전트와 충돌하지 않는가. 최종적인 결과물을 어떻게 평가할 것인가.
이렇게 적어도 세 가지 공학적 테마가 독립적으로 부상한다.
첫 번째는 런타임 (Runtime)이다.
여기서 말하는 런타임이란 에이전트가 실제로 돌아가는 환경을 말한다. 모델을 호출하고, 도구를 호출하며, 중간 상태를 저장하고, 필요하면 재개한다. 단기 문맥 (Short-term Context)과 장기 기억 (Long-term Memory)을 분리한다. 코드 실행이나 브라우저 조작을 격리한다. 외부 세계에 부작용 (Side Effect)을 일으키는 조작을 관리한다.
두 번째는 편성 (Orchestration)이다.
하나의 에이전트뿐만 아니라, 여러 에이전트를 어떻게 조합할 것인가 하는 문제다. 조사하는 에이전트, 검증하는 에이전트, 구현하는 에이전트, 리뷰하는 에이전트가 있다고 가정하자. 그것들은 직렬로 움직이는가, 병렬로 움직이는가. 누가 결과를 통합하는가. 도중에 모순이 발생하면 어떻게 하는가. 자원이 부족할 때 어떤 것을 대기시킬 것인가.
세 번째는 안전 (Safety)이다.
에이전트가 문장을 내보내는 정도라면 아직 괜찮다. 하지만 파일을 수정하고, 메일을 보내고, 결제를 일으키고, 사내 데이터를 읽고, 코드를 실행한다면 이야기가 달라진다. 오작동뿐만 아니라 외부로부터의 유도 (Induction)에도 대비해야 한다. 웹페이지나 메일 본문 속에 에이전트를 속이는 지시가 섞여 있을 수 있다. 도구의 출력에 다음 행동을 탈취하는 문장이 포함될 수도 있다.
안전은 마지막에 필터를 배치하면 끝나는 문제가 아니다.
어느 계층에서 무엇을 신뢰할 것인가. 어떤 입력을 명령으로 취급하고, 어떤 입력을 단순한 데이터로 취급할 것인가. 어떤 조작에 인간의 확인을 거칠 것인가. 어떤 기억을 공유해도 되는가. 어떤 로그를 감사 가능한 형태로 남길 것인가. 이것들을 설계하지 않는 한 에이전트는 실전 권한을 가질 수 없다.
즉, 무게 중심이 '모델을 어떻게 똑똑하게 쓸 것인가'에서 '똑똑한 실행 단위를 어떻게 운용할 것인가'로 옮겨갔다.
이 변화를 간과하면 에이전트를 언제까지나 데모의 연장선으로 취급하게 된다. 데모에서는 돌아간다. 하지만 길게 실행하면 망가진다. 인원을 늘리면 혼선이 생긴다. 권한을 부여하면 위험해진다. 고객에게 넘기면 설명할 수 없게 된다.
에이전트가 프로세스(Process)가 된다는 것은 바로 그런 의미이다.
현재 다중 에이전트 시스템(Multi-agent system)의 상당수는 솔직히 말해 아직 미흡하다.
여러 에이전트를 세운다. 각각에 역할을 부여한다. 한 에이전트의 출력을 다른 에이전트의 입력으로 전달한다. 프롬프트(Prompt)로 "당신은 리뷰 담당입니다", "당신은 구현 담당입니다"라고 지시한다. 필요하다면 대화 이력이나 중간 결과물을 공유한다.
이것은 작동한다. 작은 규모의 예시에서는 꽤 잘 돌아가는 것처럼 보인다.
하지만 OS(운영체제)의 비유를 빌리자면, 이는 fork한 프로세스를 수동적인 IPC로 연결하고 있는 단계에 가깝다. IPC란 프로세스 간 통신(Inter-Process Communication)을 의미한다. 별개로 동작하는 실행 단위들이 메시지, 공유 메모리(Shared memory), 파이프(Pipe), 파일 등을 통해 정보를 주고받는 메커니즘이다. 현재의 다중 에이전트에서는 이 통신의 상당 부분이 자연어 프롬프트에 억지로 밀어 넣어지고 있다.
자연어는 유연하지만 경계가 모호하다.
어디까지가 명령이고 어디부터가 데이터인가. 어떤 정보가 신뢰할 수 있는 정보이며 어떤 정보가 미검증 정보인가. 특정 에이전트의 발언을 다른 에이전트가 어느 정도의 권한으로 실행해도 되는가. 공유된 문맥(Context) 중 어떤 것이 현재도 유효한가. 이러한 것들이 명시적인 시스템 구조가 아니라 프롬프트를 작성하는 방식에 의존하고 있다.
스케줄러(Scheduler)도 아직 취약하다.
스케줄러란 어떤 실행 단위를 언제 실행할지를 결정하는 메커니즘이다. OS에서는 CPU가 유한하기 때문에 프로세스를 순차적으로 실행해야 한다. 에이전트에서도 모델 호출, 외부 API, 브라우저, 데이터베이스, 예산, 인간의 확인 시간은 유한하다. 모든 것을 동시에 실행하면 비용이 폭증한다. 순서를 잘못 잡으면 필요한 전제 조건이 갖춰지기 전에 작업이 진행된다. 너무 오래 기다리게 하면 전체 지연(Latency)이 늘어난다.
네임스페이스(Namespace)를 통한 격리도 미성숙하다.
네임스페이스란 특정 실행 단위에서 보이는 세계를 한정하는 메커니즘이다. OS에서는 컨테이너마다 보이는 파일 시스템, 프로세스, 네트워크를 분리할 수 있다. 에이전트에서도 같은 발상이 필요하다. 조사 에이전트에게는 읽기 전용 자료만 보여준다. 구현 에이전트에게는 특정 리포지토리(Repository)만 넘겨준다. 고객 A의 기억과 고객 B의 기억을 섞지 않는다. 검증 전의 정보를 확정된 정보로서 다른 에이전트에게 전달하지 않는다.
자원과 권한의 추상화도 아직 갖춰지지 않았다.
어떤 도구는 읽기만 허용한다. 어떤 도구는 쓰기도 허용한다. 어떤 조작은 인간의 승인 후에만 실행한다. 어떤 메모리는 일시적으로 사용하고 어떤 메모리는 장기 보존한다. 어떤 모델에는 저비용으로 초안을 작성하게 하고, 어떤 모델에는 고비용으로 최종 판단을 하게 한다. 이러한 설계를 에이전트별 프롬프트와 개별 코드만으로 관리하는 데에는 한계가 있다.
최근 에이전트 군집을 네트워크로 다루는 생각, 에이전트 실행 기반을 클러스터(Cluster) 관리 방식에 가깝게 만드는 생각, 실행 트리(Execution tree)를 시각화하는 메커니즘 등이 등장하고 있다. 이것들은 단순한 신제품의 유행으로 보기보다, "업계가 드디어 프로세스 스케줄러, 자원 격리, 네임스페이스를 만들기 시작했다는 신호"로 읽는 것이 좋다.
진화의 선은 아마 다음과 같을 것이다.
처음에는 가공되지 않은 fork이다. 에이전트를 여러 개 기동하고 프롬프트로 연결한다.
다음에는 프로세스 모델이 굳어진다. 에이전트란 무엇인가, 태스크(Task)란 무엇인가, 상태(State)란 무엇인가, 메모리(Memory)란 무엇인가, 도구 호출(Tool call)이란 무엇인가가 명시적인 단위로 나뉜다.
그다음에는 스케줄링, 격리, 통신의 표준화가 진행된다. 어떤 에이전트가 언제 실행되고, 무엇을 볼 수 있으며, 무엇을 호출할 수 있고, 어떤 형식으로 결과를 전달할지가 개별 구현이 아닌 기반(Infrastructure)의 책무가 된다.
마지막으로 커널(Kernel)과 같은 계층이 보인다.
여기서 말하는 커널이란 OS의 핵심이라는 의미를 빌린 표현이다. 에이전트 실행의 최소한의 권한, 자원, 상태, 통신, 감사를 다루는 계층이다. 애플리케이션마다 매번 만드는 것이 아니라, 그 위에 다양한 에이전트 애플리케이션이 올라가는 공통 기반이 된다.
이 연재는 그 선을 쫓아간다.
Agentic OS 기술 스택은 한 장의 그림으로 보면 이해하기 쉽다.
단, 이 그림은 제품 카테고리의 목록이 아니다. 어느 계층에 어떤 회사가 있는지를 나열하고 싶은 것도 아니다. 여기서 보고 싶은 것은 각 계층이 어떤 직관을 단련하는 장소인가 하는 점이다.
아래에서부터 순서대로 살펴본다.
| 계층 | 이름 | 거기서 단련하는 직관 |
|---|---|---|
| L0 | 연산력의 토대 | 클러스터 전체에서 계산을 어떻게 배분하고, 고장 나도 지속하며, 훈련과 추론을 일체로 운용할 것인가. |
| ... |
L0는 연산력의 토대이다.
여기서 보는 것은 GPU가 몇 장인가 하는 것만이 아니다. 대량의 계산 자원을 어떻게 할당하고, 어떻게 채워 넣으며, 어떻게 고장에 견디게 할 것인가 하는 문제이다. 훈련(Training)과 추론(Inference)은 별개로 보이지만, 실제로는 동일한 클러스터, 동일한 네트워크, 동일한 운용상의 제약을 두고 다툰다. 거대한 모델을 만드는 힘과 그 모델을 저렴하고 안정적으로 배포하는 힘은 서로 분리된 것이 아니라 연결되어 있다.
L1은 추론 서비스(Inference Service)이다.
모델에 입력을 던지면 답이 돌아온다는 관점은 너무 거칠다. 추론에서는 과거의 토큰으로부터 만든 내부 상태를 재사용한다. 이것이 KV 캐시(KV Cache)이다. KV는 모델이 주의 집중 메커니즘(Attention Mechanism)을 통해 과거의 문맥을 참조하기 위해 가지는 키(Key)와 값(Value)의 묶음이다. 긴 문맥을 다룰수록 이 캐시는 커진다. 캐시를 어디에 두고, 어떻게 재사용하며, 어떻게 버릴 것인가가 대기 시간(Latency)과 비용을 결정한다.
투기적 추론(Speculative Decoding)도 여기에 포함된다. 이는 작고 빠른 모델이 앞선 후보 토큰들을 미리 실행하면, 큰 모델이 이를 한꺼번에 확인하는 방식이다. 예측이 적중하면 품질을 크게 떨어뜨리지 않으면서 출력을 빠르게 할 수 있다. 즉, 추론 서비스는 단순한 API가 아니다. 토큰이 입구에서 출구까지 통과하는 경로 전체를 조율하는 계층이다.
L2는 모델(Model)이다.
여기서는 모델을 마법의 상자로 취급하지 않는다. 어떤 아키텍처(Architecture)가 어떤 문맥 길이(Context Length), 추론 속도, 기억 처리 방식, 멀티모달성(Multimodality)을 가능하게 하는지를 살펴본다. 세계 모델(World Model)이라는 용어 역시 여기서는 수식어가 아니다. 외부 세계의 상태 변화를 내부에서 예측하고, 행동의 결과를 가늠하는 능력이 어느 정도인가라는 구체적인 문제로 다룬다.
사후 훈련(Post-training)도 중요하다. 사전 학습(Pre-training)된 모델에 대해 인간의 선호도, 태스크의 성공, 환경으로부터의 보상을 사용하여 행동을 조정한다. 특히 여러 시도가 동시에 진행되고 나중에 보상이 돌아오는 것과 같은 비동기 강화학습(Asynchronous RL)은 에이전트의 훈련과 궁합이 좋다. 단말 측(On-device) 모델도 여기서 다룬다. 모든 것을 클라우드로 보내는 것이 아니라, 지연 시간(Latency), 프라이버시, 비용 문제로 인해 손안의 단말에서 구동되는 모델이 담당하는 범위가 넓어지고 있다.
L3는 런타임(Runtime)이다.
여기서부터 에이전트는 명확하게 프로세스(Process)에 가까워진다. 실행 환경을 격리한다. 코드를 안전한 상자(Sandbox) 안에서 실행한다. 브라우저 조작을 기록한다. 도구 호출(Tool Calling)의 결과를 저장한다. 단기 문맥과 장기 기억을 분리한다. 장기 기억이란 단순히 오래된 대화를 전부 집어넣는 것이 아니다. 나중에 재사용할 수 있는 형태로 사실, 판단, 선호도, 결과물, 실패 사례를 정리하여 검색할 수 있도록 만드는 것이다.
L4는 오케스트레이션(Orchestration)이다.
단일 에이전트가 할 수 있는 일에는 한계가 있다. 조사, 계획, 실행, 검증, 감사를 하나의 문맥에 몰아넣으면 문맥은 비대해지고 책임은 모호해지며 실패 지점을 파악하기 어려워진다. 그래서 역할을 나눈 여러 에이전트를 조합한다. 하지만 나눈다고 해서 자동으로 좋아지는 것은 아니다. 통신 형식, 책임 경계, 동기화(Wait/Sync), 경합 해결(Conflict Resolution), 실행 트리(Execution Tree)의 가시성(Observability)이 필요해진다.
L5는 안전(Safety)이다.
이는 L1부터 L4까지를 가로지른다. 추론 서비스에서는 입력과 출력의 취급이 문제가 된다. 모델에서는 유해한 행동이나 속기 쉬운 특성이 문제가 된다. 런타임에서는 도구와 권한이 문제가 된다. 오케스트레이션에서는 특정 에이전트의 오염된 출력이 다른 에이전트를 통해 확산되는 문제가 있다.
레드팀(Red Teaming)이란 공격자나 악조건의 입장에서 시스템을 의도적으로 망가뜨리려는 검증이다. 프롬프트 인젝션(Prompt Injection) 공격이란 외부 데이터 속에 명령조의 문장을 섞어 에이전트의 판단을 탈취하려는 공격이다. 에이전트 기반의 안전은 이러한 것들을 단발적인 필터로 막는 것이 아니라, 명령과 데이터의 분리, 권한 최소화, 감사, 인간 확인(Human-in-the-loop), 격리를 조합하여 구축한다.
L6는 개발 체계(Development System)이다.
에이전트를 만든다는 것은 프롬프트를 쓰는 것만이 아니다. 사양(Specification)을 결정한다. 기대하는 행동을 테스트 가능한 형태로 구체화한다. 실패 사례를 수집한다. 평가 환경을 구축한다. 도구의 모크(Mock)를 준비한다. 회귀 테스트(Regression Test)를 돌린다. 배포 후에 로그를 보고 개선한다. 하네스(Harness)란 이러한 평가와 실행의 프레임워크를 말한다. 단순히 "똑똑하게 대답했는가"가 아니라, 지정된 환경에서 지정된 제약 조건 하에 업무를 완료했는지를 측정한다.
여기에는 코딩 CLI도 포함된다. 코드를 작성하는 주체가 인간뿐만이 아니게 되기 때문이다. 인간이 사양을 전달하면 에이전트가 편집하고, 테스트를 실행하고, 리뷰를 받고, 다시 수정한다. 이때 중요한 것은 누가 썼느냐가 아니라, 어떤 사양에 대해 어떤 차이(Diff)가 발생했으며 어떤 검증을 통과했는가이다.
L7은 수직적 응용(Vertical Application)이다.
금융, 교육, 콘텐츠 안전과 같은 영역은 마지막에 단순히 껍데기를 씌우는 것이 아니다. 오히려 그 반대다. 현장의 요구사항이 아래 계층에 필요한 능력을 결정한다.
금융에서는 설명 가능성(Explainability), 감사(Audit), 권한, 데이터 경계가 강력하게 요구된다. 교육에서는 학습자 개개인의 장기 기억, 오류 패턴의 파악, 개입 타이밍이 중요해진다. 콘텐츠 안전(Content Safety)에서는 대량의 입력을 고속으로 처리하면서도, 경계 사례(Edge cases)를 인간에게 되돌려주는 설계가 필요하다.
즉, 응용 계층은 단순한 겉모습이 아니다. 하위 계층에 대한 요구 사양이다.
마지막으로, Harness 능력 모델이 전체를 연결한다.
어떤 에이전트가 정말로 쓸모 있는지는 모델 단독의 점수만으로는 결정되지 않는다. L0의 연산 능력(Compute) 제약, L1의 추론 비용, L2의 모델 능력, L3의 실행 환경, L4의 편성, L5의 안전, L6의 평가, L7의 현장 요구사항이 맞물려야 비로소 결정된다. 어느 하나만 강력하더라도 전체적으로는 병목이 발생한다.
이 연재에서는 그 맞물림을 살펴본다.
에이전트 이야기는 위에서부터 시작하고 싶어지기 마련이다.
어떤 일을 자동화할 수 있는가. 어떤 UI가 좋은가. 어떤 업무에 투입할 것인가. 어떤 에이전트를 몇 대나 배치할 것인가. 이런 이야기는 이해하기 쉽다. 눈에 보이는 성과와 가깝기 때문이다.
하지만 위에서부터만 읽으면 핵심을 놓치게 된다.
상위 계층의 비용은 하위 계층의 물리적인 제약에 의해 결정되기 때문이다.
예를 들어, '장기 기억을 많이 사용하면 똑똑해진다'라는 말이 있다. 하지만 기억은 공짜가 아니다. 검색하는 데에도 계산이 필요하다. 문맥(Context)에 넣으려 해도 토큰이 필요하다. 모델이 긴 문맥을 읽으려면 KV 캐시(KV Cache)가 불어나게 된다. 캐시가 불어나면 메모리 대역폭(Memory Bandwidth)을 점유한다. 메모리 대역폭이 막히면 병렬 처리 수가 떨어진다. 병렬 처리 수가 떨어지면 대기 시간과 비용이 상승한다.
즉, '기억을 갖게 한다'라는 상위 설계는 하위의 대역폭 및 캐시 제약과 직결되어 있다.
여러 에이전트를 병렬로 실행하는 경우도 마찬가지다. 병렬로 돌리면 빨라지는 것처럼 보인다. 하지만 각 에이전트가 모델을 호출하고, 도구(Tool)를 호출하며, 동일한 데이터를 읽고 쓴다면 어딘가에서 자원을 두고 다투게 된다. 추론 서버의 큐(Queue)가 길어질 수도 있다. 외부 API의 제한에 걸릴 수도 있다. 공유 메모리의 정합성이 깨질 수도 있다. 인간의 확인 대기 시간이 길어질 수도 있다.
평가도 마찬가지다. 좋은 평가 체계를 만들려면 실행 중간 과정을 관측할 수 있어야 한다. 최종 출력만 봐서는 왜 성공했는지, 왜 실패했는지 알 수 없다. 중간의 도구 호출, 참조한 기억, 모델의 판단, 재시도, 권한 확인 등을 추적할 수 없다면 개선할 수 없다. 즉, 평가의 질은 런타임(Runtime)과 편성 계층의 가관측성(Observability)에 의존한다.
그렇기에 밑바닥부터 읽어야 한다.
L0와 L1을 모르면 에이전트의 비용을 논할 수 없다. L2를 모르면 어디까지 모델에 맡겨야 할지 판단할 수 없다. L3를 모르면 장기 기억이나 도구 활용을 설계할 수 없다. L4를 모르면 다중 에이전트의 편성은 단순한 대화극에 그치게 된다. L5를 모르면 실제 환경의 권한을 부여할 수 없다. L6를 모르면 납품 가능한 품질을 확보할 수 없다. L7을 모르면 무엇을 최적화해야 할지 알 수 없다.
중간부터 시작하면 답을 먼저 보고 문제를 나중에 알게 된다.
예를 들어, '에이전트에게는 메모리가 필요하다'라고 말하는 것은 쉽다. 하지만 어떤 기억을 어디에 둘 것인가. 검색으로 가져올 것인가, 문맥에 상주 시킬 것인가. 사용자별로 나눌 것인가, 조직 단위로 공유할 것인가. 오래된 기억은 어떻게 버릴 것인가. 주입된 허위 정보는 어떻게 격리할 것인가. 이를 고려하려면 하위 계층의 제약을 반드시 알아야 한다.
'다중 에이전트로 역할을 분담한다'라고 말하는 것도 쉽다. 하지만 통신 비용, 대기 시간, 책임 경계, 실패 시의 재실행, 로그의 결합, 권한의 전파를 고려하지 않는다면 분담은 복잡성만 가중시킬 뿐이다.
'평가가 중요하다'라고 말하는 것도 쉽다. 하지만 평가 대상의 실행을 재현할 수 없다면 평가는 안정적이지 않다. 중간 상태를 취할 수 없다면 개선점을 알 수 없다. 현장의 성공 조건이 사양(Specification)으로 정의되어 있지 않다면, 점수가 올라가더라도 아무런 도움이 되지 않는다.
그래서 이 연재는 토대부터 올라간다.
먼저 계산 자원과 추론의 제약을 본다. 그다음 모델을 본다. 그 위에서 런타임, 편성, 안전, 연구 개발 체계, 수직적 응용으로 나아간다. 상위 계층을 경시하기 위해서가 아니다. 상위 계층을 올바르게 설계하기 위해 하위 계층부터 읽는 것이다.
이 연재에서는 한 회당 하나의 계층을 다룬다.
표면적인 용어만 소개하고 끝내지 않는다. 각 계층에서 무엇이 제약이 되고, 어떤 추상화(Abstraction)가 탄생하며, 상위 계층에 어떤 영향을 미치는지 추적한다. 제품명이나 유행어를 나열하는 것이 아니라, 왜 그 메커니즘이 필요하게 되었는지를 가능한 한 인과관계로 설명한다.
다음 회는 L0와 L1을 다룬다.
제목은, '추론 비용은 칠판에서 역산할 수 있다'이다.
추론 비용은 요금표만 봐서는 알 수 없다. 토큰을 하나 출력하기까지 어떤 메모리를 읽고, 어떤 캐시(Cache)를 유지하며, 얼마나 병렬로 처리하고, 어디서 대기하는지를 살펴보아야 한다. 에이전트(Agent)가 긴 문맥(Context)을 가지고, 여러 개가 실행되며, 도구(Tool)를 수없이 호출한다면 그 비용은 더욱 쌓이게 된다.
이 지점을 파악하면 위의 설계가 보이는 방식이 달라진다.
긴 컨텍스트(Context)를 사용해야 할 것인가. 메모리 검색(Memory Search)으로 끝낼 것인가. 저렴한 모델과 고성능 모델을 어떻게 나눌 것인가. 여러 에이전트를 병렬로 배치할 가치가 있는가. 평가(Evaluation)를 어느 입도(Granularity)로 돌릴 것인가. 이 모든 것은 추론의 물리적 특성으로부터 역산할 수 있다.
우선, 거기서부터 시작한다.
가져가야 할 핵심은 세 가지다.
첫째. 에이전트는 '호출(Call)'에서 '스케줄링 가능한 프로세스(Schedulable Process)'로 이동했다.
단발적인 모델 호출에 도구를 추가하는 정도라면, 실패해도 다시 시도하면 된다. 하지만 길게 실행되고, 상태(State)를 가지며, 권한(Permission)을 갖고, 여러 개가 나열된다면 그것은 관리되어야 할 실행 단위가 된다. 여기서 필요한 것은 프롬프트(Prompt)의 기교뿐만 아니라 상태, 자원, 권한, 실패, 관측(Observation)을 다루는 기반이다.
둘째. OS화(OS-ization)의 핵심은 런타임(Runtime), 편성(Orchestration), 안전(Safety), 평가(Evaluation)의 네 가지에 있다.
런타임은 에이전트를 격리하고, 기억을 갖게 하며, 도구를 호출하게 하고, 재개 가능하게 만든다. 편성은 여러 에이전트를 배치하고 통신시켜 전체로서 업무를 완료하게 한다. 안전은 입력, 기억, 도구, 권한을 가로질러 무엇을 믿고 무엇을 중단할지를 결정한다. 평가는 최종 출력뿐만 아니라 중간 실행 과정을 포함하여 업무로서 성립했는지를 측정한다.
셋째. 앞으로 희소해질 사람은 프롬프트를 잘 치는 사람이 아니다.
모델, 도구, 문맥, 기억, 권한, 평가를 하나의 생산 시스템으로 연결할 수 있는 사람이다.
프롬프트는 중요하지만, 그것만으로는 실제 서비스되는 에이전트를 움직일 수 없다. 어떤 모델을 언제 사용할 것인가. 어떤 도구를 어떤 권한으로 호출할 것인가. 어떤 문맥을 전달하고 어떤 기억을 저장할 것인가. 실패 시 어디로 되돌릴 것인가. 무엇을 성공으로 간주할 것인가. 어떤 로그를 봐야 개선할 수 있는가. 이들을 하나의 흐름으로 설계할 수 있는 사람이 필요해질 것이다.
에이전트는 이제 단순한 채팅의 연장이 아니다.
그것은 계산 자원 위에 추론 서비스가 올라가고, 모델이 올라가고, 실행 환경이 올라가고, 편성·안전·평가가 올라가며, 마지막으로 현장의 업무가 올라가는 계층 구조를 가진 시스템이 되어가고 있다.
이 계층을 밑바닥부터 읽는 것이 앞으로의 에이전트를 이해하는 가장 확실한 길이 될 것이다.
이 기사는 독립 블로그 **AI Watch (aiwatch-jp)**의 연재 「Agentic OS 기술 스택을 밑바닥부터 읽기」 제0회입니다 (초출: aiwatch-jp.pages.dev). 연산력부터 응용까지 한 단계씩 내려가는 총 63회 + 거래로 다시 읽는 자매편 11회.
- 제1회: 추론 비용은 칠판에서 역산할 수 있다 ―― 우선 첫 번째 단계, 가장 밑바닥인 연산력부터
- 제12회: 에이전트의 기억 ―― 저장이 아니라 '왜 그렇게 했는가'를 남기기 ―― '프로세스'가 된 에이전트는 무엇을 기억하는가
- 제34회: 층을 묶는 외각 ―― 모델을 제어 가능한 루프(Loop)에 담기 ―― 이 기사에서 말하는 '관리하는 층', 그 정체
- 제14회: 단계를 쌓을수록 무너진다 ―― 신뢰성의 절벽과 편성의 패턴 ―― 여러 에이전트를 어떻게 묶을 것인가
- 제49회 (최종회): 밑바닥까지 다 읽은 사람에게 ―― 무엇을 배우고 무엇을 연습할 것인가에 대한 지도 ―― 전부를 다 읽은 그 너머로
연재 전체와 움직이는 맵은 이쪽에서 확인하세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기