지난 이야기
이전 에피소드 작업을 통해 UI/UX를 개선하며 화면은 어느정도 안정됐다. 그러나 지속적인 기록 리듬을 만드는 게 필요해보였고 이번 글에는 그 장치를 만든 과정을 담았다.
기록 리듬 문제 재정의
이 에피소드에서의 작업은 "어떻게 하면 사용자의 일상에 자연스러운 기록 리듬을 만들까?"라는 질문에 답을 찾아보는 과정이었다.
UI 톤을 맞추고 나니 "수행할 미션이 있으면 좋겠다”는 생각이 들었다. 토끼굴 성장 여정만으로는 일일 기록 리듬을 만들기 어렵다고 판단했고, 감정 기반 허브와 추천 데이터를 만들어보기로 했다. 목표는 ① 감정을 고르면 바로 맞춤 챌린지를 제안하는 허브를 만든다. ② 진행 과정에서 매끄러운 흐름을 위해 UX·카피를 정리한다. ③ 챌린지 완료 후 레시피 화면으로 넘어갈 때 데이터가 누락되지 않도록 안정화한다. 이렇게 세 가지를 잡았다.
챌린지 허브 설계

"깡총 챌린지"라는 이름으로 홈화면에서만 진입할 수 있는 게이트를 만들었다. 바텀 탭에 넣어야할까 잠시 고민했는데, 이미 바텀 탭에 마일스톤 기능인 토끼굴이 있었다. 토끼굴이 더 "레시피 기록"이라는 앱의 본질에 가깝다고 여겼기 때문에 바텀 탭에 그대로 두었다. 그리고 홈화면에서 진입 가능한 챌린지 메인 상단에 8가지 감정(기쁨·평온·활력·그리움·피로·모험·아늑함·건강)으로 레시피 추천 장치를 넣었다.
감정 기반 추천 로직
사용자가 선택한 감정의 태그와 challenge_recipes.json 안의 레시피 태그가 하나라도 겹치면 추천 목록에 올리고, 난이도와 미완료 여부로 정렬해 보여준다. 이를 위해 감정 옵션마다 해시태그 세트를 붙여 두었다. 초기 기획 시에는 매칭률이 낮았지만 지금은 전체 태그가 매칭된다. '기쁘고 행복해요'는 바비큐 립 같은 파티 메뉴에 #축하, #특별한날 을 붙이고 '평온하고 차분해요'는 허브차·힐링 레시피에 #명상, #차분함을 달았다. '활기차고 신나요'는 세계 요리·고난이도 메뉴로 #도전, #활력 태그를 부여했고, '피곤하고 지쳐요'는 회복식에 #든든함, #회복을 매칭해 에너지 식단이 즉시 노출된다. 이를 관리하기 위해 감정 태그 ↔ 레시피 태그 매핑 표를 별도로 관리하는 mood-tag-mapping.md 파일을 만들었다. Flutter 단에서는 진입 → 감정 선택 → 태그 매칭 → 추천 카드 → 완료 카드 흐름을 유지한다.
3가지 메인 챌린지 카테고리
챌린지 허브는 사용자의 기분과 상황에 맞는 레시피를 제안하기 위해 3가지 큰 축으로 구성했다. 현재 총 51개 챌린지가 세부 카테고리로 나뉘어 있다.(여기는 앞으로 더 늘리거나, 아예 다른 방향을 고민중이다.)
- 감정별 챌린지: 감정 상태에 맞춘 레시피 큐레이션. 감정을 선택하면 해당 무드 태그와 매칭되는 요리들을 추천한다.
- 세계 맛 여행: 한식부터 이탈리아·멕시코·인도까지 다양한 나라와 지역의 요리를 탐험하는 카테고리. 아시아·유럽·아메리카·퓨전 테마로 구성해 이국적인 맛과 문화를 담았다.
- 건강 라이프: 다이어트·면역강화·식물성 식단 등 건강 목표에 맞춘 레시피. 자연식·케어 등 웰빙을 위한 요리를 제안한다.
진행 UX와 카피 폴리싱
챌린지의 뼈대를 세운 뒤에는 사용자 집중도 높이기 작업을 진행했다. 완료 카드가 터치되지 않던 문제를 해결하고, 카테고리 색상을 앱 팔레트에 맞춰 파스텔 톤으로 통일했다. 진행 화면은 '단계별 진행'과 '완료 & 기록' 두 스탭으로 나눠 최소한의 정보만 보여주고, 다음 동작이 명확히 보이도록 했다. 챌린지 완료 후에는 원할 경우 레시피로 기록할 수 있도록 했다.
챌린지→레시피 파이프라인 안정화

기능을 붙이며 가장 크게 막혔던 문제는 챌린지를 끝내고 레시피 작성 화면으로 넘어갈 때 '소스·양념'과 '만드는 법' 필드가 텅 비는 이슈였다. 원인을 추적해 보니 챌린지 JSON을 만들 때 조리 단계를 포함하지 못했고, 소스·양념 리스트도 그대로는 레시피 입력 폼에 들어가지 않아서였다. 전환 로직을 다시 짜서 조리 단계를 별도 JSON에서 가져오게 했다. 소스·양념 리스트는 문자열로 합쳐 레시피의 '소스 비율' 필드에 매핑하도록 재설계했다. try-catch로 실패 상황을 잡고 전환이 꼬이면 허브로 되돌리는 예외 처리도 붙였다.
추천 데이터 JSON 구조 정리
홈 화면 추천 영역도 손을 봤다. 챌린지 카드와 별개로 "오늘은 뭘 해볼까?"를 꾸준히 던지려면 데이터 구조를 정리할 필요가 있었다.
세 가지 콘텐츠 블록 기획
기획 단계에서 세 가지 축을 정했다. 첫째는 계절 재료로 만드는 제철 레시피. 가을 전어구이, 김장철 보쌈, 겨울 호떡처럼 시의성 있는 요리를 제안해 "지금 이 계절에 챙겨야 할 맛"을 상기시킨다. 둘째는 가볍게 참고할 수 있는 요리 상식 카드. 향신료 보관법, 마이야르 반응, 수비드 조리법처럼 1분 안에 읽을 수 있는 팁으로 요리를 부담스럽지 않은 학습 경험으로 바꾼다. 셋째는 책·영화 추천 카드. '줄리 & 줄리아', '리틀 포레스트: 겨울과 봄', '소금, 지방, 산, 열'처럼 요리를 콘텐츠로 확장해 주는 작품으로 주방 밖에서도 영감과 감상 기록을 이어 갈 거리를 제공한다.

콘텐츠 운영 전략과 업데이트 주기
제철 레시피 블록은 "금요일마다 변경"되도록 업데이트 주기를 설정했다. 이를 위해 미리 리스트를 만들어 두고 금요일에 해당 시즌 레시피가 교체되면 일주일 동안 같은 카드가 유지된다. 더 자주 변경되면 좋겠지만 1인 운영 시 현실적인 주기로 세팅했다. 요리 상식 카드와 책·영화 카드는 시즌을 타지 않는 영역이어서 수십 개의 콘텐츠를 미리 만들어두고 캐러셀 형태로 좌우 스와이프 시 랜덤 노출되도록 만들었다. 앱에 진입할 때마다 새로운 조합이 등장하여 '업데이트되고 있다'는 인상을 줄 수 있고, 운영하는 입장에서도 실제로 잦은 수정 없이 데이터 풀만 가끔 보강하면 된다. 랜덤 캐러셀 구조 덕분에 홈 화면이 정적인 목록으로 굳어 있지 않고, 사용자마다 다른 큐레이션을 체감하게 된다.
JSON 구조 설계와 데이터 아키텍처
세 블록을 lib/data/content/*.json 파일로 체계화하면서 각 콘텐츠 블록마다 제목, 설명, 태그, 이미지 경로 같은 키 구조를 동일하게 맞췄다. 제철 레시피는 조리법을 접어두기-펼쳐두기로 구현해 필요한 사람만 볼 수 있게 했다. JSON 안에 instructions 배열로 조리 순서를 담아 두면 화면에서는 이를 확장 가능한 위젯으로 표현한다.
AI 이미지 생성 프롬프트 전략
제철 레시피와 요리 상식 카드 이미지는 AI 이미지 생성 도구로 직접 만들었다. 프롬프트 작성 시 각 콘텐츠의 핵심 키워드를 조합했다. 예를 들어 "가을 전어구이"라면 "grilled fish, Korean traditional dish, realistic"처럼 사실적인 표현으로 요리 이미지를 담으려했고, "마이야르 반응"이라면 "browning reaction, detailed description, educational illustration"처럼 설명 자료의 성격을 강조했다. 큐레이션 섹션(책·영화)은 실제 작품 표지 이미지를 가져왔다. 모든 이미지는 assets/images/content/ 경로 아래에서 관리하고, JSON에는 상대 경로만 기록해 나중에 이미지를 교체하거나 추가할 때도 구조를 유지할 수 있게 했다.
사용자 경험과 기록 유도 흐름
홈 화면을 스크롤하며 사용자는 계절 콘텐츠나 요리 지식, 문화 콘텐츠를 훑어본 뒤 자연스럽게 기록을 시작할 수 있다. 제철 레시피는 계절감을 환기하고, 토막 상식 카드는 새로운 배움을 제공하며, 책·영화 추천은 요리 너머의 영감을 준다. 이 세 가지 요소가 시너지를 내어 사용자가 '무언가를 기록하고 싶다'는 영감을 얻도록 하고자 했다.
사실 기능적으로는 이미 기록 플로우가 돌아간다. 그럼에도 홈 콘텐츠 섹션을 만든 건 레시피가 재료·조리법·문화권·라이프스타일을 조합해 끝없이 변주되는, 그 자체로 콘텐츠가 풍부한 카테고리라고 생각했기 때문이다. 또한 사용자가 홈을 처음 마주했을 때 "여긴 레시피를 다루는 공간이구나"라고 자연스럽게 인지하기를 바랐다. 그걸 가장 쉽게 보여줄 수 있는 장치가 콘텐츠 블록이라고 판단했다. 그래서 계절·지식·문화 섹션을 홈에 배치하고, 그다음 아카이빙이나 챌린지 실행으로 이어지게 흐름을 묶었다.
마무리하며
깡총 챌린지의 허브는 현재 감정에 맞는 미션을 즉시 제안하고, 폴리싱된 진행 화면은 집중을 돕는다. 전환 파이프라인을 안정화하면서 챌린지와 레시피가 끊기지 않게 연결됐고, 로컬 JSON 기반 홈 추천 데이터가 다시 챌린지로 이어지는 순환을 만든다.
이 과정을 통해 몇 가지 중요한 점을 배울 수 있었다. 첫째, 추천 기능은 데이터 정비와 UX 설계가 정교하게 맞물려야만 비로소 제 역할을 할 수 있다는 사실이다. 둘째, 챌린지와 레시피처럼 여러 기능이 연결된 플로우에서는 중간 단계의 데이터 유실을 막는 방어 로직이 필수적이라는 점을 다시 한 번 확인했다. 마지막으로, 추천 콘텐츠는 1인 개발 환경에서도 데이터 구조만 잘 설계해두면 충분히 유지보수할 수 있겠다는 작은 가능성을 엿볼 수 있었다.
다음 에피소드 예고
Episode 06에서는 TestFlight 직전 데이터 안전망을 다듬는다. 레시피 데이터 백업 전략, Hive 디버깅, Native Storage 전환 검토까지 "데이터가 사라지지 않는 앱"을 만들기까지의 험난했던(?) 과정을 공유한다.