Episode 03 - Orchestration & Parallel
이 글에서 다루는 것
지금까진 에이전트 하나한테 잘 시키는 법이었어요 — 결정을 먼저 끝내고(1편), 컨텍스트를 가볍게 유지하고(2편)요. 그런데 여기엔 은근한 한계가 하나 있어요. 매 단계마다 사람이 옆에 딱 붙어서 일일이 시키면, 에이전트가 아무리 빨라도 결국 사람 속도에 묶여버리거든요.
진짜 도약은 사람의 자리가 바뀔 때 와요. 루프 안에서 매번 직접 시키는 대신, 루프 위로 한 칸 올라가서 — 알아서 돌아가게 만들어두고 방향만 잡아주는 거죠. (요즘은 이걸 'loop engineering'이라고 부르기 시작했더라고요. 내가 코드를 치는 게 아니라, 코드를 치는 루프를 짜는 일이라는 거예요.)
규모를 키우는 방향은 둘이에요. 같은 일을 스스로 반복하게(시간) 만들거나, 다른 일을 동시에(공간) 돌리거나요. 이 글에선 그 두 방향이랑, 흐트러지지 않게 잡아주는 두 가지를 정리해봤어요.
핵심 메시지
핵심은 하나예요 — 매번 직접 시키지 말고, 알아서 돌아가게 만들어두고 위에서 지켜보는 거죠. 그걸 네 갈래로 풀면 이래요.
- 스스로 반복 — Agentic Loop, 고치고 검증하며 돌게
- 동시에 — Parallel Agents, 독립된 일은 한꺼번에
- 나누고 합치기 — Orchestrator–Worker, 지휘자가 나눠 일꾼에게
- 흐름은 코드로 — Code-as-Control-Plane, 반복 순서는 코드로 고정
규모를 키우는 두 축 — 시간(반복)과 공간(동시에)
1. Agentic Loop - 스스로 고치고 검증하며
매번 "돌려봐"를 사람이 시킨다
에이전트가 코드를 고치면, 누군가는 그걸 돌려보고 맞는지 확인해야 하잖아요. 보통은 그 "돌려봐 → 어, 틀렸네 → 다시 고쳐"를 사람이 매번 시켜요. 에이전트는 빠른데, 그 사이사이에 사람이 끼니까 속도가 거기서 묶여버리죠. 테스트라는 명확한 합격·불합격 신호가 이미 있는데도요.
통과·실패 신호를 쥐여주고 스스로 닫게
핵심은 에이전트한테 스스로 확인할 수단을 쥐여주는 것이에요. 테스트·빌드처럼 통과/실패가 딱 갈리는 신호를 주면, 에이전트가 "고침 → 돌려봄 → 실패면 다시" 를 알아서 반복하다가 통과하면 멈추거든요. 사람은 매 단계가 아니라 결과만 보면 되죠.
자동 루프 — 고침 · 검증 · 통과/실패
재미있는 건, 이걸 시키는 데 별도의 for문 코드가 필요 없다는 거예요. 그냥 말로 하면 돼요.
❯ 고치고, npm test 통과할 때까지 반복해줘
이 한 줄이면 모델이 스스로 고침→테스트→반복을 돌아요. 모델 자체가 루프인 셈이죠. 통과하면 알아서 멈추고요.
종료조건은 꼭 넣기
단, 조심할 게 하나 있어요. 멈춤 조건 없이 돌리면 안 되는 문제를 붙잡고 끝없이 도는 수가 있거든요 — 이걸 요즘 loopmaxxing이라고 부르더라고요. 시간이랑 토큰만 태우는 거죠. 종료조건도 말로 주면 됩니다.
❯ 3번 실패하면 멈추고 상황만 보고해
Claude Code에는 이걸 스킬로 만들어둔 것도 있어요. /goal은 목표를 달성할 때까지(테스트 통과 같은 완료 기준) 도는 것이고, /loop는 일정 간격으로 반복(배포 상태 폴링 같은 모니터링)이에요. 목적이 달라서 구분해 쓰면 좋아요.
지난 편(세로 조각)에서 본 그 "스스로 확인할 신호"가 여기서 자율의 조건이 돼요. 신호가 없으면 자율도 없거든요 — 그래서 검증 수단을 만들어주는 게 자동화의 출발점인 셈이에요.
언제 안 쓰나 — 통과/실패를 기계로 딱 잘라 판정할 수 없는 주관적인 작업엔 한계가 있어요. 그리고 위에서 말한 멈춤 조건은 선택이 아니라 필수고요.
2. Parallel Agents - 독립된 일은 동시에
직렬로 하면 느리다
로그인·검색·푸터처럼 서로 상관없는 일 세 개를, 하나 끝나야 다음 시작하는 식으로 줄 세우면 그냥 느리잖아요. 사람이 직렬로 시켜서 그렇지, 일 자체는 동시에 해도 되는 경우가 꽤 많아요.
여러 에이전트한테 동시에 던지고, 끝나면 모으기
서로 안 엮인 일은 여러 에이전트한테 한꺼번에 맡겨요. 각자 따로 돌다가, 끝나면 결과를 모으는 거죠.
병렬 — 독립된 일을 여러 에이전트에 동시에
여기서 지난 편의 컨텍스트 격리가 중요해져요. 각 에이전트가 서로의 작업을 안 보고 자기 것만 봐야, 섞이지 않고 깨끗하게 굴러가거든요. 그런데 컨텍스트만 격리하면 안 되고, 파일도 격리해야 해요. 같은 폴더에서 두 에이전트가 동시에 파일을 고치면 서로 덮어쓰니까요.
먼저 — git worktree로 폴더를 나눈다
그 파일 격리를 해주는 게 git worktree예요. 같은 저장소를 브랜치별로 폴더를 따로 만들어주는 git 기능이죠.
❯ git worktree add ../wt-login -b feat-login
❯ git worktree add ../wt-search -b feat-search
❯ git worktree add ../wt-footer -b feat-footer
이러면 폴더 세 개가 생기고, 각 폴더에서 claude 세션을 하나씩 열어요. 각자 자기 폴더(브랜치)에서만 작업하니까 충돌이 0이에요. 끝나면 각 브랜치를 main에 merge하면 되고요 — 이 합치는 건 사람이 하나씩 검토하며 해요.
Claude Code에선 이걸 자동으로 — claude --bg와 agent view
worktree를 손으로 안 만들어도 돼요. 백그라운드로 던지면 알아서 해주거든요.
❯ claude --bg "hero 영역 메인 페이지 개발"
❯ claude --bg "footer layout 개발"
던질 때마다 백그라운드 세션이 자동 worktree로 격리돼서 병렬로 돌아요. 사람은 끝나길 기다리지 않고요. 돌아가는 것들은 claude agents(agent view) 한 화면에서 봐요 — 어떤 게 일하는 중이고, 어떤 게 내 승인을 기다리는지요. 클릭하면 그 세션으로 들어가고, 끝나면 각 브랜치를 main에 merge합니다.
같은 일을 N번 — 만들고 고르기
병렬이라고 다 '다른 일을 나눠 동시에'만 있는 건 아니에요. 같은 과제를 N개 에이전트한테 동시에 시키고, 나온 결과들을 비교해 제일 나은 하나만 고르는 방식도 있어요 — N-Variant Generate-then-Pick이라고 해요.
❯ 이 정렬 로직, 서로 다른 접근으로 3개 구현해줘 — 각각 worktree에서
테스트 통과한 것 중 제일 깔끔한 하나만 채택하는 거죠. 한 번에 완벽히 맞히려 애쓰는 것보다, 여러 개 만들어 고르는 쪽이 품질이 높을 때가 꽤 많거든요. (이 시리즈에서 두고두고 나올 '여러 개 만들고 고르기' 의 첫 등장이에요.)
언제 안 쓰나 — 서로 의존하는 일은 병렬로 못 해요(A 결과가 있어야 B를 하니까요). 의존이 있으면 묶어서 순서대로 하고요. 그리고 동시에 N개를 돌리면 사용량(quota)도 그만큼 N배로 들어요 — 빠른 대신 비싼 거죠.
3. Orchestrator–Worker - 나누고 합치기
한 에이전트가 큰일을 통째로 = 느리고 무거워진다
각 영역이 서로 다른 판단이 필요한 큰 일이 있어요. 예를 들어 모듈마다 테스트를 붙이는 일 — auth 모듈과 billing 모듈은 봐야 할 코드도, 짜야 할 테스트도 다르죠. 이걸 한 에이전트가 혼자 하나씩 하면 느리고, 여러 영역을 다 머리에 쥐면 컨텍스트도 무거워져요.
지휘자가 나눠주고, 일꾼이 실행하고, 다시 합친다
그래서 역할을 나눠요. 지휘자(orchestrator) 에이전트가 일을 영역별로 쪼개서 일꾼(worker) 들한테 나눠주고, 결과를 받아서 모으죠. 일꾼은 자기 조각만 하고요. 시키는 건 이렇게 말 한 번이면 돼요.
❯ auth·billing·api 세 모듈에 각각 테스트를 붙여줘.
모듈마다 서브에이전트 하나씩 — 자기 모듈만 읽고 테스트 짜.
폴더 사이는 건드리지 말고, 끝나면 보고해.
각 서브에이전트가 자기 모듈만 읽고 테스트를 설계·작성해요(병렬). 지난 편의 격리(Subagent Isolation)가 여기서 그대로 쓰이죠 — 각 일꾼은 자기 컨텍스트에서 일하고, 지휘자는 결과만 모아요.
지휘자가 나눠 주고, 일꾼들이 실행하고, 합친다
그리고 만들기는 동시지만, 합치기는 하나씩(직렬) 이에요. 여럿이 동시에 만들어도, 합칠 땐 사람이 하나씩 검토하고 머지하죠. 이 사람 검문이 품질을 지켜줘요.
2번과 뭐가 다르냐면 — 애초에 서로 별개인 일들(로그인·검색·푸터)을 그냥 동시에 굴리면 2번(Parallel)이에요. 하나의 큰 일을 지휘자가 조각내 뿌리고 다시 합치면 3번이고요. 별개의 여러 일이냐, 한 일을 나눈 거냐 — 이게 그 축이에요.
언제 안 쓰나 — 단순 치환·포맷처럼 나눌 것 없이 한 번에 되는 일엔 안 써요. 각 조각이 저마다 판단이 필요할 때만 지휘 구조가 값어치를 해요. 작은 일에 얹으면 배보다 배꼽이 크고요.
4. Code-as-Control-Plane - 반복 순서는 코드로 고정
매번 모델이 정하면, 흐름이 매번 달라진다
매 턴 모델이 "다음 뭐 할까"를 정하게 두면, 매번 순서가 조금씩 달라져요. 정해진 다단계 작업(테스트→수정→재검증)인데도 어떤 땐 단계를 빼먹고, 어떤 땐 순서가 꼬이죠. 30개를 처리해야 하는데 모델 판단에 맡기면 중간에 하나쯤 빠질 수도 있고요. 재현이 안 되는 거예요.
흐름은 코드가 고정하고, 모델은 판단이 필요한 칸만
그럴 땐 흐름(무엇을·몇 개·병렬·검증)을 코드 스크립트로 미리 고정해요. 모델은 판단이 필요한 말단 호출에만 부르고요. 이건 채팅 세션 안이 아니라 세션 밖에서 하는 방식이에요 — 스크립트를 실행하는 건 Claude가 아니라 사람(또는 CI) 이고요. 터미널에서 이렇게요.
❯ python orchestrate.py
스크립트 안은 이렇게 생겼어요.
# orchestrate.py
failing = run_tests() # 실패한 테스트의 대상 파일
fixes = parallel(map(fix_one, failing)) # 파일마다 병렬로 모델 호출
verify(fixes) # 다시 돌려 통과 확인
세 줄을 뜯어보면 역할 분리가 보여요. 1줄(무엇을 고칠지)과 3줄(통과했는지)은 그냥 pytest를 돌리는 평범한 코드예요 — 모델이 안 들어가요. 모델이 들어가는 건 가운데 fix_one 하나뿐이죠. 왜냐하면 "깨진 이 파일을 어떻게 고칠까"는 파일마다 원인이 달라서 if/else로 못 적거든요. 코드로 적을 수 있는 건 코드가, 판단이 필요한 것만 모델이 — 이게 이 패턴의 전부예요.
흐름은 코드가 고정 — 모델은 각 칸의 일만
fix_one의 실체 — 모델을 함수처럼 부른다
그럼 fix_one은 어디 있는 뭘까요? orchestrate.py 안에 정의된 평범한 파이썬 함수예요. 그 함수 몸통이 모델을 부르는 거죠. 방법이 두 가지예요.
하나는 로컬에서 claude -p를 셸로 부르는 것.
def fix_one(f): # orchestrate.py 안의 함수
subprocess.run(["claude", "-p", f"{f} 이 파일만 테스트 통과하게 고쳐"])
파일이 30개면 이 claude 프로세스가 30개 떠요. 호출 방향을 헷갈리기 쉬운데 — claude -p가 스크립트를 실행하는 게 아니라, 스크립트가 claude -p를 파일마다 한 번씩 실행하는 거예요. 정리하면 이 방향이죠: 사람/CI → python orchestrate.py → claude -p (파일 수만큼, 병렬로).
다른 하나는 클라우드 — Managed Agents SDK예요. anthropic 패키지로 클라우드 샌드박스 세션을 여러 개 열어 같은 걸 하는 거죠. 파일마다 격리된 세션 하나씩요. 로컬 머신 자원에 안 묶인다는 게 장점이고요.
여기서 헷갈리기 쉬운 게 있어요 — 이건 세션 안의 서브에이전트가 아니에요. 서브에이전트는 한 세션 안에서 모델이 관리하고, 결과가 메인 컨텍스트로 돌아오죠. 이건 세션 밖에서 코드가 진짜 독립 세션을 N개 띄우는 거예요. 그 N개는 서로를 모르고, 각자 자기 파일 하나만 알고 끝나요. 그래서 30개든 300개든 코드는 안 흔들려요 — 정확히 그 수만큼, 하나도 안 빼고, 진짜 동시에요.
참, 이 orchestrate.py 자체는 누가 짜냐면 — 그것도 세션에서 시키면 돼요. "테스트 실패 파일 뽑아서 파일별로 병렬로 고치고 검증하는 스크립트 짜줘"라고요. AI가 짠 스크립트가, 실행되면 다시 AI를 부르는 구조인 거죠. 그리고 코드로 흐름이 고정돼 있으니 실행 전에 사람이 그 흐름을 읽고 검토할 수 있다는 것도 덤이에요.
언제 쓰나
이 패턴이 값어치를 하는 조건은 셋이에요 — 작업이 여러 개고, 서로 독립이고, 각각의 판단이 단순 반복일 때요. 라이브러리 버전 마이그레이션(파일 수백 개 일괄), 모듈마다 테스트·문서 붙이기, PR·로그·이슈 수백 개 각각 요약·분류 같은 것들이죠. 신호는 이거예요 — "이걸 사람이 손으로 하면 같은 일을 지겹게 반복하겠는데?" 싶으면 이 패턴 후보예요.
반대로 실패가 두세 개뿐이거나, 파일이 서로 얽혀 있거나(하나 고치면 딴 게 깨짐), 원인을 아직 몰라 탐색해야 하는 일이면 — 그냥 세션에서 대화로 하는 게 나아요. "한 번 깊게 생각해야 하는데?" 싶으면 세션이죠. 무슨 단계가 나올지 모르는 탐색엔 모델이 정하는 쪽이 낫거든요. 그래서 보통은 둘을 섞어요.
3번과 뭐가 다르냐면 — 3번은 지휘자(모델)가 나눠요. 흐름을 모델이 결정하죠. 4번은 흐름을 코드가 고정하고 모델은 말단만 해요. 그래서 매번 똑같이 재현돼요.
함께 보면 좋은 패턴
위 네 가지 곁에, 한 발 더 들어가면 만나는 패턴들이에요. 대표만큼 깊게는 안 가고, 각각 뭘 하는지·대표 중 무엇과 짝인지만 짚고 갈게요.
Plan-Mode vs Build-Mode Split : 계획 바퀴와 구현 바퀴를 가르기
같은 루프를 "계획(빠진 것 찾아 TODO 만들기)" 모드와 "구현(한 항목 만들고 테스트)" 모드로 갈라서, 매 바퀴 새 컨텍스트로 도는 방식이에요. 계획과 구현이 한 머릿속에 섞이면 서로를 흐리거든요.
1번(Agentic Loop)의 정돈된 버전이에요. 1번이 한 루프 안에서 다 한다면, 이건 그 루프를 두 모드로 갈라 각자 깨끗한 상태에서 돌게 해요.
Per-Role Model Routing : 역할마다 다른 모델을 배정하기
지휘자–일꾼으로 나눴다면, 한 발 더 — 일꾼마다 모델도 다르게 줄 수 있어요. 깊은 리서치엔 똑똑하고 비싼 모델, 빠른 반복 실험엔 가볍고 싼 모델, 이런 식으로요. 강점과 비용에 맞춰 라우팅하는 거죠. (네이버 사례에선 리서치에 Opus, 실험에 Sonnet을 썼더라고요.)
3번(Orchestrator–Worker)의 확장이에요. 3번이 일을 역할별로 나눴다면, 이건 모델을 역할별로 나눠요. 같은 분업인데, 나누는 게 일에서 모델로 한 칸 더 간 거죠.
Graduated Failure Escalation : 실패가 쌓이면 단계적으로 손을 든다
자동 루프를 돌리다 계속 실패하면? 무작정 같은 걸 반복하게 두면 토큰만 태워요. 그래서 실패가 쌓이는 정도에 따라 — 처음엔 작은 것부터 손보고, 그래도 안 되면 전략을 바꾸고, 끝내 안 되면 멈추고 사람을 불러요. 전기 차단기(circuit breaker) 같은 안전장치예요.
1번(Agentic Loop)의 안전장치예요. 1번의 종료조건("3번 실패하면 멈춰")이 한 번에 멈추기라면, 이건 그 멈춤을 단계적으로 설계한 거예요. 가벼운 조정 → 전략 전환 → 사람 호출로 차근차근.
이 편의 나머지 패턴
이외에도 오케스트레이션·병렬로 묶이는 패턴은 많아요. 이름과 한 줄로 훑고 갈게요.
| 패턴 | 한 줄 |
|---|---|
| Headless Batch Fan-Out | claude -p를 루프로 돌려 수백 파일을 한꺼번에 처리 (4번의 원형) |
| Scheduled Autonomous Loop | 루프를 cron·타이머에 걸어 백그라운드에서 여러 개 |
| Fixed-Pipeline-over-Agent | 자유롭게 두지 말고 localize→repair→validate 고정이 더 싸고 정확할 때 |
| Composable Skill Pipeline | 브레인스토밍→계획→TDD→리뷰가 강제로 이어지는 스킬 체인 |
| Hub-and-Spoke | 매니저 하나가 전문 스포크들을 중앙에서 조율 |
| Multi-Persona Team | PM·아키텍트·개발·QA 역할 페르소나로 분업 |
| Agent Swarm + Merge Queue | 떼로 병렬 + 머지 큐로 합치는 순서를 직렬화 |
| AutoResearch Loop | 점수를 목표로 바꿈→잼→commit/reset 반복해 자동 개선 |
| Atomic Experiment (OFAT) | 한 번에 한 변수만 바꿔 원인을 짚기 |
| Population Search | 후보 집단·재조합·변이로 국소 최적에서 탈출 |
마무리 - 한 문장만 가져간다면
핵심은 이거예요 — 매번 직접 시키지 말고, 알아서 돌아가게 만들어두고 위에서 지켜보기!
네 가지는 결국 사람을 루프 안에서 루프 위로 올려줘요 — 같은 일은 스스로 반복하게, 다른 일은 동시에, 큰일은 나누고 차례로 합치고, 반복되는 흐름은 코드로 고정해서요.
| 할 일 | 패턴 | 한 줄 |
|---|---|---|
| 스스로 반복 | Agentic Loop | 통과/실패 신호 쥐여주고 스스로 닫게 |
| 동시에 | Parallel Agents | 독립된 일은 worktree로 격리해 한꺼번에 |
| 나누고 합치기 | Orchestrator–Worker | 지휘자가 나눠 주고, 합치는 건 차례로 |
| 흐름 고정 | Code-as-Control-Plane | 반복 순서는 말 말고 코드로 |
다음 편 — 팀으로 개발하기. 에이전트를 여럿 굴리는 걸 넘어, 사람과 에이전트가 한 팀처럼 일하는 법 — 역할을 나누고, 일을 주고받고, 서로의 결과를 검토하며 협업하는 패턴들을 다뤄볼게요.
참고 영상
