Ari.dev

나도 안 쓰는 앱을 만들었습니다 — 토스 미니앱 출시 회고

앱스토어 등록비가 아까워 토스 미니앱을 골랐다. 첫 출시는 열흘 만에 됐지만 다음 업데이트 하나에 두 달이 걸렸고, 반려 6번의 진짜 원인은 프로젝트 첫날 고른 라우터였다. 유저 34명과 리텐션을 그대로 공개하는 사이드 프로젝트 회고.

회고

첫 출시는 열흘 만에 됐습니다. 그런데 그 다음 업데이트 하나를 내보내는 데 두 달이 걸렸고, 그동안 반려를 여섯 번 받았습니다. 최근 한 달 유저는 34명입니다. 잘 된 이야기는 아니지만 그래서 쓸 만한 이야기가 됐습니다.

사이드 프로젝트를 시작했다가 멈춘 적 있는 분들을 생각하며 씁니다. 저도 그랬고, 지금도 완전히 벗어나진 못했습니다.

4년차 프론트엔드 개발자입니다. 회사에서는 호텔 운영 어드민과 예약 서비스를 만듭니다. 회사 일은 요구사항이 오고 일정이 잡히고 리뷰가 붙습니다. 혼자 만드는 건 그 전부가 없다는 뜻인데, 없어서 편한 게 아니라 없어서 아무도 나를 안 밀어준다는 뜻이더군요.


뭘 만들었나

머니터미, 경제·금융 용어를 카드로 배우고 퀴즈로 확인한 뒤 복습 알림으로 다시 만나게 하는 학습 앱입니다. 토스 미니앱(Apps in Toss)에서 동작합니다.

React 18, TypeScript, Vite, Tailwind, Supabase로 만들었고 2026년 3월 말에 시작해 8월 초까지 커밋 170개를 쌓았습니다.

왜 토스 미니앱이었나 - 돈이 없어서

기술적으로 흥미로워서가 아닙니다. 앱스토어와 플레이스토어는 올리는 데 돈이 듭니다.

유저가 몇 명이나 올지 모르는 상태에서 등록비부터 내는 게 순서가 아니라고 봤습니다. 유저가 어느 정도 늘어야 그 돈을 낼 가치가 생기니까요. 토스 미니앱은 그 비용 없이 이미 사람이 있는 곳에 올릴 수 있었습니다.

지금 돌아보면 이 판단은 맞았습니다. 34명이 왔으니까요. 등록비를 먼저 냈다면 회수하지 못했을 겁니다. 다만 맞는 판단이었다는 게 기분 좋은 종류의 확인은 아니었습니다.

만들면서 내린 판단 두 가지

첫 화면에 통계를 두지 않았습니다. 학습 이력이 없는 사람에게 진도율과 정답률을 보여주는 건 빈 대시보드를 보여주는 것과 같습니다. 그래서 처음 들어온 사람에게는 "단어 1개만 배워볼까요?" 하나만 띄웠습니다. 할 일을 하나로 줄이면 시작 부담이 줄 거라고 봤습니다.

복습 알고리즘은 있는 걸 줄여 썼습니다. 간격 반복 학습으로 SM-2가 알려져 있는데, 그대로 쓰기엔 파라미터가 많았습니다. ease와 interval, 반복 횟수만 남기고 정답 여부와 힌트 사용 여부로 다음 복습일을 계산하게 했습니다. 하루 복습량은 10개로 잘랐고요. 알고리즘을 완전히 구현하는 것보다 사용자가 부담을 느끼지 않는 게 먼저라고 판단했습니다.

두 판단 다 지금도 맞다고 생각합니다. 문제는 이게 이미 앱을 켠 사람에 대한 고민이었다는 겁니다. 앱을 켜게 만드는 문제는 손도 대지 않았습니다.

5월, 한 달을 쉬었습니다

커밋 기록이 정직합니다.

3월 ██████████ 61
4월 ███ 18
5월 █ 8        <- 여기
6월 ████████ 51
7월 █████ 31
8월 1

5월에는 다른 일이 바빴습니다. 그런데 바빠서 못 한 것만은 아니었습니다. 유저가 없으니까 개발할 맛이 안 났습니다.

5월 커밋 8개를 열어보니 7개가 심사 반려 대응이었습니다. 새 기능은 하나도 없었습니다. 그 달에만 반려를 네 번 받았고요. 만들고 싶은 걸 만드는 시간이 아니라, 통과하기 위해 고치는 시간이었던 거죠.

이게 사이드 프로젝트에서 제일 위험한 구간이라고 생각합니다. 회사 일이면 재미없어도 합니다. 일정이 있고 기다리는 사람이 있으니까요. 혼자 만드는 건 재미가 유일한 연료인데, 아무도 안 쓰면 그 연료가 끊깁니다. 그리고 연료가 끊기면 유저가 늘 일도 없어지니까 다시 재미가 없어집니다.

6월에 다시 붙긴 했습니다. 다만 "동기를 되찾아서"는 아니었고, 만들다 만 게 눈에 밟혀서에 가까웠습니다.

재설치하면 기록이 사라지던 문제

초기에는 로컬에 저장한 게스트 토큰으로만 사용자를 구분했습니다. 앱을 지웠다 깔거나 기기를 바꾸면 그동안 배운 게 전부 날아갔습니다. 학습 앱에서 진도가 사라지는 건 앱을 지울 이유를 하나 더 주는 셈입니다.

처음에는 이메일 OTP로 계정을 연결하게 만들었습니다. 이메일만 넣으면 기록이 따라오게요. 그런데 이 방식은 심사에서 막혔습니다. 토스 미니앱은 토스 로그인 외의 자체 로그인을 제공할 수 없다는 규정이 있었고, 관련 코드를 전부 걷어내야 했습니다.

두 달쯤 지나 다른 길을 찾았습니다. 토스가 주는 익명 키를 해시해서 서버 프로필과 잇는 방식입니다. 로그인을 요구하지 않으면서 같은 사람을 알아볼 수 있고, 규정에도 걸리지 않습니다. 결과적으로는 이쪽이 더 나은 설계였습니다. 가입 절차가 아예 없으니까요.

플랫폼 위에 올린다는 건 이런 겁니다. 내가 고른 해결책이 막히고, 대신 플랫폼이 준 도구로 다시 풀어야 합니다. 답답했지만 결과물은 더 나아졌습니다.

기술적으로는 이 작업이 제일 만족스러웠습니다. 그런데 이것도 결국 이미 쓰고 있는 사람을 잃지 않기 위한 일이었습니다.

출시는 열흘, 그 다음 업데이트는 두 달

3월 27일, 처음으로 빌드를 올렸습니다. 심사에 넣은 건 아니고 실기기에서 돌려보려고 올린 테스트 빌드였는데, 그날 하루에만 11개를 만들었습니다. 10시 57분에 첫 번째, 15시 36분에 열한 번째. 로컬에서 되던 게 토스 안에서는 다르게 동작하니 올려서 확인하는 수밖에 없었습니다.

그리고 4월 7일에 출시됐습니다. 처음 빌드를 올린 지 열흘 남짓이었습니다. 여기까지는 순조로웠다고 말할 수 있습니다.

문제는 그 다음이었습니다. 다음 날 올린 업데이트가 반려됐고, 거기서부터 두 달을 막혔습니다.

반려빌드
4/820260408-78
5/720260507-80
5/2820260528-81
5/29 12:2720260529-85
5/29 14:5420260529-86
6/120260601-88

5월 29일에는 두 번 떨어졌습니다. 12시 27분에 반려되고, 고쳐서 다시 올리고, 14시 54분에 또 반려됐습니다.

5월에는 출시가 한 번도 없었습니다.

1차 반려는 4건이었습니다

백버튼이 시스템 것과 앱 자체 것 두 개가 같이 보인다, 첫 화면에서 뒤로가기를 눌러도 미니앱이 안 닫힌다, 랜딩 스킴이 접속되지 않는다, 그리고 토스 로그인 외에 자체 로그인을 제공할 수 없다.

앞의 셋은 규격을 몰라서 생긴 문제라 고치면 됐습니다. 백버튼은 토스가 주는 백 이벤트를 단일 핸들러로 통합하고, 화면 자체 백버튼을 제거해 시스템 것 하나로 통일했습니다.

문제는 네 번째였습니다. 이메일 OTP 로그인을 통째로 들어내야 했고, 그게 앞서 말한 재설치 기록 유실 문제의 해결책이었습니다.

나머지 다섯 번은 전부 같은 사유였습니다

앱 내 기능의 랜딩 스킴이 정상적으로 작동하도록 수정해 주세요.

같은 문장을 다섯 번 받는 동안 제가 한 일은 이렇습니다.

시점한 일
5/28scheme URI에서 pathname을 못 읽고 있던 것 발견, 추출 로직 추가
5/29랜딩 라우팅과 기본 홈 리다이렉트가 경합하던 문제 제거
5/29단위 테스트 12케이스 추가, Sentry breadcrumb으로 실기기 스킴 값 캡처
6/1HashRouter를 BrowserRouter로 교체

마지막 반려 사유는 이랬습니다.

기능 스킴에 포함된 # 기호를 제거 후 다시 요청해주세요.

HashRouter를 쓰고 있었습니다. 그러니 주소에 #가 들어갔고, 플랫폼이 받는 스킴은 그걸 처리하지 못했습니다. 파싱 로직을 아무리 고쳐도 통과할 수 없는 구조였습니다.

6월 1일 오전 10시 30분에 여섯 번째 반려를 받았습니다. 라우터를 갈아끼우고 다시 올려서, 같은 날 12시 56분에 출시됐습니다. 두 달을 막고 있던 게 두 시간 만에 풀린 겁니다.

두 달 동안 저는 제가 짠 파싱 코드를 의심했습니다. 로그를 심고, 경합을 없애고, 테스트를 열두 개 썼습니다. 전부 필요한 작업이었지만 원인은 아니었습니다. 정작 봐야 했던 건 라우터를 무엇으로 골랐는가였고, 그건 프로젝트 첫날 별생각 없이 정한 것이었습니다.

의심의 방향이 틀렸던 겁니다. 내가 최근에 짠 코드부터 의심하는 건 자연스럽지만, 그 코드가 올라앉은 전제는 잘 안 봅니다. 오래됐고 잘 돌던 것일수록 더 그렇고요.

풀리고 나서는 6월 한 달에만 여덟 번 출시했습니다. 막혀 있을 때 아무것도 못 내보내다가, 뚫리니까 쌓여 있던 게 한꺼번에 나간 겁니다. 5월 커밋이 8개, 6월이 51개인 것도 같은 이야기입니다.

심사가 끝난 뒤에도 푸시 알림 동의 문구가 검수에서 한 번 더 걸렸습니다. 플랫폼 위에서는 코드만 통과하면 되는 게 아니라 문구도 통과해야 하더군요.

출시하고 본 숫자: 34

4월에 출시했고, 최근 한 달(2026.07.18 ~ 08.18) 다녀간 사람은 34명입니다. 하루 접속자는 1명에서 5명 사이였습니다.

리텐션은 이렇습니다.

머니터미 리텐션 곡선. D0 100%에서 D1 30%로 떨어지고 D9 이후로는 3%에 머문다.
D1D3D7D9 이후
잔존율30%15%10%3%

D9 이후의 3%는 비율로 쓰면 그럴듯하지만 34명 기준이니 한 명입니다. 중간에 D5가 21%로 D4(12%)보다 높은 구간도 있는데, 이것도 표본이 작아서 생긴 흔들림이지 뭔가 좋아진 게 아닙니다.

숫자를 크게 보이게 쓰는 방법은 압니다. "출시 한 달 만에 30명 돌파" 같은 문장이요. 그런데 그렇게 쓰면 제가 배울 게 없어집니다.

내가 상정한 사용자는 없었습니다

이건 좀 놀랐던 부분입니다.

연령인원
30대 초반14명
40대11명
20대 초반4명
20대 후반2명
30대 후반2명
60대 이상1명

만들 때는 막연히 사회초년생을 떠올렸습니다. 경제 용어를 처음 접하고 부담을 느끼는 사람이요. 그래서 진입장벽을 낮추는 데 공을 들였고요.

실제로 온 사람은 30대 초반과 40대가 4분의 3이었습니다. 20대 후반은 2명입니다.

토스에 있는 사용자 분포를 따라간 것일 수도 있고, 금융 정보에 관심을 갖는 시기가 제 짐작보다 늦은 것일 수도 있습니다. 34명으로는 알 수 없습니다. 확실한 건 제가 머릿속에 그린 사용자와 실제로 온 사람이 달랐고, 저는 그 차이를 출시하고 나서야 알았다는 겁니다.

가장 후회하는 것

여기까지 쓰고 나니 하나로 모입니다.

저도 안 쓰는데 남들은 쓸 거라고 생각했습니다.

만드는 동안 이 앱으로 금융 용어를 공부한 적이 없습니다. 기능이 도는지 확인하려고 켰을 뿐입니다. 복습 알림이 와도 껐습니다. 제가 하루에 10개씩 경제 용어를 외우고 싶은 사람이 아니었으니까요.

그러면서 다른 사람은 그럴 거라고 가정하고 넉 달을 썼습니다.

진입장벽을 낮추고 복습 주기를 조정하고 재설치해도 기록이 남게 만든 건 전부 좋은 작업이었습니다. 다만 그 전에 물었어야 할 질문이 있었습니다. 이 앱을 매일 켤 이유가 나한테 있나. 나한테 없으면 남한테도 웬만해선 없습니다.

만들고 싶은 걸 만드는 건 사이드 프로젝트의 특권입니다. 하지만 만들고 싶은 것과 쓰고 싶은 것은 다르고, 저는 그 둘을 구분하지 않았습니다.

그래서 지금

접지는 않았습니다. 어떻게 하면 유저를 늘릴 수 있을지 계속 생각하고 있습니다. 다만 방향은 바뀌었습니다. 예전에는 기능을 더 좋게 만들면 사람이 올 거라고 봤는데, 지금은 사람이 올 이유부터 찾아야 한다고 봅니다. 순서가 반대였던 거죠.

이번에 얻은 건 앱이 아니라 질문입니다. 내가 이걸 쓸까? 다음에 뭘 만들든 이 질문을 첫 커밋 전에 하려고 합니다.

34명이 적은 숫자라는 건 압니다. 그래도 34명은 0명이 아니고, 그중 몇 명은 일주일 뒤에도 돌아왔습니다. 그 사람들이 왜 돌아왔는지는 아직 모릅니다. 그걸 알아내는 게 다음 할 일입니다.


머니터미 - https://minion.toss.im/DLp6xN1t

댓글