아내를 위해 만든 앱 성장기

앱 성장기 시리즈 — 아내를 위해 만든 단식 앱 케톤의 격주 회고.

앱 성장기 시리즈 이전 글

제가 매일 아침 켜는 화면이 이겁니다.

06-metabase-dashboard

Metabase라는 오픈소스 데이터 시각화 도구입니다. SQL로 뽑은 결과를 차트와 대시보드로 모아주는 도구인데, 무료고 Docker 한 줄로 띄울 수 있어서 1인 개발자한테도 부담이 없습니다. 여기에 DAU, WAU, MAU, 일별 신규 설치 카드를 몇 장 만들어놓고 출근 인사 대신 한 번씩 봅니다. 두 달 전 출시했는데, 절대 숫자는 여전히 작습니다. 그래도 추세는 정직하게 위쪽이라서 보는 맛이 있습니다.

벤치마크를 잠깐 옆에 놓고 보면 좀 신기합니다. Adjust의 2025년 Health & Fitness 카테고리 리포트 기준으로 단식·다이어트 앱 D1 리텐션 평균이 25~30%, D7 리텐션이 10~15%라고 나옵니다. [출처: Adjust Mobile App Trends 2025] 케톤은 W18 cohort 기준으로 D1 60.5%, 한 번이라도 첫 주에 다시 방문한 비율(W1)이 70%입니다. 카테고리 평균의 거의 두 배입니다. 추세선이 카테고리 평균 위쪽에서 우상향 중인 상태. 인디 개발자한테는 꽤 든든한 그림입니다.

01-w14-w18-trend

오늘 글의 진짜 주제는 사실 이 차트가 아닙니다. 헛다리 두 번 짚은 이야기입니다. 데이터를 잘 볼 줄 모르는 인디 개발자가 AI한테 너무 의지하다가 두 번 헛짚었습니다. 그런데 둘 다 결과적으로는 앱에 도움이 됐다는 게 함정입니다. 추천하지는 않습니다만. ^^;;

헛다리 1 — AI를 너무 믿었습니다

저는 SQL을 다룰 일이 많지 않아 익숙하지 않습니다. 데이터 분석을 제대로 공부한 적도 없습니다. 그래서 매일 BigQuery에 들어갈 쿼리를 ChatGPT나 Claude한테 부탁하곤 했습니다. “어제부터 7일간 D1, D7 리텐션 뽑아줘”, “v1.3.0 이후 신규 가입 카운트 해줘” 같은 식이었습니다. 결과 한 번 돌려보고 숫자가 그럴듯해 보이면 그대로 markdown 표에 박아넣었습니다. 다음 날도, 그 다음 날도 똑같은 쿼리를 복붙으로 돌렸습니다.

그러다 사고가 두 번 났습니다.

사고 A — D7이 한 자릿수로 무너진 줄 알았는데

W16 cohort(4월 13~19일 설치자)의 D7 리텐션이 4.8%로 잡혔습니다. 21명 중에 한 명만 일주일을 버텼다는 그림이었습니다. 그 전 주는 30%대였는데 갑자기 5분의 1로 내려앉은 겁니다. 식은땀이 났습니다.

02-d7-correction

5월 1일에 같은 cohort를 다시 뽑아봤더니 D7이 23.8%였습니다. 5배 차이. 측정창이 다 닫히지도 않았는데 도래 안 한 사람들을 0으로 잡아서 평균을 짓눌렀던 겁니다. 비유하자면 점심 영업이 한창인 12시 정각에 “오늘 점심 매출 0원입니다” 보고서 쓴 셈입니다. 분모는 21명인데 분자가 측정 가능한 사람은 3명뿐인 상태로 나누기를 해버린 겁니다.

거기다 측정 정의도 너무 좁았습니다. 정확히 설치 후 7일째 그 하루에만 방문해야 D7로 카운트되는 쿼리였는데, 단식앱 사용자는 매일 들어오기보단 격일~주 2~3회로 들어오는 분들이 더 많습니다. D7에 한해 ±1일을 허용해서(설치 후 6~8일 사이에 한 번이라도 방문하면 D7로 카운트) 측정하는 쪽이 단식앱 특성에 맞습니다. ±1 허용은 D7에만 둡니다. D1이나 D3까지 같이 넓히면 측정창이 D2 같은 날을 양쪽에서 잡아 중복 카운트가 나거든요. 좁은 정의 그대로 두면 자연스럽게 잡혔을 사람들이 0으로 빠지는 겁니다.

이 두 함정이 곱해져서 4.8%라는 비관 수치가 만들어졌습니다.

사고 B — 함께 탭 합류가 9일 연속 0건이라며

같은 시기에 사고가 하나 더 있었습니다. 4월 23일에 함께 탭(v1.3.0)을 출시하고 나서, 매일 보던 일간 리포트에 신규 합류 0건이 9일 연속으로 박혔습니다. 누적 9명에서 정체. 신규 설치는 매일 들어오는데 함께 탭 합류만 0이라는 게 좀 이상하긴 했지만, “기능이 망가졌다” 쪽으로 진단이 자연스럽게 굳어졌습니다.

9일째 되던 날 무심코 함께 탭을 켜봤다가 잠깐 멈칫했습니다. 라이브 활동 배너에 새로 들어온 분들이 멀쩡하게 떠 있었습니다. 카드에 붙은 누적 단식 횟수 뱃지가 0회로 표시되고 있었는데, 처음 들어온 사람의 단식 횟수가 0인 건 자연스러운 그림이었습니다. 즉 앱 화면에는 신규 합류자가 매일 들어오고 있었던 겁니다. 일간 리포트는 9일째 합류 0건이라는데 앱 화면은 사람들이 들어오는 중. 이 모순을 보고서야 데이터 쪽이 이상하다는 걸 인정했습니다.

옆에서 보던 아내도 한마디 거들었습니다. “신규 유저가 들어오는데 합류가 0이라는 게 말이 되는 거 아니야?”

03-community-zero-mismatch

원인은 황당하게 단순했습니다. Kotlin 데이터 클래스 필드명은 isFirstTime(camelCase), Firebase Analytics로 발화되는 키는 is_first_time(snake_case)이었는데, 제 SQL은 isFirstTime으로 조회하고 있었습니다. 항상 NULL이 나올 수밖에 없는 구조였고, 그래서 9일 내내 0건으로 잡혔습니다.

is_first_time으로 다시 조회해봤더니 9일 누적 합류자가 59명이었습니다. 신규 설치자가 거의 전원 함께 탭에 합류하고 있었습니다. "마비"가 아니라 “오히려 잘 굴러가고 있는데 내 눈에만 안 보이던” 상태였습니다.

두 사고가 같이 가르쳐준 것

저는 사실 데이터 보는게 그다지 익숙하지 않았던 앱 개발자 입니다. AI한테 SQL 받고, 결과 한 번 보고, 매일 같은 쿼리를 복붙으로 돌리는 워크플로우를 SKILL로 만들어 한 달 넘게 사용하고 있었습니다. 그 과정 어디에도 “내가 묻는 질문이 정의상 맞는지”, “내가 쓰는 키가 코드의 진짜 키랑 같은지” 검증할 단계가 없었습니다. 한 번 잘못 만든 SQL이 매일 그대로 복제되는 구조였습니다.

AI가 거짓말한 게 아니라, 제가 잘못된 질문을 던지고 잘못된 답을 그대로 받아 적었을 뿐입니다. 검증은 사람이 해야 하는 건데, 그 사람이 데이터를 잘 볼 줄 모르면 검증 자체가 안 일어납니다.

그래서 Metabase를 띄웠습니다

Metabase 도입은 "SQL 직접 짜는 게 실패해서 도망간 것"이 아닙니다. 더 잘 보려고 갈아탄 겁니다.

Docker 를 이용하면 docker compose 파일 하나와, BigQuery 서비스 계정 JSON 하나로 Metabase를 간단히 올릴 수 있습니다. 그리고 Metabase에 쿼리를 저장하면 처음 보셨던 스크린샷 처럼 결과를 그대로 차트로 볼 수 있습니다. 이걸 바탕으로 앱에서 보고 있는 주요 데이터 카드를 18개 정도 만들었습니다. DAU/WAU/MAU 추이, 코호트 리텐션, 기능 채택률, 단식 퍼널, 채널 분석 같은 것들입니다.

도구가 바뀐다고 위 두 사고가 자동으로 안 났을까요? 그건 아닙니다. 다만 카드를 만드는 시점에 “이 쿼리가 진짜로 코드 발화 키랑 일치하나”, **“측정창이 다 닫혔나”**를 한 번은 확인하게 됩니다. 매일 똑같은 쿼리를 매일 새로 칠 때보다 검증 빈도가 훨씬 올라갑니다. SQL은 git으로 관리하고 각 쿼리와 결과로 나온 항목들이 무엇을 의미하고 어떻게 정의되어 있는지도 설명에 남깁니다.

도입 과정 자체가 점검의 시간이었습니다. 카드 18장을 만들면서 옛날 쿼리들을 한 번씩 다시 들여다봤고, D7 측정창 문제 외에도 작은 버그를 몇 개 더 잡았습니다. 그리고 차트로 보면 이상치가 더 빨리 눈에 띈다는 것도 만들어보고 알았습니다. 표로 보던 시절엔 4.8%와 23.8%가 그냥 다른 두 숫자였는데, 차트로 그려놓으니까 푹 꺼지는 점이 시각적으로 비명을 지릅니다.

헛다리 2 — 잘못된 신호로 옳은 결정을 한 셈입니다

여기서부터가 좀 웃긴 구간입니다.

위에서 D7이 4.8%로 무너진 줄 알았다고 말씀드렸습니다. 그게 측정 오류였다는 건 5월 1일에야 알았습니다. 그 사이 2~3주 동안 저는 **“D7이 한 자릿수다”**라는 잘못된 전제 위에서 대응을 두 개 굴리고 있었습니다. 그런데 그 대응이 둘 다 결과적으로 앱에 좋은 일을 하고 갔습니다.

헛다리 A → 22개 언어 번역 점검 → 5성 리뷰

D7이 무너졌다고 본 시점에 가설을 세웠습니다. “해외 유저 비중이 갑자기 71%까지 올라갔는데, 내가 한국어 말고는 한 글자도 못 읽잖아? 번역 품질 때문에 첫날에 다 빠지는 거 아닐까?” 이 가설로 22개 언어를 전수 점검하기 시작했습니다.

근거였던 4.8%는 가짜였습니다. 그런데 점검하다가 진짜 문제를 찾았습니다. 러시아어 번역에서 "단식"으로 옮긴 단어가 정교회 사순절 쪽 종교 금식 어감과 섞여 있었습니다. 건강 앱을 깔았는데 “사순절 시작” 같은 문구를 읽게 되는 상황이었습니다. v1.1.1에서 이걸 고쳐서 배포했고, 며칠 뒤 러시아 유저에게 처음으로 별 다섯 개짜리 리뷰를 받았습니다. 답글도 번역기로 한국어를 러시아어로 돌려서 적었습니다. 인디 개발자한테 첫 5성 리뷰가 주는 동력은 꽤 큽니다.

잘못된 신호로 시작한 작업이 진짜 문제를 잡았습니다. 운이 좋았습니다.

헛다리 B → 함께 탭 → D1·D3·D7 모두 큰 폭 상승

같은 D7 4.8%를 보고 또 다른 가설도 굴리고 있었습니다. “사람들이 첫 주에 빠지는 건 단식이 외로워서 아닐까?” 그래서 4월 23일에 v1.3.0으로 함께 탭을 출시했습니다. 익명 닉네임으로 지금 단식 중인 사람들이 보이고, 프리셋 이모지 응원을 하루 한 번 보낼 수 있는 얇은 커뮤니티입니다. 설계 과정은 따로 한 편으로 풀어놨습니다 → 단식 앱에 커뮤니티를 붙이기로 했습니다

베이스라인이라고 봤던 4.8%는 가짜였습니다. 진짜 D7은 30%대였습니다. 위기가 아니었는데 위기 대응을 했더니 그 대응이 정말 좋았습니다. install_version 기준으로 같은 정의로 비교했더니:

05-community-tab-effect

D1, D3, D7이 모두 두 자릿수 %p씩 같은 방향으로 올랐습니다. 표본은 작긴 합니다(v1.2.0 30명 vs v1.3.x 17명). 그래도 세 지표가 같이 흔들리는 건 단발 노이즈로 보기 어렵습니다. 단발이면 보통 한 지표만 튑니다.

잘못된 데이터로 옳은 결정을 한 셈입니다

번역 점검도, 함께 탭도, 둘 다 잘못된 신호로 시작했지만 끝에 가서 좋은 결과를 만들었습니다. 이게 좀 웃깁니다. "데이터를 정확히 보는 게 중요하다"는 글을 쓰고 있는데 그 글의 두 챕터가 "잘못 본 데이터로 옳은 결정을 했다"로 끝납니다.

물론 운이 좋았던 겁니다. 헛다리가 매번 좋은 자리로 떨어지지는 않습니다. 운이 안 좋았으면 엉뚱한 가설로 두세 주를 그냥 태웠을 거고, 그 시간에 D1 onboarding 같은 진짜 우선순위를 놓쳤을지도 모릅니다. 그래서 Metabase로 갈아탄 것입니다. 다음번엔 운에 기대지 않고 정확한 신호 위에서 결정을 하고 싶었습니다.

추천하지는 않습니다. 그냥 처음부터 데이터를 잘 보는 쪽이 좋습니다.

마치며 — 추세는 좋지만 절대 숫자는 작습니다

추세가 우상향이고, 리텐션이 카테고리 평균 위쪽에 있는 건 사실입니다. 다만 절대 숫자는 여전히 작습니다. WAU 두 자릿수, 신규 설치 일주일에 수십 명 단위. 카페에 앉아서 주변을 둘러보면 손가락으로 셀 수 있는 수준입니다. 좋은 리텐션이 좋아 보이는 건 모수가 작아서 그렇기도 합니다. 작은 모수에서 좋은 게 큰 모수에서도 좋을 거라는 보장은 없습니다.

그래서 다음 2주는 두 가지를 봅니다.

하나는 유입 채널입니다. 지금까지 신규 설치의 89%가 Play Store 오가닉입니다. 검색 알고리즘 한 곳에 의존하는 게 좀 위태로워서 다른 채널을 만들어볼 생각입니다. 그 첫 신호가 며칠 전에 한 명 잡혔습니다. UTM이 naver_blog/dev-story로 찍힌 분이 한 명 들어오셨습니다. 이 시리즈 글을 읽고 케톤을 깔아주신 분이라는 뜻입니다. N=1이고 통계적 의미는 0이지만, 콘텐츠가 사람을 데려올 수 있다는 첫 데이터 포인트였습니다. 이 분이 일주일 뒤에도 다시 들어오시는지는 다음 에피에서 그대로 들고 오겠습니다.

다른 하나는 지속성입니다. 유입 채널이 늘어나 신규가 두 배 세 배가 됐을 때, 지금의 D1 60%, W1 70%가 그대로 유지될지. 작은 모수에서 만들어진 리텐션 패턴이 더 큰 모수에서도 깨지지 않는지를 봐야 합니다. 안 깨지면 PMF에 가까워진 것이고, 깨지면 지금 보이는 좋은 숫자가 초기 얼리어답터들이 만든 착시일 수 있습니다. 어느 쪽이든 다음 격주에 솔직하게 들고 오겠습니다.

오늘 글 끝까지 읽어주셔서 감사합니다. 다음 에피는 2주 뒤입니다. 숫자가 좋아도 나빠도 그대로 올립니다. 간헐적 단식 기록을 조용히 남기고 싶으신 분, 그리고 인디 개발기에 호기심이 동하신 분은 플레이스토어에서 "케톤"을 검색해보세요. 다음에 뵙겠습니다.

👉 케톤 — Play Store에서 보기

러시아 유저에게 긍정 리뷰 하나를 받기까지

며칠 전에 스토어에서 리뷰 하나를 발견했습니다. 별 5개에, 제가 한 글자도 못 읽는 언어로 긴 칭찬이 달려 있었어요.

01-russian-review

언어 설정이 ru-ru인, 러시아 분으로 추정되는 유저였습니다. 해석기를 돌려봤더니 “쾌적하고 사용자 친화적인 인터페이스와 멋지고 무료이며 미니멀한 기능을 갖춘 훌륭한 앱을 만들어주셔서 정말 감사합니다” 라는 뜻이더라고요.

이 리뷰 하나를 받기까지 대략 한 달 정도가 걸렸습니다. 그리고 그 한 달 동안 저는 러시아어를 한 글자도 더 배우지 않았어요. 대신 좀 많이 오만했다는 걸 배웠고, 앞으로는 유저한테 직접 물어볼 줄 아는 앱을 만들어야겠다는 생각을 하게 됐습니다. 오늘 풀어놓을 이야기는 그 한 달입니다.

발단 — ru-ru 유저들이 연속으로 사라졌어요

W15, W16 주간 analytics 리포트를 보다가 눈에 걸리는 줄이 하나 있었어요. 러시아어 설정 유저들이 연달아 D1에서 이탈했다는 내용이었습니다. 설치 다음날 돌아오지 않은 거예요.

모수가 작은 편이라 통계적으로 유의하다고 말하긴 어려웠습니다. 처음엔 그냥 넘기려 했어요. “우연이겠지” 하고요. 근데 다음날 아침에 커피 마시면서 다시 보니까, 우연치고는 너무 깔끔하더라고요. 같은 주간에 영어나 한국어, 일본어 설정 유저들은 그렇게까지 나란히 빠지진 않았거든요. 유독 러시아어만 깔끔하게 이탈하고 있었습니다.

그래서 한 가지 가설이 머릿속에 떠올랐습니다.

설마, 번역 품질이 엉망인 거 아닐까?

오만한 믿음 — “스킬이 있으니까 괜찮겠지”

이 가설이 불편했던 이유는, 케톤에는 이미 /localize 라는 자체 스킬이 있었기 때문입니다. 새 문자열을 추가하면 22개 언어로 자동 번역해주고, 길이 초과 체크하고, format specifier 정합성까지 맞춰주는 도구였어요. 저는 이 스킬을 꽤 신뢰하고 있었습니다. 스킬 문서에도 "quality gates"라고 적어뒀거든요.

그래서 처음 든 생각은 이거였어요. “러시아어 번역이 이상하면 이미 스킬이 걸러냈을 텐데?”

근데 생각해보면 이게 얼마나 오만한 믿음이었는지 조금만 더 들여다보면 바로 보입니다. 제가 러시아어를 한 글자도 못 읽거든요. 폴란드어도, 힌디어도, 우르두어도요. 검증하는 주체인 저 자신이 결과를 읽을 수 없는데 “스킬이 검증해줄 거야” 라고 믿고 있었던 거예요. 이건 신뢰가 아니라 그냥 외면이었습니다.

한번 확인해보자, 싶어서 검수를 돌려보기로 했습니다.

조사 — 에이전트 23명으로 20개 언어 전수 검수

혼자서는 못 합니다. 저는 러시아어 Б도 못 읽으니까요.

그래서 AI 에이전트를 동원했습니다. 언어별로 네이티브 페르소나를 하나씩 세워서 총 19개 페르소나를 만들었어요. 예를 들면 “파리에 사는 30대 여성, Yuka와 Petit BamBou 같은 건강앱을 일상적으로 쓰는 사람” — 이 페르소나가 프랑스어 strings.xml을 한 줄씩 읽어내려가면서 “이건 어색해요”, “이 문장은 Sie와 Du가 섞여 있어요” 같은 리뷰를 남기는 식이었습니다. 거기에 Play Store 마케팅 카피까지 검수하는 에이전트 3명을 더 붙여서 총 23명.

검수 범위는 app/src/main/res/values-*/strings.xml 20개 + fastlane/metadata/android/*/ Play Store 카피 전수였습니다. 이게 몇 시간이 걸리더라고요. 에이전트들이 병렬로 돌아가는데도, 결과를 취합해서 HTML 리포트로 뽑고 다시 읽고 정리하는 시간까지 하면 하루를 통째로 썼습니다.

02-agent-library

그리고 결과가 나왔는데, 솔직히 좀 충격이었어요.

발견 — 한두 곳이 아니었습니다

결과를 요약하면 20개 언어 전부에서 크고 작은 이슈가 나왔습니다. 의학 효능 주장이 원문에 없는데 번역본에 추가돼 있다든지, 브랜드명 "Ketone"이 언어마다 Keton, Cetona, Chetone, ケトン 식으로 제각각 현지화돼 있다든지, 숫자 체계가 한 화면 안에서 데바나가리랑 라틴이 섞여 있다든지… 카탈로그로 정리해보니 언어를 넘나들며 반복되는 패턴이 10가지 정도였어요.

발단이 ru-ru 이탈이었으니 러시아어에서 특히 눈에 띈 것 몇 개만 짧게 짚어보겠습니다.

러시아어에는 "금식/단식"에 해당하는 단어가 크게 두 가지가 있다고 합니다. 하나는 정교회 사순절 같은 종교적 금식, 하나는 건강 목적의 세속 단식이요. 케톤은 세속 건강 앱인데 번역본에는 종교 단어가 여기저기 섞여 있었어요. 러시아 네이티브 페르소나의 리뷰를 읽다가 이런 말을 봤습니다. “건강앱을 켰는데 ‘사순절 시작’ 이라고 적혀 있으면 종교 앱인가 싶을 거예요.” 제가 만든 건 간헐적 단식 타이머인데 러시아 유저는 절반쯤 종교 앱 느낌으로 읽고 있었던 거예요.

그 외에도 러시아어는 굴절 언어라서 과거분사에 성별이 들어간다고 하더라고요. "나는 했다"가 남성형 기본값으로 쫙 깔려 있어서 여성 유저 입장에서는 자기 얘기처럼 안 읽히는 구조였고요. 반말과 존대가 한 앱 안에서 왔다갔다 하는 톤 혼용도 있었습니다. 정책 하나만 먼저 정해뒀어도 막을 수 있던 건데, 그 정책이 없었던 거예요.

실행 — 스킬을 다시 짰습니다

여기서 솔직히 고민이 들었어요. 러시아어만 고치고 끝낼 것인가, 아니면 이 10개 패턴이 앞으로 새 번역에 또 들어가지 않도록 구조적으로 막을 것인가.

후자를 택했습니다. 어차피 다음 번역에도 같은 함정이 반복될 거니까요.

세 가지를 손봤어요.

첫째, 용어집을 대폭 확장했습니다. 원래 .claude/glossary.md 에는 “케토시스는 ketosis로 번역” 같은 의학 용어 9개만 있었어요. 이걸 7개 정책으로 재구성해서, 브랜드명 보호·의학 주장 hedge·종교 단식 용어·톤 일관성·성별 중립·숫자 체계·중복 번역 금지까지 언어별 매트릭스로 담았습니다. 위에서 얘기한 러시아어 이슈들이 여기에 다 들어갔어요.

둘째, /localize 스킬에 Semantic QA 단계를 끼워넣었습니다. 기존 스킬은 "기계적 품질"만 체크했거든요. 길이 초과, format specifier, 중복 키 같은 거요. 여기에 “의미적 품질” 체크를 추가했습니다. 브랜드명이 현지화됐는지, 원문에 없는 의학 주장이 들어갔는지, 남성형 과거분사가 강제되는지 같은 걸 정규식과 에이전트 리뷰로 잡아내는 거예요.

/localize 파이프라인은 이런 흐름이 됐습니다.

04-localize-pipeline

주황색 부분이 이번에 새로 추가된 단계예요. 나머지는 원래 있던 것들인데 순서랑 범위를 다시 짰습니다.

셋째, /localize-audit 이라는 새 스킬을 하나 더 만들었습니다. 기존 /localize 는 “새 문자열을 번역할 때” 쓰는 증분 도구였어요. 근데 이번에 필요했던 건 “이미 있는 번역을 전수 검수” 하는 역방향 도구였거든요. 그래서 이번에 수동으로 한 작업을 그대로 스킬로 박제했습니다. 다음에 비슷한 의심이 들면 명령어 한 줄로 돌릴 수 있게요.

여기까지 쓰고 나서 v1.1.1 배포를 시도했습니다. 그리고 바로 Play Store API가 거부하더라고요. "폴란드어 제목이 30자 한도를 넘었다"고요. 검수 과정에서 폴란드어 Play Store 제목을 좀 더 자연스럽게 고치다가 속격 굴절 때문에 단어 길이가 늘어나버린 거예요. Semantic QA 끝나고 나서 길이 재검증을 안 한 탓입니다. 이 사고는 또 다른 교훈이었습니다 — “길이는 예전에 통과했으니까 안전” 이라는 가정이 얼마나 위험한지. 결국 “Ketone: Post Przerywany IF” (26자)로 줄여서 재배포했고, v1.1.1은 그렇게 세상에 나갔습니다.

보상 — 2일 뒤의 그 리뷰

v1.1.1 배포가 4월 15일 저녁이었어요. 그 리뷰가 도착한 게 4월 17일이었습니다. 딱 이틀 뒤요.

01-russian-review

솔직히 말씀드리면, 이 리뷰와 v1.1.1 업데이트의 인과관계를 증명할 방법은 없습니다. 우연의 일치일 수도 있어요. 이 유저분이 пост vs голодание 이슈를 눈치채고 달라진 걸 체감해서 리뷰를 남긴 건지, 아니면 그냥 어느 날 앱이 마음에 들어서 별점을 준 건지, 저는 모릅니다. 앞으로도 알 길이 없을 거예요.

다만 타이밍이 좀 극적이긴 했어요. 한 달 동안 ru-ru 이탈 6명 붙잡고 씨름하다가, 번역 고쳐서 배포하고, 이틀 뒤에 러시아 유저한테서 첫 5성 리뷰가 온다는 게 말이에요.

답장을 남겨야 하는데 저는 러시아어를 못하잖아요. 그래서 번역기를 띄우고 한국어로 “이 앱을 계속 써주셔서 정말 감사합니다. 앞으로도 잘 부탁드립니다” 같은 말을 적어서 러시아어로 돌렸어요. 돌린 문장을 다시 한국어로 역번역해서 이상하지 않은지 확인한 다음 답글을 달았습니다. 제가 러시아 유저와 나눈 첫 번째 대화입니다. 둘 다 기계 번역으로 대화한 거지만요.

근데 — 왜 러시아어를 지원하냐고요?

이 지점에서 한 번 솔직하게 말씀드리고 싶은 게 있습니다.

러시아어를 한 글자도 못 읽는 제가 왜 러시아어를 지원하고 있을까요? 아랍어도요. 힌디어, 우르두어, 벵골어, 태국어, 베트남어도 마찬가지예요. 1인 개발자가 22개 언어를 깔아두는 게 무리수라는 건 저도 압니다. 이번 같은 사건이 일어날 수밖에 없는 구조거든요.

근데 저는 인디 개발자니까요. 한국어랑 영어만 지원하면 타겟 시장이 좁아도 너무 좁아요. 반대로 22개 언어를 깔아두면 이론적으로는 세계 어디서든 접속해서 쓸 수 있는 앱이 됩니다. 마케팅 비용 0원짜리 앱한테는 이 "어디서든 쓸 수 있다"는 게 꽤 중요한 레버예요. 지난 주에 첫 유입이 생긴 국가가 몇 개 더 늘었거든요.

05-app-going-global

완벽하지 않은 걸 압니다. 아직 제가 못 읽는 언어의 번역본에 어떤 이슈가 남아있는지 다 모릅니다. 이번에 10개 패턴을 잡았지만 11번째 패턴이 또 있을 거예요. 그래도 AI 에이전트라는 도구가 손에 쥐어진 이상, 주어진 도구를 끝까지 써서 할 수 있는 데까지는 해보자는 쪽입니다. 23명 페르소나 세워서 검수 돌리고, 결과 보고 스킬 업그레이드하고, 다시 배포하고. 이번에 한 게 그 과정이었어요.

배운 것 — 데이터만 보면 추측밖에 못 합니다

이번 사건에서 진짜로 배운 건 따로 있습니다.

ru-ru D1 이탈 6명이라는 데이터는 "뭔가 문제가 있다"까지는 알려줬어요. 하지만 “왜” 는 끝내 알려주지 않았습니다. 제가 번역 품질을 의심한 건 데이터가 알려준 답이 아니라 저의 추측이었어요. 맞았을 수도 있고, 틀렸을 수도 있습니다. Бегун=Бегун 중복을 본 979fbfe8 유저가 진짜로 그 화면 때문에 나갔는지, 아니면 그냥 잊어버린 건지, 지금도 모르거든요.

데이터만 보고 “아마 이것 때문일 거야” 라고 추측해서 한 달 동안 에이전트 23명 동원하고 스킬 세 개 고치는 건 좀 가성비가 떨어집니다. 추측이 틀렸으면 이 한 달은 그냥 헛수고였을 거예요. 러시아 유저한테 “혹시 번역이 이상한가요?” 라고 한 번만 물어볼 수 있었다면, 하루 만에 답이 왔을 텐데 말이죠.

그래서 다음에 배포할 기능이 이거입니다.

다음 배포 — 유저한테 직접 물어볼 수 있는 채널

다음 버전에서 더보기 화면 상단에 “당신의 한마디가 필요해요” 라는 카드를 하나 추가하려고 합니다. 탭하면 모달이 올라오고, 자유 입력 텍스트 필드와 선택 이메일, 그리고 번역·버그·제안·칭찬 네 가지 카테고리 칩이 뜨는 간단한 폼이에요. 제출하면 Firestore의 feedback 컬렉션에 그대로 쌓입니다.

로그인 없어도 되고, 이메일도 선택 입력이에요. 그냥 유저가 "이 번역 이상해요"라고 한 문장 툭 던지고 앱으로 돌아갈 수 있으면 됩니다. 제가 Firebase 콘솔에서 읽고, 번역기로 번역해서, 필요하면 답을 남기는 식으로 운영할 생각이에요.

06-feedback-entry

07-feedback-modal

이게 있었으면 이번 한 달 중 적어도 절반은 아꼈을 거라고 생각합니다. 러시아 유저 중 한 명이라도 “이거 종교 앱 같은데요?” 라고 한 줄만 남겨줬으면 제가 거기서부터 팠을 거예요. 데이터만 보고 추측하는 대신요. 그리고 네이티브 스피커가 번역 오류를 지적해주기 시작하면, 기계 QA로는 절대 못 잡는 차원의 품질 개선이 열릴 거라고 봅니다. 어떤 문장이 "문법은 맞는데 어색하다"인지, 어떤 단어가 "직역은 맞는데 실제로 안 쓴다"인지는 결국 그 언어를 모국어로 쓰는 사람만 알거든요.

마치며

한 달 동안 있었던 일을 정리하고 나니 이런 느낌입니다. 한 명의 러시아 유저에게 긍정 리뷰 하나를 받기까지 에이전트 23명이 동원됐고, 스킬 세 개가 갈아엎어졌고, 배포가 한 번 거부당했고, 용어집이 아홉 배쯤 커졌습니다. 효율로 따지면 말이 안 되지만, 인디 개발자한테는 리뷰 하나가 꽤 큰 동력이 됩니다. 그래서 이만큼 한 걸 후회하진 않아요.

다음번에는 추측하지 않는 방법을 만들어둘게요. 유저가 직접 말해줄 수 있는 창을 하나 열어두는 것. 그게 이번 사건에서 제가 얻은 가장 실용적인 교훈이었습니다.

러시아 유저분, 다시 한 번 감사합니다. 답글 러시아어는 번역기가 도와줬지만 마음은 진짜였어요.

👉 케톤 — Play Store에서 보기