AI가 계산을 하지 않는 예산 관리 앱을 만들었습니다
요약
기존 예산 앱들이 '무엇을 썼는지'에 초점을 맞춘 것과 달리, 이 앱은 '오늘 얼마까지 쓸 수 있는지'라는 질문에 단 하나의 숫자로 답합니다. 핵심은 잔액에서 예정된 지출을 제외한 '안전하게 쓸 수 있는 금액(safe-to-spend)'을 계산하는 엔진입니다. AI는 이 계산 결과를 바탕으로 사용자에게 재정적 조언을 제공합니다.
핵심 포인트
- 지출 가능 금액을 사전에 계산하여 예산 관리를 개선했습니다.
- 순수 Dart '엔진' 레이어를 구축해 유닛 테스트와 엣지 케이스 처리에 집중했습니다.
- AI(Gemini)는 회계 처리 대신, 로컬에서 계산된 사실 기반의 설명 및 조언 역할만 수행합니다.
대부분의 예산 관리 앱은 하나의 질문에 답합니다: 내가 무엇을 썼는가? 하지만 제가 실제로 스스로에게 던지는 질문은 다릅니다: 28일에 후회하지 않으려면 오늘 얼마까지 쓸 수 있을까?
그래서 저는 두 번째 질문에 단 하나의 숫자로 답변하는 Android 앱인 Budget Lover를 만들었습니다. 이 앱은 매일 '안전하게 쓸 수 있는' 금액과, 추가 질문을 할 수 있는 AI 어드바이저 기능을 제공합니다. 저는 컴퓨터 과학 학생이며 이것은 개인 프로젝트입니다. 아직 출시되지 않았기 때문에 아래 내용은 에뮬레이터에서 데모 데이터를 사용하여 구축하고 테스트한 내용입니다.
단 하나의 숫자: 안전하게 쓸 수 있는 금액 (safe to spend)
핵심 아이디어는 간단합니다. 계좌에 있는 잔액에서 다음 급여일 전까지 이미 지출이 예정된 모든 것을 뺀 값을 계산하는 것입니다:
// 제 엔진을 간소화한 코드
safe = balance
- upcomingBills
...
남은 금액은 자유롭게 쓸 수 있는 돈이며, 이를 다음 수입일까지 남은 일수로 나누면 일일 할당액이 됩니다. 실제 버전에서는 월별 예산 한도, 여행 경비, 지출 기록에서 감지된 부채 상환 및 구독료 같은 항목들도 처리하지만, 구조는 동일합니다.
저는 이 모든 것을 Flutter나 Firebase 임포트가 없는 순수한 Dart '엔진' 레이어에 넣었습니다. 이것이 프로젝트에서 최고의 결정이었다고 생각하는데, 그 이유는 밀리초 단위로 유닛 테스트(unit test)를 할 수 있고, 앱에는 많은 엣지 케이스(edge case)가 존재하기 때문입니다 (월말, 변동하는 급여일, 내일 발생하는 청구서 등).
AI는 설명하고, 코드가 계산한다
저는
사용자가 질문을 하면, 앱은 먼저 관련 **사실(facts)**들을 로컬에서 계산합니다: 현재 지출 가능한 금액(safe-to-spend), 구매 후 예상 금액, 새로운 일일 할당량, 다가오는 청구서 등입니다. 그 후에야 이 사실들과 질문을 Gemini로 전송하고, 결과를 일반 언어로 설명해 달라고 요청합니다.
위의 스크린샷에 있는 어드바이저의 답변("새로운 지출 가능 금액 €290, 판정: 빠듯함")은 제가 만든 엔진이 생성한 숫자를 기반으로 합니다. 모델의 역할은 회계 처리가 아니라 톤과 설명입니다. 부가적인 효과는 다음과 같습니다: 사실들은 단지 합계와 카테고리 이름일 뿐이므로, 모델은 개별 거래 내역을 볼 필요가 없습니다.
동일한 엔진은 '만약에?' 시뮬레이터를 구동합니다. 이 시뮬레이터는 실제 데이터로 한 번 계산을 실행하고, 변화가 가해진 경우(€150 지출, 구독 취소, 수입 감소 등)로 다시 한번 계산하여 그 차이를 보여줍니다. 아무것도 저장되지 않습니다.
앱에 API 키가 없음
초기에 제가 저지른 실수는 앱 내부에 AI 키를 포함하여 배포한 것이었습니다. APK 안에 있는 것은 무엇이든 추출될 수 있습니다. 저는 Firebase AI Logic으로 전환했는데, 이는 앱과 Gemini 사이에 위치하며, 따라서 앱에는 어떤 키도 포함되어 있지 않습니다. App Check와 결합하여 요청은 실제 앱에서만 작동합니다.
비용도 발생합니다. 무료 티어 제한이 낮기 때문에 어드바이저에게는 일일 메시지 카운터가 있습니다(스크린샷에서 "10 left"를 볼 수 있음). 그리고 영수증 읽기와 같은 작은 작업에는 더 가볍고 저렴한 모델을 사용합니다.
가장 많이 배운 작지만 중요한 기능들
- 영수증 스캔: 사진이 경량 Gemini 모델로 전송되면 금액, 가맹점, 카테고리를 반환합니다. 이 답변을 파싱하는 것은 유효성 검사가 포함된 일반 코드로 이루어지므로, 잘못된 답변이 데이터를 손상시킬 수 없습니다.
- 구독 서비스: 정기적인 결제 내역이 한 곳에 모여 연간 비용과 함께 표시됩니다. 앱은 이름만으로 종류(스트리밍, 음악, 클라우드 등)를 파악하여, 세 개의 스트리밍 서비스처럼 중복되는 부분을 발견하고 이름을 언급하지 않고도 AI에게 그 종류를 알려줄 수 있습니다.
- 여행: 여행별 예산, 일별 및 인당 비용, 실시간 통화 변환 기능을 제공합니다.
- 월간 요약: PDF로 내보낼 수 있는 스토리 형식의 카드입니다.
- 경험치(XP)와 배지: 좋은 습관에 대한 작은 보상입니다.
- 15개 언어 지원, 오른쪽에서 왼쪽으로 쓰는 아랍어 포함. 저는 직접 작은 번역 계층과, 번역이 박스보다 길 경우 실패하는 레이아웃 테스트를 작성했습니다.
과거의 나에게 전하고 싶은 말
- 로직을 위젯에 넣지 마세요. 엔진 계층은 일주일 만에 그 가치를 증명해냈습니다.
- 모델이 함수가 할 수 있는 일을 하도록 두지 마세요. 숫자가 아닌 언어 처리에 사용하세요.
- 지루한 부분을 테스트하세요. 이 프로젝트에는 50개가 넘는 테스트 파일이 있으며, 제가 발견한 버그 대부분은 UI 문제가 아니라 날짜 경계 케이스였습니다.
- 데모 데이터가 중요합니다. 실제 데이터를 건드리지 않고 스크린샷을 찍고 테스트할 수 있도록 데모 계정을 만들었습니다.
사용 기술 (Stack)
Flutter와 Dart, 상태 관리를 위한 Provider, Firebase Authentication 및 Firestore, Gemini를 활용한 Firebase AI 로직, 그리고 Flutter의 PDF 및 인쇄 패키지입니다.
저는 이와 같은 앱과 웹사이트 구축을 위한 프리랜서 작업을 찾고 있습니다. 제 작업물에 대해 더 보고 싶거나 앱 아이디어가 있다면 포트폴리오에서 저를 찾아주세요.
포트폴리오: https://ostyl51.github.io
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기
