Project
정산칠판 Apps in Toss 미니앱 제작 기록
정산칠판을 만들고 있다. 앱 이름은 우리 모임 정산 칠판, appName은 dutchpay-board로 잡았다. 아직 출시 확정된 프로젝트 소개 글은 아니고, Apps in Toss에 올리려고 구현 중인 개발 기록이다.
만들려는 건 한 번짜리 더치페이 계산기가 아니다. 여행, 회식, 모임처럼 돈 쓴 내역이 여러 번 쌓이는 상황을 정리하는 작은 모임 가계부에 가깝다.
토스 더치페이는 “오늘 점심값” 같은 1회성 정산에 잘 맞는다. 내가 만들고 있는 정산칠판은 “여행 4일치”, “회식 3차까지”, “동아리 운영비 몇 건”처럼 영수증이 계속 쌓인 뒤 마지막에 한 번 정산하는 쪽을 보고 있다.
지금 만든 것
현재 구현은 Apps in Toss 공식 생성기 기반의 Vite + React + TypeScript 프로젝트다. @apps-in-toss/web-framework, TDS 모바일 패키지, Granite 설정을 붙였고, 빌드는 ait build로 앱인토스 업로드용 산출물을 만드는 흐름이다.
기능은 MVP에 필요한 것만 먼저 넣었다.
- 모임 생성
- 멤버 일괄 입력
- 멤버 추가, 이름 수정, 삭제
- 영수증 추가
- 결제자, 금액, 메모, 함께 쓴 사람 선택
- 모임별 총 지출, 영수증 수, 멤버 수 요약
- 정산 전 검토 체크
- 정산 결과 계산
- 사람별로 낸 돈, 쓴 돈, 차액 설명
- 단체방에 붙여 넣을 정산 문구 복사
- 데이터 백업, 복원, 초기화
처음부터 공유 링크, 송금 딥링크, 광고, 리워드 같은 걸 다 넣으면 앱이 빨리 복잡해진다. 그래서 이번 단계에서는 “모임 만들고, 영수증 쌓고, 마지막에 누가 누구한테 얼마 보내야 하는지 계산한다”까지만 확실하게 잡았다.
정산 로직
정산은 크게 두 단계다.
첫째, 멤버별로 순잔액을 만든다.
낸 돈 - 본인 몫 = 차액
차액이 양수면 받을 사람이고, 음수면 보낼 사람이다. 예를 들어 A가 60,000원을 냈고 본인 몫이 25,000원이면 A는 35,000원을 받아야 한다. 반대로 B가 낸 돈은 없고 본인 몫이 20,000원이면 B는 20,000원을 보내야 한다.
둘째, 받을 사람과 보낼 사람을 금액 순서대로 맞춘다. 많이 받을 사람과 많이 보낼 사람부터 매칭해서 송금 줄을 만든다. 이러면 영수증이 여러 건이어도 결과는 “누가 누구에게 얼마” 형태로 압축된다.
균등 분할은 원 단위 정수로 처리했다. 나누어떨어지지 않는 잔돈은 결제자 쪽에 붙인다. 나중에 가중치 분할이나 직접 금액 입력도 타입과 계산 함수에는 남겨뒀지만, 화면에서는 아직 균등 분할만 저장한다. 출시 전 MVP에서는 이게 더 낫다고 봤다.
정산 전에 한 번 더 보게 만든 것
정산 앱에서 제일 무서운 건 계산식보다 입력 누락이다. 수식이 맞아도 영수증 하나 빠지면 결과는 틀린다.
그래서 정산 결과 화면 앞에 검토 항목을 넣었다.
- 영수증이 실제로 들어갔는지
- 어떤 멤버가 한 번도 영수증에 포함되지 않았는지
- 같은 제목과 금액의 영수증이 중복으로 보이는지
- 삭제된 멤버가 남아 있는 영수증이 있는지
이건 거창한 검증 시스템은 아니다. 그래도 단톡방에 정산 결과를 던지기 전에 “뭐 빠진 거 아님?”을 한 번 줄여준다. 정산 도구는 계산을 잘하는 것도 중요하지만, 사용자가 입력 실수를 눈치챌 수 있게 만드는 것도 중요하다.
저장 방식
서버는 아직 없다. 데이터는 기기 안에 저장한다.
기본은 localStorage고, 앱인토스 환경에서는 Storage API에도 저장을 시도한다. 일반 브라우저에서는 앱인토스 네이티브 Storage가 없을 수 있으니, 실패하면 localStorage만 쓰게 했다.
백업과 복원은 JSON 텍스트로 처리했다. 예쁘지는 않지만 MVP에서는 충분하다. 서버 계정, 로그인, 클라우드 동기화까지 붙이면 앱이 커진다. 지금은 “이 기기에서 모임 하나 만들고 정산한다”가 기준이다.
일부러 뺀 것
가장 먼저 뺀 건 토스 송금 딥링크다. 계획서에는 송금 버튼까지 생각해뒀지만, 공식 허용 스펙을 확실히 확인하기 전까지 하드코딩하지 않기로 했다.
공유 SDK도 아직 붙이지 않았다. 지금은 단체방 공유 문구를 복사하는 수준이다. 나중에 공식 API 확인이 끝나면 앱인토스 공유 기능을 붙일 수 있다.
광고, 결제, 리워드, 로그인도 뺐다. 이번 앱은 게임이 아니라 비게임 생활 편의 미니앱이고, 정산이라는 주제 자체가 민감할 수 있다. 전화번호나 계좌번호 같은 민감정보 입력도 받지 않는다. 검수 리스크를 줄이는 게 먼저다.
Apps in Toss 쪽에서 신경 쓴 것
일반 웹앱으로 만들면 대충 브라우저에서만 확인해도 된다. 그런데 이건 Apps in Toss 미니앱으로 올릴 거라 기준이 조금 다르다.
granite.config.ts에는 appName, 브랜드 이름, 대표 색상, 앱 아이콘 URL을 넣었다. WebView 설정도 튀지 않게 잡았다. 뒤로가기와 홈 버튼은 켜고, pull to refresh나 과한 bounce는 껐다.
권한은 클립보드 쓰기만 요청한다. 현재 앱에서 필요한 건 정산 문구나 백업 JSON을 복사하는 정도라서 그렇다. 필요 없는 권한을 먼저 요청하면 앱이 괜히 무거워 보인다.
지금 상태
지금 정산칠판은 “출시 직전 완성품”이라기보다는, Apps in Toss에 올릴 수 있는 MVP 뼈대를 만든 상태다.
모임을 만들고, 멤버를 넣고, 영수증을 쌓고, 정산 결과를 보는 흐름은 들어갔다. 반대로 진짜 배포 전에 확인해야 할 것도 남아 있다.
- 앱인토스 WebView에서 첫 진입, 뒤로가기, 저장 동작 확인
.ait산출물 콘솔 업로드 테스트- 모바일 폭에서 입력 화면 깨지는 곳 없는지 확인
- 공유 SDK 공식 스펙 확인
- 송금 딥링크를 넣을 수 있는지 공식 기준 확인
- 신청폼의 앱 이름, appName, 설명 문구 최종 대조
정산칠판은 나중에 출시가 확정되면 프로젝트 페이지로 따로 남길 생각이다. 지금은 블로그에 개발 기록으로만 둔다. 출시 전에는 괜히 완성된 서비스처럼 말하지 않는 게 맞다.
일단 방향은 이렇다. 계산기 켜고, 카톡에 금액 적고, 누가 얼마 냈는지 다시 묻는 일을 줄이는 작은 칠판. 그 정도면 출발점으로 충분하다.