이거먹어
"오늘 뭐 먹지"를 취향·지금 상황·위치로 1~3개까지 좁혀주는 음식 결정 어드바이저.
- React Native
- FastAPI
- AI
- PostgreSQL
Setup
- Problem
매일 반복되는 "뭐 먹지?"는 사소해 보여도 결정 비용이 크다. 그리고 취향만으로 풀리지 않는다 - 핵심은 "먹고 싶은 것"과 "먹어야 하는 것"의 충돌이다. 다이어트 중이라 끌리는 걸 못 먹고, 아파서 죽을 먹어야 하는데 죽이 싫고, 추운 날엔 국물이 당긴다. 배달앱은 주문 기록과 인기·광고로 추천하지만 그건 "내가 과거에 산 것"이지 "지금 상황의 나"가 아니다. 게다가 배달앱은 주문 전환이 목적이라 "오늘은 가볍게 드세요" 같은 추천은 구조적으로 하지 않는다. 결국 끝없는 메뉴 스크롤 앞에서 결정만 더 미뤄진다.
- Context
PO/PM 전환과 빌더 작업을 병행하면서, 결정 피로라는 일상 문제를 "결정은 우리가, 실행은 기존 플랫폼이"라는 구조로 풀어본 모바일 앱 실험. 모노레포(Expo 앱 + FastAPI + 음식 그래프 파이프라인)로 혼자 끝까지 만들어봤다. 결제·배달은 직접 처리하지 않고 배민·지도 딥링크로 넘긴다. 결정 레이어만 잘하면 된다는 가설이자, 사업자 등록 부담을 피하는 현실적 선택이었다.
- Users
"오늘 뭐 먹지"를 매일 겪는 일반 사용자. 특히 다이어트·건강·알레르기 같은 제약 때문에 끌리는 걸 그대로 못 먹는 사람.
- Hypothesis
안정적 기본 취향(온보딩 그리드로 수집) 위에 지금의 맥락(다이어트·아픔·기분)을 얹는 2층 구조로 추천하면, 배달앱 검색보다 "지금의 나"에 맞는 답을 1~3개로 줄 수 있다. 그리고 "X 못 먹어 → 비슷하고 만족스러운 Y"라는 대체 추천이 이 앱의 심장이 된다.
Build
- What I did
- 음식 관계 그래프 v1 구축 - 182개 음식을 로컬 LLM(Ollama qwen2.5:7b)으로 태깅하고 임베딩(nomic-embed-text)으로 유사도 그래프를 만든 뒤, 사람 검수 보정 레이어(overrides.yaml)로 덮어씀
- 추천 파이프라인 - 하드 필터(알레르기·영구 비선호·제약) → 컨텍스트 보정(평소·다이어트·아플때·숙취·야식) → base taste 점수화 → LLM 선별·이유·대체
- 대체 추천 엔진 - "죽 싫어" 같은 입력에 "왜 이게 죽 대신 괜찮은지" 한 줄 이유와 함께 대안을 제시
- 적응형 온보딩 그리드(유튜브 뮤직식) - 음식 사진을 깔고 멀티 선택으로 base taste를 빠르게 수집
- Expo(React Native) 앱 - 스플래시 → 로그인 → 온보딩 → 추천 → 핸드오프까지 실기기(Android)에서 전체 흐름 동작
- 핸드오프 딥링크 - 배달은 검색 연결, 외식은 카카오맵 주변 검색으로 실행을 기존 앱에 넘김
- 검증 도구 선제작 - 코드 없이 가설을 떠보는 수동 컨시어지 키트와 fake-door 랜딩페이지
- Product decisions
- 결정 좁히기(decision killer) - 여러 개 보여주기가 아니라 1~3개로 강하게 좁힘. 끝없는 스크롤이 결정 피로의 원인이라 일부러 적게 준다
- "지금은 아니야"와 "싫어"를 분리 - 오늘 안 끌림(일시)이 영구 차단으로 굳지 않게
- LLM은 retrieval 다음에만 - 실제 후보를 먼저 필터로 추린 뒤 LLM은 그 안에서만 선별·설명·대체. 없는 메뉴를 지어내는 환각을 구조로 차단
- 표시명과 코드명 분리 - 마케팅 이름(이거먹어)이 바뀌어도 코드베이스는 안 갈아엎도록 표시명과 내부 코드명을 따로 운영
- 결제·배달은 핸드오프로 - 거래는 기존 플랫폼에 넘기고 결정 레이어만 책임짐
Outcome
- Metrics
Phase 0(음식 그래프) 완료 + Phase 1 MVP 상당 부분 동작. 실기기(Android, EAS dev build)에서 전체 흐름이 돈다. 다만 백엔드(API·Postgres·Ollama·이미지)가 전부 개발 Mac 로컬이라 배포가 최대 다음 과제이고, 카카오 로그인은 아직 dev stub. 사용자 지표는 측정 전.
- Result / Learning
"결정을 대신 내려준다"는 확신형 가치가 만만치 않다는 걸 확인. 1~3개로 좁히는 건 쉽지만, 그 좁힘이 신뢰받으려면 추천 품질과 속도가 먼저였다. 첫 추천 지연이 체감을 크게 좌우해서, 부정어를 결정적 파서로 처리하고 한국어 출력을 보장하고 모델을 바꿔 속도를 약 4배 끌어올렸다. 추천 "이유"의 자연스러움보다 "제약을 절대 어기지 않는다"는 신뢰가 이 제품의 1차 관문이라는 게 다음 라운드 가설.
- Retrospective
- 백엔드를 전부 개발 Mac 로컬에 둔 채로 앱 흐름을 먼저 완성한 순서가 "동작은 하지만 나만 쓸 수 있는" 상태를 만들었다. 배포를 더 일찍, 한 조각이라도 끼웠어야 했다.
- 기획서에 "먼저 정하라"고 스스로 적어둔 "누가 돈을 내는가"를 미룬 채 빌드를 키웠다. 결정이 제품 모양을 바꾸는 항목이라, 다음엔 빌드보다 앞에 둔다.
- Tech stack
- Expo
- React Native
- TypeScript
- Expo Router
- FastAPI
- SQLAlchemy
- PostgreSQL
- Ollama (qwen2.5:7b)
- nomic-embed-text
- Docker