본 기사에서는 Claude Code를 사용하여 하나의 문서를 여러 세션에서 병렬로 편집하는 방법을 소개합니다. 논점별로 세션을 분리하고, 사람이 각 세션과 직접 상호작용하며 수정안을 승인합니다. 확정된 내용은 cross-session messaging을 통해 다른 세션에 전달합니다.
사양서나 설계서처럼 목표가 명확한 경우, AI는 구현이나 테스트를 자율적이고 병렬적으로 진행할 수 있게 되었습니다. 작업 계획부터 목표 달성 여부를 컴파일러나 테스트로 확인할 수 있어 사람이 중간에 판단할 필요가 없습니다.
반면, 요구사항 정의서와 같은 문서는 그렇지 않습니다. 무엇을 요구사항으로 삼고 어디까지를 대상으로 할지는 작성하면서 결정하는 것이기 때문에, 목표를 미리 제시하기 어렵습니다. AI에게 초안 작성을 맡길 수는 있지만, 내용을 확인하고 수정안 채택 여부를 결정하는 것은 사람의 몫입니다.
AI와 함께 문서를 고치는 과정은 지시를 내리고 수정안을 확인하며 승인할지, 아니면 다시 지시할지를 결정하는 상호작용을 반복합니다. 하나의 논점이라도 납득할 만한 기술적 설명이 되기까지 여러 번의 왕복(往復)을 거치는 것은 드문 일이 아닙니다.
하나의 세션에서는 논점을 순차적으로 다룰 수밖에 없으므로, AI의 응답을 기다리는 동안 다른 논점 작업도 멈추게 됩니다. 논점 A부터 C까지 처리할 경우, 다음과 같이 응답 대기(빨간색)가 쌓이게 됩니다.
세션을 여러 개로 분리하면, 한 논점에서 AI의 응답을 기다리는 동안 다른 세션에서 다음 논점에 대한 지시를 내릴 수 있습니다. 즉, 여러 논점을 병렬적으로 다룰 수 있게 됩니다.
물론 인간의 두뇌 용량에는 한계가 있지만...😅
다만, 같은 파일을 여러 세션에서 수정할 경우 다음과 같은 2가지 유형의 충돌이 발생합니다.
| 충돌 유형 | 발생하는 일 |
|---|
| 쓰기 충돌 (Writing Conflict) | 동일한 부분을 수정하거나 오래된 내용으로 파일 전체를 덮어쓰면서 다른 세션의 변경 사항을 지워버림 |
| 의미 충돌 (Semantic Conflict) | 편집하는 부분은 겹치지 않더라도, 다른 세션에서 결정된 내용을 모른 채 작성하기 때문에 문서 전후로 내용이 서로 어긋남 |
이 두 가지는 소프트웨어 개발에서 코드를 병합(merge)할 때 발생하는 충돌과 유사합니다. 같은 줄을 두 사람이 수정했을 경우 Git이 이를 감지해 줍니다. 반면, 텍스트적으로는 문제가 없어 병합되더라도 결과 프로그램의 동작이 달라지는 경우가 생길 수 있으며, Martin Fowler는 이를 'semantic conflict'라고 부릅니다.
safely merged on a textual level but cause the program to behave differently
코드의 semantic conflict를 Git이 감지하지 못하게 하듯이, 문서의 의미 충돌 역시 편집 범위를 분리하는 것만으로는 막을 수 없습니다. 이를 방지하려면 다른 세션에서 결정된 내용을 각 세션에 전달할 필요가 있으며, 본 기사에서는 그 목적으로 cross-session messaging을 사용합니다.
본 기사의 방식은 사람이 각 세션과 직접 대화하며 수정안을 세션별로 승인하는 것입니다. 작업 분할 및 취합을 부모 AI에게 맡기는 구성과는 사람이 판단을 내리는 상대가 다릅니다.
subagent는 처리 결과를 호출자에게 반환하는 메커니즘이라, 개별 subagent와 지속적으로 대화하기는 어렵습니다. 따라서 상담이나 판단은 모두 부모 세션에 모이게 됩니다.
Agent teams에서는 teammate와 직접 상호작용할 수 있지만, 공식 문서에서는 실험적인 기능으로 분류되어 있으며 기본적으로 비활성화(disabled) 상태입니다.
Agent teams are experimental and disabled by default.
또한, 같은 파일을 편집하는 작업에는 단일 세션(single session)이나 subagent가 더 적합하다고 언급됩니다.
a single session or subagents are more effective.
메커니즘 설명에 들어가기 전에, cross-session messaging을 사용하면 실제로 어떻게 보이는지 보여드리겠습니다.
두 개의 세션인 session-01과 session-02라는 이름을 붙이고, 동일한 요구사항 정의서를 수정하는 상황입니다. session-01은 3.10절을, session-02는 3.12절을 담당합니다. session-02에서 논점 하나가 결정되면 다음과 같은 일이 벌어집니다.
session-02 화면에서는 사람의 승인을 받아 문서를 수정하고, 확정된 내용을 session-01에 전달합니다.
Q2는 (a)로 결정합시다
● requirements.md의 3.12절을 수정했습니다. 결정된 내용을 session-01에 보냈습니다.
session-01
화면에서는, 사람이 3.10절을 논의하는 도중에 수신 신호가 담긴 한 줄과 Claude의 짧은 응답만 끼어 있습니다.
› Message from @session-02: 3.12절의 Q2를 (a)로 결정했습니다.… (ctrl+o to expand)
● session-02로부터 공유(3.12의 결정)를 받았습니다
session-01
의 Claude는, 이어진 3.10절 검토에서, session-02
에서 결정된 내용을 바탕으로 문서를 수정합니다.
이 방법에서는, 작업을 시작하기 전에 정한 약속들을 --fork-session
으로 모든 세션에 계승하고, 작업 도중에 결정된 내용을 cross-session messaging
으로 다른 세션에 전달할 수 있습니다.
--fork-session
은, 세션을 재개할 때 원래의 대화를 유지한 채 새로운 세션 ID로 시작하는 옵션입니다.
When resuming, create a new session ID instead of reusing the original
먼저 하나의 세션에서 작성 방식이나 분담, 연락 방법을 결정해 두고, 그 대화로부터 각 세션을 분기시키면, 모든 세션이 같은 약속을 아는 상태로 작업을 시작할 수 있습니다. 세션마다 똑같은 설명을 반복할 필요가 없습니다. 분기한 후에 결정된 내용은, 다음에 설명할 cross-session messaging
으로 전달합니다.
cross-session messaging은 Claude Code의 세션 간 메시지 교환 기능입니다. 사람이 전송할 세션 이름을 언급하며 내용을 전달하도록 요청하면, Claude가 ListAgents
로 수신처를 찾고, SendMessage
으로 보냅니다.
수신 측 세션은, 작업 중이라면 도구를 호출하는 틈에, 대기 중이라면 새로운 턴을 시작하여 메시지를 읽습니다. 전송 측이 notify_when_idle
을 붙여두면, 상대방이 대기 상태가 되었을 때 알림을 받을 수도 있습니다.
다른 세션으로부터 도착한 메시지는, 인간의 동의로 간주되지 않습니다.
a message from another session never counts as your consent
따라서, 메시지를 받은 세션에서 권한 확인이 필요한 작업을 할 때는, 평소처럼 사람이 허가합니다.
같은 머신 위에서는, 각 세션이 수신용 Unix 도메인 소켓을 가지며, 전송 측은 그 소켓에 직접 메시지를 기록합니다. 공식 문서에도 Anthropic의 서버를 거치지 않음이 명시되어 있습니다.
never through Anthropic servers
메시지가 도착하기까지의 흐름을 OS 계층에서 보면 다음과 같습니다 (소켓 경로와 프로세스 ID는, 다음에 설명할 실제 예시의 것입니다).
수신 측 프로세스는, 전송 측이 발신처를 나타내는 태그로 감싼 본문을, 다음 Anthropic API로 보낼 요청에 포함하여 Claude에게 전달합니다.
2026년 10월 19일에 macOS 상의 Claude Code v2.1.303에서 확인했을 때, 소켓은 /tmp/cc-socks/
아래에 세션의 프로세스 ID를 파일명으로 하여 생성되어 있었습니다. 권한은 소유자만 읽기/쓰기가 가능한 설정입니다.
$ ls -la /tmp/cc-socks/
drwx------ ... .
srw------- 1 <user> wheel 0 Oct 19 10:06 22717.sock
...
자신의 세션이 사용하는 소켓 경로는, 환경 변수 CLAUDE_CODE_MESSAGING_SOCKET
에서 확인할 수 있습니다.
Claude Code는 이를 hooks와 Bash 명령어로 다음과 같이 내보냅니다.
CLAUDE_CODE_MESSAGING_SOCKET
환경 변수
SendMessage
메시지를 보냈을 때, 수신 측 소켓에 도착하는 데이터는 다음과 같습니다 (토큰과 식별자 일부는 가려져 있습니다). JSON Lines 형식으로 한 줄에 하나의 JSON 객체를 작성하며, 첫 번째 줄은 인증(auth)이고 두 번째 줄이 메시지입니다. 참고로, 인증 라인을 제외한 형식은 공식적으로 공개되지 않은 내부 형식이기 때문에 Claude Code 업데이트에 따라 변경될 수 있습니다.
{"type":"auth","token":"<32 문자 값>"}
{"msgV":1,"msg_id":"a3aed12b-...","type":"user","message":{"role":"user","content":"<cross-session-message from="uds:/tmp/cc-socks/72772.sock" from-name="Qiita記事書く_02" from-mode="prompting">
중계의 검증입니다
</cross-session-message>"},"priority":"next","from":"uds:/tmp/cc-socks/72772.sock"}
수신 측 Claude에게 전달되는 것은 message.content 문자열이며, 이를 추출하면 다음과 같습니다.
<cross-session-message from="uds:/tmp/cc-socks/72772.sock" from-name="Qiita記事書く_02" from-mode="prompting">
중계의 검증입니다
</cross-session-message>
본문은 전송 측에서 <cross-session-message> 태그로 감싸지며, 전송원 소켓(from), 세션명(from-name), 권한 모드(from-mode)가 속성으로 붙습니다. JSON에는 메시지의 ID(msg_id), priority, 그리고 회신할 전송원 소켓(from)도 포함됩니다.
각 세션은 담당하는 논점을 인간과 토론하고, 승인된 수정을 담당 범위에 반영합니다. 논점이 결정되면 문서 편집에 참여하고 있는 다른 모든 세션에 그 내용을 보냅니다.
먼저, 분기점(branching point)이 되는 세션에서 담당 분배와 연락 방법을 결정합니다. 지시 예시는 다음과 같습니다.
여러 세션에서 동일한 문서 파일을 편집합니다. 다음 규칙을 따르세요.
## 편집할 때
- 할당된 논점에 대해 인간과 토론하고, 승인된 수정 사항을 담당 범위에 반영한다.
...
규칙을 정했다면, 이 세션에 이름을 붙입니다.
새로운 터미널 탭에서 이 세션을 이름으로 지정하여 분기합니다 (-c로 최근 대화를 재개할 경우, 규칙을 정한 세션과 다른 세션에서 분기될 수 있습니다).
claude --resume session-01 --fork-session
분기된 세션에는 다른 이름을 붙이고, 해당 세션의 담당 업무를 전달합니다.
이후에도 같은 절차로 필요한 만큼 session-01에서 분기하여 각각 이름과 담당을 할당합니다.
메시지를 받았을 때의 응답은 발신자와 어떤 내용에 대한 것인지만 적힌 한 줄로 제한해야 합니다. 수신한 내용을 요약하거나 보고하는 것은 금지하고, 인간의 판단이 필요한 경우에만 그 내용을 간략하게 전달하도록 해야 합니다.
대기 중인 세션은 메시지를 받을 때마다 새로운 턴을 시작하여 응답을 작성합니다. 만약 이 응답에서 내용 요약이나 보고를 하면, 인간과의 토론 도중에 긴 응답이 끼어들어 이전 대화 기록이 화면에서 사라지게 됩니다. 메시지는 다른 모든 세션으로부터 오기 때문에, 세션이 늘어날수록 방해(interruption)도 커집니다.
응답을 한 줄로 제한하더라도,
Edit 툴은 정확한 문자열 교체를 수행합니다.
v2.1.208 버전부터는 파일을 읽어 들인 후 내용이 바뀌었더라도, 교체 전의 문자열이 현재 파일에 단 한 곳만 존재하면 편집이 적용됩니다. 이때 다른 세션이 다른 위치에 추가한 변경 사항은 그대로 유지됩니다.
반면, Write 툴은 전달된 내용으로 파일 전체를 덮어쓰며, 기존 내용에 대한 추가나 병합은 수행하지 않습니다.
It doesn't append or merge.
다만, 두 세션이 같은 위치를 동시에 수정했을 경우의 충돌은 Edit 툴로도 막을 수 없습니다. 따라서 Edit 툴을 사용할 뿐만 아니라, 세션별로 담당 범위를 나누어 놓는 것이 좋습니다.
현재 시점에서 Claude에게 글을 쓰게 하면 'AI 느낌의 문장'이 되어 사람의 손보기가 반드시 필요해집니다.
본 기사에서 보여드린 방법으로도 문서 생성에 필요한 수고의 양은 변하지 않았고 최적의 해법이라고 생각하지는 않지만, 앞으로도 다양한 기술이 발전해서 조금이라도 편해지면 좋겠습니다.