증상 — 새 재료는 3건 쌓였는데 글은 0편이었다
회사 기술 블로그의 글감은 사람이 고르지 않는다. 매일 정해진 시각에 도는 자동 작업이 회사 안의 작업 기록과 코드 변경 이력을 훑어 후보를 모으고, 후보마다 점수를 매겨 그날의 한 편을 고른다. 여기에 재료 창구를 하나 더 붙였다. 개인 프로젝트 기록만 보던 파이프라인에, 그동안 쌓인 업무 자산의 변화를 읽는 창구를 하나 더 연결했다.
연결한 뒤 수집 결과를 열어 보면 새 창구의 이름이 분포에 떠 있었다. 후보도 3건 쌓여 있었다. 그런데 그 축에서 나온 글은 한 편도 없었다. 하루 이틀이 아니라 계속 0편이었다.
라이브에 올라간 9편을 전수로 다시 읽어 보니 전부 다른 축에서 나온 글이었다. 승인 절차를 4개로 줄인 기록, 작업 중간 점검 간격을 2시간에서 30분으로 당긴 기록, 병렬 작업에서 기록이 사라지던 12건을 0건으로 만든 기록처럼, 개발 도구를 다듬은 이야기가 자리를 다 차지하고 있었다.
이상한 조합이었다. 창구는 연결돼 있고 후보도 있는데 산출물만 0이다. 둘 중 하나는 거짓말을 하고 있었다.
처음 의심한 것 — 재료가 모자라서 품질 관문에 걸린다고 봤다
가장 먼저 세운 가설은 재료 부족이었다. 파이프라인 마지막에는 품질 관문이 있다. 본문에 수치가 몇 개 들어갔는지, 날짜가 붙어 있는지, 원문이 충분히 긴지를 기계가 세고, 하나라도 미달이면 그날 초안을 버린다.
새 창구가 내놓는 재료는 업무 성과 문단이다. 한 문단이 300자에서 500자 사이로 짧다. 반면 기존 기록 파일의 항목은 한 건이 그 몇 배다. 짧은 재료가 관문의 길이 조건과 수치 조건을 못 넘어 매번 탈락한다 — 여기까지는 앞뒤가 맞는 이야기였다.
이 가설이 맞다면 처방은 간단하다. 재료를 더 길게 쓰거나 관문 기준을 낮추면 된다. 실제로 기준을 낮추자는 안이 먼저 나왔다. 다행히 그 전에 탈락 사유를 직접 세어 봤다.
그 가설은 무엇으로 확인했나?
확인에 쓴 수단은 세 가지다. 첫째, 수집기가 남기는 후보 분포. 어느 창구에서 후보가 몇 건 들어왔는지 보여 준다. 둘째, 품질 관문의 탈락 사유별 집계. 수치 미달인지 날짜 미달인지 길이 미달인지를 항목별로 센다. 셋째, 이미 발행한 9편의 주제 분포를 손으로 다시 분류한 표다.
첫째 수단은 창구가 살아 있다고 말했다. 후보 3건이 실제로 적립돼 있었고 분포에도 이름이 떴다. 둘째 수단이 가설을 흔들었다. 20건을 관문에 통과시켜 보니 6건만 통과했는데, 탈락 사유가 수치 부족이 아니라 대부분 날짜 0이었다.
가장 아까운 탈락이 이거였다. 평점 4.0에서 4.7로 올리고 시도율을 2.44배로 끌어올린 작업 — 수치만 9개가 들어 있는, 개선기 유형으로 쓰기에 최상급 재료다. 이게 날짜 0으로 떨어졌다.
알리바이 — 재료는 충분했고 표기만 어긋나 있었다
날짜 0의 원인은 표기 형식이었다. 원본 문서가 기간을 (2020~2022), (2026) 같은 괄호 형태로 적는데, 관문의 날짜 검사기는 2020년처럼 년이 붙은 형태만 날짜로 읽는다. 사람 눈에는 둘 다 연도지만 기계 눈에는 한쪽만 연도다.
그래서 관문을 푸는 대신 표기를 맞췄다. 재료를 만드는 쪽이 기간: 2020년 ~ 2022년 한 줄을 같이 내놓게 하자, 같은 20건이 20건 전부 통과했다. 통과율이 6건에서 20건으로 올라갔지 기준을 낮추지는 않았다.
여기서 첫 가설이 죽었다. 재료는 부족하지 않았다. 오히려 수치 밀도로는 기존 축보다 높은 재료였고, 걸린 자리는 연도를 적는 방식 하나였다. 검사기를 의심하다 재료가 원인이었던 반대 방향 사례도 있었는데, 이번에는 재료도 검사기도 아닌 둘 사이의 표기 약속이 어긋나 있었다.

다만 관문을 통과했다고 글이 바로 나오지는 않았다. 통과한 재료가 그날의 한 편으로 뽑히려면 점수 경쟁을 먼저 이겨야 하고, 뽑힌 뒤에는 원문을 열어야 한다. 이 두 관문에 각각 다른 결함이 하나씩 숨어 있었다.
진짜 원인 ① — 적립한 경로를 아무도 열 수 없었다
후보를 적립하는 쪽은 재료의 위치를 파일 경로와 식별자 조합으로 적는다. 그런데 새 창구는 그 위치를 파이썬 스크립트 파일 안의 함수 이름으로 적었다. 재료를 꺼내 읽는 쪽은 그 경로를 받아 마크다운 문서에서 해당 제목 줄을 찾는 코드다.
파이썬 파일에는 마크다운 제목 줄이 없다. 그래서 시작 위치를 못 찾고, 파일 이름도 폴더 이름도 식별자와 안 맞아 결국 빈 문자열을 돌려준다. 화면에 남는 흔적은 원문을 못 열었다는 한 줄뿐이다.
이게 뜻하는 바가 고약하다. 설령 점수 경쟁을 이기고 그날의 한 편으로 뽑혔더라도, 그 자리에서 바로 닫혔다. 즉 후보 3건은 처음부터 글이 될 수 없는 상태로 쌓여 있었다.
근본 원인은 코드 한 줄이 아니라 계약의 부재다. 재료를 적립하는 쪽과 여는 쪽이 같은 경로 형식을 쓴다는 약속이 어디에도 검사로 남아 있지 않았다. 양쪽 다 각자의 규칙 안에서는 정상 동작이었고, 그래서 어느 쪽 로그에도 오류가 안 찍혔다.
진짜 원인 ② — 길이 점수 30점이 짧은 축을 영원히 굶겼다
두 번째 결함은 순서를 정하는 점수에 있었다. 점수 계산에는 본문 길이 항목이 있고, 250자당 1점씩 최대 30점을 준다. 짧고 밀도 높은 재료에게는 이 항목이 구조적으로 불리하다.
업무 성과 문단은 300자에서 500자라 이 항목에서 1점이나 2점을 받는다. 반면 기존 기록 파일의 상위 후보는 총점이 126점에서 128점이다. 매일 최고점 한 건을 뽑는 규칙 아래에서 이 격차는 순위 문제가 아니라 영구 탈락이다.

여기서 원칙 하나를 잘못 쓰고 있었다는 점이 드러났다. 점수는 같은 축 안에서 순서를 정하는 도구다. 축과 축 사이에 몇 편씩 배분할지를 정하는 도구가 아니다. 그런데 축 사이에도 같은 점수를 그대로 쓰고 있었고, 결과가 라이브 9편 전원 한 축 쏠림이었다.
한 축이 0편이라는 진단도 정확하지 않았다
수리 중에 자체 진단 하나가 더 깨졌다. 업무를 다룬 글이 0편이라고 적어 뒀는데, 9편을 전수로 다시 분류하니 뭉뚱그린 표현이었다.

AI 에이전트 운영이 6편, 검색 노출 진단이 1편, 코드 이력 위생이 1편, 테스트 도구 디버깅이 1편이다. 도구를 만든 층은 이미 6편 있었고, 비어 있던 자리는 어떤 업무를 AI로 다시 짜서 무엇이 얼마나 줄었는지를 다룬 사례였다.
이 구분이 중요한 이유는 구조적 원인이 거기 있기 때문이다. 글감이 코드 변경 이력과 규칙 문서, 결정 기록에서만 나오는데, 그 재료는 도구를 만든 기록이지 업무를 바꾼 기록이 아니다. 회사 업무 자산은 회수해 둔 사본 10개에 코드 변경 이력이 없어서, 채굴기 시야에 애초에 안 들어온다.
읽는 사람 쪽에서 보면 차이는 더 크다. 도구를 다듬은 6편의 독자는 개발자다. 중소기업 대표가 검색창에 치는 말은 사례 쪽에 가깝다.
고친 방법 — 새 파서 없이 기존 부품으로 돌렸다
수리는 세 갈래로 했고, 셋 다 기존 부품을 그대로 쓰는 쪽을 골랐다.
- 재료를 실체 파일로 낸다. 자산 변화 수집기가 마크다운 문서를 직접 만들고, 각 재료를 두 번째 단계 제목으로 나눈다. 기존 파서가 그대로 열고, 인접 재료를 붙이는 코드도 같은 파일에서 동작한다. 새 파서를 안 만들었다는 점이 이 수리의 핵심이다.
- 굶은 축에 차례를 준다. 최근 5편에 한 번도 안 나온 축이 후보를 갖고 있으면, 최고점 후보를 제치고 그날의 차례를 받는다. 점수는 축 안의 순서에만 쓰고 축 사이 배분은 따로 정한다는 원칙을 코드로 옮겼다.
- 재료가 지목한 문서를 같이 연다. 재료 본문이 실재하는 문서를 이름으로 가리키고 있으면 그 문서를 대조용 자료에 함께 붙인다.
세 번째가 없으면 나머지 둘이 소용없다. 업무 성과 재료는 원문이 400자라, 인접 재료까지 다 붙여도 657자다. 초안 생성의 대조 자료 하한이 6,600자이므로 구조적으로 못 넘는다. 지목한 문서까지 여니 자료 분량이 1만 1천자에서 2만 3천자 사이로 올라갔다.
제목 한 단계를 낮추는 우회는 왜 답이 아니었나?
재료 파일을 만들면서 부수 함정을 하나 밟았다. 이 파일 안에서 두 번째 단계 제목은 재료와 재료를 가르는 경계다. 그래서 한 재료 안에 소제목을 넣으려고 세 번째 단계로 한 칸 낮춰 봤다.
결과는 더 나빴다. 경계를 찾는 규칙이 첫 번째부터 세 번째 단계 제목을 전부 경계로 보기 때문에, 원문이 55자에서 잘렸다. 한 단계 낮추는 우회는 문제를 반으로 줄인 게 아니라 그대로 남겨 뒀다.

답은 제목 기호를 아예 안 쓰는 쪽이었다. 소제목 자리를 굵은 글씨로 바꾸자 810자가 한 재료로 온전히 붙었고, 축 이름표까지 붙인 뒤에는 대조 자료가 21,200자로 늘었다.
같은 실수를 막는 장치 — 완결 판정을 산출물 개수로 바꿨다
이번 일의 교훈은 한 줄로 정리한다. 소스가 배선돼 있다는 말은 그 소스가 산출물에 도달한다는 말이 아니다.
배선의 완결 판정은 적립 개수가 아니라 그 축에서 실제로 나온 산출물 개수여야 한다.
우리는 수집 분포에 새 창구 이름이 뜨는 것만 보고 배선을 완료로 셀 수 있었다. 실제로 그렇게 셌고, 그 사이 후보 3건은 열 수 없는 경로를 달고 쌓여만 있었다. 화면에 이름이 떴다는 사실이 가장 그럴듯한 오답이었다.
그래서 판정 기준을 바꿨다. 창구를 하나 연결하면 며칠 안에 그 축에서 글이 몇 편 나왔는지를 센다. 0이면 배선은 아직 안 끝난 것으로 본다. 적립 건수는 중간 지표일 뿐 완료 신호가 아니다.
값이 안 변하는 것도 신호로 올린다
같은 파이프라인의 다른 층에서 비슷한 일이 하루 뒤에 또 나왔다. 업무 자산의 변화량을 세는 숫자가 2026년 8월 21일부터 9월 4일까지 15일 내내 59로 완전히 똑같았다. 같은 기간 개인 자산은 5,608에서 6,920으로 1,312 늘었다.
수집 자체는 멀쩡했다. 9월 4일 아침 회수 작업이 파일 19,905개를 가져왔고, 회사 작업 기록 1,177건과 하위 파일 249건이 최근 날짜로 갱신돼 있었다. 스냅샷을 남기는 자동 작업도 매일 07시 55분에 정확히 돌았다.
원인은 중복 제거 규칙이었다. 같은 저장소가 이름 뒤에 다른 꼬리표를 달고 여러 벌 회수돼 3중으로 세어지던 문제를 2026년 8월 21일에 고쳤는데, 그때 규칙을 원본만 센다로 잡았다. 그런데 실제로는 원본 쪽이 죽어 있었다 — 원본은 2026년 6월 29일에 멈춘 59커밋짜리였고, 살아 있는 작업은 사본 쪽 98커밋에 있었다. 중복 제거가 정확히 반대로 골랐다.
대표를 고르는 기준을 커밋이 가장 많은 것으로 바꾸자 회사 커밋이 59에서 93으로, 저장소 수가 19에서 14로 정리됐다. 문제는 이 15일 동안 아무도 몰랐다는 사실이다. 자동 작업은 매일 실패 없이 돌았고 파일도 매일 쌓였다. 도는 것과 재는 것은 다른데, 값이 안 변하는 것 자체를 보는 눈이 없었다.
그래서 감시기를 두 축으로 새로 붙였다. 회사 커밋 수가 4일 연속 같은 값이면 경고를 올리고, 제출 문서를 갱신한 뒤 쌓인 커밋 갭이 500을 넘거나 21일이 지나면 또 경고를 올린다. 두 번째 축은 붙이자마자 발화했다 — 제출 문서가 11일째 그대로인데 그 사이 커밋이 1,105 늘었다는 신호였다.
여기에도 함정이 하나 있었다. 처음에는 최근 스냅샷 8개만 읽게 만들었는데, 비교 기준일이 그 창 밖이라 기준 스냅샷을 못 찾고 신호가 조용히 사라졌다. 기간을 비교하는 감시기는 비교 기준이 창 안에 있는지부터 확인해야 한다. 감시기가 정상이라고 말하는 것과 정상인 것은 다른 사례에서도 갈렸다.
정체는 실패처럼 보이지 않는다. 실패는 로그에 남지만 어제와 같음은 아무 데도 안 남는다. 매일 도는 계측일수록 값이 안 변하는 것 자체를 신호로 올려야 한다.
자동화 파이프라인을 세워 두고도 산출물이 안 나오는 상황을 겪고 있다면, 어느 단계에서 조용히 닫히는지부터 세어 보길 권한다. 비슷한 진단이나 업무 자동화 설계가 필요하면 상담으로 알려 주시면 된다.