Files
2nd/10_Wiki/Topics/Architecture/E-commerce_Platforms.md
T
Antigravity Agent f8b21af4be Wiki cleanup: error-doc removal, dedup merge, link normalization
10_Wiki/Topics 대규모 정리:
- 오류 캡처/미완성 stub 문서 227개 제거
- 교차폴더 중복 43클러스터 병합 (63파일 → redirect)
- 링크명 정규화: 깨진 링크 수정·redirect 직결·개념 매핑 ~2,400건
- 카테고리 MOC 6개 신규 생성
- Graph 섹션 미해결 related-keyword 링크 10,058건 제거

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 23:52:15 +09:00

191 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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<Cart> {
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 |