← back to services

live · service · android only

운명일기

사주 · 성명학 · 궁합 · 길일 — 전통적인 만세력 데이터를 기반으로 AI 가 매일의 풀이를 작성해주는 운세 앱. 우리연애 의 커플 운세 패턴을 더 밀어붙여 만든 차기작입니다.

Flutter Provider Firebase Auth In-App Purchase Node.js Express PostgreSQL Gemini API 만세력

서비스 소개

운명일기는 만세력의 전통적인 풀이 방식을 그대로 두지 않고, 사용자의 사주 · 이름 · 상대의 사주를 입력하면 AI 가 그 자리에서 자연스러운 한국어 풀이를 써내려가는 앱입니다. 오늘의 운세, 사주 분석, 성명학, 궁합, 길일 추천까지 — 무겁지 않게, 매일 한 줄씩 들춰보는 용도로 디자인됐습니다.

앱은 Flutter, 서버는 Node.js + Express + PostgreSQL. 만세력 계산은 @fullstackfamily/manseryeok 라이브러리로 정확한 사주 기둥을 뽑고, 그 결과와 사용자 컨텍스트를 함께 Gemini API 에 보내 풀이를 받아옵니다. 결제는 Google Play 인앱결제(StoreKit 2 지원 포함)로 사주 티켓을 구매하는 모델입니다.

Architecture

한 대의 VPS 위에 컨테이너로 돌아가는 일반적인 구성. 외부로는 Gemini API 와 인증 / 결제 관련 외부 SDK 를 호출합니다.

/ client Android app Flutter · Provider iOS App Store 거절 · 미출시 https · api.fate.jiny.shop / edge Nginx · reverse proxy TLS · CORS · 정적 OG 이미지 / app Express API JWT · IAP 검증 · 만세력 계산 · 티켓 회계 / data PostgreSQL 유저 · 사주 · 티켓 · 결제 내역 manseryeok npm 라이브러리 · 사주 기둥 / external Gemini API 사주 · 성명학 · 궁합 풀이 생성 Firebase Auth Google Sign-In Google Play Billing 사주 티켓 인앱결제 single VPS · Docker

Behind the scenes

만들면서 가장 인상 깊었던 두 가지 — 한쪽 스토어가 막힌 채 출시한 일, 그리고 전통 사주를 AI 에게 시킨 일.

  1. 01

    iOS 는 세 번 거절당하고 멈췄다

    기능적으로는 iOS / Android 양쪽이 모두 동작했지만, App Store 심사에서 같은 이유로 세 번 거절받고 우선 멈췄습니다. 거절 사유는 Guideline 4.3(b) — Design · Spam:

    The app primarily features astrology, horoscopes, palm reading, fortune telling or zodiac reports that duplicate the content and functionality of similar apps in a saturated category. …there are already enough of these apps on the App Store.

    표현을 다듬는다고 해결될 종류가 아니라, "사주 / 운세는 이미 차고 넘치는 카테고리이니 새로 받지 않겠다" 는 정책적 거절이었습니다. 세 번째 답을 받았을 때는 — 솔직히 — 의지가 꺾였습니다. 이미 모든 기능이 양쪽 모두에서 잘 돌아갔고, 베타 테스터들의 피드백도 좋았던 시점이라 더 그랬습니다. 결국 우선은 Android 만으로 출시 — 코드와 기능이 갖춰져 있어도 어떤 문은 그냥 닫혀 있다는 걸 한 번에 받아들여야 했습니다. iOS 재출시는 시간을 두고, 같은 만세력 엔진 위에 다른 형태(예: 일기 / 다이어리 + 보조 도구)로 다시 시도해 볼 생각입니다.

  2. 02

    Gemini 에게 사주를 시키기

    만세력으로 뽑은 일주 · 월주 · 시주 같은 정확한 데이터는 코드가 책임지고, "그래서 오늘 어떻게 살라는 건데?" 같은 풀이는 AI 에게 맡겼습니다. 처음엔 응답이 자유 텍스트라 파싱이 흔들렸고, 토큰이 부족해 마지막 결론이 잘리는 일도 잦았습니다. 그래서 Gemini 의 JSON 응답 모드를 쓰고, maxOutputTokens 를 8192 → 16384 로 두 배 늘리고, 프롬프트를 만세력 결과 + 톤 가이드 + 출력 스키마의 세 단으로 분리해 안정화했습니다. 나중에는 Docker 컨테이너 DNS 설정이 빠져 외부 API 호출이 간헐적으로 실패하는 문제까지 잡고서야 — 결과가 매번 멀쩡하게 돌아오기 시작했습니다.

    그리고 한 가지 — 개발하면서 가장 의외였던 건 "테스트 비용" 자체였습니다. 프롬프트를 한 번 다듬을 때마다 Gemini 호출이 일어나고, 그게 그대로 토큰 비용으로 돌아옵니다. 기능 하나를 안정시키기까지 같은 사주를 수십 번 풀어보는 동안, 1인 운영 입장에선 이 비용이 의외로 빠르게 쌓였습니다. 그래서 같은 입력(사주 기둥 + 요청 종류 + 날짜)에 대해서는 결과를 캐시하는 레이어를 도입했습니다 — 운영 단계에선 비용 절감 효과가 있었고, 그 이전에 개발 단계의 반복 호출 비용을 먼저 잡아주었습니다.

Screenshots

카드를 누르면 큰 이미지로 볼 수 있습니다.

More

지나온 버전과 앞으로 들어갈 항목을 별도 페이지에서 확인할 수 있습니다.