Claude Code 실전 가이드 3편입니다. 1편에서는 시작 방법과 CLAUDE.md, 2편에서는 컨텍스트 관리를 다뤘습니다. 이번 편은 서브에이전트(subagent)를 여러 개 굴리는 이야기입니다.
위임과 병렬은 다른 문제다
2편에서 서브에이전트를 컨텍스트 보호 수단으로 다뤘습니다. 탐색 과정의 부산물은 서브에이전트 쪽 컨텍스트에 남기고 메인 세션에는 결론만 받는다는 이야기였습니다. 그건 서브에이전트 하나를 띄웠을 때도 얻어지는 효과입니다.
이번 편의 주제는 그 다음입니다. 서브에이전트를 여러 개 동시에 띄울 때 무엇이 달라지고 무엇이 깨지는가. 파일 10개를 하나씩 순서대로 열어보는 것과 서브에이전트 여러 개가 나눠 보는 것은 걸리는 시간이 다르지만, 대신 "어떤 작업을 쪼갤 수 있는가", "쪼갠 것들이 서로의 발밑을 밟지 않는가"라는 문제가 새로 생깁니다. 병렬 처리의 실제 난이도는 거의 이 두 가지에 다 들어 있습니다.
병렬로 쪼갤지 순차로 둘지 — 기준은 의존성 하나
기준은 단순합니다. 작업 A의 결과가 작업 B의 입력으로 들어가면 순차, 아니면 병렬입니다.
병렬로 돌리기 좋은 경우:
- 서로 다른 레포 혹은 서로 다른 디렉터리를 각각 조사할 때 (예: 프론트 레포와 백엔드 레포에서 각각 같은 버그의 흔적을 찾는 작업)
- 여러 파일에 걸쳐 같은 성격의 독립적인 수정을 넣을 때 (예: 컴포넌트 10개에 동일한 패턴의 리팩터링)
- 같은 문제의 후보 설계안 여러 개를 각각 다른 관점에서 검토할 때 (뒤에 나올 교차검증)
순차로 둬야 하는 경우:
- 설계 결정이 먼저 나와야 구현이 시작되는 경우
- 브랜치를 만들고 나서야 그 브랜치에서 작업할 수 있는 경우
- 이슈 조사 결과에 따라 다음 단계(수정 범위)가 달라지는 경우
실무에서 자주 하는 실수는 "일단 다 던지고 보자"입니다. 의존이 있는 작업을 병렬로 던지면 서브에이전트 하나가 아직 존재하지 않는 파일을 기준으로 작업하게 되고, 나중에 합칠 때 충돌이 납니다. 반대로 명백히 독립적인 조사를 순차로 하나씩 돌리면 그냥 시간 낭비입니다. 판단은 매번 "이 결과가 다음 작업의 입력인가"를 물어보는 걸로 충분합니다.
에이전트 종류 — 용도별로 나눠 쓴다
서브에이전트는 성격에 따라 크게 세 갈래로 씁니다.
광역 탐색 전용 읽기 에이전트는 코드를 고치지 않고 위치나 네이밍 컨벤션만 훑을 때 씁니다. "이 기능이 어느 파일에 있는지", "이 프로젝트는 에러 핸들링을 어떤 패턴으로 하는지" 같은 질문에 맞습니다. 파일 내용을 전부 덤프해서 돌려줄 필요가 없는, 순수 탐색용입니다.
설계 에이전트는 구현에 들어가기 전에 아키텍처 트레이드오프를 저울질할 때 씁니다. "이 기능을 서버 액션으로 넣을지 별도 API 라우트로 뺄지" 같은 결정을 코드를 건드리기 전에 정리하는 역할입니다.
범용 조사 에이전트는 복잡한 다단계 조사가 필요할 때 씁니다. 단순 검색으로 안 끝나고 "찾고 → 읽고 → 다른 곳도 찾고" 를 반복해야 하는 작업입니다.
이 셋을 구분하는 이유는 단순합니다. 탐색만 하면 되는 작업에 구현 권한까지 쥐어주면 시키지 않은 수정이 들어갈 위험이 생기고, 반대로 설계 판단이 필요한 작업을 단순 검색 에이전트에 맡기면 트레이드오프 없이 표층적인 답만 나옵니다. 역할에 맞는 도구를 고르는 것뿐입니다.
이 외에 커스텀 에이전트를 프로젝트별로 정의해둘 수도 있습니다. 반복적으로 같은 성격의 서브 작업을 시킨다면(예: 특정 레포의 배포 파이프라인 점검, 특정 포맷의 코드 리뷰) 매번 프롬프트로 설명하는 대신 에이전트 자체를 미리 정의해두는 편이 일관성 있습니다.
모델 티어 — 비용과 품질의 트레이드오프
서브에이전트를 부를 때 모델을 메인 세션 그대로 상속시키지 않고 작업 강도에 맞춰 지정합니다. 기준은 이렇습니다.
| 작업 성격 | 모델 티어 | 예시 |
|---|---|---|
| 단순·기계적·대량 반복 | 작은 모델 | 파일 목록 grep, 포맷팅, 보일러플레이트 |
| 일반 구현·리뷰 | 중간 모델 | 기능 구현, 다중 파일 분석 |
| 까다로운 근본원인·설계·보안 | 큰 모델 | 모순 해소, 보안 취약점 분석, 아키텍처 결정 |
grep 으로 파일 위치만 찾는 작업에 가장 큰 모델을 붙이는 건 낭비입니다. 반대로 보안 관련 판단이나 원인이 여러 겹으로 얽힌 버그 분석에 작은 모델을 쓰면 표층 증상만 보고 넘어갈 위험이 있습니다. "이 작업이 틀렸을 때 대가가 얼마나 큰가"를 기준으로 티어를 고르면 됩니다. 단순 반복 작업 100개를 큰 모델로 돌리는 비용과, 보안 판단 하나를 작은 모델로 잘못 내리는 비용은 저울이 다릅니다.
worktree 격리 — 같은 폴더를 여러 에이전트가 만지면 안 되는 이유
병렬 서브에이전트를 여러 개 띄울 때 가장 흔히 터지는 문제는 같은 작업 폴더를 동시에 건드리는 것입니다. git 저장소 하나에서 에이전트 A가 브랜치를 체크아웃하는 순간 에이전트 B가 보고 있던 파일이 통째로 바뀝니다. 이걸 "checkout 레이스(race, 경쟁 상태)"라고 부르는데, 두 에이전트가 서로 다른 브랜치 작업을 하고 있다고 믿는 상태에서 실제로는 한쪽이 다른 쪽의 워킹 디렉터리를 계속 갈아엎는 상황입니다. 여기에 git add -A 같은 광범위 스테이징까지 겹치면 서로 다른 작업의 변경분이 한 커밋에 섞여 들어가는 사고로 이어집니다.
해결책은 git worktree 로 물리적으로 분리하는 것입니다. worktree 는 같은 저장소의 커밋 히스토리를 공유하면서도 별도의 디렉터리와 별도의 체크아웃 상태를 가지는 기능입니다. 즉 브랜치마다 폴더가 따로 생기니, 에이전트 A가 자기 폴더에서 체크아웃을 하든 뭘 하든 에이전트 B의 폴더는 전혀 영향을 받지 않습니다.
실제로 쓰는 규칙은 이렇습니다.
- 1세션 = 1worktree = 1이슈 = 1브랜치 = 1dev 포트 = 1PR (dev 포트까지 나누는 이유는, 두 세션이 같은 포트로 개발 서버를 띄우면 나중에 뜬 쪽이 조용히 실패하거나 앞선 세션의 화면을 보게 되기 때문입니다)
- 정식 클론(예:
~/workspace/gitlab.doksam.com/<repo>)은 기본 브랜치를 미러링하는 읽기 전용 기준점으로만 두고, 그 안에서는 체크아웃을 하지 않습니다. - 실제 작업은
git worktree add ../<repo>-<n> -b <type>/issue-<n>식으로 이슈 번호가 박힌 브랜치와 함께 새 폴더를 만들어 그 안에서 합니다.
이렇게 하면 "자동화된 프로세스가 실수로 메인 브랜치로 체크아웃해버리는" 함정도 같이 막힙니다. 정식 클론은 기본 브랜치에만 물려 있고 애초에 그 안에서 브랜치를 갈아타는 동작 자체를 하지 않으니, 다른 브랜치를 이중으로 체크아웃하려는 시도는 git 이 거부합니다. 여러 서브에이전트가 파일을 동시에 수정해야 하는 작업이라면 에이전트 실행 자체를 worktree 단위로 격리해서 부르는 것도 같은 원리입니다.
작업이 끝나면(머지와 배포까지 확인한 뒤) 그 worktree 는 그 자리에서 정리합니다. git worktree remove 로 폴더를 지우고 로컬 브랜치도 삭제합니다. 이걸 미루면 어떻게 되는지는 뒤 실사례에서 이야기합니다.
교차검증 — 고위험 판단은 다수결로
모든 판단을 여러 관점으로 검증할 필요는 없습니다. 단순 작업에 교차검증을 붙이면 시간만 늘어납니다. 다만 틀렸을 때 되돌리기 어렵거나 대가가 큰 판단 — 보안 관련 발견, 되돌리기 힘든 설계 결정 — 에는 독립된 관점 여러 개로 반박 검증(adversarial verify)을 해보고 다수결로 결론을 냅니다.
방식은 같은 질문을 서로 다른 서브에이전트에 독립적으로 던지는 것입니다. 서로의 결론을 미리 공유하지 않은 상태에서 각자 판단하게 하고, 결과가 갈리면 왜 갈렸는지를 다시 파고듭니다. 모든 관점이 같은 결론에 도달하면 확신을 갖고 진행하고, 갈리면 그 지점이 진짜 리스크가 있는 지점이라는 신호로 받아들입니다.
실사례 두 가지
이 시리즈 자체를 병렬로 검수했습니다. 초안을 편마다 다 써놓고 나서, 편 하나에 서브에이전트 하나씩을 붙여 동시에 검수시켰습니다. 각 서브에이전트에 준 지시는 동일했습니다. 존재하지 않는 기능이나 지어낸 수치가 있는지, 톤이 다른 글과 어긋나지 않는지, frontmatter 규격이 맞는지, 다른 편과 내용이 겹치지 않는지 확인하고 직접 고칠 것. 각 편이 서로 독립이라 병렬 조건에 정확히 맞았고, 서브에이전트마다 자기 담당 파일 하나만 수정하니 충돌도 없습니다.
여기서 한 가지 함정이 있었습니다. "다른 편과 겹치는지"를 판단하려면 자기 편만 봐서는 안 되고 나머지 편도 읽어야 합니다. 그래서 각 서브에이전트에게 담당 편 외에 인접한 편들의 경로까지 같이 넘겨야 했습니다. 병렬로 쪼개도 판단에 필요한 재료는 각자에게 온전히 줘야 한다는 것 — 쪼개기 전에 확인할 게 의존성만은 아니라는 뜻입니다.
worktree 는 폴더 목록에서 바로 보입니다. 제 작업 디렉터리에는 www 옆에 www-16, infra 옆에 infra-11, llm 옆에 llm-44·llm-47 같은 폴더가 나란히 있습니다. 뒤에 붙은 숫자가 그 worktree 가 담당한 이슈 번호입니다. 이름만 봐도 "어느 레포의 몇 번 이슈 작업 중인지"가 드러나서, 세션을 여러 개 띄워놓고 있어도 어느 창이 뭘 하고 있는지 헷갈리지 않습니다.
같은 레포에 숫자가 다른 폴더가 두 개 있다는 건 그 레포에서 이슈 두 개를 동시에 굴리고 있다는 뜻이고, 머지와 배포가 끝났는데도 폴더가 남아 있다면 정리를 빼먹었다는 신호입니다. 실제로 정리를 미뤄뒀다가 다음 세션이 오래된 worktree 를 열어 작업을 시작한 적이 있었고, 그 뒤로 머지·배포 확인 직후 그 자리에서 git worktree remove 하는 걸 규칙으로 굳혔습니다.
정리
정리하면 이렇습니다.
- 병렬/순차 판단 기준은 의존성 하나: 결과가 다음 입력이면 순차, 독립적이면 병렬
- 쪼갤 때는 판단에 필요한 재료를 각 서브에이전트에게 온전히 넘겼는지도 같이 본다
- 에이전트는 용도별로 나눠 쓴다: 광역 탐색 전용, 설계, 범용 조사
- 모델 티어는 작업의 실패 대가에 맞춰 고른다: 단순 반복은 작은 모델, 일반 구현은 중간, 근본원인·설계·보안은 큰 모델
- 같은 레포를 여러 에이전트가 동시에 만질 땐 worktree 로 물리적으로 분리하고, 끝나면 그 자리에서 지운다
- 고위험 판단만 독립 관점 여러 개로 반박 검증 후 다수결
병렬 처리에서 실제로 발목을 잡는 건 "몇 개를 동시에 돌릴 수 있느냐"가 아니라 "쪼갠 것들이 서로 간섭하지 않게 경계를 그었느냐"입니다. worktree 격리가 그 경계를 파일시스템 레벨에서 강제하는 장치고, 나머지는 작업을 던지기 전에 의존성을 한 번 물어보는 습관입니다.
다음 4편에서는 MCP(Model Context Protocol)로 외부 시스템—데이터베이스, 이슈 트래커, 모니터링—을 Claude Code 에 붙여 쓰는 이야기를 다룹니다.