BUILD 편 (3/3) · 앞선 두 편: BEFORE — 게이트는 만들었는데 한 번도 통과하지 못했다 · AFTER — 게이트를 풀지 않고 계층을 분리했다
앞의 두 편은 사건을 다뤘습니다. 이 편은 구조를 다룹니다 — 워크스페이스를 어떻게 짜고, 무엇을 계약으로 고정하고, 어디까지 왔는지.
⚠ 먼저 밝혀둡니다. 이 글에 "완성했습니다"는 없습니다. 정본으로 승격된 지식은 0건입니다. 그 사실을 §5와 §8에 그대로 적었습니다. 본문의 모든 수치는 2026-08-05에 저장소와 워크스페이스를 직접 세거나 테스트를 실행해서 얻은 값입니다.
1. 시작은 아주 사소한 불편이었습니다
강연 영상을 하나 보고 정리를 남깁니다. 두 달 뒤 그 정리를 다시 꺼냅니다. 그리고 매번 같은 자리에서 막혔습니다.
"이 문장, 강연자가 진짜 저렇게 말했나?"
정리에는 결론이 남아 있습니다. 그런데 그 결론이 영상 몇 분 몇 초에서 나왔는지, 원래 표현이 무엇이었는지가 없습니다. 그러면 그 정리는 읽을 수는 있지만 근거로 쓸 수 없는 글이 됩니다. 회의에서 인용하려면 영상을 다시 열어 찾아야 하고, 찾다 보면 기억과 다른 경우가 나옵니다.
요약 도구는 이미 많습니다. 저도 여러 개 써봤습니다. 공통점이 있었습니다. 요약은 잘 남는데 출처가 안 남습니다. 원문과 요약 사이의 연결선이 생성 시점에만 존재하고, 파일로 저장되지 않습니다.
더 곤란한 것은 그다음입니다. 출처가 안 남으면 틀렸는지 확인할 방법도 없습니다. 요약이 세 문장 중 한 문장을 지어냈어도 티가 나지 않습니다. 이게 개인 메모라면 넘어갈 수 있는데, 그 메모를 근거로 판단을 하기 시작하면 넘어갈 수 없는 문제가 됩니다.
2. 그래서 이번에 정한 질문 하나
범위를 넓히면 끝이 없어서 한 문장으로 고정했습니다.
한 편의 강연에서, 나중에 원문으로 되짚을 수 있는 형태의 지식을 남길 수 있는가.
여기 서 "되짚을 수 있는"이 조건 전부입니다. 예쁘게 요약하는 것, 많이 넣는 것, 자동화하는 것은 이번 목표가 아닙니다. 주장 하나마다 원문의 어느 구간에서 왔는지가 파일로 남아 있는가 — 이것만 봅니다.
3. 워크스페이스를 어떻게 짰나 (전체 구성)
먼저 큰 그림입니다. 시스템은 하나의 파이프라인이고, 밖에서 들어오는 것과 나가는 것이 정해져 있습니다.
[들어오는 것] 공개 강연 영상 URL (한국어 자막이 있는 것)
│
▼
┌──────────────┐
│ traceable-pkm │ ← 이 시스템
└──────────────┘
│
[나가는 것] ① 원문에 묶인 지식 항목 ② 검증 보 고서 ③ 사람 승인 기록밖으로 나가지 않는 것도 정했습니다. 이미지 생성, 외부 사실확인, 자동 스케줄 실행, 위키 자동 쓰기는 이번 범위에서 제외했습니다. 범위를 좁게 잡은 이유는 §8에 적습니다.
안쪽은 다섯 단계이고, 각 단계는 입력 → 하는 일 → 산출물 → 다음으로 넘어가는 조건으로 고정했습니다. 마지막 항목이 이 설계의 전부입니다.
그리고 규칙끼리 부딪힐 때의 순서를 미리 못 박았습니다.
전역 금지선 > 분야 규칙 > 작업 규칙 > 개인 취향아래 층은 조건을 더할 수 있지만 위 층을 풀 수는 없습니다. 이 한 줄이 나중에 가장 많이 저를 막았습니다.
마지막으로 사용자에게 보이는 상태를 세 개로만 줄였습니다. 초안 → 검토 준비 → 승인. 내부 상태는 훨씬 많지만, 밖으로는 이 셋만 보입니다. 검토 준비가 승인으로 자동으로 넘어가는 경로는 만들지 않았습니다.
4. 실제로 만든 것 — 기능 세 개와, 그 기능이 막는 실패
부품은 여러 개지만 일을 하는 것은 세 개입니다. 기능 이름만 적으면 자랑이 되니 그 기능이 없었을 때 실제로 났던 일을 짝으로 적습니다.
① 원본을 해시에 묶었다 — 원문이 바뀌어도 파생물이 남아 있던 것을 막는다
자막은 다시 받으면 달라 질 수 있습니다. 자동 자막은 특히 그렇습니다. 예전 방식에서는 원문을 다시 받아도 앞서 만든 요약이 그대로 남아 있었고, 그러면 그 요약이 존재하지 않는 원문을 가리키는 상태가 됩니다.
지금은 파생 데이터 전부가 원문의 SHA-256에 묶여 있습니다. 원문이 바뀌면 해시가 달라지고, 해시가 다르면 검사에서 걸립니다. 그리고 원본은 덮어쓰지 않습니다 — 바뀐 원문은 새 기록이 되고 옛 기록은 남습니다.
② 기계 검사를 의미 검토보다 먼저 돌린다 — 모델이 자기 산출물을 채점하던 것을 막는다
처음에는 순서를 반대로 뒀습니다. 모델에게 요약을 만들게 하고, 같은 모델에게 "이거 맞아?"를 물었습니다. 통과율이 아주 좋았습니다. 당연합니다. 만든 쪽이 채점했으니까요.
지금은 기계가 먼저 봅니다. 사람이 판단할 여지가 없는 것만 검사합니다 — 필수 파일이 있는가, 해시가 맞는가, ID가 중복인가, 인용문이 그 시각 구간 안의 연속된 원문인가, 참조가 실제로 존재하는가 같은 것들입니다. 실제 검사 이름은 H01_REQUIRED_FILES부터 H14_EXTRACTOR_IDENTITY까지 14종입니다.
기계 검사가 전건 통과한 뒤에야 다른 모델이 의미를 봅니다. 그 모델에는 쓰기 권한을 주지 않았고, 판단 근거로 시각이 붙은 원문을 같이 넘깁니다. 기억으로 판단하지 못하게 만드는 장치입니다.
14번째 검사는 나중에 추가한 것인데, 이게 실제로 사고를 막았습니다. 오프라인 테스트용 임시 추출기의 결과가 정식 결과처럼 섞여 들어올 수 있는 경로가 있었습니다. 임시 추출기는 의미를 이해하지 못하고 규칙만으로 뽑기 때문에, 그 결과가 정식으로 집계되면 품질 통계가 조용히 오염됩니다. 지금은 추출기 정체를 확인해서 차단합니다.
③ 승인은 사람만 한다 — "안정" 딱지가 저절로 붙던 것을 막는다
가장 짧은 규칙이 가장 셌습니다. status: stable과 verified: human:*은 어떤 코드도 자동으로 만들 수 없습니다. 기계 검사가 통과하고 다른 모델도 통과시켜도, 사람이 직접 승인 명령을 실행하지 않으면 정본이 되지 않습니다.
그리고 승인 뒤에 묶음이 바뀌면 그 리뷰는 낡은 것으로 처리하고 검증을 다시 요구합니다. 승인 시점과 파일 상태가 어긋나는 것을 막기 위한 것입니다.
5. 지금까지 관찰된 결과 (실측 · 명령을 같이 적습니다)
숫자를 만들지 않기 위해, 아래는 전부 실행 출력입니다.
scripts 폴더 *.py 계수schemas 폴더 *.json 계수subskills 하위 SKILL.md 계수profiles 하위 파일 계수python -m pytest -q 실행, 종료코드 0정본 0건은 세 가지로 확인했습니다. 정본을 모으는 폴더가 아직 생성되지 않았고, 승격 산출물이 0건이며, 워크스페이스 전체에서 status: stable 문자열을 가진 파일이 0건입니다. 하나만 봤으면 "아직 안 만들어졌나" 정도로 넘어갔을 텐데, 세 개가 같은 답을 주니 확정할 수 있었습니다.
그리고 묶음 19개 중 17개가 한 편에 몰려 있습니다. 이 편중이 이 프로젝트의 실제 이야기입니다. 같은 강연 하나를 17번 다시 만들었다는 뜻이고, 그동안 통과하지 못했다는 뜻입니다. 앞선 BEFORE 편이 그 17번의 기록입니다.
인용 검증에는 값을 두 개 남깁니다. 대표 강연 한 편에서 원문과 글자 그대로 일치한 인용은 1건, 공백·구두점 정규화를 허용한 뒤 일치한 인용은 41건 전부입니다. 두 값을 함께 남기는 이유는, 41/41만 적으면 "완벽하게 일치했다"로 읽히기 때문입니다. 실제로는 대부분 자막의 공백·구두점 차이를 안고 있습니다. 이 차이를 숨기지 않는 것이 이 시스템의 성격입니다.
6. 따라 해보고 싶으시면 — 가장 작은 형태부터
전체를 만들 필요는 없습니다. 되짚을 수 있게 만드는 것만 가져가면 됩니다. 도구는 무엇이든 좋고, 폴더와 규칙 세 줄로 시작할 수 있습니다.
1) 폴더를 두 칸으로 나눕니다.
sources/ 원본 (한 번 넣으면 고치지 않는다)
work/ 원본에서 만든 것 (얼마든지 다시 만든다)이 구분 하나가 절반입니다. 원본과 파생물을 섞어두면 무엇이 근거인지가 사라집니다.
2) 규칙 세 줄을 파일로 적습니다. 머릿속에 두지 말고 파일에 둡니다.
1. 주장 하나에는 원문 인용과 그 인용이 나온 시각 구간을 함께 적는다.
2. 인용은 원문에서 그대로 가져오고, 요약을 인용 자리에 넣지 않는다.
3. 원문을 다시 받았으면 새 기록으로 남기고, 이전 기록을 덮어쓰지 않는다.3) 검사 한 개를 붙입니다. 이게 시작점으로 가장 중요합니다.
인용문을 원문에서 문자열로 찾아보고, 못 찾으면 그 항목을 통과시키지 않는다.
검사 하나로도 효과가 큽니다. 요약이 슬쩍 표현을 바꾼 경우가 여기서 걸립니다. 그리고 이 검사는 사람 판단이 들어가지 않아서 매번 같은 답을 줍니다.
4) 만든 쪽과 채점하는 쪽을 나눕니다. 같은 대화창에서 "이제 검수 모드로 봐줘"는 검수가 아닙니다. 새 대화를 열고, 앞의 맥락 없이 산출물과 원문만 주고 물어보시는 것으로 충분합니다.
5) 마지막 승인은 직접 하십시오. 통과 표시가 다 떠도, 정본으로 올릴지는 사람이 정합니다.
7. 판정은 네 가지로 나누십시오 (두 가지로는 부족합니다)
이 부분이 실제로 가장 크게 도움이 됐습니다. 통과/차단만 두면 판정하지 못한 것이 통과로 집계됩니다.
PASSPASS_WITH_NOTEHOLDFAIL중지 조건도 미리 정해두면 좋습니다. 저는 이렇게 정했습니다 — 파일이 없거나, 형식이 깨졌거나, 검사가 0개 돌았거나, 상태가 애매하거나, 도구가 실패하면 그 자리에서 멈춥니다. 특히 "검사가 0개 돌았다"를 통과로 읽지 않는 것이 중요했습니다. 아무것도 검사하지 않은 것과 전부 통과한 것은 출력이 비슷하게 보입니다.
8. 한계와 대가 (얻은 것 옆에 잃은 것)
아직 안 된 것부터 적습니다.
지금 막고 있는 것 하나를 밝혀둡니다. 기존에 만들어둔 리뷰 문서들은 옛 형식으로 저장돼 있어서, 지금의 검증기로 보면 형식 오류가 납니다. 그래서 예전 리뷰를 그대로 승인 경로에 재사용할 수 없습니다. 다음 작업은 새 형식으로 다시 검증하고 리뷰를 다시 받는 것이고, 그 결과가 통과여도 마지막 승인은 사람이 합니다.
대가도 적습니다. 이 설계는 공짜가 아니었습니다.
- 느립니다. 강연 한 편을 넣는 데 다섯 단계를 지나야 하고, 중간에 막히면 앞으로 돌아갑니다. 그냥 요약을 뽑는 것보다 훨씬 오래 걸립니다.
- 한 편에 17번을 썼습니다. 게이트를 세게 잡은 대가입니다. 게이트를 풀면 빨라지지만, 그러면 애초에 만든 이유가 사라집니다.
- 범위를 좁혔습니다. 인문 분야의 학습 정리, 한국어 자막이 있는 공개 강연만 받습니다. 넓히면 검사 규칙이 흔들리기 때문에 일부러 좁게 뒀습니다. 넓히는 것은 정본 1건이 나온 뒤로 미뤘습니다.
버린 설계도 적어둡니다. 이게 없으면 왜 지금 모양인지 설명이 안 됩니다.
- 게이트를 완화하는 안을 버렸습니다. 원문 인용이 없는 종류의 지식(여러 강연을 이어 붙인 통찰 같은 것)을 넣으려면 "모든 주장은 인용을 가져야 한다"를 풀어야 했습니다. 풀지 않고, 근거의 종류가 다른 계층을 옆에 새로 만드는 쪽을 택했습니다. 자세한 것은 AFTER 편에 있습니다.
- 역할과 모델을 한 필드에 적던 방식을 버렸습니다. 예전에는 검토자 이름에 모델명을 붙여 한 문자열로 저장했습니다. 그러면 모델을 바꿀 때 역할 이름까지 바뀌어 이력이 끊깁니다. 지금은 역할과 실제 호출 모델을 따로 적습니다.
- 오프라인 임시 추출기를 정식 경로로 허용하던 것을 버렸습니다. 편해서 남겨뒀는데, 그게 통계를 오염시킬 수 있는 경로였습니다. 14번째 검사가 이걸 막습니다.
9. 결론 — 가져가실 규칙 세 개
이 작업에서 실제로 값이 있었던 것은 기능 개수가 아니라 무엇을 자동으로 하지 않기로 정했는가였습니다.
첫째, 원본과 파생물을 폴더 단위로 분리하십시오. 이것만 해도 나중에 근거를 되짚을 수 있습니다. 도구가 없어도 됩니다.
둘째, 검사 하나를 사람 판단 없이 돌아가게 만드십시오. 인용을 원문에서 문자열로 찾는 검사 하나가, 사람이 열 번 훑는 것보다 안정적으로 같은 답을 줍니다. 그리고 그 검사가 실제로 무언가를 거부하는지 일부러 틀린 항목을 넣어 확인해 보십시오. 거부한 적이 없는 검사는 검사가 아닙니다.
셋째, 마지막 승인을 자동화하지 마십시오. 여기까지 만들어놓고 마지막 한 칸을 자동으로 채우면, 앞의 모든 검사가 통과 도장 찍는 절차가 됩니다.
그리고 이 글의 상태를 다시 적어둡니다. 검증 엔진과 운영 청사진은 갖췄고, 첫 정본 승격으로 뒷부분을 증명해야 하는 상태입니다. 다음 편은 그 승격이 되든 안 되든 결과를 적겠습니다. 안 되면 안 된 이유를 적습니다.
10. 참고
- 같은 시리즈: BEFORE 편(게이트를 한 번도 통과하지 못한 기록) · AFTER 편(게이트를 풀지 않고 계층을 분리한 기록)
- 이 글의 수치 출처: 저장소 파일 계수 ·
python -m pytest -q실행 출력 · 워크스페이스 파일 계수 (모두 2026-08-05) - 설계에 참고한 것: 문서를 네 종류로 나누는 Diátaxis, 결정 기록을 맥락·결정·결과(양면) 로 남기는 ADR, 아키텍처를 상세도 층으로 나눠 설명하는 C4 모델