냉장고 속 유통기한, 앱 하나로 끝냈다 — "홈 인벤" 앱 개발기

Rony·2026년 6월 19일
post-thumbnail

"분명히 샀는데 또 샀네." "이거 언제 산 거지?" 냉장고 문을 열 때마다 반복되는 이 두 문장을 없애고 싶었다. 그렇게 만든 가정용 재고관리 앱 홈 인벤(Home Inven) 의 기능과 구현 이야기를 여기에 풀어볼까 한다..


1. 어떤 앱인가

홈 인벤은 가정 안의 식품·생활용품·의약품 재고를 한곳에서 관리하는 모바일 앱이다. 핵심은 두 가지 문제를 푸는 데 있다.

  • 유통기한을 놓쳐서 버리는 음식 을 줄인다.
  • 다 떨어진 줄 모르고 또 사거나, 산 줄 알고 안 사는 재고 착오를 막는다.

처음에는 인터넷 없이도 돌아가는 완전 오프라인 앱으로 2025년도에 배포되었지만, 지금은 가족과 재고를 공유하고, 4개 언어를 지원하며, 홈 화면 위젯과 바코드 스캔까지 갖춘 앱으로 발전했다.


2. 기술 스택

크로스 플랫폼 모바일 앱이라 React Native + Expo 조합을 선택했다. 한 코드베이스로 iOS와 Android를 모두 커버하면서, 카메라·알림·백그라운드 작업 같은 네이티브 기능은 Expo 모듈로 안정적으로 끌어다 쓸 수 있다는 점이 좋았고, 무었보다 내가 nodejs 개발자이기 때문에 선택한것도 없지않아 있.... ㅋ

영역사용 기술
프레임워크React Native 0.76 + Expo SDK 52
언어TypeScript (strict mode)
상태 관리Zustand 5
로컬 저장소AsyncStorage
클라우드 / 인증Supabase (Postgres + Auth)
결제 / 구독RevenueCat (react-native-purchases)
내비게이션React Navigation 7 (Stack + Bottom Tabs)
알림expo-notifications + expo-task-manager
카메라 / 이미지expo-camera, expo-image-picker, expo-image-manipulator
다국어i18next + react-i18next
공유 인텐트expo-share-intent
날짜 처리date-fns 4
차트react-native-chart-kit

React Native 개발을 시작하게되면 개발자들은 Expo 선택여부 앞에 많은 고민에 잠기게 된다. Expo 를 쓰면 확실히 쉽게 개발을 시작할 수 있지만 또 블로그 글을 보다보면 나중에는 어차피 갈아탄다 아니다 이런 얘기가 많기 때문이다.
둘다 써본 결론은 Expo 로 하는게 더 좋다? 인것같다.
요새 Expo 모듈이 잘 나오고 있어 개발이 더 편하기도 하고, 나중에 expo 에서 지원을 안하는 기능때문에 이젝트해야 한다고 하지만 실제 구현하려는 기능이 expo 에서 거의 구현이 가능한게 많기 때문이다.
정 신경쓰인다면 개발전에 GPT 등에게 생각하고 있는 기능에 필요한 모듈이 expo 에서 지원이 되는지 한번 확인해보는것도 좋을것같다.


3. 핵심 기능과 구현 이야기

3.1 재고 관리의 기본기

물품마다 이름·카테고리·보관 위치·수량·단위·구매 링크·사진·메모·바코드를 담을 수 있다. 카테고리(식품, 생활용품, 의약품 등)와 보관 위치(냉장실, 냉동실, 창고 등)는 기본값을 제공하면서도 사용자가 자유롭게 추가·수정·삭제할 수 있게 했다. 즐겨찾기와 핀 고정으로 자주 쓰는 물품을 위로 끌어올릴 수도 있다.

목록 화면은 실시간 검색, 상태 필터(임박/만료/부족/소진), 카테고리·위치 필터, 정렬을 모두 지원한다. 여기서 신경 쓴 부분은 사용자의 편의성이다.
단순히 리스트만 보여주는것이 아니라 "pin" 기능을 통해 자주 사용하는 물건을 상위로 배치 할수 있고 리스트형식이 아니라 그리드 형식으로 노출선택이 가능하도록 기능을 추가했다.

3.2 유통기한, 색으로 말한다

날짜 숫자만 보여주면 사람은 위급함을 못 느낀다. 그래서 남은 기간을 4단계 상태로 환산하고 색을 입혔다.

상태조건색상
안전(safe)8일 이상 남음초록
주의(warning)4~7일 남음주황
위험(danger)0~3일 또는 당일빨강
만료(expired)기한 경과회색

처음엔 홈화면을 어떻게 보여주는게 좋을까 고민을 하다가 통계화면과 같은 차트를 넣었었는데, 눈에 잘 들어오지 않았다. 그러다가 문득 일정관리를 캘린더로 하는게 생각나서 유통기한도 캘린더로 보여주는게 한눈에 남은 일자를 파악할수 있어서 좋을것같다는 생각이 들어 홈화면은 캘린더 형식으로 유통기한을 보여주게 수정했고, 한화면에 재고가 부족한 아이템도 보일 수 있도록 재고 영역도 추가하게 되었다.
달력 위에 어느 날 무엇이 만료되는지 점으로 찍어주고, 날짜를 탭하면 그날 만료되는 물품이 캘린더 하단에 펼쳐진다. 이 캘린더모양은 그대로 위젯으로도 반영된다.

3.3 스마트 알림 — 앱을 안 켜도 알려준다

알림은 이 앱의 심장이다. 두 종류로 나뉜다.

  • 일일 정기 알림 — 매일 사용자가 정한 시각(기본 오전 9시)에 "유통기한 경과 2개, 재고 부족 1개" 식으로 그날의 점검 거리를 요약해 보낸다. 문제가 없으면 "오늘의 재고 점검 완료!" 처럼 메시지 자체가 바뀐다. 알림을 탭하면 해당 상태 필터가 적용된 목록으로 바로 딥링크된다. 주로 인터넷에서 물건을 구매하는 시간에 맞춰 알림을 맞추면 좋을것 같았다.
  • 즉시 이벤트 알림 — 수량을 줄이다 최소 수량 이하로 떨어지거나 0이 되면 그 자리에서 "재고 부족 / 재고 소진" 알림이 뜬다.

가장 까다로웠던 건 앱이 꺼져 있어도 알림이 최신 데이터를 반영하게 만드는 일이었다. 로컬 알림은 예약 시점의 데이터로 고정되기 때문에, 그 사이 재고가 바뀌면 내용이 어긋난다. 이를 expo-task-manager 의 백그라운드 태스크로 풀었다. 약 12시간 주기로 시스템이 앱을 깨워 최신 재고로 일일 알림을 다시 스케줄링하고, 이 태스크는 앱 종료는 물론 기기 재부팅 후에도 살아남는다.

알림 제어는 계층 구조로 설계했다. 전역 설정으로 알림 전체를 끄거나, 물품마다 notificationsEnabled 를 꺼서 특정 물품만 알림에서 제외할 수 있다.

3.4 바코드 스캔으로 빠르게 차감

장 본 물건을 일일이 손으로 입력하는 건 고통이다. 그래서 expo-camera 로 실시간 바코드 스캔을 붙였다. 등록된 물품의 바코드를 비추면 해당 물품을 찾아주고, 여러 개를 연속으로 찍은 뒤 각각의 차감 수량을 조정해 한 번에 반영할 수 있다. 스캔 라인 애니메이션을 주어 정말 스캐너로 찍는듯한 느낌을 주도록 공을 들였다.

3.5 구매 링크 공유로 한 번에 등록

쇼핑 앱에서 산 물건을 등록할 때, 상품 페이지를 공유하면 앱이 알아서 채워주면 어떨까. expo-share-intent 로 외부 앱의 공유 시트에 홈 인벤을 띄우고, 넘어온 URL을 분석한다. 이미 같은 링크로 등록한 물품이 있으면 그 상세 화면으로 보내고, 없으면 상품명·대표 이미지·가격까지 미리 채운 추가 화면으로 연결한다. 단축 URL을 따라가며 실제 상품 URL을 복원하고 상품 정보를 뽑아내는 스크래핑 로직이 이 기능의 핵심이다. 주로 사용하는 앱이 쿠팡과 N+스토어 이기 때문에 해당 앱에서 "공유" 로 "홈인벤" 을 선택시 위의 기능이 작동하도록 적용했다.

3.6 다국어 — 4개 언어 동시 지원

한국어로 시작했지만 한국어·영어·중국어·일본어 4개 언어를 지원한다. i18next + react-i18next 로 구성하고, 모든 UI 문자열은 t('네임스페이스.키') 로만 출력한다. 하드코딩된 문자열은 두지 않는 것을 규칙으로 삼아, 새 화면을 만들 때 4개 언어 파일에 키를 함께 추가한다.

언어 선택은 앱이 알아서 시작한다. 최초 실행 시 expo-localization 으로 기기 언어를 감지해 지원 언어면 그대로, 아니면 영어로 떨어뜨린다. 한번 정해지면 설정값으로 저장되고, 이후엔 사용자가 직접 바꿀 수 있다. 날짜와 요일도 Intl.DateTimeFormat(i18n.language, ...) 로 언어에 맞춰 표시한다.


4. 앱의 장점

4.1 오프라인 우선, 그러나 막히지 않는 클라우드 — Repository 패턴

이 앱의 출발점은 "인터넷 없이도 완벽하게 돌아간다" 였다. 동시에 "가족과 냉장고를 공유하고 싶다" 는 요구도 있다. 로컬 저장과 클라우드 동기화는 보통 서로 충돌하는 요구지만, 저장소 추상화 로 깔끔하게 분리했다.

IStorageRepository 라는 인터페이스 하나를 정의하고, 이를 두 구현체가 따른다.

  • AsyncStorageRepository — 로그인하지 않은 사용자용, 모든 데이터를 기기 로컬에 저장
  • SupabaseRepository — 로그인한 사용자용, 같은 인터페이스를 Postgres 쿼리로 구현
let currentRepository: IStorageRepository = new AsyncStorageRepository();

export const getRepository = () => currentRepository;
export const setRepository = (repo: IStorageRepository) => {
  currentRepository = repo;
};

화면과 서비스 코드는 언제나 getRepository() 만 부른다. 로그인 여부에 따라 실제 구현체가 통째로 교체될 뿐, 호출하는 쪽은 자신이 로컬을 쓰는지 클라우드를 쓰는지 신경 쓰지 않는다. 덕분에 "오프라인 전용 앱" 에 클라우드를 얹으면서도 화면 코드는 거의 손대지 않았다.

4.2 가족과 함께 쓰는 워크스페이스

로그인하면 워크스페이스를 만들고 가족을 이메일로 초대할 수 있다. 초대를 수락한 구성원은 같은 재고를 함께 보고 편집한다. 한 사람이 우유를 차감하면 다른 가족의 화면에도 반영되는 구조다. 워크스페이스·멤버·초대 상태는 Supabase에 모델링했고, 권한은 owner/member로 구분한다.
우리집에서는 재고는 내가 차감하고 구매는 와이프가 하기 때문에 이런 구조가 필수이기도 했다.

4.3 홈 화면 위젯

앱을 열지 않고도 임박한 유통기한을 보고 싶다는 건 자연스러운 욕구다. 네이티브 위젯 모듈(WidgetDataModule)에 유통기한이 있는 물품 데이터를 동기화해, 홈 화면 위젯에서 바로 확인할 수 있게 했다. 앱 시작 시점과 데이터 변경 시점에 위젯 데이터를 갱신한다.

4.4 디테일을 챙기는 작은 장치들

  • 이미지 경로 마이그레이션 — 사진을 절대 경로로 저장하던 구버전 데이터를, 앱 업데이트 시 상대 경로로 자동 변환한다. 기기 백업·복원 후에도 사진이 깨지지 않게 하기 위함이다.
  • 버전 체크 — 앱 시작과 포그라운드 복귀 시 최신 버전을 확인해 업데이트를 안내한다.
  • 평점·피드백 유도 — 적절한 시점에 앱스토어 리뷰와 피드백 모달을 띄우되, 사용자를 귀찮게 하지 않도록 노출 시점을 상태로 관리한다.

5. 유료화

구글, 애플, 카카오 로그인을 지원하는데, 로그인을 하게되면 그때부터 클라우드에 데이터가 올라가기 때문에 비용이 발생된다. 물론 로그인을 하지않아도 모든기능을 동일하게 사용가능하지만 로그인을 하면 데이터 백업과 재고 공유가 지원된다.
클라우드 서버 비용이 들어가기 때문에 나중에 사용자가 늘어나면 유료화를 진행할까 생각했지만 사용자수가 많아야 앱의 가치가 높아지는 그런 앱이 아닌경우 초기부터 유료화 정책이 적용되어 있어야 추후 사용자의 반발을 줄일 수 있다는 이야기가 생각나 유료화 작업을 진행하기로 했다. ( 괜찮...겠지...? )
아직은 작업이 진행중이고 금액도 결정되지않았다.. 첫 한달은 무료 사용으로 제공할 예정이다.


6. 마치며

홈 인벤은 "나도 모르게 유통기한이 지나 버려지는 식품은 없게하자" 라는 단순한 목표에서 출발했다.
그 목표를 지키기 위해 오프라인 우선 설계를 택했고, 거기에 클라우드 공유·바코드 스캔·다국어·위젯을 하나씩 얹으면서도 핵심 가치를 흐리지 않으려 노력했다.

음식을 덜 버리고 싶은 사람,
생활용품 떨어지는 타이밍을 놓치고 싶지 않은 사람,
산것같긴한데 물건을 어디에 두었는지 자주 잊어버리는 사람
이라면 한번 써보고 피드백을 주면 정말 고맙겠다. (굽신굽신...)

인터넷 없이도 바로 시작할 수 있고, 가족과 함께 쓰고 싶어지면 그때 로그인하면 된다.

홈 인벤 — 집에 뭐가 있는지 외우지 말자. 앱이 기억한다.

앱스토어
https://apps.apple.com/kr/app/id6753967518

구글플레이
https://play.google.com/store/apps/details?id=com.homeinven.app

한국어·English·中文·日本語 지원 / iOS · Android

profile
sang kwon seo

0개의 댓글