--- id: wiki-2026-0508-point-of-sale title: Point of Sale category: 10_Wiki/Topics status: verified canonical_id: self aliases: [POS, retail-pos, payment-terminal] duplicate_of: none source_trust_level: A confidence_score: 0.9 verification_status: applied tags: [retail, payments, pos, square, stripe] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: TypeScript framework: Stripe Terminal / Square API --- # Point of Sale (POS) ## 매 한 줄 > **"매 retail transaction 의 capture system — 매 hardware + software + payments + analytics"**. 매 cash register → ECR (1970s) → cloud POS (Square 2009, Toast 2011, Shopify POS) → 매 modern unified commerce (online + offline + AI inventory + loss prevention). ## 매 핵심 ### 매 components - **매 hardware**: terminal (iPad/Android), card reader (chip + tap + Apple Pay), receipt printer, cash drawer, barcode scanner, kitchen display. - **매 software**: catalog, cart, tax, discounts, tips, split bill, refunds, customer profiles, inventory. - **매 payments**: card-present (EMV chip + NFC), digital wallets (Apple Pay, Google Pay), QR (Alipay, WeChat), BNPL (Klarna, Afterpay). - **매 analytics**: sales dashboards, item performance, employee performance, demand forecast. - **매 integrations**: accounting (QuickBooks), payroll, e-commerce (Shopify), marketing (loyalty, SMS). ### 매 modern players (2026) - **매 Square** (Block): SMB-focused, Cash App integration, free entry POS. - **매 Stripe Terminal**: developer-first, omnichannel API, embedded readers. - **매 Toast**: restaurant-vertical, kitchen ops, payroll. - **매 Shopify POS**: omni-commerce (online + retail unified inventory). - **매 Lightspeed**: retail/restaurant/golf vertical. - **매 Clover** (Fiserv): bank-distributed, app marketplace. - **매 SumUp / iZettle**: Europe SMB. ### 매 AI/ML in POS (2026) - **매 loss prevention**: computer vision 매 self-checkout 매 mis-scans (Everseen, Diebold, Mashgin Vision). - **매 demand forecasting**: per-SKU per-store sales prediction (XGBoost/transformer). - **매 dynamic pricing**: 매 perishables markdown optimization. - **매 fraud detection**: 매 chargeback prediction, 매 stolen card flagging. - **매 voice ordering / AI drive-thru**: McDonald's, Wendy's deployments. - **매 visual search**: scan product 매 photo 의 lookup. ### 매 standards / compliance - **매 PCI-DSS**: card data handling. - **매 EMV**: chip card protocol. - **매 P2PE**: point-to-point encryption. - **매 tokenization**: store token, not PAN. - **매 SOC 2**: SaaS POS providers. ### 매 응용 1. 매 retail (apparel, grocery, c-store). 2. 매 restaurants (QSR, FSR, food trucks). 3. 매 services (salons, mobile contractors). 4. 매 events / pop-ups (mobile readers). ## 💻 패턴 ### Stripe Terminal — collect in-person payment ```typescript import { loadStripeTerminal } from "@stripe/terminal-js"; const StripeTerminal = await loadStripeTerminal(); const terminal = StripeTerminal.create({ onFetchConnectionToken: async () => { const r = await fetch("/connection_token", { method: "POST" }); return (await r.json()).secret; }, onUnexpectedReaderDisconnect: () => console.warn("disconnected"), }); const discoverResult = await terminal.discoverReaders(); await terminal.connectReader(discoverResult.discoveredReaders[0]); // Server creates PaymentIntent, client collects const { paymentIntent } = await fetch("/create_pi", { method: "POST", body: JSON.stringify({ amount: 1999 }), }).then(r => r.json()); const result = await terminal.collectPaymentMethod(paymentIntent.client_secret); const confirmed = await terminal.processPayment(result.paymentIntent); console.log("paid:", confirmed.paymentIntent.id); ``` ### Square Terminal API ```javascript const { Client, Environment } = require("square"); const client = new Client({ accessToken: process.env.SQUARE_TOKEN, environment: Environment.Production, }); const checkout = await client.terminalApi.createTerminalCheckout({ idempotencyKey: crypto.randomUUID(), checkout: { amountMoney: { amount: 1999n, currency: "USD" }, deviceOptions: { deviceId: "DEVICE_ID" }, }, }); ``` ### Catalog + tax calculation ```typescript type Item = { id: string; name: string; price_cents: number; tax_rate: number; sku: string }; function calculateOrder(items: Item[], qty: Record, discount_cents = 0) { const subtotal = items.reduce((s, it) => s + it.price_cents * (qty[it.id] ?? 0), 0); const tax = items.reduce((s, it) => s + it.price_cents * (qty[it.id] ?? 0) * it.tax_rate, 0); const total = subtotal + tax - discount_cents; return { subtotal, tax, discount: discount_cents, total }; } ``` ### Receipt printer (ESC/POS) ```javascript // node-thermal-printer const { ThermalPrinter, PrinterTypes } = require("node-thermal-printer"); const printer = new ThermalPrinter({ type: PrinterTypes.EPSON, interface: "tcp://192.168.1.100", }); printer.alignCenter(); printer.println("ACME COFFEE"); printer.drawLine(); printer.tableCustom([ { text: "Latte x2", align: "LEFT" }, { text: "$10.00", align: "RIGHT" }, ]); printer.drawLine(); printer.println("TOTAL: $10.80"); printer.cut(); await printer.execute(); ``` ### EMV / NFC reader (BBPOS via Stripe) ```typescript // 매 Stripe Terminal SDK 매 BBPOS WisePOS E / Stripe Reader S700 // 매 PCI-DSS scope 의 reduce — 매 reader 매 PAN 의 handle, 매 server 매 token 의 receive const reader = await terminal.connectReader(readers[0], { fail_if_in_use: true }); ``` ### Inventory sync (Shopify POS) ```javascript // Shopify Admin API — unified inventory across channels const res = await fetch(`https://${SHOP}.myshopify.com/admin/api/2025-01/inventory_levels/adjust.json`, { method: "POST", headers: { "X-Shopify-Access-Token": TOKEN, "Content-Type": "application/json" }, body: JSON.stringify({ inventory_item_id: 12345, location_id: 67890, available_adjustment: -1, // sold one }), }); ``` ### Loss prevention (CV self-checkout) ```python # 매 simplified pseudocode — 매 actual: YOLOv8 + tracking + match to scanned barcode import cv2 from ultralytics import YOLO model = YOLO("yolov8n.pt") cap = cv2.VideoCapture(0) scanned_skus = set() # populated by barcode scanner events while True: ret, frame = cap.read() detections = model(frame)[0] visible_items = {classify_to_sku(d) for d in detections.boxes} discrepancy = visible_items - scanned_skus if discrepancy: alert_associate(f"Unscanned: {discrepancy}") ``` ### Webhook — payment.succeeded ```typescript // 매 Stripe webhook 의 receive — 매 settle order in DB import express from "express"; const app = express(); app.post("/webhook", express.raw({ type: "application/json" }), async (req, res) => { const sig = req.headers["stripe-signature"]!; const event = stripe.webhooks.constructEvent(req.body, sig, WEBHOOK_SECRET); if (event.type === "payment_intent.succeeded") { const pi = event.data.object; await db.orders.update({ stripe_pi: pi.id }, { status: "paid" }); } res.json({ received: true }); }); ``` ## 매 결정 기준 | 상황 | Solution | |---|---| | 매 SMB cafe / pop-up | 매 Square | | 매 restaurant chain | 매 Toast | | 매 omni-commerce retail | 매 Shopify POS | | 매 dev-first / custom UX | 매 Stripe Terminal | | 매 enterprise multi-store | 매 NCR / Oracle Symphony | | 매 EU SMB | 매 SumUp / iZettle | | 매 unattended kiosk / self-checkout | 매 Mashgin / Toshiba + Stripe | **기본값**: 매 Stripe Terminal (developer-first, custom flow) 또는 매 Square (turnkey SMB). ## 🔗 Graph - Adjacent: [[Shopify]] ## 🤖 LLM 활용 **언제**: 매 receipt parsing, 매 customer Q&A chatbot, 매 menu generation, 매 anomaly summary 의 사용. **언제 X**: 매 payment authorization (deterministic flow), 매 PII handling (compliance risk). ## ❌ 안티패턴 - **매 store full PAN**: 매 PCI-DSS violation. 매 token 만 store. - **매 home-grown payment terminal**: 매 EMV cert 매 expensive — 매 SaaS provider 의 사용. - **매 ignore offline mode**: 매 retail Wi-Fi 매 unstable — 매 store-and-forward needed. - **매 monolithic POS**: 매 vertical lock-in — 매 API-first (Stripe/Shopify) 의 prefer. - **매 no idempotency keys**: 매 double-charge risk on retry. ## 🧪 검증 / 중복 - Verified (Stripe Terminal docs, Square API, Shopify Admin API, PCI-DSS v4.0). - 신뢰도 A. ## 🕓 Changelog | 날짜 | 변경 | |---|---| | 2026-05-08 | Phase 1 | | 2026-05-10 | Manual cleanup — Stripe/Square/Shopify patterns + AI loss prevention |