공짜 SEO 감사 도구를 깔고 블로그 63편을 돌렸더니, 깨진 이미지 8건이 나왔습니다.
파일은 디스크에 멀쩡히 있었어요. 배포 설정에서 빠져 라이브에서만 404였던 겁니다. 갤러리가 onerror로 스스로 숨어버려서 깨진 티도 안 났고요. 눈으로도, 파일 존재 검사로도 못 찾던 것들이었습니다.
그것만으로 본전은 뽑았습니다. 그런데 계속 돌리다 보니 이상한 게 하나 보였어요. 우리 글 63편이 전부 84점을 넘기더군요.
파보니 원인이 정규식 한 줄이었습니다. 한국어를 아예 못 읽고 있었어요. 그래서 고쳤고, 고친 걸 이 글 아래에서 그대로 받아가실 수 있습니다.
먼저 — 뭘 썼는지부터
claude-seo는 Claude Code 안에서 도는 SEO 스킬팩입니다. GitHub 별 1만 5천 개, MIT 라이선스, 무료.
명령어 하나를 치면 스킬 25개와 전문 에이전트 18개가 병렬로 사이트를 훑고, 뭘 먼저 고쳐야 하는지 순서까지 정리해 줍니다.
git clone --depth 1 https://github.com/AgriciDaniel/claude-seo
bash claude-seo/install.sh
윈도우는 powershell -ExecutionPolicy Bypass -File claude-seo\install.ps1입니다. Python 격리 런타임과 Chromium까지 알아서 깔리고, 저는 1분쯤 걸렸습니다.
유료 SEO 도구는 월 $99부터 시작합니다. 내 사이트를 훑는 일에 한해서는 이제 돈을 낼 이유가 없어진 셈이에요. 백링크나 키워드 볼륨 같은 남의 데이터가 필요하면 그건 여전히 유료 API를 붙여야 하지만, 그건 다른 얘기입니다.
이런 소식, 남들보다 먼저 받으실 분?
직접 돌려보고 되는 것만 골라 매주 보내드립니다. 광고성 하이프는 거릅니다.
그런데 점수가 이상했습니다
claude-seo는 Claude Code 안에서 도는 SEO 분석 스킬팩입니다. 스킬 25개, 전문 에이전트 18개. MIT 라이선스에 무료고 관리도 활발합니다.
이 글은 도구를 깎아내리려는 게 아닙니다. 한국어로 쓰는 사람에게만 해당되는 함정이 하나 있고, 그게 조용해서 위험하다는 얘기입니다. 고치고 나면 그냥 좋은 도구예요.
원인은 정규식 한 줄입니다
scripts/content_quality.py 144번 줄._TOKEN_RE = re.compile(r"[A-Za-z][A-Za-z'\-]*")
A–Z, a–z만 잡습니다. 한국어·일본어·중국어·아랍어·러시아어·태국어는 전부 토큰 0개가 됩니다.
"한국어에서 정확도가 떨어진다"가 아닙니다. 구조적으로 못 읽습니다. 그리고 오류를 내지 않습니다. 조용히 점수만 돌려줍니다.
같은 내용을 두 언어로 넣어봤습니다
AI가 쓴 티가 나는 문단을 하나 만들어서, 같은 내용을 영어와 한국어로 각각 넣었습니다.
| 영어 | 한국어 | |
|---|---|---|
| 종합 점수 | 41 | 65 |
| AI 패턴 탐지 | 90 (잡아냄) | 0 |
| 단어 수 | 106 | 0 |
| 경고 | ai-patterns 외 2건 | 2건 |
영어판은 in conclusion, moreover, game-changing 같은 상투구를 정확히 집어냈습니다. 한국어판은 단어를 한 개도 못 셌습니다.
우리 글 8쌍으로 확인했습니다
대조군은 제가 만든 문장이니 믿기 어려울 수 있습니다. 그래서 실제 글로 다시 했습니다.
저희 블로그에는 같은 슬러그로 한국어판과 영문판이 있는 글이 8편 있습니다. 같은 필자, 같은 템플릿, 같은 내용. 언어만 다릅니다. 마크업 영향을 빼려고 본문 텍스트만 뽑아서 쟀습니다.
| 평균 점수 | 토큰 합계 | 글자 합계 | |
|---|---|---|---|
| 한국어판 | 86.6 | 644 | 25,076 |
| 영문판 | 78.8 | 6,231 | 37,042 |
8쌍 전부 한국어판이 높았습니다. 예외가 없습니다.
글자당 인식률로 보면 이렇습니다.
한국어 644 토큰 / 25,076 자 = 0.026
영어 6,231 토큰 / 37,042 자 = 0.168 → 영어가 6.5배
여기서 영어의 0.168이 정상값이라는 게 중요합니다. 영단어 평균이 4.7자에 공백 1자를 더해 약 5.7자니까 0.175 근처가 나와야 맞습니다. 계산이 들어맞아요.
즉 도구가 고장 난 게 아니라, 영어에서는 제대로 작동하고 한국어만 안 되는 겁니다. 이 대조가 없으면 "그냥 부실한 도구"로 오해하기 쉽습니다.
왜 낮아지지 않고 높아지나
보통은 못 읽으면 점수가 낮게 나올 거라고 생각합니다. 반대인 이유는 점수 계산식에 있습니다.
overall = (100 - 군더더기) × 0.25
+ (100 - AI패턴) × 0.25
+ 정보밀도 × 100 × 0.25
+ (100 - 반복) × 0.15
+ min(100, 토큰수/10) × 0.10
토큰이 14개일 때 무슨 일이 벌어지는지 따라가 보면요.
- 군더더기·AI패턴·반복 — 걸릴 단어가 없으니 전부 0. 앞의 세 항이 만점에 가깝게 지급됩니다
- 정보밀도 — 분모가 토큰 수입니다. 분모가 14이니 오히려 부풀려집니다
- 길이 보너스 — 여기만 비어 있는 걸 반영하는데, 가중치가 0.10뿐입니다
합치면 85~90점. 관측된 값과 정확히 맞습니다. 비어 있는 게 감점이 아니라 가점으로 작동합니다.
덤 — HTML로 넣으면 더 심해집니다
이 도구는 HTML 파일도 받습니다. 그런데 HTML에는 CSS 클래스명과 태그가 잔뜩 들어 있고, 그건 전부 알파벳입니다.
| 입력 | 토큰 | 점수 | 경고 |
|---|---|---|---|
| 본문 한국어만 (3,364자) | 145 | 89 | thin-content |
| HTML 파일 통째로 | 1,684 | 91 | 없음 |
차이 1,539개(91%)가 CSS 클래스명과 태그입니다. 그 마크업 노이즈가 토큰 수를 300 넘게 부풀려서 "내용이 부실하다"는 경고를 지워버립니다.
그래서 고쳤습니다
문제를 찾았으니 패치를 만들었습니다. 세 가지를 고쳤어요.
- 토크나이저에 한글·가나·한자·키릴 추가
- 조사 절삭 —
클로드는·클로드를·클로드가를클로드하나로 묶습니다. 안 묶으면 반복 계산이 어긋납니다 - 한국어 어구 목록 — AI 상투구 41개, 군더더기 26개
| 패치 전 | 패치 후 | |
|---|---|---|
| 영어 슬롭 | 41점 | 41점 (불변) |
| 한국어 슬롭 | 65점 | 39점 |
| 한국어 토큰 (8쌍 합계) | 644 | 5,763 |
| 한국어 평균 점수 (8쌍) | 86.6 | 74.4 |
한국어 슬롭 39점이 영어 슬롭 41점과 거의 같아졌습니다. 같은 내용이면 같은 점수가 나오는 게 정상이죠.
영어 결과가 41점 그대로인 것도 중요합니다. 잘 되던 걸 망가뜨리지 않았다는 증거니까요. 실제 글에서 잘못 잡는 경우(오탐)도 없었습니다.
안 고친 것과 못 고친 것
중간에 실수를 하나 했습니다. 한글에는 대문자가 없어서 고유명사를 못 잡길래, "반복 등장하는 낱말"을 고유명사로 세는 코드를 넣었어요. 돌려보니 반복이 특징인 슬롭 글이 오히려 밀도 만점을 받았습니다. 정반대로 작동해서 걷어냈습니다.
정보밀도는 원본 그대로 뒀습니다. 애초에 문제는 분모가 14였던 거고, 토크나이저를 고치면 자동으로 풀립니다.
남은 한계도 적어둡니다.
조사 절삭이 형태소 분석이 아니라 규칙 기반입니다. 나는의 는처럼 조사가 아닌 걸 뗄 수 있어요. 정확히 하려면 Kiwi나 KoNLPy가 필요한데 설치 부담이 커서 넣지 않았습니다.
어구 목록은 제 글투 기준으로 고른 것입니다. ko-patterns.json을 열어서 본인 글에 맞게 고치세요. 그러라고 JSON으로 뺐습니다.
한국어만의 문제가 아닙니다
정규식이 ASCII만 받으니 일본어·중국어·아랍어·러시아어·태국어 사용자도 똑같은 점수를 받습니다. 별 1만 5천 개짜리 도구가 비영어권 전체에 무의미한 숫자를 주고 있는 셈입니다.
그래서 원저자에게 보낼 이슈와 수정 PR을 준비해뒀습니다. 업스트림에 제안한 건 모든 언어에 통하는 최소 수정입니다.
# 기존
_TOKEN_RE = re.compile(r"[A-Za-z][A-Za-z'\-]*")
# 제안
_TOKEN_RE = re.compile(r"[^\W\d_][\w'\-]*", re.UNICODE)
영문 산문 8편으로 확인해보니 5편은 토큰이 완전히 동일했고, 나머지 3편의 차이는 기존 정규식이 잘라먹던 것들이었습니다(MP4를 MP로, v24를 v로). 오히려 고쳐진 쪽입니다.
병합되면 이 패치에서 토크나이저 부분은 빼고 한국어 어구 목록만 남기면 됩니다.
배운 것
이 버그가 위험한 건 조용해서입니다. 오류가 났으면 바로 알았을 텐데, 그럴듯한 숫자를 돌려주니 몇 달을 그냥 믿게 됩니다.
점수가 하나 나오는 도구를 쓸 때는 답을 아는 입력을 한 번 넣어보는 게 좋습니다. 일부러 못 쓴 글을 넣어서 낮게 나오는지 보는 거죠. 그 한 번이 이걸 잡아냅니다.
같은 이유로 저희는 확인 가능한 것들을 스크립트로 옮겨두는 편입니다. Claude에게 기억을 붙인 기록도 같은 생각에서 나온 작업이었습니다.