sPTC(추측적 프로그래밍 도구 호출) 분석
AI 에이전트에게 복잡한 질문을 던지면, 모델은 답을 바로 내놓지 않고 검색을 하거나 파이썬 코드를 실행하고, 때로는 더 작은 서브 에이전트를 호출해 결과를 기다린다.
우리가 챗봇 화면 앞에서 가장 답답함을 느끼는 순간도 바로 이때다. 모델이 화면에 열심히 코드를 한 줄 한 줄 타이핑(토큰 생성)하고, 그 코드가 완전히 다 작성된 뒤에야 엔터 키를 누르듯 도구를 실행하고, 그 도구의 응답이 올 때까지 또 수초에서 수십 초 동안 멍하니 기다리기 때문이다.
2026년 8월, MIT CSAIL의 연구원 Alex Zhang은 이 낭비되는 대기 시간을 획기적으로 압축하는 sPTC(Speculative Programmatic Tool Calling) 기법 [1]을 공개했다.
핵심 아이디어는 단순하면서도 강력하다. “모델이 파이썬 코드를 치는 동안 이미 인자가 결정된 도구 함수를 백그라운드에서 미리 실행해 두자”는 발상이다.
MIT CSAIL의 연구를 바탕으로, sPTC가 왜 등장했는지, 그림자 실행기(Shadow REPL)를 통해 어떻게 안전하게 도구를 앞당겨 실행하는지, 그리고 실제 벤치마크 성능과 현실적인 한계점을 알기 쉽게 정리했다.
1. 기존 방식의 병목: 왜 AI 에이전트는 늘 기다려야 할까?
전통적인 AI 에이전트의 도구 사용(Tool Calling)은 크게 두 가지 흐름으로 발전해 왔다.
- 전통적 JSON 도구 호출 (JSON Schema): 모델이 사전에 정의된 JSON 스키마 규격에 맞춰
{"tool": "search", "query": "..."}텍스트를 완성하면, 시스템이 파싱하여 도구를 실행하고 결과를 다시 프롬프트에 넣어준다. - 프로그래밍 방식 도구 호출 (Programmatic Tool Calling / REPL): 모델에게 파이썬 코드 실행기(REPL)를 기본 도구로 주고, 검색이나 서브 모델 호출을 파이썬 내부의
search(),llm_query()같은 일반 함수로 제공한다. 모델은 복잡한 논리를 파이썬 루프나 조건문으로 유연하게 짠다.
하지만 두 방식 모두 한 가지 공통된 비효율을 겪고 있었다. 바로 순차적 직렬 실행(Sequential Execution) 방식이다.
[ 기존의 순차적 실행 흐름 ]
토큰 생성 (타이핑 중...) ────▶ [코드 생성 완료] ────▶ 도구 실행 대기 (수초 소요) ────▶ [결과 수신] ────▶ 다음 생각 시작
(GPU 풀가동 / 대기) (GPU 놀고 있음 / I/O 대기)
비유하자면, 식당에서 손님이 주문서에 여러 메뉴를 적고 있을 때, 지배인이 손님이 볼펜을 내려놓을 때까지 멍하니 서 있다가 그제야 주방에 첫 주문을 넣는 것과 같다.
만약 손님이 첫 줄에 양파 수프를 적고 있는 것이 확실하다면, 손님이 다음 줄에 메인 스테이크를 적고 있는 동안 주방 보조에게 먼저 양파 볶기를 시키면 어떨까?
2. sPTC의 해결책: 생성과 실행의 시공간 중첩
sPTC는 LLM의 토큰 생성 시간(Compute Time)과 도구의 네트워크 및 실행 지연 시간(Tool Latency)을 겹쳐서 처리한다.
| 실행 방식 | 타임라인 및 작업 흐름 | 총 소요 시간 |
|---|---|---|
| 기존 순차 실행 | [코딩 10초] ➔ [검색 A 3초] ➔ [검색 B 3초] ➔ [답변 5초] |
21초 |
| sPTC 병렬 중첩 | [코딩 10초 (내부에서 검색 A, B 동시 백그라운드 완료)] ➔ [답변 5초] |
15초 (28% 단축) |
모델이 긴 생각이나 코드를 작성하고 있는 동안, 뒤에서 실행될 도구들은 이미 결과를 다 받아놓고 대기하는 것이다.
3. sPTC는 어떻게 안전하게 미리 실행할까?
코드가 아직 다 끝나지도 않았는데 도구를 미리 돌렸다가, 코드가 에러가 나거나 의도치 않은 파일 삭제 같은 사고가 터지면 어떻게 할까?
sPTC는 이 문제를 해결하기 위해 5단계 파이프라인과 그림자 실행기(Shadow REPL)라는 안전장치를 둔다.
[ LLM 토큰 생성 스트리밍 ]
│
▼
[ 1. 실시간 부분 파싱 (AST Parser) ]
│
▼
[ 2. Shadow REPL 환경에서 안전성 검증 ]
├─ 순수 함수 / 고정값 ──▶ [ 3. 비동기 사전 실행 ]
└─ 파일 I/O / 부작용 ──▶ [ 실행 보류 (Gated) ]
│
▼
[ 4. 캐시 저장소에 결과 보관 ]
│
▼
[ 실제 REPL이 해당 라인 실행 ] ──▶ [ 5. 캐시에서 0.001초 만에 즉시 반환 (Hit) ]
1) 토큰 스트리밍과 실시간 부분 파싱 (Incremental AST Parsing)
LLM이 코드를 한 토큰씩 출력할 때마다 구문 분석기(AST Parser)가 부분 코드를 실시간으로 읽어 들인다.
2) 그림자 환경 (Shadow REPL) 복제
실제 사용자의 메인 파이썬 환경을 그대로 복제한 가벼운 샌드박스(Shadow REPL)를 백그라운드에 띄운다.
[개념 짚고 가기: Shadow REPL(그림자 실행기)이란?]
실제 사용자의 데이터나 파일 시스템에 영향을 주지 않도록, 메모리 상에서 독립적으로 분기된 가상 복제 환경입니다.
이곳에서 부분 코드를 미리 돌려보며 변수의 계산값이나 조건문의 참/거짓 여부를 안전하게 예측해 봅니다.
3) 부작용 검사와 비동기 사전 실행 (Speculative Launch)
도구 함수에 들어갈 인자(Argument)가 안전하게 계산 완료되었는지 확인한 뒤, 외부 I/O 부작용이 없다면 비동기 백그라운드 태스크로 즉시 실행을 발주한다.
4) 백그라운드 캐싱 및 투명한 반환 (Cache Hit)
실행 결과는 고유한 호출 식별자와 함께 캐시에 저장된다. 나중에 LLM의 생성이 모두 끝나고 실제 메인 REPL이 그 코드를 진짜로 실행할 때, 함수를 다시 부르지 않고 이미 받아둔 캐시 결과를 0초 만에 즉시 반환한다.
4. 어떤 호출을 미리 실행할 수 있고, 어떤 호출을 막을까?
sPTC는 무조건 도구를 마구잡이로 실행하지 않는다. 연산의 안전성과 결정론적 성격에 따라 엄격하게 대상을 구분한다.
| 구분 | 코드 예시 | sPTC 처리 방식 | 이유 |
|---|---|---|---|
| 리터럴 직접 입력 | llm_query("오디세이 줄거리 요약해줘") |
즉시 실행 | 입력 문자열이 코드에 확정되어 있어 즉시 발주 가능 |
| 순수 연산 변수 의존 | text = "apple" + "_pie"search(text) |
즉시 실행 | Shadow REPL에서 text 변수값을 오차 없이 계산 가능 |
| 안전한 조건문 / 반복문 | for i in range(2): fetch_data(i) |
즉시 실행 | 반복 횟수(0, 1)가 고정되어 있어 2개 호출을 모두 사전 실행 |
| 파일 I/O 및 외부 변경 | f = open("data.txt", "w")delete_database() |
❌ 실행 차단 | 실제 파일이나 DB를 건드리는 부작용(Side-effect)은 코드 확정 전까지 금지 |
| 비결정적 도구 | random_dice() |
⭕ 고유 ID 관리 | 매번 결과가 달라질 수 있는 도구는 호출마다 고유 ID를 붙여 결과 분리 |
이처럼 sPTC는 외부 상태를 망가뜨리지 않는 안전한 읽기/추론 작업에만 선별적으로 추측 실행을 적용한다.
5. JIT 컴파일러로서의 sPTC: 숨겨진 병렬성 발굴
sPTC는 단순한 대기 시간 단축을 넘어, 자연스러운 파이썬 코드 속에 숨겨진 병렬성을 찾아내는 경량 JIT(Just-In-Time) 컴파일러 역할도 수행한다.
예를 들어 LLM이 다음과 같이 코드를 순차적으로 작성했다고 하자.
# LLM이 순서대로 생성한 코드
title = llm_query("Give a title for: The Odyssey")
blurb = llm_query("One-line blurb for: The Odyssey")
사람이나 일반 파이썬 인터프리터는 1번 줄이 끝나야 2번 줄을 실행한다.
하지만 sPTC의 파서는 1번 줄의 llm_query가 완성된 즉시 백그라운드로 쏘아 올리고, LLM이 2번 줄을 타이핑하는 순간 2번 줄의 llm_query도 연달아 백그라운드로 쏘아 올린다.
결과적으로 순차적으로 적힌 코드임에도 불구하고 두 개의 무거운 LLM 질의가 네트워크상에서 완벽하게 동시에(Parallel) 수행된다.
6. 실제 성능 실험과 벤치마크 결과
Alex Zhang은 8대의 NVIDIA H100 GPU 환경에서 복귀형 언어 모델 프레임워크인 RLM과 Qwen3-30B-A3B-Instruct 모델을 이용해 벤치마크를 수행했다.
- 평가 데이터셋: OOLONG, OOLONG-Pairs (복잡한 추론 및 도구 호출 벤치마크)
- 속도 향상 결과: 전체 에이전트 응답 지연 시간 기준 약 1.0배 ~ 1.2배 단축
[ OOLONG 벤치마크 지연 시간 비교 ]
기준 실행 시간 (Baseline): ████████████████████ (1.0x)
sPTC 추측 실행 적용 시: █████████████████ (최대 약 1.2x, 원문 표현은 1-1.2x)
왜 2배, 3배가 아니라 1.2배 수준일까?
이론상 완벽한 중첩이 일어나더라도 현실에서 1.2배 안팎의 속도 개선을 보이는 데는 몇 가지 이유가 있다.
- 도구 지연 시간의 편차: 도구 응답이 0.1초 만에 끝나는 초경량 도구라면 토큰 생성 시간과 겹쳐봤자 줄어드는 절대적인 시간이 적다. 반대로 도구가 수 초 이상 걸리는 무거운 서브 에이전트 호출일수록 sPTC의 가속 효과가 극대화된다.
- 생성 토큰 길이와 비율: 모델이 코드를 작성하는 시간 자체가 전체 실행 시간에서 차지하는 비중에 따라 절감 폭이 결정된다.
- 서버 큐 대기 시간: 백그라운드로 보낸 서브 LLM 쿼리가 추론 서버의 큐에서 대기하게 되면 중첩 효과가 반감된다.
7. 한계와 엔지니어링 시사점
sPTC는 매력적인 기법이지만 고려해야 할 트레이드오프가 있다.
- 헛발질로 인한 연산 낭비 (Wasted Compute): LLM이 코드를 작성하다가 문법 에러를 내거나 중간에 생각을 바꿔 다시 쓰는 경우, 이미 백그라운드에서 실행한 도구의 연산 비용과 토큰 비용은 낭비된다.
- 추론 서버 부하 가중 (Server Saturation): 트래픽이 몰리는 혼잡한 서버 환경에서 추측성 호출을 과도하게 날리면 메인 추론 큐가 막힐 위험이 있다.
- Shadow REPL 오버헤드: 매 토큰마다 AST를 검사하고 가상 환경을 유지하는 비용이 소모된다.
sPTC는 AI 에이전트가 코드를 타이핑하는 동안 독립적인 도구 호출을 미리 백그라운드에서 실행함으로써, 토큰 생성 시간과 도구 대기 시간을 겹쳐 없애는 영리한 에이전트 JIT 최적화 기술이다.
참고 문헌 및 원문
- [1] Zhang AL. Speculative Programmatic Tool Calling. 2026. (블로그 원문 · GitHub 오픈소스)