sgkstudio.
엔지니어링

Claude Code 병렬 세션의 기록 유실 12건을 0건으로

Claude Code 병렬 세션이 공유 문서를 서로 지우던 문제는 락이 아니라 '통째 다시 쓰기'라는 구조를 바꾸자 멈췄습니다. 30개 저장소 소급 감사에서 영구 유실 12건은 전부 가드 배선 이전이었고, 배선 이후는 0건입니다. 반면 번호 충돌은 락을 걸고도 3건이 더 났고, 발급기를 만든 뒤에도 경로 하나 때문에 한 번 더 겹쳤습니다.

2026-09-03세션 종료 절차 문서 1건 (2026-07-24 ~ 2026-09-02 수정 이력)30개 저장소 소급 유실 감사 1회 (2026-08-09) · 번호 재정리 기록 1건 (2026-08-14)실측 사고 기록 — 큐 유실 · 번호 충돌 · 미기록 지적 · 프롬프트 덮어쓰기

세션이 끝날 때마다 무엇이 사라지고 있었나

세션 하나가 끝나면 에이전트는 공유 문서 3개를 갱신합니다. 진행 큐(지금 열린 작업 목록), 결정 기록(무엇을 왜 정했나), 학습 기록(무엇을 배웠나)입니다. 다음 세션은 이 세 문서만 읽고 이어서 일하므로, 여기서 빠진 항목은 다음 세션에 존재하지 않습니다.

문제는 세 가지 형태로 나타났습니다. 큐 항목이 근거 없이 사라졌고, 결정·학습 번호가 서로 다른 항목에 겹쳐 붙었고, 대표가 세션에서 한 지적이 어디에도 남지 않았습니다. 셋 다 증상이 조용합니다. 파일은 멀쩡히 열리고 오류도 없습니다.

규칙상 기존 공유 문서는 통째로 덮어쓰지 않고 부분 편집만 합니다. 사람이 손으로 고친 자리를 보존하려는 규칙이고, 새 메모리 파일만 새로 씁니다. 그런데도 항목이 사라졌다면 편집 자체가 아니라 편집 앞뒤의 절차 어딘가가 비어 있다는 뜻입니다.

되돌린 사실은 git에 남지만, 왜와 다시 꺼내지 마라는 판정은 어디에도 안 남아 있었다

비용은 재작업입니다. 2026년 8월 7일 큐 41번 항목이 '세션 발화'라고만 적혀 있어 다음 세션이 엉뚱한 대화 기록을 뒤졌고, 남은 '파이프라인' 한 단어를 소프트웨어로 오독해 세션 하나가 통째로 엉뚱한 산출물(헌장 2건과 비평 10회)을 만들었습니다. 같은 달 8일에는 한 세션 안에서 이미 기각한 축을 2회 다시 꺼냈습니다.

이 글은 승인 게이트를 다룬 관련 글의 뒷면입니다. 그 글이 에이전트를 언제 멈추게 할지를 다뤘다면, 이 글은 멈춘 뒤 무엇을 남길지를 다룹니다.

처음 잰 숫자 — 영구 유실 12건, 번호 충돌 44개와 5개, 미기록 지적 4건

재는 방법은 세 가지였습니다. 유실은 git 이력을 거슬러 올라가 큐에서 해소 근거 없이 사라진 항목을 세는 소급 감사입니다. 번호 충돌은 결정·학습 기록 파일에서 같은 번호가 헤딩으로 두 번 나오는지 세는 전수 검사입니다. 미기록 지적은 대표 발화 원문을 최근 7일치 긁어 규칙·메모리·기각 목록·큐 어디에 있는지 대조하는 회수입니다.

처음 잰 값 — 전부 파일과 git 이력에서 직접 셌습니다
측정 축처음 잰 값어떻게 쟀나
큐 영구 유실12건 (30개 저장소)2026-08-09 소급 감사 초회 실행
결정 번호 충돌5건/527 (이 저장소) · 6건/166 (트레이딩 저장소)결정 기록 파일 전수
누적 번호 충돌학습 44개 · 결정 5개2026-08-14 재번호 작업 기록
미기록 지적12건 중 4건2026-08-08 최근 14일 상위 지적 대조
진행 문서 크기3,477줄 · 현재 단계 표기 4중복2026-07-25 진단

번호 충돌은 같은 번호가 서로 다른 두 항목에 붙은 경우만 셌습니다. 같은 결정을 이중 기록한 경우는 따로 1건 있습니다.

처음 잰 숫자 네 칸. 큐 영구 유실 12건, 결정 번호 충돌 5건/527, 미기록 지적 12건 중 4건, 진행 문서 3,477줄
고칠 대상이 된 네 숫자 — 넷 다 오류 없이 조용히 쌓였습니다

가장 뼈아픈 숫자는 두 번째 줄입니다. 결정 번호 하나가 서로 다른 두 결정에 붙어 있었습니다. 번호가 겹치면 그 번호를 근거로 적은 큐 항목이 어느 결정을 가리키는지 알 수 없고, 큐 항목은 근거를 잃는 순간 유령이 됩니다. 2026년 8월 4일 실측에서는 해소 근거를 세션 로그에만 적고 결정 기록에 안 남긴 항목이 5일간 큐에서 부활을 반복했습니다.

세 번째 형태의 손실은 더 늦게 보였습니다. 2026년 8월 8일 최근 14일 상위 지적 12건을 원문에서 긁어 대조하니 4건이 규칙에도 메모리에도 큐에도 없었습니다. 무엇을 남길지 고르는 주체가 그 세션에서 지적을 무시한 당사자라, 놓치면 놓친 줄도 모릅니다.

가설 — 동시에 쓰니까 깨진다, 락을 걸면 멈춘다

첫 진단은 동시성이었습니다. 같은 디렉토리에서 세션 여러 개가 같은 문서를 동시에 편집하니 한쪽이 다른 쪽을 덮는다는 가설입니다. 편집 도구의 유일한 안전장치는 '고치려는 원문이 파일에 그대로 있는가' 검사인데, 이건 동시 충돌만 잡습니다. 백업인 큐 드롭 검사는 커밋본과 작업본을 비교하므로 옆 세션이 아직 커밋하지 않은 항목은 애초에 시야 밖입니다.

락이 필요했던 이유는 단순합니다. 종료 절차가 만지는 공유 문서 3개에 락이 하나도 없었습니다. 실측 피해로 이 저장소 결정 번호 충돌 5건과 트레이딩 저장소 6건이 이미 쌓여 있었고, 결정 번호 하나가 파일의 858행과 10101행에서 서로 다른 결정으로 두 번 정의돼 있었습니다.

그래서 2026년 8월 9일 종료 절차 맨 앞에 락을 넣었습니다. 세션은 종료 절차를 시작하기 전에 저장소 단위 락을 잡고, 못 잡으면 기다렸다 재시도하며, 마지막 8번 단계에서 반드시 풉니다. 세션이 죽어 락만 남으면 30분 뒤 자동 만료하고, 깨진 락 파일은 스스로 고칩니다.

  • 기본은 기다렸다 재시도 — 종료 절차 한 사이클은 보통 몇 분이고, 상대가 끝난 뒤 다시 잡으면 큐와 결정 기록을 상대의 최신본 위에서 읽게 됩니다
  • 지금 끝내야 하면 요약을 별도 보류 파일에 직접 남기고 종료 — 파일명에 deferred가 들어가야 다음 세션 최상단에 뜨고, 다음 세션은 전문을 반영한 뒤 파일을 지웁니다
  • 상대 세션이 죽은 듯하면 30분 만료를 기다리거나 락을 회수합니다

이 가설이 맞다면 락 이후 번호 충돌은 0건이어야 했습니다. 큐 유실도 병렬 세션이 없는 구간에서는 나오지 않아야 했습니다.

락을 걸고도 왜 충돌이 3건 더 났나

락을 도입한 뒤 2026년 8월 12일과 13일에 번호 충돌이 3건 더 났습니다. 락은 동시 실행만 직렬화하지 번호를 세지는 않습니다. 두 세션이 차례로 들어와도 각자 '마지막 번호 더하기 1'을 눈으로 읽으면, 앞 세션이 쓴 번호를 뒤 세션이 못 볼 때 같은 번호를 집습니다.

못 보는 이유는 표기 방식에 있었습니다. 이 기록 파일들은 한 헤딩이 여러 번호를 덮는 범위 표기를 씁니다. 학습 865번부터 868번까지를 헤딩 하나로 적는 식이고, 이 저장소에만 그런 헤딩이 58개입니다. 마지막 헤딩만 읽는 grep도, 최댓값 더하기 1도 범위의 뒷부분을 못 봅니다. 그래서 이미 쓰인 번호가 '비어 있음'으로 통과했습니다. 문서에 적혀 있던 '헤딩 개수를 세어 확인하라'는 지시는 같은 이유로 실제로는 안 통했습니다.

번호를 세는 두 방법의 코드 비교. 이전은 마지막 헤딩을 grep으로 읽어 더하기 1, 범위 헤딩 58개의 뒷부분을 못 본다. 이후는 발급기 명령이 범위 헤딩·샤드·회수 아카이브를 전부 보고 다음 빈 번호를 준다
락은 순서만 정한다 — 세는 방법이 틀리면 같은 번호가 나옵니다

유실 쪽에도 락으로 설명되지 않는 사례가 있었습니다. 2026년 7월 30일 한 커밋이 큐 13항목을 지우면서 본문에는 '기존 9건 미터치'라고 적었고, 그중 2건은 그 뒤 파일 어디에도 없습니다. 병렬 세션이 아니라 세션 하나가 혼자 한 일입니다. 같은 기간 세션 로그는 363커밋 동안 유실 0건이었습니다.

두 문서의 차이는 동시성이 아니라 쓰는 방식이었습니다. 큐는 매번 통째로 다시 쓰고, 세션 로그는 덧붙이기만 합니다. 다시 쓰는 쪽이 남의 항목을 빠뜨려도 편집은 성공하므로 안전장치가 발동하지 않습니다. 락 가설은 여기서 반쯤 무너졌습니다.

진짜 원인 — 통째 다시 쓰기, 눈으로 세는 번호, 그리고 32줄 예산

원인은 셋이었고 셋 다 구조입니다. 첫째, 큐를 통째로 다시 쓰는 방식 자체가 유실의 동인입니다. 병렬은 그 사고율을 곱할 뿐입니다. 둘째, 번호를 눈으로 세는 절차입니다. 락이 순서를 정해 줘도 세는 방법이 틀리면 같은 번호가 나옵니다. 동시성 문제가 아니라 조회 문제입니다.

셋째는 예산입니다. 큐 블록은 32줄 안에 있어야 합니다. 세션 시작 때 훅이 자동으로 주입하는 분량이 그만큼이라, 넘치면 초과분이 다음 세션에서 잘려 나갑니다. 예산이 있으니 넘치면 누군가 지워야 하고, 지우는 순간 근거 없이 사라집니다. 2026년 8월 4일 포렌식에서 진행을 실제로 끊은 유실 3건이 전부 이 자리에서 나왔고, 셋 다 측정 항목이었습니다.

측정 항목이 먼저 사라지는 데는 이유가 있습니다. 반쯤 만든 기능은 git 상태, 미머지 브랜치, 깨진 테스트로 계속 눈에 띄어 누군가 다시 집습니다. 측정하지 않은 숫자는 저장소 어디에도 흔적이 없어 큐에서 빠지는 순간 존재 자체가 사라집니다. 도달률, 잔액 구간, 기준선이 그렇게 사라진 셋이었습니다.

예산 32줄은 2026년 8월 10일 산문 규칙에서 쓰기 시점 차단으로 바뀌었습니다. 병렬 세션 둘이 같은 32줄을 서로 모르고 나눠 쓰다 넘긴 게 실제 원인이었고, 그날 항목 4건과 상태 줄 하나가 밀려났습니다. 락은 동시 실행만 직렬화했을 뿐 예산은 아무도 보지 않았습니다.

지적이 기록에 안 남는 원인도 같은 부류입니다. 대화 원문은 30일 롤링이라 30일 안에 규칙이나 메모리로 압축하지 않으면 원문까지 사라집니다. 발화 자체는 명령 이력에 113일 남지만 그 위의 맥락은 없습니다. 요약에 기대면 놓친 지적은 영구히 소실됩니다.

조치 — 검사기 다섯 개와 발급기 하나, 그리고 흘려보내기

조치는 사람에게 주의를 요구하지 않는 방향으로 잡았습니다. 종료 절차의 각 단계를 명령 호출로 바꾸고, 어기면 쓰기 시점에 막히게 했습니다.

종료 절차에 들어간 검사기와 발급기
조치무엇을 막나언제 도나
큐 드롭 감사이번 커밋에서 해소 근거 없이 사라진 큐 항목종료 절차 + 커밋 직전 훅 (커밋 자체가 막힌다)
소급 유실 감사이미 사라져 아무도 모르는 항목 — 전 이력을 거슬러 본다종료 절차 (2026-08-09 신설)
측정 기한 감사큐에 남아 있는데 기한만 지나가는 측정 항목종료 절차 — 측정하거나 기한을 새로 잡는다
예산 가드큐 블록 32줄 초과 쓰기 — exit 2로 차단쓰기 직전 훅 (2026-08-10)
지적 회수최근 7일 대표 발화 원문을 규칙·메모리·큐와 대조종료 절차 1.4단계 (2026-08-08)
번호 발급기눈으로 세는 번호 — 범위 헤딩·샤드·회수 아카이브를 전부 보고 발급결정·학습 기록 쓰기 전 (2026-08-14)

큐 드롭 감사와 소급 유실 감사는 대체재가 아닙니다. 앞은 이번 커밋만 보고, 뒤는 전 이력을 봅니다.

예산 초과분은 삭제하지 않고 회수 파일로 흘려보냅니다. 초과분 전문과 출처 커밋을 별도 파일에 남기고 큐에는 포인터 1줄만 둡니다. 통합해 줄 수를 줄이는 선택지는 있지만 내용을 버리는 선택지는 없습니다. 막히면 명령 하나가 관찰 항목만 오래된 쪽부터 옮기고, 승인 대기 항목과 대표 소유 항목은 절대 옮기지 않습니다.

큐 항목 규격도 바꿨습니다. 항목마다 다음 세션이 실행해 진위를 재확인할 수 있는 근거 포인터(명령, 파일 경로, 커밋 해시)를 붙이고, PR 번호는 근거로 인정하지 않습니다. PR은 사후에 폐기하거나 대체할 수 있는데 그 사실이 큐에 전파되지 않기 때문입니다. 2026년 8월 5일 실측에서 큐가 가리킨 PR 149번은 라이선스 사유로 폐기한 이식본이었고, 문자 그대로 실행했다면 여러 세션에 걸쳐 제거한 리스크를 다시 들여올 뻔했습니다.

세션 종료 절차 흐름도. 락 잡기에서 시작해 감사 4종, 지적 회수, 기각 목록 확인, 공유 문서 3개 편집, 번호 발급, 커밋과 잔여 0 확인, 락 해제, 다음 세션 시작 프롬프트 발급 순으로 흐른다. 문장으로만 적힌 단계는 0개
모든 단계가 명령 호출입니다 — 문장으로만 남은 단계가 하나 있었고 그 단계만 돌지 않았습니다

문서가 늙는 문제는 회전으로 풀었습니다. 진행 문서가 1,500줄을 넘으면 30일 이상 지난 섹션을 월별 아카이브로 옮기고 본문에는 포인터 1줄만 남깁니다. 큐 블록은 파일 최상단 10줄 이내에 정확히 1개만 두고, 두 번째 큐 사본은 만들지 않습니다. 14일 지난 세션 로그의 '미결' 라벨은 '당시 미결(동결)'로 바꿔, 라벨 자체가 현재가 아님을 말하게 했습니다. 덧붙이기만 하면 문서는 커지는데 내용은 늙습니다.

세션 로그 헤더의 일련번호도 없앴습니다. 2026년 7월 24일 병렬 세션이 같은 번호를 동시에 집어 108차와 102차가 각 2개씩 생겼습니다. 시각과 세션 이름을 헤더로 쓰면 충돌하지 않습니다. 결정·학습 번호는 이 교훈을 못 받아 실제로 충돌해 있었고, 그래서 발급기가 필요했습니다.

왜 규칙을 문장이 아니라 명령으로 적어야 했나

종료 절차 문서에서 명령 호출이 아니라 문장으로만 적힌 단계가 딱 하나 있었습니다. 다음 세션이 이어받을 시작 프롬프트를 발급하라는 9번 단계입니다. 2026년 8월 23일 초판은 이 자리를 조건부 문장으로 뒀고, 그 단계만 돌지 않았습니다. 긴 문서 끝의 조건부 문장은 안 돕니다. 같은 구조의 다른 사례로, 프롬프트 코칭 규칙은 전체 대화 기록에서 3회 발동에 그쳤습니다.

그래서 8월 24일 발급을 명령으로 바꿨습니다. 검사 명령이 발급 필요 여부를 판정하고, 발급 명령이 직전 프롬프트를 아카이브로 옮기고 포인터를 갱신한 뒤 축 5개를 검사합니다. 파일을 직접 쓰는 길은 막았습니다. 파일명이 하나뿐이라 아직 소비하지 않은 프롬프트가 조용히 덮이기 때문이고, 2026년 8월 31일 실제로 발급 4회에 아카이브 1회라는 사고가 났습니다.

커밋 단계도 같은 병을 앓았습니다. 문서에 '제안만 하고 실행 금지'가 남아 있어 종료 절차 때마다 대표에게 커밋을 되물었고, 8월 13일 하루에만 '커밋해'가 12회 나왔습니다. 커밋을 자율로 돌린 뒤에는 잔여 미커밋을 0으로 만드는 확인까지 절차에 넣었습니다. 조용히 두고 나가면 다른 저장소처럼 625건, 386건이 쌓입니다.

도구가 없는 게 아니라 부를 수 없는 경로로 적혀 있으면, 규율은 그 자리에서 무효가 된다

다시 재니 — 배선 이후 유실 0건, 번호는 한 번 더 겹쳤다

2026년 8월 9일 30개 저장소 소급 감사 초회 실행이 재측정입니다. 영구 유실 12건은 전부 가드를 배선한 8월 4일 이전이었고, 배선 이후는 0건입니다. 발견한 12건은 회수 파일에 원문과 직전 커밋 해시를 보존했고, 큐에는 포인터만 남겼습니다. '이미 해소됐겠지'라고 판정해 지우는 선택은 하지 않았습니다.

락에 막혀 종료 절차를 못 연 세션의 보류 파일도 배선을 확인했습니다. 파일명에 deferred가 들어가면 세션 시작 훅이 디렉토리와 시간에 상관없이 매 세션 최상단에 띄우고, 다음 세션이 전문을 반영한 뒤 삭제하는 것이 완료 신호입니다. 별도 상태 파일은 두지 않았습니다.

막대 두 개. 가드 배선 전 영구 유실 12건, 배선 후 0건. 30개 저장소 소급 감사, 2026-08-09
유실은 락이 아니라 가드 배선 시점을 기준으로 갈렸습니다

번호 충돌은 결과가 갈렸습니다. 락만으로는 3건이 더 났고, 발급기를 붙인 뒤 2026년 8월 14일 누적 44개와 5개를 재번호로 정리했습니다. 그런데 8월 28일 다시 한 번 겹쳤습니다. 문서에 발급기 경로가 상대경로로만 적혀 있어, 저장소 루트가 아닌 곳에서 연 세션은 그 명령을 못 찾았고, 에이전트는 바로 아래 문단이 '안 통한다'고 명시한 grep 방식으로 되돌아갔습니다. 결정 번호 하나가 다시 두 결정에 붙었습니다.

같은 날 회사 PC는 자기 샤드만 보고 태그 번호 하나를 서로 다른 3개 항목에 재사용했고, 그중 하나는 정본에 이미 병합돼 있었습니다. 발급기는 이제 샤드·정본·회수 아카이브를 전부 보고 다음 번호를 주며, 900 이상은 회수 재번호 전용 구간이라 신규 발급에서 뺍니다.

전후 — 종료 절차 문서를 다시 읽어 뽑았습니다
처음지금
큐 영구 유실12건 (가드 배선 전)0건 (배선 후, 30개 저장소)
번호 채번눈으로 마지막 더하기 1발급기 — 샤드·정본·회수 아카이브 전부 조회, 절대경로로 호출
큐 예산 위반산문 규칙쓰기 시점 exit 2 차단
지적 회수없음7일치 원문 대조 (초회 12건 중 4건 등재)
커밋되묻기 (하루 12회)자율 + 잔여 미커밋 0 확인
시작 프롬프트 발급조건부 문장명령 + 덮어쓰기 차단

번호 충돌의 '지금' 값은 0이 아닙니다. 2026-08-28 사고 뒤 절대경로로 고쳤지만 그 이후 충돌 건수를 다시 센 계측은 아직 없습니다.

전후 표 여섯 줄. 큐 영구 유실 12건에서 0건, 번호 채번은 눈으로 세기에서 발급기로, 예산 위반은 산문 규칙에서 쓰기 시점 차단으로, 지적 회수는 없음에서 7일치 대조로, 커밋은 하루 12회 되묻기에서 자율로, 시작 프롬프트는 조건부 문장에서 명령으로
여섯 축 가운데 숫자로 닫힌 축은 하나뿐이고 나머지는 방식이 바뀌었습니다

미기록 지적은 재측정값이 없습니다. 초회 회수에서 4건을 등재했지만, 그 뒤 몇 건을 새로 놓쳤는지 세는 계측은 아직 없습니다. 이건 아래 한계로 넘깁니다.

남는 한계 — 검사기는 자기가 안 도는 곳을 못 지킨다

  • 락 만료는 30분입니다. 세션이 죽으면 옆 세션이 그 시간 동안 막힙니다
  • 체크포인트 훅은 컨텍스트가 150K 미만이면 아무것도 쓰지 않습니다. 짧은 세션이 락에 막혀 그냥 끝나면 흔적이 0이 됩니다. 보류 파일 규약이 그 틈을 막지만, 실측 피해 2건(결정 2건·학습 7건·큐 4건을 우연히 발견한 경우와 결정 1건을 30시간 방치한 경우)이 규약 이전에 이미 있었습니다
  • 지적 회수는 사람이 30일 안에 압축해야 합니다. 발화는 113일 남지만 그 위의 맥락은 없습니다
  • 발급기는 있어도 부르지 않으면 없는 것과 같습니다. 상대경로 사고가 그 증거입니다
  • 대화가 벌어진 디렉토리와 작업 저장소가 다를 수 있어, 발화 근거는 경로와 시각까지 적어야 다음 세션이 찾습니다

가장 큰 한계는 검사기가 자기가 안 도는 곳을 못 지킨다는 점입니다. 큐 드롭 가드는 이번 커밋만 보고, 소급 감사가 전 이력을 봅니다. 가드 배선 전 구간, 가드 없는 저장소, 우회 플래그를 켠 커밋은 소급 감사만 잡습니다. 그리고 소급 감사는 종료 절차 안에서만 돌므로, 종료 절차를 건너뛴 세션은 여전히 시야 밖입니다.

같은 구조의 문제를 겪는 팀이라면 공유 문서를 통째로 다시 쓰는 자리부터 찾으시길 권합니다. 그 자리에 락을 거는 것보다 덧붙이기로 바꾸는 편이 유실을 더 많이 줄였습니다. 자동화 운영 설계 문의는 상담으로 남겨 주시면 됩니다. 작성: SGK Studio.

같은 방식으로 우리 업무를 재보고 싶다면

이 글에 쓴 계측·판정·자동화는 저희가 실제로 매일 돌리는 방식 그대로입니다. 어떤 작업을 자동화할 수 있고 어디를 사람이 잡아야 하는지, 현재 업무 흐름을 놓고 같이 짚어 드립니다.

새 글이 올라오면 알려 드립니다

이런 계측 기록을 새로 쓰면 메일로 한 통 보냅니다. 광고나 판촉은 보내지 않습니다.