1. 시작은 "단계마다 잘했는데 결과를 못 믿겠다"였습니다</h2><p>일을 네 단계로 나눴다고 해봅시다. 모으고, 나누고, 검수하고, 내보냅니다. 각 단계를 맡은 사람은 자기 몫을 성실하게 합니다. 모으는 사람은 열심히 모으고, 나누는 사람은 받은 것을 열심히 나눕니다. 그런데 다 끝나고 나면 이상한 일이 생깁니다. <strong>어느 단계에서도 사고가 보고되지 않았는데, 결과를 자신 있게 인용하지 못합니다.</strong></p><p>이유는 단순합니다. 나누는 사람은 <strong>모은 것이 전부라고 믿고</strong> 나눴습니다. 검수하는 사람은 <strong>나눈 것이 원문을 보존했다고 믿고</strong> 검수했습니다. 내보내는 사람은 <strong>검수를 통과했다고 믿고</strong> 내보냈습니다. 각자는 정직했지만, 각자가 <strong>자기 앞의 것을 믿었을 뿐 재보지 않았습니다.</strong></p><p>여기서 무서운 것은 실패의 모양입니다. 앞 단계가 조용히 조금 틀리면, 뒤 단계는 그 틀린 것을 <strong>정교하게</strong> 처리합니다. 결과물은 형식이 완벽하고 숫자도 깔끔합니다. 그래서 티가 안 납니다. 틀린 입력 위에서 성실하게 일한 결과는, 아무 일도 안 한 결과보다 알아보기 어렵습니다.</p><h2>2. 그래서 이번에 정한 질문 하나</h2><p>"각 단계를 어떻게 더 잘하나"가 아니었습니다. 질문은 이것이었습니다.</p><blockquote><p><strong>무엇이 다음 단계로 넘어가도 되는가.</strong></p></blockquote><p>이 질문이 각 단계의 성능 문제를 <strong>연결의 문제</strong>로 바꿉니다. 한 단계의 산출물은 다음 단계의 <strong>전제</strong>가 됩니다. 그러면 그 전제가 참인지 확인할 책임이 어디 있느냐가 정해져야 합니다. 저는 이렇게 정했습니다 — <strong>전제를 물려받는 쪽이 다시 잰다.</strong> 앞 단계의 보고를 믿는 것이 아니라, 자기 손으로 한 번 더 잽니다.</p><h2>3. 사용한 개념과 도구 — 네 고리와, 고리 사이의 잠금장치</h2><p>밖에서 보면 이 시스템에 들어오는 것은 커뮤니티의 글과 댓글이고, 나가는 것은 사람이 열어 보는 표 한 개입니다. 그 사이가 네 고리입니다.</p><pre><code>수집 커뮤니티 원문 → 빠짐없이 가져온다 → 원본 기록 → 모집단이 전부인가
분류 원본 기록 → 유형·주제를 붙인다 → 분류 결과 → 입력 수 = 출력 수인가
검수 분류 결과 → 원문 보존을 대조한다 → 검수 보고 → 대조가 전수인가
발행 검수 통과분 → 밖으로 내보낸다 → 공개 결과 → 정말 보이는가</code></pre><p>오른쪽 칸이 이 설계의 전부입니다. 그것이 <strong>넘어가는 조건</strong>이고, 동시에 <strong>다음 고리가 물려받는 전제</strong>입니다. 같은 문장이 두 이름을 가진다는 것이 핵심입니다 — 앞 고리에는 "여기까지 해야 끝"이고, 뒤 고리에는 "여기서부터 시작해도 된다"입니다.</p><p>그리고 고리 사이에 규칙 하나를 못 박았습니다.</p><pre><code>앞 고리의 보고 < 뒤 고리의 재측정</code></pre><p>앞 고리가 "22,019건 다 넘겼습니다"라고 말해도, 뒤 고리는 자기가 받은 것을 세어 봅니다. 이것이 중복처럼 보이지만 중복이 아닙니다. 앞 고리의 계수는 <strong>보낸 것</strong>을 세고, 뒤 고리의 계수는 <strong>받은 것</strong>을 셉니다. 두 값이 같다는 확인이 곧 전달이 무사했다는 증거이고, 다르면 그 자리에서 멈춥니다.</p><h2>4. 실제로 지킨 규칙 세 개와, 그 규칙이 막는 실패</h2><p>기능 자랑이 되지 않도록, 규칙 옆에 <strong>그 규칙이 없었을 때 실제로 났던 일</strong>을 짝으로 적습니다. 사건의 자세한 내용은 각각 해당 편에 있으니 여기서는 각도만 적습니다.</p><h3>① 물려받은 전제를 자기 손으로 다시 잰다 — 앞 단계의 조용한 실패가 뒤 단계의 정교한 오답이 되는 것을 막는다</h3><p>분류 단계는 수집이 빠짐없다고 <strong>믿지 않고</strong>, 자기가 받은 줄 수를 셉니다. 검수 단계는 분류가 원문을 보존했다고 <strong>믿지 않고</strong>, 원문과 대조합니다. 이 재측정이 없으면 앞 단계의 누락이 뒤 단계에서 <strong>정상적으로 처리된 정상 데이터</strong>가 됩니다. 빠진 것은 비명을 지르지 않습니다. 그냥 조용히 없습니다.</p><p>여기서 한 가지를 더 배웠습니다. <strong>재측정은 방법이 달라야 합니다.</strong> 같은 계수기로 두 번 세는 것은 두 번 잰 것이 아니라 한 번 잰 것을 두 번 적은 것입니다. 실제로 줄 수만 세는 검사는 줄 수가 맞는데 글이 빠진 경우를 통과시켰습니다(07-INTEGRITY 편).</p><h3>② 넘어가는 조건을 산출물이 아니라 '검사 통과'로 적는다 — 파일이 있으면 됐다고 읽는 것을 막는다</h3><p>"분류 결과 파일이 생겼다"는 넘어가는 조건이 아닙니다. 조건은 "입력 수와 출력 수가 같다"처럼 <strong>참·거짓이 갈리는 문장</strong>이어야 합니다. 산출물의 존재를 통과로 읽으면, 덜 만들어진 파일과 잘못 만들어진 파일이 같은 칸에 들어갑니다.</p><p>이 구분이 특히 중요한 곳이 마지막 고리였습니다. 내보내는 쪽이 "성공"이라고 답했는데 실제로는 아무에게도 안 보이는 상태였던 적이 있습니다(14-PUBLISH 편). 그래서 발행의 넘어가는 조건은 "요청이 성공했다"가 아니라 <strong>"바깥에서 다시 읽어서 보였다"</strong>로 바꿨습니다. 보내는 쪽의 응답이 아니라 받는 쪽의 관측이 판정입니다.</p><h3>③ 자기 한계를 등급으로 함께 넘긴다 — 뒤 단계가 참고값을 사실로 쓰는 것을 막는다</h3><p>분류에는 잘 맞는 축과 덜 맞는 축이 있었습니다. 같은 40건을 두 번 독립으로 돌렸을 때 유형 판정은 35/40이 일치했고, 주제 판정은 24/40이 일치했습니다(05-CLASSIFY 편). 이때 선택지는 둘입니다. 덜 맞는 축을 <strong>빼거나</strong>, 등급을 달아 <strong>함께 넘기거나</strong>.</p><p>빼면 깔끔해지지만 정보가 사라집니다. 그래서 등급을 달아 넘겼고, 최종 산출물에서도 "유형은 신뢰, 주제는 참고값"이라는 표시가 파일 안 안내 시트까지 따라갔습니다 (16-CANON 편). <strong>한계를 함께 넘기지 않으면, 다음 사람은 그것을 한계가 없는 값으로 씁니다.</strong> 경고를 문서 밖에 적어두면 파일이 복사되는 순간 떨어져 나갑니다.</p><h2>5. 지금까지 관찰된 결과 (전부 기발행 값 · 출처를 같이 적습니다)</h2><p>⚠ 이 표에는 이 글을 위해 새로 잰 값이 <strong>없습니다.</strong> 전부 이미 공개한 편에 실린 값이고, 오른쪽 칸에 어느 편인지 적었습니다.</p><table><thead><tr><th>고리</th><th>관찰된 값</th><th>기발행 출처</th></tr></thead><tbody><tr><td>수집</td><td>글 22,019건 · 댓글 36,465건 · 수집 12.5분</td><td>04-COLLECT</td></tr><tr><td>수집</td><td>본문 0자 글 693건(빈 글 569 · 이미지 77 · 첨부 47)</td><td>04-COLLECT</td></tr><tr><td>분류</td><td>한 번에 40건이면 완주, 100건은 멈춤, 250건은 라벨이 무너짐</td><td>05-CLASSIFY</td></tr><tr><td>분류</td><td>유형 판정 일치 35/40 · 주제 판정 일치 24/40 (같은 40건 두 번 독립 실행)</td><td>05-CLASSIFY</td></tr><tr><td>검수</td><td>줄 수만 세는 검사가 통과시킨 유실 2건 · 무증상 탈락 6건</td><td>07-INTEGRITY</td></tr><tr><td>검수</td><td>최종 대조 입력 22,019 = 병합 22,019 · 완전일치 검사 551조각 결함 0</td><td>07-INTEGRITY</td></tr><tr><td>검수</td><td>검사 가시 범위 40% → 100%</td><td>09-INSPECT</td></tr><tr><td>발행</td><td>게시 11편 · 바깥에서 다시 읽어 전건 공개 확인 · 제목 일치 11/11</td><td>14-PUBLISH</td></tr><tr><td>산출</td><td>최종 표 1개 · 42.7MB · 6시트 (글 22,019행 × 17열 · 댓글 36,465행)</td><td>16-CANON</td></tr></tbody></table><p>이 표에서 제가 가장 오래 들여다본 줄은 <strong>수집의 693건</strong>입니다. 본문이 0자인 글이 693건 있었는데, 이것을 "수집 실패 693건"으로 적었다면 뒤의 모든 단계가 실패율을 안고 갔을 것입니다. 실제로는 빈 글·이미지만 있는 글·첨부만 있는 글이었습니다. <strong>형태를 실패로 잘못 적는 순간, 그 오해가 사슬 끝까지 갑니다.</strong> 첫 고리의 라벨 하나가 마지막 표의 해석을 바꿉니다.</p><p>그다음이 <strong>분류의 24/40</strong>입니다. 이 숫자를 감췄다면 최종 표를 받은 사람은 주제 열을 유형 열과 같은 무게로 읽었을 것입니다.</p><h2>6. 따라 해보고 싶으시면 — 가장 작은 형태부터</h2><p>단계가 두 개만 있어도 시작할 수 있습니다. 도구는 필요 없고, 문장 세 개면 됩니다.</p><p><strong>1) 두 단계 사이에 '넘어가는 조건' 한 줄을 적으십시오.</strong> 참·거짓이 갈리는 문장으로 적습니다. "결과 파일을 만든다"가 아니라 "입력 줄 수와 출력 줄 수가 같다"입니다.</p><p><strong>2) 뒤 단계가 그 조건을 자기 손으로 확인하게 하십시오.</strong> 앞 단계의 보고서를 읽는 것이 아니라, 받은 것을 직접 셉니다. 그리고 <strong>앞 단계와 다른 방법으로</strong> 셉니다.</p><p><strong>3) 못 재는 것을 목록으로 함께 넘기십시오.</strong> "이 값은 신뢰, 이 값은 참고" 두 줄이면 충분합니다. 등급이 없으면 받는 쪽은 전부 같은 무게로 씁니다.</p><p><strong>4) 되돌릴 수 없는 마지막 고리 앞에 사람을 두십시오.</strong> 앞의 모든 고리는 다시 돌릴 수 있지만, 밖으로 나간 것은 되돌릴 수 없습니다. 되돌릴 수 없는 단계에만 사람의 확인을 붙여도 대부분의 사고가 막힙니다.</p><h2>7. 판정은 네 가지로 나누십시오 (두 가지로는 부족합니다)</h2><p>고리 사이를 "통과/차단"으로만 보면, <strong>잴 수단이 없어서 못 정한 것</strong>이 통과로 집계됩니다.</p><pre><code>PASS 물려받은 전제를 다시 재서 일치했고, 넘어가는 조건도 통과했다
PASS_WITH_NOTE 통과했으나 등급이 있다 — 참고값이라는 표시를 달아서 넘긴다
HOLD 이 단계에는 그 전제를 잴 수단이 없다 — 넘기지 않고 멈춘다
FAIL 다시 잰 값이 앞 단계의 보고와 다르다</code></pre><p><code>HOLD</code>가 이 표의 핵심입니다. <strong>잴 수 없다는 것은 통과가 아닙니다.</strong> 잴 수단이 없는데 넘기면, 그 뒤로는 아무도 그것을 다시 묻지 않습니다. 판정하지 못한 것을 판정한 것처럼 적지 않는 칸이 하나 있어야 합니다.</p><h2>8. 한계와 대가 (얻은 것 옆에 잃은 것)</h2><p>이 사상은 공짜가 아니고, 만능도 아닙니다. <strong>못 막는 것부터 적습니다.</strong></p><p><strong>사슬은 첫 고리가 애초에 못 가져온 것을 영원히 모릅니다.</strong> 수집 단계가 어떤 글을 아예 못 봤다면, 뒤의 어느 고리도 그 부재를 관측하지 못합니다. 뒤 고리들은 전부 "받은 것"을 기준으로 재기 때문입니다. 없는 것은 세어지지 않습니다. 이 사각을 줄이려면 사슬 <strong>바깥의 다른 원천</strong>과 대조해야 하는데, 그것은 이 구조가 주는 보장이 아닙니다. 저는 이 글에서 그 대조까지 했다고 주장하지 않습니다.</p><p><strong>재측정이 같은 방법이면 같은 오류를 반복합니다.</strong> 두 번 재는 것과 다르게 재는 것은 다릅니다. 같은 계수기를 두 번 돌리면 그 계수기가 못 보는 결함은 두 번 다 안 보입니다. 그래서 뒤 고리의 재측정은 앞 고리와 <strong>다른 축</strong>이어야 하는데, 매번 다른 축을 찾는 것이 실제로는 가장 어려웠습니다.</p><p><strong>느립니다.</strong> 고리마다 다시 재므로 같은 데이터를 여러 번 훑습니다. 한 번에 쭉 흘려보내는 방식보다 확실히 오래 걸리고, 중간에 걸리면 앞으로 돌아갑니다. 이 비용을 내지 않으려면 넘어가는 조건을 느슨하게 해야 하는데, 그러면 애초에 사슬로 만든 이유가 사라집니다.</p><p><strong>등급을 달아 넘기는 것은 읽는 사람이 읽어야 작동합니다.</strong> 참고값 표시를 파일 안까지 배달해도, 표를 열자마자 데이터 칸으로 건너뛰는 사람에게는 닿지 않습니다. 형식의 한계 안에서의 타협이지 완전한 방어가 아닙니다.</p><p><strong>그리고 버린 설계도 적어둡니다.</strong> 처음에는 각 단계가 자기 검사만 잘하면 된다고 봤습니다. 단계별로는 전부 통과인데 전체 결과를 신뢰할 수 없는 상태를 겪고 버렸습니다. <strong>단계의 품질과 사슬의 품질은 다른 것</strong>이었습니다.</p><h2>9. 결론 — 가져가실 규칙 세 개</h2><p><strong>첫째, 파이프라인은 단계의 나열이 아니라 전제의 사슬입니다.</strong> 각 단계가 잘하는 것과 전체를 믿을 수 있는 것은 다른 문제입니다. 앞 단계의 산출물은 뒤 단계의 전제가 되고, 전제가 틀리면 뒤 단계는 <strong>정교하게 틀립니다.</strong> 성실한 작업이 오답을 더 알아보기 어렵게 만듭니다.</p><p><strong>둘째, 넘어가는 조건은 산출물이 아니라 검사 통과로 적으십시오.</strong> "만들었다"는 조건이 아닙니다. 참·거짓이 갈리는 문장이어야 하고, 그 문장을 <strong>물려받는 쪽이</strong> 자기 손으로, 앞 단계와 다른 방법으로 확인해야 합니다.</p><p><strong>셋째, 자기 한계는 감추지 말고 등급으로 함께 넘기십시오.</strong> 덜 맞는 값을 빼면 깔끔해지지만 정보가 사라지고, 그냥 넘기면 다음 사람이 그것을 사실로 씁니다. 값과 등급을 한 쌍으로 보내는 것이 유일하게 정직한 전달입니다.</p><h2>10. 참고</h2><p>전제를 물려받는 쪽이 확인한다는 발상은 계약 기반 설계(design by contract)의 선행조건·사후조건을 파이프라인 단계에 옮긴 형태입니다. 잴 수 없을 때 통과가 아니라 멈추는 쪽을 고르는 것은 안전 실패(fail-closed)의 흔한 형태이고, 등급을 산출물 안에 동봉하는 것은 이 시리즈의 산출물 관리 편에서 정한 규칙을 사슬 전체로 넓힌 것입니다. 각 고리의 사건 자체는 수집·분류·검수·발행 편에 각각 적혀 있고, 이 글은 그 편들을 잇는 선만 그렸습니다.</p>