소개
시도하고자 했던 것과 그 이유
기프티콘이나 모바일 상품권, 마트 할인 쿠폰은 유효기간이 지나 소멸되어 버려지는 금액이 매년 엄청납니다. 이를 방지하기 위해 캡처본 이미지를 올리면 쿠폰 정보를 자동으로 스캔해 관리해 주는 서비스 아이디어를 기획했습니다.
하지만 개인이 사이드 프로젝트로 서비스를 운영할 때 가장 큰 문제는 서버 비용(이미지 저장소, 백엔드 서버, AI Vision API 호출 비용)입니다.
따라서 이번 프로젝트에서는 백엔드 서버 없이 스마트폰(브라우저) 내부 자원만 활용하여 비용을 0원으로 만들고, 초고속으로 작동하는 Local-First(로컬 퍼스트) 하이브리드 쿠폰 방어 플랫폼 '쿠폰가드(Coupon Guard)'를 제작 및 Vercel에 직접 배포해 보는 것을 목표로 했습니다.
진행 방법
어떤 도구를 사용했고, 어떻게 활용하셨나요?
- AI 에이전트: 기획 및 하이브리드 파싱 로직 설계, 자바스크 립트/CSS 전면 작성
- Tesseract.js: 브라우저 온디바이스 OCR 엔진 (클라이언트 측 1차 로컬 파싱 담당)
- GitHub & Vercel: 버전 관리 및 프론트엔드 호스팅 배포
- Web APIs: FileReader(서버 없는 이미지 변환), IndexedDB(로컬 저장소), navigator.share(모바일 네이티브 공유)
핵심 기술 Architecture: 왜 Local-First 방식인가?
서버에 이미지를 업로드하고 처리하는 방식 대신, 브라우저 단에서 즉시 처리하는 흐름을 구축했습니다.
1. 사용자가 이미지 파일 선택 (모바일 다중 이미지 선택 지원)
2. 브라우저가 이미지를 Base64 텍스트로 바로 변환 (서버 저장 X)
3. 1차 로컬 OCR (Tesseract.js) 실행: 사용자 기기 단에서 0원으로 텍스트 추출 및 정규식 검증
4. 2차 조건부 AI 라우팅 (Gemini Flash Vision): 필수 5대 항목(사용처, 쿠폰명, 금액, 유효기간, 바코드) 중 누락이 발생할 때만 AI API로 최소 전송
5. 데이터 저장: 추출된 정제 JSON과 이미지를 사용자 스마트폰 내부 IndexedDB(로컬 저장소)에만 저장
Local-First 방식의 큰 장점 3가지
1. 서버 비용 0원: 백엔드 서버나 이미지 저장소용 S3, 데이터베이스(DB) 서버를 구축하고 유지할 필요가 없습니다.
2. 0.1초 초고속 로딩: 이미지가 사용자 폰 내부 메모리(IndexedDB)에 저장되므로, 매장 결제 직전 앱을 켤 때 서버 다운로드 대기 시간 없이 즉시 켜집니다.
3. 개인정보 보호: 쿠폰이나 개인 혜택 캡처본이 외부 서버에 남아있지 않고 사용자 스마트폰 안에만 저장되므로 보안상 매우 안전합니다.
프롬프트 전문 (AI 코딩 에이전트 활용)
[기본 시스템 뼈대 생성 프롬 프트]
HTML과 JavaScript로 별도의 백엔드 서버 없이 동작하는 쿠폰 스캔 웹 UI를 만들어줘.
a. 사용자가 이미지 파일(쿠폰 캡처본)을 업로드할 수 있는 <input type="file" multiple> 버튼 제공
b. 자바스크립트 FileReader를 사용해 서버 업로드 없이 브라우저에서 이미지를 미리보기로 노출
c. 선택된 이미지를 Tesseract.js (또는 Vision API)로 전달해 { brand, title, amount, expiryDate, barcode } 형태의 JSON 결과를 받아오는 흐름 작성해 줘.
d. 파싱된 데이터와 이미지는 서버 없이 브라우저의 IndexedDB에만 로컬로 저장되도록 해줘.
[조건부 하이브리드 라우팅 프롬프트]
비용 절감을 위해 2단계 조건부 하이브리드 OCR 엔진 구조로 보완해 줘.
1단계: 브라우저 온디바이스 Tesseract.js로 로컬에서 텍스트 추출 및 정규식 파싱 진행.
2단계: 추출 결과에서 { brand, title, amount, expiryDate, barcode } 5가지 필수값 중 1개라도 null이거나 실패하면 'AI 보완 필요' 상태로 라우팅.
결과와 배운 점
과제 항목 달성 여부 점검
1. 프론트엔드 AI 웹 UI 빌드 및 이미지 업로드: 완료 (FileReader 기반 서버 없는 이미지 미리보기 및 다중 선택 UI 구현)
2. 핵심 페인포인트 해결 MVP 기능 구현: 완료 (쿠폰 캡처본 스캔 및 데이터 정제, 직접 수정/삭제 기능 구현)
3. UI/UX 고도화 및 브랜딩 (파비콘, SEO 등): 완료 (이모지 파비콘 적용, 쾌적한 폼 레이아웃 및 네이티브 공유 연동)
4. 실서비스 배포: 완료 (배포 URL: https://coupon-guard-swart.vercel.app/)
5. 실제 결제 모듈 (토스 페이먼츠 / 폴라 등) 연동: 미완료 (이번 주차는 쿠폰 관리 효율화 Local-First에 집중하여 결제 기능은 생략)
6. 그로스 및 마케팅 구조화 (SEO/GEO/바이럴): 진행 중 (친구 소문내기 공유 루프 탑재, 향후 검색 최적화 단계로 확장 예정)
주요 완성 기능 및 구현 화면
- 단일 페이지(SPA) 웹 앱 배포 URL: https://coupon-guard-swart.vercel.app/
- 모바일 완벽 호환 UI: 스마트폰 갤러리 다중 선택 지원 및 터치 기반 인터페이스
- 금액 및 날짜 인풋 제어: 날짜 자동 하이픈(YYYY-MM-DD) 및 금액 순수 숫자 처리
- 필수값 유효성 검사: 필수 정보 누락 시 해당 입력창으로 커서 자동 포커스 이동
- JSON 미리보기 모달: DB 인서트 직전의 정제된 JSON 데이터를 개발자/유저가 직접 검증 및 복사 가능
- 모바일 네이티브 공유: 스마트폰 공유하기(navigator.share) 창과 바로 연결
배운 점과 나만의 꿀팁
1. 정규식(Regex)의 한계와 보완: 로컬 OCR은 텍스트가 조금만 일그러져도 '3,000원'을 '3,000 #'으로 읽는 등 오차가 발생합니다. 콤마가 포함된 숫자를 감지하는 보완 로직을 두어 로컬 성공률을 대폭 올려야 AI 호출 비용을 진짜 0원으로 방지할 수 있습니다.
2. 입력 편의성 UX: 'AI 보완 필요'라는 안내 문구가 박스에 들어있을 때, 사용자가 클릭(focus)하자마자 텍스트가 자동으로 지워지도록 처리하면 사용성이 극대화됩니다.
과정 중 시행착오
모바일 UI 겹침 현상: 카드 헤더에 파일명, 상태 태그, 삭제 버튼, 인풋 박스가 한 줄에 빽빽하게 들어가다 보니 모바일 화면에서 요소들이 심하게 깨지고 겹치는 현상이 발생했습니다.
해결: 파일명을 깔끔하게 숨기고 숫자 순번(1, 2, 3)만 단 순화하여 남긴 뒤, 입력창(Input Box)을 다음 줄로 넓게 내리는 구조로 레이아웃을 완전히 리팩토링하여 가독성과 조작 편의성을 높였습니다.
앞으로의 계획 및 미구현 과제 (Next Step)
이번 주차 스프린트에서 시간 관계상 다루지 못했거나 고도화가 필요한 부분은 향후 차기 스프린트 계획으로 수립했습니다.
1. 실제 결제 모듈(토스 페이먼츠 / 폴라 등) 연동: 유료 쿠폰 보관함이나 프리미엄 마감 알림 구독 기능을 위해 결제 게이트웨이 연동 모듈을 추가할 계획입니다.
2. 실제 Gemini Flash Vision API 키 서버리스 연동: 현재는 로컬 Tesseract.js 파싱으로 구현되어 있으나, 향후 API Key를 Vercel 환경 변수로 안전하게 연결하여 클라우드 비전 AI 보완 파이프라인을 정식 구축할 예정입니다.
3. 디데이(D-Day) 알림 및 소멸 방지 푸시(Push) 기능: IndexedDB에 저장된 쿠폰의 유효기간을 바탕으로 마감 임박 시 웹 푸시를 보내는 로컬 서비스 워커(Service Worker)를 구현하여 서비스의 핵심 가치인 '방어'를 극대화하겠습니다.