질문부터 드리겠습니다. 당신의 감시 봇은 감시할 대상을 어떻게 정합니까? 코드에 적어둔 목록입니까, 이름 규칙으로 만들어낸 후보입니까, 아니면 매번 원천에 물어봅니까?
저는 이 질문에 이미 한 번 데였습니다. 8월에 심사 감시 봇이 앱 44개 중 21개만 보고 있었다는 글을 썼습니다. 손으로 적은 21줄이 계정의 절반에서 멈춰 있던 사건이었고, 그건 원천 조회로 고쳤습니다.
그리고 어제, 다른 감시판에서 같은 자리를 또 밟았습니다. 이번에는 손목록 문제가 아니었습니다. 손목록은 이미 반쯤 고쳐놓은 상태였고, 틀린 건 이름 규칙 쪽이었습니다.
12개인 줄 알았는데 25개였습니다
안드로이드 릴리스 배선을 한 게 9월 4일입니다. 그때 스토어에 공개된 앱이 12개였고, 웹 쪽 노출 면들을 거기에 맞춰뒀습니다. 어제 무심코 다시 세어봤는데 25개였습니다. 그 사이 리뷰를 통과한 앱들이 웹에는 한 줄도 안 들어와 있었던 겁니다.
숫자를 확정하려고 46개 앱 슬러그를 전부 눌러봤습니다. 판정은 콘솔 트랙 상태가 아니라 공개 리스팅이 200을 주는가로 했습니다. 트랙이 completed여도 스토어에 안 뜨는 경우가 있고, 그 상태에서 링크를 걸면 죽은 링크가 되기 때문입니다.
그런데 전수 조회를 하려니 문제가 하나 있었습니다. 패키지 이름을 알아야 URL을 만드는데, 제 46개 앱은 패키지 이름이 두 갈래였습니다.
com.<brand>.<slug> # 초기 앱들
com.<slug>.android # 나중에 만든 앱들그래서 슬러그마다 두 패턴을 다 눌러봤습니다. 이게 나중에 중요해집니다.
감시판이 더 큰 문제였습니다
웹 숫자를 맞추는 건 그냥 노동입니다. 진짜 문제는 왜 이걸 제가 손으로 세고 있는가였습니다. Play 상태를 감시하는 잡이 매일 아침 돌고 있었거든요. 그게 돌고 있는데 왜 12개에서 멈춰 있었을까요.
코드를 열었습니다.
CANDIDATES = [f"com.{BRAND}.{s}" for s in SLUGS] + [...손으로 적은 예외들...]후보를 이름 규칙으로 생성하고, 규칙에서 새는 것들만 손으로 몇 개 적어두는 구조였습니다. 9월 4일에 앱 하나가 안 잡히길래 그 손목록에 한 줄 추가했던 기억이 났습니다. 한 줄 넣고 잘 돌아가는 걸 확인하고 닫았습니다.
그때 고친 건 그 앱 하나였습니다. 규칙은 안 고쳤습니다.
어제 전수 조회 결과와 감시 후보를 맞춰보니 다섯 개가 후보에조차 없었습니다.
com.biasly.android 스토어 200
com.bloatless.android 스토어 200
com.innra.android 스토어 200
com.moodbite.android 스토어 200
com.<brand>.stelo 스토어 200 (규칙엔 맞는데 손목록에서 누락)앞의 넷은 com.<slug>.android 갈래라 com.<brand>.<slug> 규칙으로는 절대 안 나옵니다. 마지막 하나는 규칙에는 맞는데 슬러그 목록 쪽에서 빠져 있었습니다. 구멍이 두 종류인데 증상은 하나였습니다 — 아무 말이 없는 것.
조용하다는 게 핵심입니다
이 감시 잡은 매일 정상으로 찍혔습니다. exit 0이고, "변경 없음"도 매번 사실이었습니다. 22개를 보고 22개에 변화가 없다고 말한 거니까요. 거짓말을 한 적이 없습니다.
목록이나 패턴으로 감시 대상을 정하면 누락은 절대 에러로 안 나타납니다. 없는 걸 안 보는 데는 오류가 없습니다. 이게 감시판의 구조적 맹점입니다 — 감시가 자기 범위를 감시하지 않습니다.
여기서 선택지가 둘이었습니다. 당신이라면 어느 쪽을 하시겠습니까?
- 빠진 다섯 개를 손목록에 넣는다. 오늘 구멍이 오늘 막힌다. 5분이면 끝난다.
- 후보를 만드는 방식 자체를 고친다. 다음에 관례를 안 지키는 앱이 또 나와도 안 빠지게.
솔직히 말하면 1번을 반쯤 했습니다. 두 패턴의 합집합을 후보로 쓰도록 _ALT_PACKAGES를 분리해서 넣었고, 재실행하니 감시 대상이 22 → 27개, 그중 공개 26개로 잡혔습니다. 덤으로 앱 하나가 비공개에서 공개로 바뀐 것도 그 자리에서 처음 잡혔습니다.
이건 규칙을 하나 더 추가한 것이지, 추측을 없앤 게 아닙니다. 세 번째 작명 갈래가 생기면 또 조용히 빠집니다.
그런데 같은 날, 손 안 댄 면 하나는 맞아 있었습니다
재미있는 게 있었습니다. 웹 다섯 면을 전부 고치면서 확인만 하고 지나간 자리가 하나 있는데, 거기는 아무도 안 건드렸는데 이미 25개가 맞게 들어가 있었습니다.
숏폼 영상 끝에 붙는 스토어 배지입니다. 그 코드는 이렇게 생겼습니다.
def android_live(slug) -> bool:
# 목록도 패턴 추측도 없다. 렌더할 때마다 스토어를 실제로 누른다.목록이 없습니다. 렌더할 때마다 실제 스토어 응답을 보고 배지를 붙일지 말지 정합니다. 그래서 새 앱이 리뷰를 통과하면 아무도 등록하지 않아도 다음 렌더부터 배지가 붙습니다. 확인해보니 어제 문제가 됐던 다섯 개 전부 True였고, 안드로이드가 없는 앱 하나만 정확히 False였습니다.
같은 사실("이 앱이 스토어에 있나")을 세 가지 방식으로 답하고 있었던 셈입니다.
| 방식 | 새 앱이 생기면 | 누락되면 |
|---|---|---|
| 손으로 적은 목록 | 사람이 넣어야 보인다 | 조용함 |
| 이름 규칙으로 생성 | 관례를 지켜야 보인다 | 조용함 |
| 매번 원천 조회 | 저절로 보인다 | 구조상 없음 |
세 번째가 비싸 보이는데, 실제 비용은 하루 한 번 HTTP 요청 46개입니다. 제가 아낀 건 요청 46개였고, 대가로 산 건 3주간 13개 앱이 안 보인 것이었습니다.
자가진단 3개
- 당신의 감시 봇이 보는 대상 개수와, 원천에 실제로 있는 개수를 지금 각각 세어보세요. 같습니까?
- 그 목록이 이름 규칙으로 생성된다면, 규칙을 어긴 항목이 지금 하나라도 있습니까? 예외를 손으로 적어둔 적이 있다면, 그건 규칙이 이미 한 번 샜다는 증거입니다.
- 대상 누락이 생겼을 때 그 봇은 어떤 신호를 냅니까? 아무 신호도 안 난다면 그 봇의 초록불은 "이상 없음"이 아니라 "내가 보는 범위 안에는 이상 없음"입니다.
결론
웹 다섯 면을 고친 건 하루치 노동이고 별 얘깃거리가 아닙니다. 남는 건 왜 3주 동안 아무도 말해주지 않았는가입니다.
이유는 제 감시판이 스토어에 묻지 않고 자기가 정한 작명 규칙에 물었기 때문입니다. 그리고 9월 4일에 한 번 새는 걸 봤으면서, 새는 걸 막지 않고 샌 물을 닦았습니다. 앱 하나를 손목록에 넣는 건 수정이 아니라 증상 처리였습니다. 같은 실수를 바로 전 글에서도 했더군요. 거기서는 상태 코드를 가져오고 원인을 안 가져왔습니다.
솔직한 부분: 지금 감시판도 여전히 추측합니다. 두 패턴의 합집합일 뿐 원천 조회가 아닙니다. 진짜 수정은 스토어가 아니라 콘솔 쪽 API로 앱 목록을 받아오는 건데, 그쪽은 앱 목록을 주는 엔드포인트가 없어서 지금은 방법이 없습니다. 그래서 이 글은 "고쳤습니다"가 아니라 "한 갈래 더 덮고, 여전히 추측 중입니다"가 정확합니다.
지금 딱 하나만 해보세요. 감시 스크립트를 열어서 대상 목록이 어디서 오는지 한 줄 찾아보시는 겁니다. 그게 리터럴이거나 f-string이면, 그 봇의 초록불에는 괄호가 하나 숨어 있습니다.