Skip to content

almang-idle/zerobase-pos

Repository files navigation

Zerobase POS

제로 웨이스트샵 전용 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                 # 초기 데이터 시딩

설치 및 실행

1. 저장소 클론

git clone <repository-url>
cd zerobase

2. 의존성 설치

npm install

3. Firebase 프로젝트 설정

  1. Firebase Console에서 새 프로젝트 생성
  2. Firestore Database 활성화 (테스트 모드로 시작)
  3. Storage 활성화
  4. 웹 앱 추가 및 구성 정보 복사

4. 환경 변수 설정

.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_here

5. 초기 데이터 시딩 (선택사항)

npx tsx scripts/seed.ts

이 스크립트는 샘플 상품 10개를 Firestore에 추가합니다.

6. 개발 서버 실행

npm run dev

브라우저에서 http://localhost:3000 접속

사용 방법

상품 관리

  1. 상단 네비게이션에서 상품관리 클릭
  2. 신규 추가 버튼으로 상품 등록
    • 상품명, 타입(리필/일반), 단가, 카테고리 입력
    • 이미지 URL 입력 (1024x1024 권장)
    • 검색 키워드 입력 (쉼표로 구분)
  3. 등록된 상품은 즉시 판매 화면에 표시

판매 프로세스

Walk-in 고객 (일반 결제)

  1. 판매 화면에서 상품 카드 클릭
    • 일반 상품: 클릭 시 수량 +1, 재클릭으로 수량 증가
    • 리필 상품: 클릭 시 무게 입력 키패드 표시
  2. 장바구니에서 수량/무게 조정
  3. 결제수단 선택 (현금/계좌이체/카드)
  4. 전화번호 입력 후 주문 열람 링크 생성 (선택사항)

리필 고객 (저울 사용)

  1. 고객이 IoT 저울에서 제품별로 계량
    • 저울에서 전화번호 뒷 4자리 + 제품 + 무게 전송
  2. POS 좌측 리필 대기 고객에 자동 표시
  3. 고객 카드 클릭 시 장바구니 자동 구성
  4. 필요시 일반 상품 추가
  5. 결제수단 선택
  6. 전화번호 전체 입력 후 주문 열람 링크 생성

저울 API 연동

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} 링크로 접속하여:

  1. 전화번호 뒷 4자리 입력
  2. 주문 상세 확인 (구매 내역, 결제 금액, 보관 안내)

데이터 스키마

Products (상품)

{
  name: string;                  // 상품명
  type: "refill" | "normal";     // 리필/일반
  unit_price: number;            // g당 or 개당 가격
  category: "세제" | "화장품" | "식재료" | "기타";
  image_url: string;
  is_active: boolean;
  search_keywords: string[];
}

Scale Events (저울 이벤트)

{
  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;
}

Orders (주문)

{
  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 업데이트

결제 수단 추가

  1. lib/types.tsPaymentMethod 타입 확장
  2. CartPanel.tsx에 버튼 추가
  3. CheckoutModal.tsx에 텍스트 매핑 추가

배포

Vercel 배포

npm install -g vercel
vercel

환경 변수는 Vercel Dashboard에서 설정하세요.

Firebase Security Rules

프로덕션 환경에서는 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

About

제로웨이스트 매장용 POS 시스템

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors