들어가며
팝펀치는 직장 스트레스를 만화 캐릭터 연타로 푸는 캐주얼 게임이다. 직장인, 회장, 도깨비, 좀비 같은 캐릭터를 톡톡 치면 반창고와 별이 튄다. 10초에서 3분짜리 도전 모드로는 점수를 겨룬다. 앱은 10개 언어로 나오고 광고로 운영하며, 순위와 업적은 Game Center에 올린다.
코드와 스토어 정보는 몇 주에 걸쳐 거의 다 준비해 둔 상태였다. 남은 건 마지막 점검과 심사 요청뿐이었고 그날 에이전트에게 맡긴 일도 한 줄이었다.
“앱스토어 커넥트에서 팝펀치 정보를 최종 점검하고 리뷰 요청합시다.”
에이전트는 Claude Code 데스크톱 앱이었다. 손에 쥔 도구는 빌드와 업로드를 맡는 fastlane, App Store Connect API 키, 그리고 앱 안에 붙은 브라우저였다. 결과부터 말하면 그날 오후 심사 제출을 마쳤다. 다만 “점검하고 누르기”로 끝날 줄 알았던 일에서 꽤 많은 것이 걸러졌다.
1. 상태부터 읽었다
에이전트는 웹 화면을 열기 전에 API로 상태를 통째로 읽었다. 앱 정보와 언어별 이름·부제, 버전, 연결된 빌드, 리뷰 노트, 언어별 스크린샷, 판매 국가, Game Center 항목까지 한 번에 뽑아 저장소의 원본 문서와 나란히 놓고 비교했다.
첫 발견은 빌드였다. 심사용 버전에 연결된 빌드는 6일 전(10월 17일)에 올린 빌드 10이었고 그 뒤로 앱 코드 커밋이 27개 더 쌓여 있었다. 새로 접히는 iPhone Duo 레이아웃, 평가 요청, 드래그 펀치, 바뀐 개인정보처리방침 주소가 모두 빌드 10에는 없었다. 이미 올린 iPhone Duo 스크린샷은 빌드 10에 없는 화면을 보여 주고 있었다. 그대로 냈다면 “스크린샷이 실제 앱과 다르다”는 이유로 돌아올 수 있는 상태였다.
에이전트는 빌드 10으로 낼지, main 최신으로 새로 빌드할지를 물었다. 나는 최신 코드를 받아 새로 빌드하라고 했다. fastlane이 Release 빌드를 만들어 올렸고 빌드 11은 그날 오후 처리를 마쳤다.
사람이 정한 것 — main 최신으로 빌드 11을 올리고 그 빌드로 제출한다.
2. 설명 한 줄이 앱과 달랐다
다음으로 걸린 건 문구였다. 11개 언어 설명과 리뷰 노트에 “도전권은 하루 10회”라고 적혀 있었다. 그런데 원격 설정(Firebase Remote Config)은 바로 그날 5회로 내려가 있었다. 빌드 10도 원격 값을 읽으니 심사자가 앱을 켜면 5회를 보게 된다. 설명과 앱이 서로 다른 말을 하고 있었다.
에이전트는 저장소의 원문(Localization/*.json)이 이미 5회로 바뀌어 있는 걸 확인하고 그 내용대로 API로 11개 언어 설명과 리뷰 노트를 고쳤다. 이 숫자는 나중에 설명에서 아예 빠진다. 검토 단계에서 “원격 값은 언제든 바꿀 수 있는데 설명은 새 버전을 내야 고칠 수 있다”는 지적이 나왔기 때문이다. 숫자를 박아 두면 원격 값을 바꾸는 순간 또 어긋난다.
같은 단계에서 판매 국가에 중국 본토가 켜져 있는 것도 찾았다. 중국에서는 돈을 받지 않는 게임도 판호가 필요하다. 그래서 출시 가이드에 빼기로 적어 둔 항목이었는데 실제 설정에는 반영이 안 돼 있었다.
사람이 정한 것 — 문구는 저장소의 원문에 맞추고, 바뀔 수 있는 숫자는 설명에서 뺀다. 중국 본토는 제외한다.
3. 웹 화면에서만 보이는 것들
API로 보이지 않는 항목은 브라우저로 확인했다. 내가 미리 로그인해 둔 App Store Connect 화면을 에이전트가 읽어 나갔다.
- 앱이 수집하는 개인정보(App Privacy) 답변이 게시되지 않은 상태였다. 이게 없으면 심사에 낼 수 없다.
- 앱 배포 계약, 디지털 서비스법, 전자상거래법 항목은 모두 활성이었다.
- Game Center 리더보드·업적·도전·활동 24개가 전부 “제출 준비 중”이었다. 이 항목들은 앱 버전과 같이 심사에 넣어야 한다.
에이전트가 App Privacy의 “게시” 버튼을 누르려 하자 Claude Code의 자동 권한 검사가 그 클릭을 막았다. 공개되는 내용을 바꾸는 동작이라서다. 에이전트는 우회하지 않고 멈춘 뒤, 내가 직접 누르거나 허용해 달라고 남겼다. 이 버튼은 뒤에서 내가 심사 제출을 다시 지시한 다음에야 눌렸다.
사람이 정한 것 — 밖으로 공개되는 버튼은 사람의 지시를 확인한 뒤에 누른다.
4. 검토자 다섯을 동시에 돌렸다
제출 직전에 한 가지를 더 부탁했다. 그로스 마케터의 눈으로 고칠 게 없는지, 언어별 현지화가 자연스러운지, 키워드가 잘 붙어 있는지, 스크린샷(Duo 포함)이 제대로 올라갔는지 봐 달라는 것이었다.
에이전트는 이 일을 서브 에이전트 다섯에게 나눴다. 마케팅·ASO 검토 하나, 아시아 언어(일본어·중국어 간체·번체) 하나, 유럽 언어(스페인어·독일어·프랑스어·포르투갈어·이탈리아어) 하나, 그리고 스크린샷을 맡은 검토자 둘이었다. 둘은 실제로 올라간 스크린샷 110장을 두 묶음으로 나눠 봤다. 다섯이 동시에 돌았고 몇 분 뒤 보고가 차례로 돌아왔다.
쓸모 있었던 지적은 이런 것들이었다.
- 설명이 사실보다 많이 약속했다. 설명에는 “사진·이름·대사는 백업에서 빠진다”고 적혀 있었다. 그런데 코드에서 백업 제외 표시가 붙는 건 사진 파일뿐이었다. 개인정보처리방침에도 “백업에서 빠지는 건 사진뿐”이라고 쓰여 있었다. 심사자가 둘을 나란히 보면 걸리는 문장이었다.
- 4번 스크린샷 캡션. 영어 캡션이 “Pick a target, even a photo”였다. 실존 인물 사진을 넣을 수 있는 기능과 붙으니 “아무나 골라 때려라”로 읽힐 수 있었다. 괴롭힘과 명예훼손을 다루는 심사 가이드라인 1.1.1에 걸릴 수 있는 표현이었다. 독일어·스페인어·중국어도 비슷했다.
- 일본어 한 단어. 진동을 뜻하려고 쓴 「バイブ」가 엉뚱한 뜻으로 읽힐 수 있다는 지적이었다. 「振動」으로 바꿨다.
- 멕시코 스페인어 키워드. 스페인 스페인어를 그대로 복사해 두었다. 미국 스토어는 미국 영어와 멕시코 스페인어 키워드를 같이 색인하는데 그 100자를 버리고 있었다.
- 기본 언어. 한국어로 되어 있어서 영국이나 동남아처럼 현지화가 없는 나라에서는 한국어 페이지가 보인다. 영어로 바꿨다.
보고를 그대로 믿지는 않았다. 백업 문구는 에이전트가 코드를 직접 열어 확인했다. 프랑스어 버튼 글자가 잘렸다는 지적과 Duo 화면에서 캐릭터가 잘려 보인다는 지적도 이미지를 직접 열어 맞는지 봤다. 둘 다 사실이었다.
지적은 골라서 받았다. 말풍선 장면이나 접힌 Duo 화면처럼 스크린샷을 새로 찍어야 하는 항목, 앱 안 영어 표시를 현지화하는 항목은 다음 버전으로 미뤘다. 반대로 이름·부제·키워드·설명은 출시 뒤에는 새 버전을 내야만 바꿀 수 있어서 이번에 정리했다.
사람이 정한 것 — 필수 두 가지(백업 문구, 4번 캡션)와 권장 문구·키워드·기본 언어만 고치고, 재촬영이 필요한 것은 다음 버전으로 미룬다.
5. 원본 없이 캡션만 바꾸기
4번 캡션을 바꾸려면 스크린샷을 다시 만들어야 했다. 캡션 글자가 이미지 안에 그려져 있기 때문이다. 그런데 6.9인치 스크린샷의 원본 캡처가 남아 있지 않았다. 남은 건 이미 만들어 올린 결과 이미지뿐이었다.
에이전트는 다른 길을 골랐다. 스크린샷을 만드는 스크립트로 새 캡션의 위쪽 배경과 글자만 다시 그려 기존 이미지의 아래쪽(앱 화면 부분)과 이어 붙였다. 배경 그라데이션은 위치로만 정해지니 이음매가 보이지 않는다. 다만 정말 그런지는 확인해야 했다.
- 먼저 작업용 폴더의 이미지가 App Store Connect에 올라간 이미지와 바이트까지 같은지 비교했다.
- 같은 방법으로 1번 이미지 위쪽을 다시 그려 원본과 픽셀이 같은지 봤다. 글자 크기가 그대로인지를 이걸로 확인했다.
- 이음매 바로 아래 줄이 원본과 같은지도 비교했다.
함정이 두 개 있었다. 이 스크립트는 언어마다 “가장 긴 캡션 줄”에 맞춰 모든 장의 글자 크기를 정한다. 그래서 이탈리아어와 포르투갈어는 새 캡션 길이 때문에 그 언어 전체의 글자 크기가 달라졌다. 4번만 글자가 커지거나 작아지게 되니 길이를 맞춘 문구로 다시 정했다. 또 에이전트가 영어 캡션을 바꾸는 걸 빠뜨렸다. 9개 언어를 한 장에 모아 본 확인용 이미지에 “Pick a target”이 그대로 남아 있는 걸 보고 찾아냈다.
사람이 정한 것 — 새 캡션은 “때릴 대상”이 아니라 “캐릭터나 내 사진을 고른다”는 뜻으로 쓴다. 한국어 캡션은 그대로 둔다.
6. 녹화에 얼굴이 찍히면 안 된다
마지막 점검을 앞두고 앱 쪽 확인도 부탁했다. 특히 이 한 가지는 분명히 해 두고 싶었다. 사용자가 사진을 넣었을 때 화면을 녹화하면 그 얼굴이 찍히면 안 된다.
팝펀치는 사진을 iOS의 보안 입력 필드가 쓰는 캔버스 안에 그린다. 비밀번호 칸이 스크린샷과 녹화에서 비어 보이는 것과 같은 원리다. 에이전트는 사진이 화면에 나오는 곳을 코드에서 모두 찾았다. 게임 화면, 위쪽 캐릭터 버튼, 캐릭터 시트, 이름 짓기 화면, 이렇게 네 곳이었고 모두 이 캔버스 안에 있었다. 결과 공유 이미지에는 처음부터 사진이 들어가지 않는다.
이 캔버스는 iOS 내부 구조에 기대고 있어서 OS가 바뀌면 사라질 수 있다. 그래서 캔버스를 찾지 못하면 사진 모드 자체를 막게 해 두었다. 보안을 끄는 개발용 옵션은 Release 빌드에 들어가지 않는다.
private var photoModeAvailable: Bool {
#if DEBUG
if UserDefaults.standard.bool(forKey: "disableSecure") { return true }
#endif
return container.canSecure
}
에이전트는 실제로 올린 빌드 11의 실행 파일도 열어 봤다. 그 옵션 이름, 디버그 로그 문자열, 테스트 광고 ID가 하나도 없었다. 그래도 마지막 확인은 사람 몫이었다. 내가 TestFlight로 받은 빌드 11에서 직접 녹화하고 스크린샷을 찍어 봤다. 얼굴은 찍히지 않았다.
사람이 정한 것 — 녹화 가림은 코드 확인으로 끝내지 않고 실기기 녹화로 최종 확인한다.
7. “빌드 11에 디버그 창이 있잖아?”
그 실기기 확인 중에 화면 위에 낯선 창이 떠 있는 걸 봤다. FPS, GPU 시간, 메모리, 프레임 그래프가 나오는 검은 상자였다.
심사에 낼 빌드에 디버그 창이라니. 나는 “새 빌드를 올려야 하지 않느냐”고 물었다. 에이전트는 업로드한 IPA를 풀어서 하나씩 봤다.
- 설정 파일(Info.plist)의 키를 모두 확인했다. 이 창을 켜는 키는 없었다.
- 앱 실행 파일과 포함된 라이브러리 전부에서 관련 문자열을 찾았다. 0건이었다.
- 서명 권한도 App Store 배포용 그대로였다. 디버깅 허용은 꺼져 있었다.
이 창은 Apple의 성능 표시 창인 Metal HUD였다. 기기 설정의 개발자 메뉴에서 켜 두면 Metal로 화면을 그리는 모든 앱 위에 뜬다. 범인은 내 iPhone에 켜 둔 개발자 설정이었다. 새 빌드는 필요 없었다.
돌아보면 둘 다 처음엔 “앱 문제”로 의심할 만한 장면이었다. 에이전트가 “아마 기기 설정일 것”이라고 넘기지 않고 실제 바이너리를 열어 근거를 댄 덕에 빨리 끝났다.
사람이 정한 것 — 새 빌드 없이 빌드 11 그대로 제출한다.
8. 제출
남은 일은 Game Center 항목을 제출에 넣는 것이었다. 웹 화면에서는 항목마다 페이지를 열고 “심사에 추가”를 눌러야 해서 24번을 반복해야 했다. 에이전트는 하나만 화면에서 넣어 본 뒤, 그 항목이 API에서 어떤 모양으로 들어가는지 확인했다. 그러고 나서 나머지 23개를 API로 넣었다. 리더보드 8개, 업적 8개, 도전 4개, 활동 4개에 앱 1.0까지 모두 25개 항목이었다.
마지막 “심사를 위해 제출”은 내가 계속 진행하라고 한 뒤에 눌렸다. 화면에 “25개의 항목 제출됨”이 떴고 버전 상태는 “심사 대기 중”으로 바뀌었다. 승인되면 바로 출시되도록 해 두었다.
사람이 정한 것 — Game Center 24개를 앱과 함께 제출하고, 승인되면 자동으로 출시한다.
마치며
그날 일은 꽤 깔끔하게 나뉘었다. 에이전트가 잘한 일은 전부 보기와 지루한 검증이었다. 11개 언어의 설명을 원문과 한 글자씩 대조하고 110장의 스크린샷을 열어 보고, 바이너리 문자열을 뒤지고 픽셀을 비교했다. 사람이라면 피곤해서 대충 넘겼을 것들이다.
어떤 지적을 받고 어떤 지적을 미룰지, 공개 버튼을 언제 누를지, 실기기에서 마지막으로 무엇을 확인할지. 이런 고를 것을 고르는 일은 내가 해야 했다. 에이전트도 그 지점에서는 멈춰서 물었다.
다음에는 스토어 설명과 앱 동작이 같은 원본에서 나오게 하려고 한다. 숫자처럼 바뀌는 값은 설명에 쓰지 않는다. 스크린샷 원본 캡처도 지우지 않고 보관해 둘 생각이다. 이번처럼 캡션 하나 고치려고 이미지를 이어 붙이는 일은 한 번이면 충분하다.
심사 결과가 나오면 이 글 아래에 덧붙이겠다.