
내 상품의 설명문을 기계로 검산했더니, 모든 오류가 '과소 표기'로 나타났다
요약
상품 설명문과 실제 콘텐츠 간의 불일치를 Claude Code를 활용해 자동 검증한 사례를 다룹니다. 과소 표기 오류가 발생하는 구조적 원인을 분석하고, 정규표현식의 엄격도 조절을 통한 탐지 최적화 과정을 설명합니다.
핵심 포인트
- 상품 설명문과 실제 내용의 불일치는 구조적으로 '과소 표기' 방향으로 발생함
- Claude Code를 활용해 텍스트 추출 및 Bigram 기반 유사도 검증 수행
- 정규표현식의 엄격도(Precision/Recall) 조절을 통한 탐지 오류 관리 필요
- 검사 결과가 0건일 경우, 실제 오류가 없는 것인지 탐지 실패인지 반드시 확인해야 함
내가 판매하고 있는 기술서의 「무료로 읽을 수 있는 미리보기」를, 처음으로 구매자의 눈으로 다시 읽어보았다.
링크가 끊어지지 않았는지, 배포가 제대로 되고 있는지——그런 점검은 몇 번이고 해왔다.
하지만 「거기에 적혀 있는 내용이 사실인가」를 확인해 본 적은 단 한 번도 없었다.
다시 읽어보니, 적혀 있는 내용과 실제 내용이 다른 부분이 차례차례 나타났다. 세어보니 17곳이었다.
그리고 불일치의 방향이 전부 같았다.
가장 심각했던 것은 이것이다. 무료 장의 「다음 장 이후에서 해결하는 고통」이라는 표에 다음과 같이 적혀 있었다.
제5장: 「3시간의 세션이 후반부에 엉망이 되었다」 → 컨텍스트 열화의 탐지와 자동 리커버리 (Automatic Recovery)
실제 제5장은 「파일 소실로부터 5분 만에 복구하는 메커니즘」이었다. 완전히 다른 이야기다.
게다가 전 100장을 통틀어 「열화」, 「품질이 저하」 등의 단어를 대입해 보아도, 그 고통을 다루는 장은 찾을 수 없었다.
즉, 가지고 있지 않은 내용을 구매를 결정하는 단계에서 약속하고 있었다.
그 외에도 이런 것들이 나왔다.
| 적혀 있던 수 | 실제 내용 |
|---|---|
| 동봉된 example hook는 667개 | 909개 |
| ... | ... |
멈춰버린 카운트다운이 특히 심했다. 독자는 지금 페이지를 열어 「남은 기간 18일」을 읽는다.
마감 기한은 거의 2개월 전에 지났다.
667 대 909. 30 대 34. 57만 대 61만. 7 대 9.
과장은 단 한 건도 없었다. 전부가 과소 신고였다.
이것은 우연이 아니라 구조적인 문제라고 생각한다. 과하게 적으면 산 사람이 화를 낸다. 적게 적어도 아무도 화를 내지 않는다.
그래서 과대한 주장은 자연스럽게 도태되고, 과소한 주장만이 계속 남는다.
책은 매달 장(Chapter)이 늘어나는데, 설명문은 작성한 날 그대로 멈춰 있다. 아무도 불평하지 않으므로,
스스로 세어보지 않는 한, 영구적으로 남는다.
이하는 Claude Code(나의 자율 루프)에게 직접 시킨 검사다. 절차는 다른 상품에도 그대로 사용할 수 있다.
본문 중에서 「제N장: ~」라고 적힌 부분을 전부 추출하여, 그 설명이 실제 제N장의 제목과
얼마나 겹치는지 측정한다. 일본어이므로 2글자씩 나누어 집합의 중첩을 확인했다.
def bigrams(s):
s = re.sub(r'[\s、。「」『』()()・::—\-→+\d]', '', s)
return set(s[i:i+2] for i in range(len(s) - 1))
...
중첩이 0이었던 1건이 위의 「제5장」이었다.
이 부분이 이번에 가장 큰 배움이 되었다.
장 수의 불일치를 찾는 식을 느슨하게 작성하면 182건이 나왔다. 내용을 보니 대부분이
「제3장까지 무료」(무료 범위에 대한 이야기)나 「제10~12장에 있음」(장의 범위 지정)이었으며,
장의 총수에 대한 이야기가 아니었다. 위양성 (False Positive)이 지배적이었다.
그래서 식을 엄격하게 조였더니 4건까지 줄었다. 하지만 이번에는 진짜 오류를 놓치고 있었다.
# 너무 느슨함: 「제3장까지 무료」도 「제56장에서 다룸」도 잡아냄
COUNT = re.compile(r'(\d{1,3})\s*章')
# 너무 엄격함: 「21장으로, ...」와 같은 실제 총수 신고를 놓침
...
결국 어떻게 했는가. 중간 정도의 너비로 22건을 뽑아낸 뒤, 눈으로 분류했다.
자동 탐지 식은 찾고 있는 대상이 아니라 「그 식이 잡아낼 수 있는 형태」만을 잡아낸다.
그리고 식을 엄격하게 조였을 때의 오류는 「놓치는」 방향이기에 조용하며, 알아차릴 수 없다.
「0건입니다」라는 결과는, 실제로 없을 때와, 찾지 못했을 때 양쪽 모두에서 나온다.
그래서 검사가 0건을 반환했을 때는 반드시 세 가지를 확인했다.
- 모집단이 비어 있지 않은가 (올바른 형태의 기술이 몇 건 있는지 센다)
- 식이 심어놓은 오류를 잡아낼 수 있는가 (일부러 틀린 문자열을 만들어 맞혀본다)
- 절대 존재하지 않는 것으로 인해 실패하는가
세 번째가 효과적이었던 예를 들겠다. CLI의 옵션이 실재하는지 확인할 때, 다음과 같이 쓰고 싶어진다.
claude --some-option --version # → 버전 정보가 나옴 = 실재하는가?
이것은 아무것도 측정하지 못하고 있다. --version이 미지의 옵션 검사보다 먼저 처리되어 종료되기 때문이다.
절대 존재하지 않는 이름을 같은 형태로 흘려보내도, 그것 또한 「통과」한다.
timeout 20 claude --zzz-definitely-not-real </dev/null
# → error: unknown option '--zzz-definitely-not-real' ← 대조군이 실패함
timeout 20 claude --max-turns 1 </dev/null
...
대조군이 실패하지 않는 시험은, 아무것도 측정하지 못하고 있는 것이다.
같은 밤에 또 한 번 당했다. 다른 게시 사이트의 기사를 세어보니 딱 120개에서 멈췄다.
너무 딱 떨어지는 숫자다. 다른 경로로 총수를 확인하니 141개였다.
while page <= 20: # ← 20페이지 × 6개 = 120개에서 딱 끊겨 있었다
딱 떨어지는 숫자가 나오면, 우선 자신의 계산 방식의 상한선을 의심한다.
이미 공개된 기사 11개가 이 책을 「26장」이라고 쓰고 있었다 (실물은 34장).
처음에는 26을 34로 고칠 생각이었다. 하지만 이 책은 매달 장(Chapter)이 늘어난다.
다음에 장을 추가한 날, 또다시 11개가 동시에 낡은 정보가 된다.
그래서 수정 방식을 바꿨다. 총수에 대한 언급 자체를 없앤다.
「26장으로 정리」 → 「체계적으로 정리」. 한 번 고쳐두면, 이후 얼마나 늘어나도 올바른 상태를 유지한다.
성장하는 것의 분량을, 외부 면에 고정된 숫자로 적지 않는다.
적어도 되는 것은 늘어나지 않는 수(가격, 무료로 읽을 수 있는 범위)뿐이다.
하룻밤 사이에 6번, 같은 형태의 실수를 반복했다.
- 6월의 정정 사항을 배포했을 때, 같은 주장을 담은 다른 책의 제1장을 놓쳤다
- 판매 문구를 수정했을 때, 같은 숫자를 적고 있는 무료 장을 놓쳤다
- 무료 장을 수정했을 때, 판매 문구에 남은 나머지 3권을 놓쳤다
- 상품을 수정했을 때, 그 상품을 소개하고 있는 기사를 세지 않았다
- README를 수정한 직후, 그 README가 안내하고 있는 배포 페이지 211장이 남아 있었다
- 기사 측에서 몇 주 동안이나 수정해 온 동일한 안내가, 내가 배포하는 도구의 README에는 손대지 않은 채 남아 있었다
정정 사항을 배포할 때는, 그 주장을 담고 있는 면을 횡단하여 모두 센 다음에 배포한다.
「수정했다」고 생각했을 때 남아 있는 것은, 대개 내가 그때 보지 못했던 면이다.
이 기사의 바탕이 된 수정 사항 중에서, 나는 「Kindle 버전은 당시의 전 44장 그대로」라고 쓰고 공개했다.
44는 다른 판본의 장 수였으며, Kindle 버전의 내용을 확인해서 얻은 숫자가 아니었다.
2시간 뒤에 자신의 작업 기록을 다시 읽고 깨달아, 단정적인 표현을 삭제했다.
「확인하지 않은 숫자를 단정하지 마라」라고 고치고 다니는 와중에, 똑같은 패턴에 미끄러졌다.
검산의 대상에 자신의 시정(Correction) 문구도 포함해 두는 것이 좋다.
이러한 「조용히 틀린 채로 계속 움직이는」 형태의 사고를, 실제로 일어난 사례로부터 역산하여
증상으로부터 유추할 수 있는 형태로 정리한 책이 있다. 제3장까지 무료로 읽을 수 있다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기