상품 listing 그리드
상품 listing grid, 빈 catalog와 안전한 카드 링크를 표시합니다.
상품 listing 그리드
준비
ecommerce를 활성화하고 Publishable Key를 사용하며 active market에 배정된 상품을 공개하세요. 빠른 시작에서 시작합니다. 브라우저 호출에는 API origin 등록이 필요하며 이 서버 예제는 CORS admission의 증거가 아닙니다.
예제는 공개 SDK 0.65.1, Next.js 16.3.8 App Router, React 19.2.4, Node 24.15.0 조합입니다. 자신의 앱에 npm install @01.software/sdk@0.65.1로 설치하세요. force-dynamic으로 SDK 호출을 build가 아닌 요청 때 실행합니다. cacheComponents와 static export를 쓰지 않는 구성입니다. 컴파일과 통제된 로컬 transport 검사는 hosted 제공 여부나 원격 tenant admission의 증거가 아닙니다.
Listing 그리드 표시
// app/products/page.tsx
import { createClient } from '@01.software/sdk'
export const dynamic = 'force-dynamic'
export default async function ProductsPage() {
const client = createClient({
publishableKey: process.env.NEXT_PUBLIC_SOFTWARE_PUBLISHABLE_KEY!,
apiUrl: process.env.SOFTWARE_API_URL,
})
const page = await client.commerce.product.listingPage({
limit: 24,
basePath: '/products',
emit: 'canonical-id',
})
if (page.cards.length === 0) return <p>No published products yet.</p>
return (
<ul>
{page.cards.map((card) => (
<li key={card.id}>
<a href={card.href}>
{typeof card.title === 'string'
? card.title
: (card.title.en ?? card.title.ko ?? 'Untitled')}
</a>
<span>{card.priceRange.minPrice}</span>
<ul aria-label="Options">
{card.swatches.map((swatch) => (
<li key={swatch.optionValueId}>
<a href={swatch.href}>{swatch.label}</a>
</li>
))}
</ul>
</li>
))}
</ul>
)
}정상·빈 결과·실패
/products를 여세요. listingPage()는 colorway가 아닌 상품 단위로 페이지를 나누고 상세 레시피로 이어지는 card·swatch URL을 만듭니다. 카드 0개는 정상인 빈 catalog입니다. unlisted 상품은 listing에서 빠지지만 direct detail로 열 수 있습니다. draft·archived·아직 공개 시점이 오지 않은 상품은 공개되지 않습니다. listing과 detail에서 같은 market·content locale context를 유지하세요.
credential·feature·tenant·네트워크 오류는 throw합니다. 잡아서 빈 목록으로 바꾸지 마세요. 읽기 재시도 boundary를 복사합니다.
// app/products/error.tsx
'use client'
export default function ProductError({ reset }: { reset: () => void }) {
return (
<div role="alert">
Catalog unavailable. <button onClick={reset}>Retry read</button>
</div>
)
}공개 재고 경계
Catalog 카드와 상세는 공개 shaped DTO입니다. availableForSale은 캐시된 힌트이며 수량이나 예약이 아닙니다. stock, reservedStock을 표시하거나 catalog에서 가용 수량을 계산하지 마세요. stockSnapshot()은 특정 시점 overlay, stockCheck()는 요청 수량 검사이며 최종 재고 admission은 checkout이 다시 확인합니다. 조회로 재고를 예약하지 않습니다.
다음 액션
카드나 swatch를 상품 상세에서 여세요. 전체 여정은 Ecommerce, query hook·필터·cache resource는 SDK, catalog 소유권은 커머스 운영을 따릅니다.