당신의 검증기는 한도를 넘는 것만 막습니까, 아니면 한도에 얼마나 못 미치는지도 셉니까?
저는 앞의 것만 하고 있었습니다. 몇 달 동안 초록불이었고, 그 초록불이 제 앱 46개의 검색 노출 면적을 3분의 1로 묶어 두고 있었습니다.
하려던 일
스토어에는 검색어를 직접 넣는 필드가 하나 있습니다. 한도는 100입니다. 앱 46개의 검색 노출을 늘려 보려고, 우선 그 필드를 얼마나 채우고 있는지부터 세기로 했습니다.
로케일 슬롯 678개를 세니 평균 채움이 72였습니다. 그런데 분포가 이상했습니다.
en-* 96
ko 53
ja 52
zh-Hans 44영어권만 한도에 붙어 있고 나머지는 절반쯤에서 멈춰 있었습니다. 처음엔 자연스럽게 읽었습니다 — 번역가가 짧게 쓴 거겠지, 그 언어는 낱말이 짧으니까.
당신이라면 이 분포를 어떻게 읽으시겠습니까
여기서 갈림길이 있습니다. "번역가가 짧게 썼다"로 읽으면 다음 작업은 낱말을 더 채워 넣는 일입니다. 46개 앱 × 여러 로케일에 손번역을 더 붓는 일이 됩니다.
저는 다른 걸 먼저 물었습니다. 왜 하필 비라틴만 짧은가. 언어가 짧은 거라면 한국어와 일본어와 중국어가 비슷하게 짧은 건 설명이 되는데, 그 셋이 거의 정확히 3분의 1 근처에 몰려 있는 건 언어로 설명이 안 됩니다.
진짜 원인
한도는 100자인데, 제 검증기가 100바이트로 재고 있었습니다.
라틴 문자는 UTF-8에서 한 글자가 1바이트입니다. 그래서 영어권은 아무 문제가 없었습니다. 한글·일본어·중국어는 한 글자가 3바이트입니다. 검증기가 "100바이트 초과"에서 자르면 비라틴 로케일은 실한도의 3분의 1 지점에서 잘립니다. 33자쯤에서 더 못 넣게 되니, 사람이 그 앞에서 멈춘 것처럼 보였던 겁니다.
증거는 깔끔했습니다.
- 라이브 678슬롯 중 100바이트를 넘는 것: 216건
- 100자를 넘는 것: 0건
아무도 진짜 한도를 넘긴 적이 없습니다. 216개 슬롯은 존재하지 않는 한도에 막혀 있었습니다.
비어 있던 총량은 23,089자였습니다. 이건 번역 비용이 드는 면적이 아닙니다. 이미 그 언어로 서비스하는 앱들이고, 그 시장에서 검색될 낱말을 넣을 자리가 비어 있었을 뿐입니다.
고친 형태
# 틀림 — 한도의 단위를 바꿔 버린다
if len(keywords.encode("utf-8")) > 100:
keywords = truncate(keywords)
# 맞음
if len(keywords) > 100:
raise ValueError("키워드 한도 초과")그리고 한 줄을 더 넣었습니다. 이게 실제 교훈입니다.
남은_면적 = max(0, 100 - len(keywords))넘치는 것만 막는 검사기는 비어 있는 것을 영원히 못 봅니다. 통과 신호는 "한도를 지켰다"만 말해 주고, "한도의 3분의 1에서 멈췄다"는 절대 말해 주지 않습니다.
감사 결과
| 항목 | 값 |
|---|---|
| 로케일 슬롯 | 678 |
| 평균 채움(전) | 72자 |
| 평균 채움(후) | 90자 |
| 100바이트 초과 | 216건 |
| 100자 초과 | 0건 |
| 비어 있던 총량 | 23,089자 |
같은 감사에서 결함 넷을 더 잡았습니다. 전각 쉼표로 낱말을 구분해 문자열 전체가 한 단어로 색인되던 슬롯, 제3자 상표가 들어간 슬롯(정책 위반), 포지셔닝이 바뀌었는데 옛 낱말이 남아 새 낱말을 밀어내던 슬롯, 그리고 남의 앱 키워드가 들어간 슬롯.
이 감사는 세 층으로 이어졌습니다. 키워드 다음은 본문이었고(스토어 설명에서 아포스트로피까지 빠져 있었습니다), 그다음은 부제였습니다(부제 36칸이 영어 원문 그대로였습니다). 세 필드 다 같은 종류의 구멍이 있었습니다.
자가진단 3줄
- 당신의 길이 검사는 무슨 단위로 셉니까?
len(s)인지len(s.encode())인지 지금 열어서 보세요. 다국어를 다루는데 후자면 비라틴 사용자만 조용히 손해를 보고 있습니다. - 검사기가 "미달"을 셉니까? 상한만 보는 검사기는 하한이 0인 것과 같습니다. 채움률을 한 줄 찍는 것만으로 이런 게 드러납니다.
- "통과했다"를 몇 달째 안 의심하고 있습니까? 통과하는 검사기는 질문을 멈추게 합니다. 그게 이 버그가 오래 산 진짜 이유입니다.
솔직한 부분
채움을 늘린 것이 실제로 노출을 늘렸는지는 아직 모릅니다. 스토어 검색 순위는 즉시 반영되지 않고, 이 배치가 심사를 통과한 뒤 최소 2주는 지나야 비교할 수 있습니다. 지금 말할 수 있는 건 면적이 늘었다는 것뿐입니다.
채운 낱말이 좋은 낱말인지도 별개 문제입니다. 자리를 채우는 것과 맞는 검색어를 고르는 것은 다른 일이고, 이 글은 앞의 것만 다룹니다. 그리고 총량 숫자에 속기 쉽다는 것도 같은 주에 배웠습니다 — 51만 자가 비어 있다고 적어 두고 기준을 바꾸니 1만 9천 자였던 일이 바로 다음에 나왔습니다.
지금 다국어 필드를 다루는 코드가 있으시다면, encode 를 한 번만 grep 해 보세요. 거기 걸리는 게 있으면 그건 검증기가 아니라 상한입니다.