--- id: wiki-2026-0508-e-commerce-platforms title: E-commerce Platforms category: 10_Wiki/Topics status: verified canonical_id: self aliases: [ecommerce, online-store-platform, headless-commerce] duplicate_of: none source_trust_level: A confidence_score: 0.9 verification_status: applied tags: [ecommerce, shopify, stripe, headless] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: typescript framework: shopify-hydrogen/medusa/stripe --- # E-commerce Platforms ## 매 한 줄 > **"매 e-commerce 의 매 catalog × cart × checkout × fulfillment × payments × tax + 매 every regional edge case"**. 2026 의 매 SaaS (Shopify, BigCommerce, commercetools), 매 headless (Hydrogen, Medusa.js, Saleor, Vendure), 매 PSP (Stripe, Adyen) 가 dominant — 매 buy-vs-build 의 매 default 의 buy. ## 매 핵심 ### 매 platform tiers 1. **All-in-one SaaS** — Shopify, BigCommerce, Wix. 매 lowest TCO. 2. **Headless / composable** — Shopify Hydrogen, commercetools, Saleor, Medusa.js, Vendure. 매 custom UX 필요. 3. **Self-hosted / OSS** — Medusa, Vendure, Saleor (Apache 2 / MIT). 4. **Marketplace SaaS** — Mirakl, Sharetribe. 5. **B2B-specific** — Spryker, BigCommerce B2B, commercetools. ### 매 PSP / payments - **Stripe** — global default, broad APM coverage. - **Adyen** — enterprise / omnichannel. - **PayPal/Braintree, Klarna, Afterpay, Apple/Google Pay** — APMs. - **Crypto / stablecoin** — Coinbase Commerce (niche). ### 매 cross-cutting concerns - **Tax** — Stripe Tax, Avalara, TaxJar (US sales tax post-Wayfair, EU VAT IOSS, UK VAT). - **Shipping** — ShipStation, Shippo, EasyPost. - **Search** — Algolia, Typesense, Meilisearch. - **CMS** — Sanity, Contentful, Storyblok (PIM/CMS hybrid). - **Fraud** — Stripe Radar, Riskified, Signifyd. ## 💻 패턴 ### Stripe Checkout (PCI-light) ```ts import Stripe from 'stripe'; const stripe = new Stripe(process.env.STRIPE_SECRET!); const session = await stripe.checkout.sessions.create({ mode: 'payment', line_items: [{ price: 'price_123', quantity: 2 }], automatic_tax: { enabled: true }, shipping_address_collection: { allowed_countries: ['US', 'GB', 'KR'] }, success_url: 'https://shop.example.com/success?cs={CHECKOUT_SESSION_ID}', cancel_url: 'https://shop.example.com/cart', }); return Response.redirect(session.url!, 303); ``` ### Stripe webhook (idempotent) ```ts import { headers } from 'next/headers'; export async function POST(req: Request) { const sig = (await headers()).get('stripe-signature')!; const body = await req.text(); const event = stripe.webhooks.constructEvent(body, sig, process.env.STRIPE_WEBHOOK_SECRET!); // 매 idempotency: 매 event.id 의 record, 매 already-processed skip if (await db.processedEvents.has(event.id)) return new Response(null, { status: 200 }); switch (event.type) { case 'checkout.session.completed': await fulfillOrder(event.data.object as Stripe.Checkout.Session); break; } await db.processedEvents.insert(event.id); return new Response(null, { status: 200 }); } ``` ### Shopify Hydrogen (Storefront API) ```ts import { storefrontClient } from '~/lib/shopify'; const PRODUCT = `#graphql query Product($handle: String!) { product(handle: $handle) { id title descriptionHtml variants(first: 10) { nodes { id price { amount currencyCode } availableForSale } } images(first: 5) { nodes { url altText } } } }`; const { data } = await storefrontClient.request(PRODUCT, { variables: { handle } }); ``` ### Medusa.js custom backend ```ts // backend 의 custom plugin import { OrderService } from '@medusajs/medusa'; class FraudGuardService { constructor(private orderService: OrderService) {} async beforeCapture(orderId: string) { const score = await fetch('https://radar/api', { /* … */ }).then(r => r.json()); if (score.risk > 0.8) await this.orderService.cancel(orderId); } } ``` ### Cart state (Server Component + Cookie) ```ts import { cookies } from 'next/headers'; export async function getCart(): Promise { const id = (await cookies()).get('cart_id')?.value; return id ? storefront.cart.get(id) : storefront.cart.create(); } ``` ### Algolia product search index ```ts import { algoliasearch } from 'algoliasearch'; const client = algoliasearch(APP_ID, ADMIN_KEY); await client.saveObjects({ indexName: 'products', objects: products.map(p => ({ objectID: p.id, title: p.title, brand: p.brand, price: p.price.amount, inStock: p.inventory > 0, _tags: p.collections, })), }); ``` ### Tax (Stripe Tax inline) ```ts const tax = await stripe.tax.calculations.create({ currency: 'usd', line_items: [{ amount: 5000, reference: 'sku_1', tax_behavior: 'exclusive' }], customer_details: { address: { line1: '...', city: 'Seattle', state: 'WA', postal_code: '98101', country: 'US' }, address_source: 'shipping', }, }); ``` ### B2B quote → order ```ts // commercetools / Vendure pattern const quote = await ct.quotes.create({ customer, lineItems, validUntil: addDays(new Date(), 14) }); // 매 buyer accept → order 의 transition const order = await ct.orders.fromQuote(quote.id); ``` ## 매 결정 기준 | 상황 | Approach | |---|---| | Lean DTC start | Shopify (basic) + Stripe | | Custom UX, brand priority | Shopify Hydrogen or Saleor + headless CMS | | Self-host / OSS / cost control | Medusa.js or Vendure | | Enterprise composable | commercetools + Algolia + Contentful + Adyen | | Marketplace | Mirakl or Sharetribe | | B2B with quotes/contracts | commercetools / Spryker | **기본값**: Shopify for SMB; Hydrogen for premium DTC; commercetools for enterprise composable; Stripe as PSP unless enterprise (then Adyen). ## 🔗 Graph - 부모: [[Web-Architecture]] - 변형: [[Headless-Commerce]] - Adjacent: [[Algolia]] · [[Sanity]] ## 🤖 LLM 활용 **언제**: 매 platform comparison, 매 webhook handler 의 scaffold, 매 GraphQL Storefront query 의 작성, 매 tax/shipping flow explanation, 매 catalog data model design. **언제 X**: 매 PCI-DSS / SCA / regional tax 의 final compliance review (legal + Stripe/Adyen docs). 매 fraud rules in production (data scientist + risk team). ## ❌ 안티패턴 - **Roll-your-own checkout**: 매 PCI scope explode + tax + APM hell — Stripe/Adyen Checkout 사용. - **No webhook idempotency**: 매 duplicate fulfillment / charge — event.id dedupe. - **Cart in localStorage only**: 매 multi-device 가 broken — server-side cart. - **No automatic_tax**: 매 EU VAT / US Wayfair 의 manual mess. - **Storefront API token in client**: 매 secret leak — 매 server-only token. - **Sync inventory in serverless cold path**: 매 oversell — event-driven inventory + reservation. ## 🧪 검증 / 중복 - Verified (Shopify Hydrogen docs, Medusa.js docs, commercetools docs, Stripe docs, Adyen docs). - 신뢰도 A. ## 🕓 Changelog | 날짜 | 변경 | |---|---| | 2026-05-08 | Phase 1 | | 2026-05-10 | Manual cleanup — e-commerce platform landscape, Shopify/Stripe/headless patterns |