watermarks-remover
AI 티를 지우는 도구를 검사 게이트 점검용으로 열었습니다. 그런데 AI를 잡으라고 만든 지표가, 사람이 쓴 제 글을 먼저 잡았습니다. 그래서 긴 글 전용으로 좁혀서만 넣었습니다(2026-09-29).
AI가 만든 파일에 남는 「AI가 만들었다는 흔적」을 지워 주는 도구입니다. 저는 지우려고 연 게 아니라 제 검사 장치를 점검하려고 열었습니다. 그런데 AI를 잡으라고 만든 잣대가, 사람이 쓴 제 글을 먼저 잡았습니다.
먼저 — 「AI가 만들었다는 흔적」이 뭔가요
AI로 글이나 그림을 만들면, 결과물에 「이건 AI가 만들었습니다」라는 표시가 몰래 들어갑니다. 세 가지 방식이 있습니다.
| 방식 | 비유하면 |
|---|---|
| 눈에 안 보이는 글자 | 글 사이에 폭이 0인 유령 글자를 섞어 넣음 |
| 단어 고르는 습관에 심기 | 만들 때부터 특정 패턴이 나오게 확률을 살짝 비틂 |
| 파일 안에 이름표 | 사진 파일 구석에 「누가 언제 만들었다」를 적어 둠 |
이 도구는 그 셋을 찾아서 지웁니다. 만들어진 지 11일 만에 「좋아요」가 16,619개 붙었습니다.
저는 지우려고 연 게 아닙니다
오해가 없게 적어 둡니다. 제가 이걸 연 이유는 제 사이트를 배포하기 전에 돌리는 검사 장치를 점검하려는 것이었습니다. 두 가지가 궁금했습니다.
- 제 검사 장치에 새는 곳이 있나
- 제가 규칙으로만 적어 두고 검사기는 안 만든 항목이 하나 있는데, 그걸 기계가 잴 수 있나
결론부터 말하면 도구는 전면 기각이고, 궁금증 두 개 중 하나는 풀렸고, 예상 못 한 게 하나 나왔습니다.
잘 만든 부분 — 「모를 때 어떻게 하는가」가 좋았습니다
이 도구에서 값나가는 부분은 지우는 코드가 아니라 모르는 상황을 다루는 태도였습니다. 넷을 적어 둡니다.
하나 — 모르는 파일은 건드리지 않고 죽습니다. 예전엔 정체를 모르면 「일단 글이겠지」 하고 처리했습니다. 지금은 아무것도 안 쓰고 오류를 내며 종료합니다. 잘못 건드려서 파일을 망가뜨리느니 멈추는 쪽을 고른 것입니다.
둘 — 같은 글자라도 앞뒤를 보고 다르게 처리합니다. 유령 글자 중에는 정상적으로 쓰이는 것도 있습니다. 이모지를 이어 붙일 때 쓰는 글자가 그렇습니다. 그래서 「이 글자는 무조건 삭제」가 아니라 「이모지 사이에 있으면 살린다」처럼 자리를 봅니다.
특히 인상적인 주석이 하나 있었습니다 — 「분류만 보고 지우면 갓 만들어진 진짜 글자를 파괴한다.」 실제로 그 사고를 겪고 고친 흔적이 남아 있었습니다.
셋 — 지운 뒤에 다시 검사합니다. 「지웠다」로 끝내지 않고 결과물을 다시 검사기에 넣어 봅니다. 그래서 「깨끗해짐」과 「지웠는데 아직 남아 있음」이 다른 결과로 나옵니다.
넷 — 자기 검사 결과를 스스로 못 믿습니다. 발견한 것을 네 등급으로 나누고, 그중 제일 거친 검사 방법은 스스로 최하 등급으로 내립니다. 주석에 이유가 적혀 있습니다 — 「검사기가 걸었다는 건 신호이지 판정이 아니다.」
제 자료에 돌려 봤더니 — 잡을 게 0건이었습니다
여기서 기각이 확정됐습니다. 이 도구의 검사기를 그대로 가져와 제 사이트 전량에 돌렸습니다.
| 무엇을 쟀나 | 결과 |
|---|---|
| 글 196편 + 완성된 웹페이지 238장 (6.1MB) | 0건 |
| 청소 기능을 돌려 보고 전후 비교 | 196편 전부 한 글자도 안 바뀜 |
| 발행한 이미지 14장 | 14장 전부 이름표 없음 |
즉 제 자료에는 애초에 지울 게 없었습니다. 도구가 나쁜 게 아니라 제게 해당되는 문제가 아니었던 것입니다.
→ 배운 것: 검출 도구를 들이기 전에 내 자료에 먼저 돌려 봐야 합니다. 좋다고 들여놨는데 잡을 게 0건이면, 그건 그냥 돌아가는 비용만 내는 장치입니다.
그런데 탐났던 잣대 하나를 제 글에 돌렸더니
이 편의 제목이 되는 자리입니다.
이 도구에는 「AI 냄새」를 점수로 매기는 기능이 따로 붙어 있습니다. 세 가지를 봅니다. 그중 제가 탐냈던 게 「문장 길이가 얼마나 들쭉날쭉한가」였습니다.
원리는 이렇습니다. 사람이 쓴 글은 문장 길이가 제멋대로입니다. 세 글자짜리 문장 다음에 마흔 글자짜리가 오기도 합니다. AI가 쓴 글은 길이가 고르게 정돈되는 경향이 있습니다.
제가 이걸 탐낸 이유는, 제 글쓰기 규칙에 「문장 리듬을 단조롭게 만들지 말 것」이 규칙으로만 있고 검사기가 없었기 때문입니다.
그래서 제 글에 돌려 봤습니다. 사람이 쓴 제 글이 잡혔습니다.
이게 도구가 고장 난 게 아닙니다. 문장 길이가 고르다는 것과 AI가 썼다는 것은 같은 게 아닌데, 이 잣대는 앞의 것만 잽니다. 정돈해서 쓴 사람 글은 그대로 걸립니다.
→ 잣대가 재는 것과, 그 잣대로 판정하려는 것이 같은지 먼저 봐야 합니다.
그래서 반쪽만 가져왔습니다
「문장 리듬」 항목은 가져왔는데 조건을 붙였습니다.
- 긴 글에만 씁니다. 문장이 몇 개 안 되면 들쭉날쭉을 잴 수가 없습니다
- 짧은 글용 기준은 안 만듭니다 — 제 짧은 글 표본으로 다시 재 보기 전까지는
- 「AI가 썼나」를 판정하는 데 안 씁니다. 제 글이 단조로워졌나 보는 데만 씁니다
(2026-09 점검) 이 반쪽도 점검 때는 만들지 않은 상태였습니다. 문장 리듬을 재는 검사기가 제 쪽에 없었습니다.
(2026-09-29) 이제 넣었습니다. 사이트를 배포하기 전에 도는 검사 줄에 «문장 리듬» 검사를 하나 더 세웠습니다. 긴 글의 문장 길이가 너무 고르면 배포가 멈춥니다. 위의 세 조건은 그대로 지켰습니다.
| 조건 | 이렇게 정했습니다 |
|---|---|
| 긴 글에만 | 문장이 20개 이상인 것만 잽니다 |
| 쉬운 설명과 자세한 기록 | 한 편 안에서도 따로 잽니다 — 쓴 때도 말투도 달라서 |
| 멈추는 선 | 들쭉날쭉한 정도가 0.35 아래 (8월에 쓴 선 그대로) |
처음 돌리자마자 두 편이 걸렸습니다. 둘 다 쉬운 설명 부분이었습니다. 쉽게 쓰려고 문장을 짧게 끊다 보니, 박자가 똑·똑·똑·똑 고르게 늘어선 것입니다. 걸린 문단만 내용은 그대로 두고, 이어지는 두세 문장을 한 문장으로 묶어 고쳤습니다.
그리고 8월에 쓴 계산기는 남아 있지 않았습니다. 새로 만든 계산기로 8월 글에 다시 돌려 보니 선 아래로 떨어지는 건 이번에도 짧은 페이지 두 편뿐이었습니다. 다만 점수 자체는 8월 숫자와 다르게 나옵니다 — 문장을 어디서 자르느냐에 따라 숫자가 흔들리기 때문입니다.
진짜 수확은 제 코드의 결함 하나였습니다
이 조사의 실제 산출은 남의 기법이 아니라 제 규칙 위반 한 건이었습니다.
제 전역 규칙 첫 줄이 이렇습니다 — 「애매하거나 실패하면 안 하는 쪽이 기본값.」 그리고 제 배포 검사 장치의 설명 주석에도 자기가 그렇게 동작한다고 적혀 있습니다.
그런데 실제 코드는 반대였습니다.
| 적혀 있던 것 | 실제 동작 | |
|---|---|---|
| 모르는 종류의 파일을 만나면 | 멈춘다 | 그냥 통과시킨다 |
검사할 파일을 고를 때 「아는 확장자만」 골랐습니다. 모르는 확장자는 검사 대상에서 조용히 빠집니다.
지금 당장 새는 건 0건입니다. 그런데 새로운 종류의 파일이 결과물에 하나 생기는 순간, 경고 한 줄 없이 무검사로 통과합니다. 그리고 그건 아무 화면에도 안 나타납니다.
(2026-09-28) 고쳤습니다. 점검해 보니 그때까지도 배포 검사는 아는 확장자 여덟 가지만 읽고 나머지는 건너뛰고 있었습니다. 9월에 AI용 마크다운 판 226장이 새로 생겼을 때 검사를 탄 것도, 마크다운이 마침 처음부터 목록에 있던 운이었습니다. 이제는 읽을 목록에도, 건너뛸 목록(그림 두 종류·빈 파일)에도 없는 파일이 나오면 배포가 멈춥니다. 모르는 확장자 파일 하나를 일부러 넣고 배포를 돌려, 올리기 전에 멈추는 것까지 확인했습니다.
덤 — 제 수집기가 원본이 아니라 복제본을 물어 왔습니다
마지막으로 하나 더 나왔습니다.
제가 만든 자동 수집기가 후보 목록에 이 도구를 올렸는데, 원본이 아니라 복제본이었습니다.
| 원본 | 복제본 | |
|---|---|---|
| 만든 날 | 8월 11일 | 8월 19일 (8일 뒤) |
| 좋아요 | 16,619 | 929 (3일 만에) |
| 설명문 | 1,120줄 | 1,063줄 중 1,058줄이 원본과 똑같음 |
복제본인데 「복제본」 표시가 안 붙어 있었습니다. 원본을 그대로 베껴서 새로 올린 것이라 시스템상으로는 별개의 물건으로 잡힙니다. 사람이 안 대 보면 못 가릅니다.
다시 열어 볼 조건
기각이지만 영원히는 아닙니다. 넷 중 하나가 생기면 다시 엽니다.
- 반년에 한 번 다시 훑을 때 표식이 처음으로 1건이라도 나올 때
- 한국어에서 검증된 탐지기가 나올 때 (지금은 검증 수단 자체가 없어 판정이 불가능합니다)
- 이 도구의 알려진 결함들이 고쳐져 새 판이 나올 때 — ⚠ 다만 도구가 고쳐져도 잡을 게 없으면 여전히 기각이라 1번부터 다시 잽니다
- 제가 이미지나 문서를 외부에 배포하는 일이 생길 때
여기부터는 자세한 기록입니다
지운 것은 하나도 없고, 대신 제 배포 스크립트가 제 규칙을 어기고 있는 걸 찾았습니다. watermarks-remover 는 AI 생성물에 박히는 프로버넌스 표식을 걷어내는 파이썬 엔진입니다. 11일 만에 별 16,619개. 제가 이걸 연 이유는 표식을 지우려는 게 아니라 제 발행 파이프라인의 검사 게이트를 점검하려는 것이었습니다 — 배포 전 마커 스캔이 새는 곳이 있나, 규칙으로만 있고 검사기가 0인 「균일한 문장 리듬」을 결정론 코드로 만들 수 있나. 도구는 전면 기각했습니다. 제 발행 코퍼스 6.1MB 를 이 레포의 스캐너로 훑으니 표식이 0건이었기 때문입니다. 그런데 유일하게 탐났던 지표 하나를 제 글에 돌렸을 때 제일 값비싼 사실이 나왔습니다 — AI 를 잡으라고 만든 지표가, 사람이 쓴 제 글을 먼저 잡았습니다.
무엇을 하는 물건인가 — 「확실한 것」과 「최선노력」을 리포트에서 합산하지 않는다
AI 가 만든 파일에서 「이건 AI 가 만들었다」는 증거를 걷어내는 엔진입니다. 증거를 세 종류로 봅니다. 눈에 안 보이는 유니코드로 심어진 캐리어, 생성 시 토큰 선택 확률을 비틀어 심는 통계 워터마크, 파일 안에 구조로 박히는 프로버넌스 메타데이터.
설계의 중심은 이 셋의 성격이 다르다는 걸 인정한 데 있습니다. 유니코드는 결정론 코드로 지우고 몇 개 지웠는지 세서 돌려줍니다. 파일 메타데이터도 지운 뒤 자기 출력물을 다시 스캔해 잔존을 신고합니다. 반면 통계 워터마크는 외부 LLM 에게 글을 다시 쓰게 하는 것 말고 방법이 없고, 그건 검산이 불가능합니다. 레포 방침이 이렇게 적혀 있습니다 — “리포트는 검증 가능한 작업과 최선노력 작업을 반드시 분리해야 한다.” 이 한 줄이 여기서 제일 값나가는 문장입니다.
| 항목 | 실측 (2026-08-22) |
|---|---|
| 규모 | 151 파일 · 약 1.13MB · 별 16,619 · 포크 1,902 |
| 엔진 / 테스트 | service/scripts 14,141 LOC · 테스트 41파일 10,592 LOC · def test_ 549개 |
| 의존성 | 런타임 0 (Python 3.10+ stdlib). dev 4종만 정확 핀 |
| 라이선스 | MIT — ⚠ 픽셀 계열 백엔드는 우산 밖(상류에 라이선스 없음 / 비상업 연구용) |
| 활동 | 08-11 생성 → 08-21 마지막 push. 활동 기간 11일, 커밋 141, 릴리스 5회 |
| 기여 분포 | 27명이지만 오너가 63/122 — 버스 팩터 1 |
11일짜리 스프린트입니다. 별 16,619개는 채택이 아니라 바이럴이고, 장기 유지보수 이력은 아직 없습니다. CI 는 3-OS 매트릭스에 lint·의존성 감사·OpenAPI 스펙 검증까지 걸려 있어 나이에 비해 단단해 보이는데, 뒤에서 그 단단함이 무엇을 못 잡는지가 나옵니다.
대표 기법 — 값이 나가는 건 지우는 코드가 아니라 「모를 때 어떻게 하는가」다
| 기법 | 내용 |
|---|---|
| fail-closed 라우팅 | 확장자에도 매직바이트에도 안 걸리는 입력은 예전엔 텍스트로 폴백했습니다. 지금은 파일을 쓰지 않고 종료코드 2로 죽습니다. “UTF-8 로 못 읽힌다” 만으로는 바이너리 판정을 하지 않아 다른 인코딩 텍스트는 살립니다 |
| 문맥 인지 스트립 | 같은 코드포인트라도 앞뒤를 보고 다르게 처리합니다 — ZWJ 는 이모지 사이에서만, 한글 필러는 같은 자모 뒤에서만 살립니다. 그리고 미할당 문자를 유니코드 카테고리로 잡지 않고 명시 레인지로만 잡습니다. 근거가 주석에 있습니다 — “Cn 규칙은 갓 할당된 진짜 문자를 파괴한다.” 실제로 그 사고를 겪고 사후 수리한 이력이 있습니다 |
| PDF 2단 파이프라인 | 메타데이터 제거 도구가 PDF 를 증분 갱신합니다 — 종료코드 0, 뷰어엔 안 보이는데 원본 바이트는 남고 되돌릴 수 있습니다. 유일한 단서가 “파일이 오히려 커진다”입니다. 그래서 뒤에 재직렬화를 한 단계 붙여 참조 잃은 객체를 실제로 떨굽니다 |
| 청소 후 재검사 | “지웠다” 로 끝내지 않고 산출물을 다시 검사에 태워 잔존을 돌려줍니다. 「청소 완료」와 「청소했지만 남았다」가 종료코드로 갈립니다 |
| 소견 신뢰도 4등급 | 모든 발견을 confirmed / probable / informational / likely_false_positive 로 매핑하고, 전체 바이트 스캔은 스스로 최하 등급으로 강등합니다 — “스캐너 히트는 신호이지 판정이 아니다.” |
| 도구 버전 프로브 | PATH 에 있다고 available 이라 하지 않고 실제로 --version 을 돌려 종료코드를 봅니다 — “which 하나로는 틀린 질문에 답하게 된다.” |
한 가지 더 있습니다 — 이 편의 주인공입니다. 워터마크가 아니라 「AI 냄새」를 통계로 채점하는 스코어러가 따로 붙어 있습니다. 세 항의 가중합입니다 — 상투구 사전 밀도 0.45, 문장 길이 변동계수 0.45, 어휘 다양도 0.10. 문장이 둘 미만이라 변동계수를 못 재면 그 항을 빼고 나머지로 재정규화합니다.
깨본 결과 — 지배적 실패는 오작동이 아니라 「거짓 무죄 판결」이다
확실히 지운다던 절반부터 흔들립니다. C2PA 2.x 표준에는 소프트 바인딩 해석 API 가 정식으로 들어가 있습니다. 파일에 박힌 매니페스트가 뜯겨도 비가시 워터마크나 지각 지문으로 원격 저장소를 조회해 프로버넌스를 되찾는 구조입니다. 이 레포가 지우는 것은 표준이 이미 「없어져도 되게」 설계해 둔 쪽이고, 레포도 소프트 바인딩은 범위 밖이라고 적습니다.
간판인 벤더 커버리지 네 칸 중 둘은 살아 있는 탐지 경로가 없습니다. Claude 의 표식은 공식 발표상 토큰 생성의 난수원을 바꾸는 통계 워터마크이지 유니코드 캐리어가 아닙니다. 즉 결정론적으로 검산되는 층은 그 표식을 아예 못 건드리고, 코드의 해당 탐지기는 로직 없는 예약 슬롯입니다. Gemini 칸은 레포가 스스로 사망 선고를 적어 뒀습니다 — 상류가 API 에서 텍스트 워터마킹을 철회했습니다.
효능 수치는 어디에도 없습니다. README 73,956바이트에 퍼센트 형태의 효능 수치가 0건, 벤치 폴더에 커밋된 실행 결과도 0건입니다. 그리고 오너 본인이 「결과를 낼 수 있게 만드는」 PR 을 두 번 올렸다가 두 번 미머지로 닫았습니다. 숫자가 아직 없는 게 아니라, 숫자를 낼 장치를 두 번 들였다가 두 번 물렀습니다.
반복 결함은 한 가지 모양입니다 — 못 지웠는데 깨끗하다고 인증합니다. 6일 만에 같은 모양의 이슈가 9건 열렸습니다. 잘린 오디오 태그를 소견 0건으로 보고하고 그 파일에 청결 인증을 찍고, 이미지 점수기가 죽었을 때와 워터마크가 없을 때가 똑같이 clean 으로 읽힙니다. 파싱 실패를 「없음」으로 접는 패턴이고, 사례별로 하나씩 잡고 있어 남은 포맷에서 또 나올 것으로 봐야 합니다. 그중 하나는 되돌릴 수 없습니다 — 제자리 수정을 두 번 돌리면 백업 파일을 청소본으로 덮어써 원본이 영구히 사라지는데, 같은 함수의 독스트링이 “원본은 절대 부분 손실되지 않는다” 고 약속하고 있습니다.
테스트 549개가 왜 이걸 못 잡느냐의 답이 트래커에 있습니다. “기여자들이 Claude 를 쓰는 건가요” 라는 질문에 오너가 그렇다고 답했습니다. 11일에 코드 14k + 테스트 10.6k LOC 입니다. 코드와 테스트가 같은 생성기의 같은 패스에서 나오면, 테스트는 생성기의 사각지대를 원리적으로 못 덮습니다. 커버리지 게이트 부재보다 이쪽이 본질입니다.
공정하게, 제 1차 판정 둘을 취소합니다. 광고된 동영상 경로가 파일을 손상시킨다던 이슈는 이미 고쳐져 있었습니다 — 삭제할 박스를 같은 크기의 0 채움 박스로 치환해 오프셋 테이블이 유효하게 남습니다. ⚠ 관련 문자열이 코드에 없다고 미수정으로 읽으면 오진합니다. 다른 하나는 이슈 제목의 SSRF 라는 이름을 그대로 옮긴 것이 과장이었습니다 — 엔드포인트가 공격자 입력이 아니라 운영자 환경변수라, 실제 결함은 내부망 피벗이 아니라 리다이렉트 시 인증 토큰과 본문이 새는 것입니다. 이슈 제목은 사실이 아니라 남의 판정입니다.
못 한 것. 이 레포의 벤치를 직접 못 돌렸습니다 — GPU 와 외부 체크아웃 4종이 필요하고 코퍼스 씨앗 8개가 전부 영어입니다. 그래서 “얼마나 지워지는가” 는 이 페이지에서도 미측정으로 남습니다. 워터마크가 실제로 박힌 파일에 대 본 적도 없습니다. 제 환경에 그런 파일이 없어서입니다.
내 환경에 대봤다 — 잡을 것이 0건이었다
레포 HEAD 의 스캐너를 그대로 임포트해 제 발행 코퍼스 전량에 돌렸습니다.
| 무엇을 쟀나 | 결과 |
|---|---|
| 보이지 않는 유니코드 — 문서 196편 + 정적 HTML 238장 + 원고 7편 (6.1MB) | 0건 |
| 청소 함수 라운드트립 — 같은 196편, 기본·파라노이드 양쪽 | 196/196 바이트 동일 = 순수 no-op |
| 발행 이미지 14장의 C2PA·AI 메타데이터 | 14/14 전부 없음 — 헤드리스 렌더 산출물이라 애초에 안 박힌다 |
| 로컬 뇌 파일까지 확대 (스킬 195편 + 메모리 180편) | 5파일에 7개 — 전부 발행 경로 밖, 조치 불필요 |
표적이 없었습니다. 훼손 위험 0이면서 동시에 변경 0이면, 그건 게이트가 아니라 장식입니다.
유일하게 탐났던 AI 냄새 스코어러는 한국어에서 절반이 죽습니다. 상투구 패턴 24개 중 비ASCII 가 0개라 가중치 0.45짜리 항이 영원히 0입니다. 같은 성격의 대조군을 두 언어로 만들어 채점하니 영어 0.887(HIGH) 대 한국어 0.438(LOW) — 임계 0.65 는 한국어가 도달할 수 없는 값입니다(이론 천장 약 0.55). 그래서 언어 중립인 한 항만 떼서 재봤습니다.
사이트 장문 98편은 중앙값 0.668 로 널찍하게 흩어져 있습니다. 임계 0.35 아래는 2편뿐이었고 둘 다 색인 성격의 짧은 페이지라, 1차에는 “오탐 2%” 로 적고 넘어갔습니다. 그런데 이 게이트를 실제로 걸려던 자리는 장문이 아니라 짧은 발행 원고였습니다. 그쪽 6편을 다시 재니 0.298~0.550 의 좁은 띠에 눌려 있었고, 그중 하나 — 제가 손으로 쓰고 게시까지 끝낸 글 — 이 0.298 로 임계 아래였습니다. 짧은 글은 사람이 써도 균일합니다. 이 지표가 재는 것은 「누가 썼나」가 아니라 「얼마나 길게 썼나」입니다.
수확 — 4종에서 1.5종으로
| 후보 | 판정 | 사유 |
|---|---|---|
| 문장 리듬 변동계수 한 항 | 채택(반쪽) | 결정론 리듬 검사기가 제게 정말 0건이 맞습니다. 다만 장문 전용이고, 짧은 채널 임계는 별도 코퍼스로 다시 재기 전까지 만들지 않습니다 |
| 가중합 3항 골격 + 결측 항 재정규화 | ⛔ 기각 | 3주 전에 제가 더 나은 형태로 만들어 뒀습니다 — 테스트케이스 파이프라인의 확신도 채점기에 규칙표·상한 클램프·선택 입력·임계 역산 스윕·기대표 잠금이 있고, “축이 다른 감점을 상쇄 금지” 같은 함정 수리가 주석에 박혀 있습니다 |
| fail-closed 파일 선택 | 원칙만 | 남에게 배울 기법이 아니라 제 준수 결함 1건이었습니다. 아래 |
| 보이지 않는 유니코드 검출 세트 | 조건부 보류 | 이득이 실측 0 이라 보험으로만 정당화됩니다. host 도 이미 있습니다 — 기존 링크 검사기가 dist 전량을 훑고 눈에 보이는 글자만 뽑는 루프를 돌립니다. 신규 파일이 아니라 그 안 세 줄입니다 |
세 번째 줄이 이 조사의 실제 산출입니다. 제 전역 규칙 첫 줄이 “애매하거나 실패하면 하지 않는 쪽이 기본값” 이고, 배포 게이트의 라이브러리 헤더 주석은 자기 자신을 fail-closed 라고 규정합니다. 그런데 그 게이트가 파일을 고르는 방식은 확장자 화이트리스트 — 아는 확장자만 검사하는 fail-open 입니다. 지금 실누락은 0건이지만, .mjs·.rss 같은 게 산출물에 생기는 순간 경고 한 줄 없이 무검사로 통과합니다.
⚠ 그리고 여기서 남의 구현은 들이지 않기로 했습니다. 레포는 매직바이트 28종 + NUL + 제어문자 비율로 판정하는데, 259 파일 규모에서 그 표는 유지보수 부채입니다. 같은 fail-closed 를 세 줄로 얻습니다 — 아는 목록 어디에도 없는 확장자가 나타나면 그냥 멈춥니다. 원칙은 채택, 구현은 기각.
(2026-09-28) 들어갔다. 점검 때까지 마커 스캔은 /\.(html|css|js|json|xml|txt|svg|md)$/i 에 안 맞으면 그냥 continue 였다 — 2026-09-17 에 마크다운 판 226장이 생겼을 때 스캔을 탄 것은 md 가 8월 배포 배선 때부터 목록에 있었기 때문이다. 이제 건너뛸 것도 목록으로 정한다(SKIP = /\.(webp|png)$/i — 그날 dist 의 비텍스트 종류 전부: 표지·게임 그림·공유 카드). 두 목록 어디에도 없는 종류가 크기 0 이 아니면 push 전에 멈춘다(빈 .nojekyll 은 샐 게 없어 통과). 틀린 표본(public/ 에 넣은 .rss 한 장)으로 실제 배포 경로를 돌려 스캔 단계에서 exit 1·push 없음을 확인했고, 표본을 빼고 다시 빌드하면 정상 dist 는 텍스트 517·건너뜀 20·모름 0 이다. 리듬 변동계수 한 항은 아직 어디에도 구현돼 있지 않다.
부수적으로 — 제 수집기는 원본이 아니라 복제본을 후보로 올렸습니다
후보 목록에 Leutenegger/watermarks-remover 가 올라와 있었습니다. 피드에 실린 것은 guillaumemeyer/watermarks-remover ★16,619 입니다. 둘은 다른 저장소입니다.
| 원본 | 복제본 | |
|---|---|---|
| 생성 | 2026-08-11 | 2026-08-19 (8일 뒤) |
| 별 | 16,619 | 929 (3일 만에) |
| 포크 플래그 | false | false — 깃허브 포크가 아니다 |
| README | 1,120줄 | 1,063줄 중 1,058줄이 원본과 일치 (99.5%) |
복제본 README 안에 원저자 저장소를 가리키는 링크가 15개 그대로 남아 있습니다 — CI 배지가 남의 저장소를 가리킵니다. 포크 관계만 끊긴 통짜 복사본입니다. 제 후보 다리는 별 수와 낱말 규칙만 보니 원본과 복제를 구분하지 못합니다. 별이 빠르게 붙는 건 도구가 좋다는 신호가 아니라 화제가 붙었다는 신호이고, 복제본은 그 화제만 빌려 가면 됩니다.
판정
| 항목 | 판정 |
|---|---|
| 레포·서비스·스킬·도커 도입 | ⛔ 기각. 파일 한 톨도 제 트리에 들이지 않습니다 |
| 파일 메타 / 이미지 / 문서 경로 | ⛔ 기각. 필요해지면 기성 도구를 직접 부릅니다 — 그쪽은 제자리 수정을 안 해서 원본 소실이 구조적으로 불가능합니다 |
| 수확 | 1.5종 — 리듬 변동계수 한 항(장문 전용) + fail-closed 준수 복구 |
| 회사 파이프라인 반입 | ⛔ 부적절. 기술 판정과 별개입니다 |
(2026-09-28 기준) 수확 1.5종 중 fail-closed 는 들어갔고(위 절), 리듬 한 항은 아직 없다.
(2026-09-29) 리듬 한 항도 들어갔다 — 배포 게이트 check-rhythm.mjs. 문장마다 어절 수를 세고 변동계수(모표준편차 ÷ 평균)를 낸다. 문장은 마침표·물음표·느낌표 뒤에 띄어쓰기가 올 때와 줄 끝에서 자르고, 본문 글자만 센다 — 머리말·도판·코드·표·제목 줄은 뺀다. 표를 빼는 이유는 실측이다. 표·제목까지 문장으로 세면 표 한 장이 아주 긴 «문장» 하나가 되어, 쉬운 설명 층이 자세한 기록보다 오히려 들쭉날쭉하게 나온다(중앙값 0.872 대 0.682). 본문만 세면 반대다(0.484 대 0.537). 층(쉬운 설명·자세한 기록)은 따로 재고, 문장 20개 미만인 층은 안 잰다 — 전수 464층 중 ko 23·en 24층이고 거의 전부 색인·자리표시 페이지다. 15·20·25 어디에 두어도 걸리는 층이 같았다. 선은 0.35 그대로, ko·en 둘 다 건다.
⚠ 8월 계산기는 남아 있지 않다. 새 계산기로 같은 98편(이 편을 들인 커밋의 부모)을 다시 재면 선 아래는 역시 짧은 페이지 2편(11·13문장)이지만, 중앙값은 0.524 로 당시 0.668 과 다르다. 판정은 재현되고 숫자는 재현되지 않는다 — 옛 숫자와 새 숫자를 나란히 놓지 말 것.
첫 전수에서 선 아래 긴 층은 ko 쉬운 설명 2층이었다 — 「Loki › 기능」 0.334, 「(가칭) 무협 게임」 0.340. 게이트가 같이 찍는 «가장 평평한 곳»(7·8·8·7어절, 6·5·7·5어절)만 내용 그대로 박자를 바꿔 0.436·0.476 이 됐다. en 은 0층. 통과한 층 중 가장 고른 것이 0.354(en 쉬운 설명 한 층)라 여유는 크지 않다. --selftest 7/7 — 한 박자 25문장은 물고, 들쭉날쭉한 것은 안 물고, 10문장짜리는 안 재고, 표·제목·도판은 안 섞고, 0.35 같은 소수는 안 자르고, ko·en 경계 제목으로 층을 가른다. 고치기 전 두 편(HEAD 판)에 돌리면 exit 1 로 멈추는 것도 확인했다.
⚠ 쉬운 설명 층이 더 잘 걸린다 — 116편 중 91편에서 쉬운 설명 쪽 박자가 더 고르다. 짧게 끊어 쉽게 쓰는 습관과 이 게이트가 부딪히는 자리다. 고칠 때 긴 문장을 억지로 끼우지 않고, 이어지는 두세 문장을 한 문장으로 묶었다.
다시 여는 조건 넷 — ① 반기 1회 재스캔에서 표식이 처음으로 1건이라도 나올 때. ② 한국어에서 검증된 텍스트 워터마크 탐지기가 나올 때. 그 전까지 재작성 층은 검증 수단이 없어 판정 자체가 불가능합니다. ③ 데이터 손실·허위 clean 4종의 PR 이 머지되고 다음 릴리스가 나올 때. ⚠ 그때도 도구가 고쳐져도 표적이 없으면 여전히 기각이라 ①부터 다시 잽니다. ④ 이미지·PDF 를 외부에 배포하는 워크플로가 생길 때.
이 편에서 값을 치른 교훈은 도구가 아니라 순서입니다 — 검출기를 들이기 전에 자기 코퍼스로 오탐률부터 재라. 그것도 실제로 걸 자리의 코퍼스로 재야 합니다. 저는 사이트 장문에서 재고 「오탐 2%」라 적었는데, 그 규칙이 사는 채널로 옮겨 재니 1/6 이었고 걸린 것은 제가 쓴 글이었습니다.
그리고 하나 더. 별 16,619개짜리 레포를 뜯어서 남은 게 제 규칙 문서 한 줄을 제 배포 스크립트 한 줄이 어기고 있더라는 자기 대조 1건이었습니다. 남의 물건을 보는 값은 가져올 것에만 있지 않습니다 — 남의 원칙을 들고 제 코드를 보면, 제 원칙으로 볼 때는 안 보이던 것이 보입니다.