제로 웨이스트샵 전용 POS 시스템 - 리필 상품과 일반 상품 통합 결제
제로 웨이스트샵에서 무게 기반 리필 상품과 일반 상품을 빠르게 결제할 수 있는 터치 친화적 POS 시스템입니다.
- 📱 터치 친화적 UI - 큰 버튼, 직관적인 레이아웃
- ⚖️ IoT 저울 연동 - 실시간 무게 데이터 수신 및 자동 장바구니 구성
- 🔄 리필/일반 상품 통합 - g당 가격과 개당 가격 동시 지원
- 🎨 사진 중심 상품 선택 - 바코드 없이 이미지로 빠른 식별
- 📦 실시간 대기 고객 - 저울에서 계량한 고객이 자동으로 표시
- 🔗 주문 열람 링크 - 고객이 구매 내역 확인 가능
- Frontend: Next.js 15 (App Router), React 19, TypeScript
- Styling: Tailwind CSS (커스텀 디자인 토큰)
- Backend: Firebase (Firestore, Storage, Auth, Cloud Functions)
- Real-time: Firestore onSnapshot
- Deployment: Vercel
zerobase/
├── app/
│ ├── (pos)/
│ │ ├── layout.tsx # POS 레이아웃 (네비게이션)
│ │ ├── sell/ # 판매 페이지 (메인 POS)
│ │ └── admin/
│ │ └── products/ # 상품 관리
│ ├── r/[token]/ # 주문 열람 페이지
│ ├── api/
│ │ ├── ingest-scale/ # 저울 데이터 수집
│ │ └── orders/ # 주문 생성 및 토큰 발급
│ └── layout.tsx
├── components/
│ └── pos/
│ ├── RefillQueue.tsx # 리필 대기 고객 리스트
│ ├── ProductGrid.tsx # 상품 그리드
│ ├── CartPanel.tsx # 장바구니
│ ├── QuantityPad.tsx # 수량/무게 입력 키패드
│ └── CheckoutModal.tsx # 결제 완료 모달
├── lib/
│ ├── firebase.ts # Firebase 초기화
│ ├── firestore.ts # Firestore 컬렉션 래퍼
│ ├── types.ts # TypeScript 타입 정의
│ ├── calc.ts # 가격 계산 유틸리티
│ └── tokens.ts # 토큰 생성 및 검증
└── scripts/
└── seed.ts # 초기 데이터 시딩
git clone <repository-url>
cd zerobasenpm install- Firebase Console에서 새 프로젝트 생성
- Firestore Database 활성화 (테스트 모드로 시작)
- Storage 활성화
- 웹 앱 추가 및 구성 정보 복사
.env.local 파일을 수정하여 Firebase 구성을 입력하세요:
NEXT_PUBLIC_FIREBASE_API_KEY=your_api_key
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=your_project.firebaseapp.com
NEXT_PUBLIC_FIREBASE_PROJECT_ID=your_project_id
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=your_project.appspot.com
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=your_sender_id
NEXT_PUBLIC_FIREBASE_APP_ID=your_app_id
SCALE_API_SECRET=your_scale_api_secret_herenpx tsx scripts/seed.ts이 스크립트는 샘플 상품 10개를 Firestore에 추가합니다.
npm run dev브라우저에서 http://localhost:3000 접속
- 상단 네비게이션에서 상품관리 클릭
- 신규 추가 버튼으로 상품 등록
- 상품명, 타입(리필/일반), 단가, 카테고리 입력
- 이미지 URL 입력 (1024x1024 권장)
- 검색 키워드 입력 (쉼표로 구분)
- 등록된 상품은 즉시 판매 화면에 표시
- 판매 화면에서 상품 카드 클릭
- 일반 상품: 클릭 시 수량 +1, 재클릭으로 수량 증가
- 리필 상품: 클릭 시 무게 입력 키패드 표시
- 장바구니에서 수량/무게 조정
- 결제수단 선택 (현금/계좌이체/카드)
- 전화번호 입력 후 주문 열람 링크 생성 (선택사항)
- 고객이 IoT 저울에서 제품별로 계량
- 저울에서 전화번호 뒷 4자리 + 제품 + 무게 전송
- POS 좌측 리필 대기 고객에 자동 표시
- 고객 카드 클릭 시 장바구니 자동 구성
- 필요시 일반 상품 추가
- 결제수단 선택
- 전화번호 전체 입력 후 주문 열람 링크 생성
IoT 저울에서 다음 엔드포인트로 POST 요청:
POST /api/ingest-scale
Content-Type: application/json
{
"phone_suffix": "1234",
"product_id": "prod_xxx",
"weight_gram": 300
}보안 (선택사항): HMAC 서명을 x-signature 헤더로 전송
고객은 /r/{token} 링크로 접속하여:
- 전화번호 뒷 4자리 입력
- 주문 상세 확인 (구매 내역, 결제 금액, 보관 안내)
{
name: string; // 상품명
type: "refill" | "normal"; // 리필/일반
unit_price: number; // g당 or 개당 가격
category: "세제" | "화장품" | "식재료" | "기타";
image_url: string;
is_active: boolean;
search_keywords: string[];
}{
phone_suffix: string; // 뒷 4자리
product_id: string;
product_name_snapshot: string;
unit_price_snapshot: number;
weight_gram: number;
line_total_snapshot: number;
is_consumed: boolean; // 주문에 소모됨
order_id?: string;
}{
phone_suffix?: string;
phone_full?: string;
items_refill: OrderItemRefill[];
items_normal: OrderItemNormal[];
total_amount: number;
payment_method: "cash" | "transfer" | "card";
status: "paid" | "cancelled";
consumed_event_ids?: string[];
}app/globals.css에서 Primary 컬러 변경:
:root {
--primary: #a1eebd; /* 연두색 기본값 */
}lib/types.ts에서 ProductCategory 타입 수정 후 UI 업데이트
lib/types.ts의PaymentMethod타입 확장CartPanel.tsx에 버튼 추가CheckoutModal.tsx에 텍스트 매핑 추가
npm install -g vercel
vercel환경 변수는 Vercel Dashboard에서 설정하세요.
프로덕션 환경에서는 Firestore Security Rules 설정 필요:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /products/{productId} {
allow read: if true;
allow write: if request.auth != null;
}
match /scale_events/{eventId} {
allow read, write: if request.auth != null;
}
match /orders/{orderId} {
allow read, write: if request.auth != null;
}
match /view_tokens/{tokenId} {
allow read: if true;
allow write: if request.auth != null;
}
}
}- Toss Payments 실제 결제 연동
- 카카오 알림톡 전송
- 상품 이미지 직접 업로드 (Firebase Storage)
- CSV로 상품 일괄 등록
- 판매 통계 대시보드
- 재고 관리
- 영수증 프린터 연동
MIT