복잡한 작업일수록, 계획을 왜 모델에게 통째로 맡기면 안 되는가
← 전체 목차 · 이전: Agent는 왜 작업 실행 전에 계획을 먼저 생성하는가 · 다음: 실행 중 계획이 통째로 무너지면, Agent는 어떻게 스스로 경로를 바꾸는가
모델에게 계획권을 전부 넘기는 것은 "확률에 운을 거는 것"과 같다. 모델은 단일 스텝의 세부 판단에는 강하지만, 단발 추론 윈도우 안에서 긴 체인 전체의 논리를 끝까지 붙들고 있지 못한다. 그 결과가 스텝 중복, 순서 뒤바뀜, 핵심 단계 누락, 주객전도다. 작업 전 계획을 세워야 하는 이유가 "왜 계획이 필요한가"를 다뤘다면, 이 문서는 그 계획을 누가, 어떤 구조로 만드는가를 다룬다.
모델 자체 계획이 무너지는 세 지점
| 원인 | 증상 |
|---|
| 모델의 추론 시야가 유한함 | 국소 판단은 강하지만 전체 목표를 후반부에 잊는다 |
| 의존 관계 검증이 없음 | 전 단계 데이터가 없어도 후속 단계를 그대로 실행해 파라미터 결손·인터페이스 오류로 이어진다 |
| 분해 입도가 통제되지 않음 | 지나치게 잘게 쪼개면 중복 호출·연산 낭비, 지나치게 굵게 쪼개면 핵심 단계 누락 |
세 원인은 누적된다. 의존 검증이 없는 자율 실행은 사실상 "모델이 운에 맡기고 실행하는 것"이며, 여기에 입도 불안정까지 겹치면 같은 요구를 두 번 실행해도 매번 다른 작업 목록이 나온다 — 이것이 불안정성의 가장 저렴한 관찰 지표다.
Demo급 Agent와 프로덕션급 Agent
| 차원 | Demo급 | 프로덕션급 |
|---|
| 계획권 | 모델이 전권 결정 | 엔지니어링이 사전 계획 |
| 모델의 역할 | 계획 + 실행을 모두 담당 | 단일 서브태스크의 추론·도구 호출만 담당 |
| 실행 리듬 | 생각하며 실행 | 먼저 계획, 실행 중 국소 수정 |
| 결과 | 복잡한 의존 앞에서 논리 붕괴 쉬움 | 근본에서부터 전체 붕괴를 회피 |
1단계: 엔지니어링층이 전치 계획 — 모호한 요구를 구조화 작업 큐로
복잡 작업이 시작되기 전, 별도의 계획 모듈이 모호한 사용자 요구를 표준화 작업 목록으로 변환한다. 각 서브태스크는 최소 세 필드를 강제로 채운다.
| 필드 | 의미 |
|---|
| 실행 목표 | 이 스텝이 달성해야 할 것 |
| 소요 도구 | 이 스텝에 필요한 자원과 능력 |
| 전치 조건 | 이 스텝을 실행하기 전에 무엇이 먼저 성립해야 하는가 |
"전치 조건"은 프롬프트 속의 당부가 아니라 서브태스크의 데이터 필드여야 한다. "먼저 조회하고 나서 수정하라"를 프롬프트에 적으면 권고이고, precondition 필드에 적으면 실행기가 강제로 검사할 수 있는 제약이 된다.
2단계: 의존 위상 정렬 — 순서는 속도가 아니라 의존이 정한다
강의존 작업 → 강제 직렬 실행 (업무 로직 정확성 보장)
무의존 작업 → 병합 병렬 실행 (Agent의 동시성 이점 보존)
전 단계가 아직 "실행 성공" 상태가 아니면 후속 스텝은 실행 전에 차단된다. 이것이 "후속 작업이 전치 데이터 없이 먼저 실행되는" 가장 흔한 붕괴 패턴을 원천에서 막는다.
3단계: 서브태스크마다 독립 상태를 건다
대기 → 실행중 → 실행성공
└→ 실행실패 → 재시도됨 → 종료됨
상태가 없으면 실패는 조용한 실패가 된다 — 사용자가 재요청해야만 문제를 알아챈다. "종료됨"도 명시적 상태다. 기록이 없는 것보다 기록된 실패가 언제나 낫다.
4단계: 분급 재시도 + 단절점 재개
| 실패 유형 | 처리 |
|---|
| 일시적 변동(타임아웃, 흔들림) | 자동 재시도 |
| 장기 실패 | 단절점에 남겨두고 공회전 재시도 금지 |
사용자가 다시 대화를 시작하면 단절점부터 이어 실행한다. 매번 처음부터 다시 도는 "성공률"이 아니라, 실패 후 이어 붙일 수 있는 **"폐루프율"**을 북극성 지표로 삼아야 한다.
핵심 통찰
- Agent의 능력 상한은 모델이 아니라 계획층이 정한다 — 같은 모델도 "자유 발산" 구조에 놓으면 중복·교차 실행을 반복하고, "통제 가능한 계획층" 안에 놓으면 폐루프로 수렴한다. 실력을 가르는 것은 어떤 모델을 썼는가가 아니라 모델 바깥에 무엇을 더했는가다.
- 복잡 작업의 실패는 대부분 능력 실패가 아니라 순서 실패다 — 모델은 조회도 할 줄 알고 수정도 할 줄 안다. 다만 둘의 선후 관계를 보장하지 않는다. 그래서 엔지니어링이 먼저 풀어야 할 문제는 "단일 스텝 품질을 올리는 것"이 아니라 "의존을 표현하고 강제하는 것"이다.
- 상태가 없으면 통제 가능성도 없다 — 서브태스크에 "대기/실행중/성공/실패/재시도/종료" 같은 명시적 상태가 없으면 실패는 조용히 블랙박스가 되고, 운영은 사용자의 재요청으로만 문제를 발견하게 된다. 관측 가능성은 재시도·롤백·스킵 세 복구 동작의 전제 조건이다.
- 잘게 쪼갤수록 수렴 경계가 더 필요하다 — 분해는 복잡도를 모델에서 스케줄러로 옮기는 일이지만, 서브태스크 개수 자체가 새로운 복잡도의 원천이 된다. 수렴 메커니즘이 없으면 분해는 한 번의 오류를 한 무더기의 중복 동작으로 증폭시킬 뿐이다.
- "가용하다"의 정의를 "한 번에 성공"에서 "실패해도 이어진다"로 바꿔야 한다 — 긴 체인 작업의 단발 성공률은 태생적으로 낮다. 단절점 보존 + 재대화 이어 실행은 성공률 문제를 폐루프율 문제로 바꾼다. 이것이 Demo와 상용의 실질적 차이다.
- 병렬은 최적화 옵션이 아니라 의존 관계가 허가한 결과다 — 위상 정렬로 강의존 직렬·무의존 병렬의 경계를 먼저 긋고 나서야 속도를 논할 수 있다. 순서 우선순위가 언제나 속도 우선순위보다 앞선다.
- 프롬프트 엔지니어링은 스케줄링 문제를 풀지 못한다 — 프롬프트를 정교화하고 대화 횟수를 늘리는 것은 여전히 "단일 추론의 품질"에 머무른다. 붕괴는 추론과 추론 사이의 이음매에서 발생하며, 이것이 "간단한 상호작용 Agent만 만들어봤다"와 "복잡한 체인형 업무를 다뤄봤다"를 가르는 판별 지점이다.
엔지니어링 실전 Tips
- 전치 조건을 데이터 필드로 만들 것: 프롬프트 속 "먼저 ~하라"는 지켜질 때도 있고 아닐 때도 있다.
precondition 필드로 만들어 실행기가 검사하게 하면 확률 문제가 결정론 문제가 된다.
- 위상 정렬은 실행 직전에 매번 계산할 것: 의존 그래프는 중간 실패·재시도로 계속 바뀐다. 계획 시점에 한 번만 계산해 고정하면 실제 실행 순서와 어긋난다.
- 실패를 한 종류로 뭉뚱그리지 말 것: "일시적 변동"과 "장기 실패"를 구분해야 한다. 전자를 재시도하는 것은 의미가 있지만, 후자를 재시도하는 것은 장애를 증폭시킬 뿐이다.
- "종료됨"도 반드시 기록할 것: 기록이 없는 것보다 "종료됨으로 기록됨"이 훨씬 가치 있다. 장애를 위치 특정하고 사후 처리할 수 있게 해준다.
- 북극성 지표를 성공률에서 폐루프율로 바꿀 것: 성공률을 목표로 삼으면 체인을 짧게 줄이려는 유인이 생긴다. 폐루프율을 목표로 삼으면 이어 실행과 안전망을 제대로 만들게 된다.
- 동시성은 허용 대상이지 기본값이 아니다: 겁이 나서 전체를 직렬로 만들면 Agent의 효율 이점을 잃는다. 올바른 방식은 위상 정렬이 어떤 것을 병렬로 돌려도 되는지 판정하게 하는 것이다.