기도모임 앱은 광고 없이 굴러가는 앱으로 시작했어요. 모임에서 같이 쓰는 앱이라 화면 아래쪽에 배너가 떠 있으면 좀 묘하잖아요. 그래서 첫 출시는 무료 앱으로 그냥 내보냈어요. 두 번째 앱부터는 무료로 쓰되 광고가 한 줄 깔리는 구조로 갔어요. 작은 게임 앱이었거든요. 광고를 단 다음에는 자연스럽게 '광고 제거'라는 일회성 구매 항목을 같이 붙이고 싶어졌어요. 그 광고 자체가 한 번은 한 달 정지를 먹어서 토글까지 만들게 된 사연이 따로 있는데, 그 얘기는 여기에 적어 뒀어요. 광고가 신경 쓰이는 분들한테는 결제 한 번으로 가려주는 선택지 정도는 두는 게 맞다 싶었거든요. 제 앱에 처음으로 결제 버튼이 붙는 자리이기도 했고요.
그 작업을 시작한 게 어느 주말 저녁이었어요. 클로드한테 "광고 제거 인앱결제 한 번 붙여줘" 하고 짧게 던졌더니, "플러터에서 인앱결제는 보통 in_app_purchase 패키지를 쓰는데, 안드로이드 쪽은 빌링 라이브러리라는 게 한 번 끼어 있어요" 같은 답이 길게 왔어요. pubspec.yaml에 패키지 한 줄 적고, 결제 버튼을 누르면 구글 결제창이 뜨도록 코드를 한 묶음 짜주더라고요. 안드로이드 폴더 어디 build.gradle 같은 데도 같이 손을 댔어요. 그게 정확히 뭐 하는 줄인지는 그날 밤엔 잘 몰랐고, 일단 빌드가 돌고 폰에 깔리는 것까지만 확인하고 잤어요. 결제 자체는 라이선스 테스터로 돌려야 하는데 그 설정까지 끝낼 자신은 없었거든요.
그 코드가 폴더에 한 달쯤 그대로 잠들어 있었어요.
받은 메일함의 빨간 점
어느 평일 아침 출근 준비하다가 폰을 들여다봤는데, 받은 메일함 위쪽에 Google Play Console이 보낸 메일이 한 통 올라와 있었어요. "Action required: Update your app to use the latest Billing Library" 같은 톤의 한 줄이었어요. 지하철에서 본문을 열어 보니 "X월 X일부터 구버전 Billing Library를 쓰는 앱은 신규 업데이트가 차단됩니다" 같은 문장이 굵게 박혀 있었어요. 끝쪽에 어떤 앱이 영향받는지 표 비슷한 게 들어 있었고, 거기 제 게임 앱 이름이 한 줄 들어가 있었어요.
머릿속에 두 가지가 같이 떴어요. '아 이게 며칠 전에 짠 그 인앱결제 코드 얘기인가' 하는 것과, '데드라인이 X월 X일이면 아직 시간 있네' 였어요. 한 달 가까이 남아 있었거든요. 회사 들어가서 메일은 못 본 척 한 번 더 닫았어요. 그 며칠 본업이 바쁜 주차이기도 했고, Billing Library라는 단어 자체가 그날 아침엔 좀 무겁게 느껴졌어요. 코드를 처음부터 다시 봐야 하는 일이라는 게 미리 짐작이 됐거든요.
그 메일이 한 주 동안 빨간 안 읽음 점인 채로 위쪽에 떠 있었어요. 그 다음 주 어느 저녁에 한 번 더 열어 봤는데 본문이 그대로였어요. '왜 이렇게 자꾸 정책이 바뀌지' 하는 생각이 그 자리에서 들었어요. 출시한 지 한 달쯤 된 앱에 갑자기 "코드 어디를 다시 짜야 한다"는 메일이 날아오는 게 솔직히 좀 부당하게 느껴졌어요. 코드 짜서 마켓에 올리면 그걸로 끝일 줄 알았는데, 그 뒤로도 외부에서 자꾸 "그건 이제 안 됩니다" 같은 한 줄이 날아오는 자리라는 게 그땐 좀 새삼스러웠어요.
그 며칠은 또 다른 앱 하나를 마무리하는 시점이라 그 메일에 시간을 따로 쓸 여유가 안 났어요. 데드라인까지는 시간이 남아 있다는 걸 핑계로 한 번 더 닫아 두고 다음 주로 미뤘어요. 그 다음 주에도 또 미뤘어요.
데드라인 일주일 전 저녁
그러다 어느 평일 저녁, 식탁에서 늦은 밥을 먹다가 폰을 보니까 그 메일이 또 위쪽에 떠 있었어요. 그 사이에 리마인더 같은 게 자동으로 한 번 더 와 있는 거였어요. 본문 끝에 적힌 날짜를 다시 봤더니 그 시점에서 일주일이 남아 있었어요. 일주일이라는 숫자가 그제서야 무게가 달랐어요. 그 게임 앱이 일주일 안에 PBL 8로 안 올라가면, 그 다음에 버그 하나 잡아서 업데이트 올리려고 해도 차단이 그대로 걸린다는 얘기였잖아요. 출시한 앱에 자물쇠가 채워지는 느낌이었어요.
밥 마저 먹고 그 밤에 책상에 앉았어요. 그 주에 같이 굴리던 다른 앱 작업은 하루 미루기로 하고, 게임 앱 폴더를 다시 열었어요. 한 달 전 주말 저녁에 잠들어 있던 인앱결제 코드를 그제서야 다시 들여다본 거예요. 클로드한테 메일 본문을 통째로 던지고 "이 메일대로 PBL 8로 올려야 하는데, 우리가 한 달 전에 짠 인앱결제 코드 PBL 어느 버전 기준이에요?" 하고 물었어요.
답이 한 박자 늦게 왔어요. "말씀하신 코드 기준은 빌링 라이브러리 7점대였어요. 8 미만이고요. 그래서 그 메일 대상에 들어가요." 그 한 줄을 읽으면서 '역시' 같은 한 박자가 같이 왔어요. 클로드 코드가 한 달 전 주말에 짜준 인앱결제 코드는 그 시점에 안드로이드 쪽에서 한참 표준처럼 쓰이던 방식이었던 거예요. 그 사이에 구글이 결제 라이브러리를 크게 갈아엎으면서, 같은 결과를 내는 코드라도 안쪽 구조가 좀 다른 모양이 돼야 한다는 거였어요. 패키지 버전 한 줄만 올린다고 끝나는 일이 아니고, 그 안에서 부르는 함수 이름이며 콜백 처리 방식이며 몇 군데가 같이 바뀌어야 한다는 답이 같이 왔어요. 그날 밤 클로드랑 핑퐁하면서 정리된 PBL 8 결제 코드 흐름은 이 프롬프트에 따로 갈무리해 뒀어요.
그날 밤은 그 작업으로 거의 새벽까지 갔어요. 패키지 버전을 올리고 빌드를 돌리면 빨간 줄이 우수수 떴어요. "이 함수는 이제 이 이름이 아니에요" 같은 영문 줄이 줄줄이 박혀 있었어요. 한 줄 고치면 또 다른 줄이 빨개졌어요. 클로드한테 그 빨간 줄을 통째로 다시 던지면 "그 줄은 이렇게 바꾸셔야 해요" 하고 새 코드 묶음을 주는 식으로 한참을 핑퐁했어요. 빌링 라이브러리 안쪽에서 결제를 시작하는 줄, 결제 끝났는지 확인하는 줄, 영수증 받는 줄. 각자 자리가 한 칸씩 옆으로 옮겨가 있었어요. 한 묶음이 다 정리되고 빨간 줄이 다 사라진 게 새벽 두 시쯤이었어요.
빌드가 통과되고 나서 그대로 AAB라는 안드로이드용 빌드 파일을 만들었어요. 첫 앱 출시할 때 만들어 둔 키스토어 파일이 폴더 어딘가에 있어서, 그걸 찾아서 build.gradle에 연결해 주는 정도로 풀렸어요. 첫 앱 때는 키스토어를 만드느라 또 한 새벽을 갈아 먹었던 자리였는데(그 첫 빌드가 진짜로 돌던 새벽 얘기는 따로 적어 뒀어요), 이번엔 그게 통째로 줄어들었어요.
AAB를 Play Console에 올렸어요. 내부 테스트라는 트랙에 처음 올리는 거였어요. 정식 출시 전에 제가 지정한 몇 명만 깔아 볼 수 있는 자리예요. 이 비공개 테스트 트랙이 나중에 테스터 20명을 모으고 사업자 등록까지 가는 입구가 되는데, 그건 한참 뒤 얘기예요. 그 다음에 인앱 상품 메뉴에 들어가서 '광고 제거'라는 일회성 상품을 한 칸 만들었어요. 상품 ID는 코드 안에서 부르는 이름이랑 정확히 같아야 한다고 해서, 코드를 한 번 더 열어서 그 줄을 확인한 다음에 그대로 옮겨 적었어요. 가격은 한국 원화로 적으면 다른 나라 통화는 자동으로 채워준다고 해서 그렇게 했어요.
그 다음이 라이선스 테스터 등록이었어요. 라이선스 테스터로 등록된 계정은 실제 결제가 일어나지 않는 테스트 결제가 가능한 자리예요. Play Console 안에서 그 항목을 찾아 제 구글 계정 이메일을 한 줄 적어 넣었어요. 한 줄 적는 게 다였는데 그 한 줄이 어디 있는지 찾는 데 시간이 좀 걸렸어요.
옆에 폰을 깨워서 내부 테스트 트랙 링크로 깔았어요. 깔린 다음에 게임 안 '광고 제거' 버튼을 처음으로 눌러 봤어요. 구글 결제창이 한 번 뜨면서 "광고 제거 — XXX원" 같은 줄이 뜨고, 그 아래에 "이 결제는 테스트 결제입니다" 같은 회색 글자가 한 줄 같이 떠 있었어요.
그 회색 글자를 봤을 때 숨을 멈췄어요. 한 달 전에 짜둔 코드가 안 올라간다 어떻게 한다 하면서 며칠을 미뤘던 자리에서, 그 새벽에 결제창 한 장이 진짜로 폰에 뜬 거잖아요. 결제 버튼을 한 번 더 눌렀어요. 한 박자 멈춘 다음에 "결제가 완료되었습니다" 같은 영수증 화면이 한 장 떴어요. 게임으로 돌아가니 광고 배너가 있던 자리가 비어 있었어요. 빈 자리가 그 새벽에 좀 묘했어요.
무료로 풀린 자물쇠
빌드를 정식 트랙에 올린 건 그 다음 날 저녁이었어요. PBL 8 기준으로 새로 짠 빌드라 그 차단 메일이 더 이상 따라오지 않을 자리였어요. 데드라인 며칠 전에 자물쇠가 풀린 거였어요. 그 다음 주 어느 평일에 받은 메일함을 다시 봤더니 그 빨간 점이 사라져 있었어요. 시스템이 자동으로 '해결됨' 처리를 한 거예요. 처음 그 메일이 떴던 출근길에서 자물쇠가 풀린 이 자리까지가 거의 한 달이었는데, 진짜로 손을 댄 건 그 새벽 한 번이었어요.
광고 제거 결제가 누구에게 실제로 일어났는지는 그 뒤로 확인 못 했어요. 정확히는 아직 한 번도 일어난 적이 없어요. 제 앱 중에 실제로 인앱결제가 들어온 자리는 그 시점까지 아예 없었거든요. 라이선스 테스터로 "테스트 결제는 됩니다"까지만 확인된 자리에서 정식 출시 자리에 한 번 올려둔 거예요. 첫 결제가 들어와야 환불 처리 같은 자리도 다음 얘기가 될 텐데, 그 자리는 아직 저한테 안 와요.
외부에서 "X월 X일까지 이거 안 하면 차단"이라고 날아오는 한 줄이 사실은 "지금 닫으면 한 번 더 따라옵니다"라는 한 줄이라는 걸 그제서야 좀 손에 잡혔어요. 코딩 자체는 그 새벽 한 번에 풀린 자리였는데, 그 한 번을 한 달 동안 미룬 무게가 마지막 일주일에 통째로 쏠려 왔어요. 그 일주일에 다른 앱 작업이 밀린 게 그 자리의 진짜 비용이었어요.
지금도 받은 메일함 위쪽에 가끔 Google Play Console이 보낸 메일이 한 번씩 올라와요. 정책이 또 바뀐다거나, 어떤 권한 설명이 더 필요해졌다거나 하는 줄들이요. 그때마다 '이번엔 미루지 말자' 같은 게 머릿속에 짧게 스쳐요. 메일을 그날 안에 한 번 열어 보는 정도까진 가게 됐어요. 그날 안에 푸는 건 또 다른 얘기지만요.

