sayren Docs

컬렉션

기획전·이벤트 상품 묶기, 조건 자동 컬렉션, 판매량 상위, 노출 기간, 순서, 스토어프론트 목록

컬렉션은 상품을 묶어 스토어프론트에 보여 주는 단위입니다. 「추석 특가」「MD 추천」처럼 셀러가 고른 상품을 정한 순서대로 보여 주거나, 「신상품」처럼 조건에 맞는 상품을 자동으로 모읍니다. 카테고리는 상품이 무엇인지를 나타내고 상품당 하나입니다. 컬렉션은 상품을 어디에 보여 줄지를 나타내고, 한 상품을 여러 컬렉션에 담을 수 있습니다.

준비

  • 컬렉션 보기: 소유자·관리자·스태프 또는 category:r
  • 컬렉션 만들기·수정·삭제·상품 담기: 소유자·관리자·스태프 또는 category:rw
  • AI 에이전트도 승인 없이 컬렉션을 만들고 고칩니다. 돈이 움직이지 않고 되돌릴 수 있는 작업입니다

1. 컬렉션 만들기

상점 관리 › 상품 › 컬렉션에서 컬렉션 만들기를 누릅니다.

  1. 제목을 입력합니다(60자까지).
  2. 주소를 입력합니다. 스토어프론트 주소 /collections/{주소}에 쓰입니다. 영문 소문자·숫자·하이픈 64자까지이고 상점 안에서 겹치지 않아야 합니다. 비우면 c- 뒤에 8자를 붙여 자동으로 만듭니다.
  3. 설명(500자까지)과 대표 이미지를 넣습니다. 대표 이미지는 상품 이미지와 같은 형식(jpg·png·webp·avif·gif)입니다.
  4. 상품 구성에서 상품을 검색해 담기를 누릅니다. 손잡이를 끌어 놓거나 위·아래 버튼으로 순서를 바꿉니다.
  5. 만들기를 누릅니다.

API로는 POST /v1/collections입니다. productIds의 배열 순서가 처음 순서입니다.

const collection = await sdk.collections.create({
  title: "추석 특가",
  slug: "chuseok",
  productIds: ["prod_003", "prod_001"],
  startsAt: "2026-09-20T00:00:00+09:00",
  endsAt: "2026-10-05T00:00:00+09:00",
});

유형은 두 가지입니다. 직접 고른 상품을 담는 직접 선택(type: "MANUAL", 기본값)과 조건으로 상품을 모으는 조건 자동(type: "AUTOMATIC")입니다. 유형은 만들 때 고르고 바꿀 수 없습니다. 바꾸려면 새로 만드십시오. 조건 자동은 5. 조건 자동 컬렉션을 보십시오.

2. 노출과 기간

설정뜻
노출 (visible)끄면 기간과 관계없이 스토어프론트에 보이지 않습니다
시작 일시 (startsAt)이 시각부터 보입니다. 비우면 바로 보입니다
종료 일시 (endsAt)이 시각부터 보이지 않습니다. 비우면 계속 보입니다. 시작 일시보다 뒤여야 합니다

목록의 상태(state)는 이 설정에서 나온 값입니다.

상태조건
노출중 (ACTIVE)노출이 켜져 있고 기간 안입니다
예약 (SCHEDULED)시작 일시 전입니다
종료 (ENDED)종료 일시가 지났습니다
숨김 (HIDDEN)노출이 꺼져 있습니다. 기간보다 먼저 봅니다

3. 상품 담기와 순서

작업API
담긴 상품 보기GET /v1/collections/{collectionId}/products
통째로 바꾸기(순서 포함)PUT /v1/collections/{collectionId}/products
뒤에 붙이기(한 번에 500개)POST /v1/collections/{collectionId}/products
하나 빼기DELETE /v1/collections/{collectionId}/products/{productId}
  • 한 컬렉션에 상품을 1,000개까지 담습니다. 상점당 컬렉션은 200개까지입니다.
  • 이미 담긴 상품을 다시 붙이면 그 자리에 둡니다. 겹치는 id는 처음 것만 남깁니다.
  • 담긴 상품은 판매 상태와 관계없이 남습니다. 스토어프론트에는 판매 중인 상품만 보입니다.
  • 상품을 삭제하면 모든 컬렉션에서 빠집니다. 컬렉션을 삭제해도 상품은 그대로입니다.
  • 상품 하나가 담긴 컬렉션은 GET /v1/collections?productId={productId}로 봅니다. 상점 플랫폼에서는 상품 수정 화면 오른쪽 「컬렉션」에서 담고 빼고, 상품 목록에서 상품을 골라 「컬렉션에 담기」로 한꺼번에 붙입니다.

동시에 고칠 때

컬렉션은 쓰기마다 revision이 1씩 오릅니다. 수정·상품 바꾸기 본문에 읽은 revision을 주면, 그 사이 다른 곳에서 바꾼 경우 409 COLLECTION_CHANGED로 거절합니다. 다시 읽어 최신 값에 고친 뒤 보내십시오. revision을 생략하면 확인하지 않고 덮어씁니다.

const current = await sdk.collections.get(collectionId);
await sdk.collections.replaceProducts(collectionId, {
  productIds: ["prod_001", "prod_003"],
  revision: current.revision,
});

4. 스토어프론트에서 보여 주기

스토어프론트 API는 노출 중인 컬렉션만 돌려줍니다. 숨김·기간 밖·없는 주소는 모두 404 COLLECTION_NOT_FOUND입니다.

const { contents } = await sdk.catalog.listCollections(); // 목록 순서(sortOrder) 순
const collection = await sdk.catalog.getCollection("chuseok");
const page = await sdk.catalog.listCollectionProducts("chuseok", { page: 1, size: 20 });
  • 상품 목록은 상품 검색과 같은 카드(ProductCard)입니다.
  • 정렬 sort는 manual(셀러가 정한 순서)과 상품 검색 정렬(recommend·latest·priceAsc·priceDesc·reviewCount·ratingDesc)입니다. 생략하면 컬렉션의 기본 정렬(productSort)입니다.
  • minPrice·maxPrice는 즉시할인을 반영한 판매가로 거릅니다.
  • 컬렉션 목록 항목에는 상품 수가 없습니다.
  • 기본 스토어프론트 템플릿(0.2.10부터)은 /collections/{slug}에 대표 이미지·제목·설명과 상품 목록(정렬·페이지)을, /collections에 노출 중인 컬렉션 모음을 그립니다. 숨김·기간 밖·없는 주소는 없는 화면입니다. 헤더 메뉴나 배너 링크에 /collections/{slug}를 걸면 됩니다.

홈 섹션에 쓰기

기본 스토어프론트 템플릿(0.2.13부터)은 홈의 상품 섹션이 컬렉션 상품을 그릴 수 있습니다. src/site/layout.json에서 상품 섹션 (productRail·productGrid·productSpotlight·reviewHighlights)의 source를 컬렉션 주소로 둡니다.

{
  "id": "fall-new",
  "type": "productRail",
  "title": "가을 신상",
  "source": { "collection": "fall-new" },
  "limit": 8,
  "moreLink": true
}
  • 섹션은 GET /collections/{slug}/products로 상품을 받습니다. 상품·순서·정렬은 컬렉션 설정을 따르므로 상점 플랫폼에서 상품을 바꾸면 코드를 고치지 않아도 섹션이 따라갑니다.
  • 컬렉션이 없거나 숨김·기간 밖이면, 또는 판매 중인 상품이 없으면 섹션을 그리지 않습니다. 예약 컬렉션은 시작 시각이 되면 나타납니다.
  • moreLink가 true면 「더 보기」가 /collections/{slug}로 갑니다.
  • 주소 형식은 컬렉션 주소와 같습니다(영문 소문자·숫자·하이픈 64자까지). collection과 sort·category는 함께 쓰지 않습니다.
  • 기획전 배너는 새 섹션 대신 editorialBanner의 링크를 /collections/{slug}로 겁니다.

5. 조건 자동 컬렉션

조건 자동 컬렉션은 조건을 모두 만족하는 판매 중인 상품을 보여 줍니다. 「신상품」「3만 원 이하」「할인 중인 상의」처럼 상품이 늘고 바뀌어도 손대지 않아도 되는 묶음에 사용합니다. 조회할 때마다 조건을 다시 계산하므로 상품을 등록하거나 가격·할인·판매 상태를 바꾸면 바로 반영됩니다.

상점 플랫폼에서는 컬렉션 만들기의 상품 구성 › 유형에서 조건 자동을 고르고 조건을 켭니다. 아래 일치 상품에 지금 조건으로 나오는 상품 수와 앞 상품이 보입니다.

조건형식뜻
등록일{ field: "createdWithinDays", value: 30 }최근 N일(1~365) 안에 등록한 상품. 조회 시각에서 N일 전까지 포함합니다
카테고리{ field: "category", categoryIds: ["cat_top"] }고른 카테고리와 그 하위 카테고리의 상품(20개까지)
가격{ field: "price", min: 10000, max: 30000 }즉시할인을 반영한 판매가가 범위 안인 상품. min·max 중 하나만 써도 됩니다(경계 포함)
할인 상품{ field: "discounted", value: true }지금 즉시할인이 적용되는 상품
판매량 상위{ field: "bestSelling", days: 30, top: 20 }다른 조건을 모두 만족하는 상품 중 최근 days일(7·30·90) 판매 수량 상위 top개(1~100). 판매가 없는 상품은 담지 않습니다
  • 조건은 1~10개이고 같은 조건은 한 번만 사용합니다.
  • 판매 중(SALE)인 상품만 담깁니다. 품절·판매 중지 상품은 관리 API 목록에도 나오지 않습니다.
  • 상품을 직접 담거나 뺄 수 없습니다(409 COLLECTION_NOT_MANUAL). 순서도 정할 수 없어 정렬(productSort)의 기본값은 LATEST(최신순)이고 MANUAL은 사용할 수 없습니다.
  • 조건에 사용하는 카테고리는 삭제할 수 없습니다(409 CATEGORY_IN_USE, error.details.collectionIds에 컬렉션 id). 컬렉션의 조건에서 먼저 빼십시오.

판매량 상위

「주간 베스트」「이 카테고리 인기 상품」처럼 많이 팔린 상품을 모읍니다. 판매량 상위는 다른 조건으로 먼저 거른 뒤 그중 판매 수량이 많은 상품을 top개 남깁니다.

  • 판매 수량은 실결제 주문의 결제 수량에서 취소·반품 수량을 뺀 값입니다. 테스트 결제 주문은 세지 않습니다.
  • 기간은 오늘을 포함한 한국 날짜 기준입니다. days: 7은 오늘과 앞 6일이고, 주문 시각의 한국 날짜로 나눕니다.
  • 판매량은 10분마다 다시 집계합니다. 새 주문과 취소는 최대 10분 늦게 반영되고, 사흘보다 오래된 주문의 취소·반품은 다음 날 새벽에 반영됩니다. 컬렉션 응답·미리보기의 salesComputedAt이 판매량 기준 시각이고, 판매량을 사용하지 않는 컬렉션이나 집계 전이면 null입니다.
  • 판매 수량이 같으면 최근에 등록한 상품이 앞이고, 그것도 같으면 상품 id 순입니다.
  • 정렬을 생략하면 판매량 상위가 있는 컬렉션은 BEST_SELLING(판매량순)입니다. 다른 정렬을 고르면 상위 top개 안에서 그 정렬로 보입니다.
  • 판매량순(BEST_SELLING)은 직접 선택 컬렉션에도 사용합니다. 기간은 판매량 상위의 기간이고, 조건이 없으면 최근 30일입니다. 직접 선택은 수량이 같으면 정한 순서를 지킵니다.
  • 스토어프론트 API에는 판매량순 정렬 값이 없습니다. 판매량순 컬렉션의 기본 정렬은 manual(컬렉션 순서)로 보이고 그 순서가 판매량 순입니다. 상세 응답(GET /collections/{slug})의 salesComputedAt으로 기준 시각을 보여 줄 수 있습니다.
const best = await sdk.collections.create({
  title: "이달의 인기 상의",
  slug: "best-tops",
  type: "AUTOMATIC",
  rules: [
    { field: "category", categoryIds: ["cat_top"] },
    { field: "bestSelling", days: 30, top: 20 },
  ],
});
best.productSort; // "BEST_SELLING"
best.salesComputedAt; // "2026-10-02T01:00:00.000Z" — 이 시각까지의 주문을 셉니다
// 저장 전에 결과를 봅니다 — 데이터를 바꾸지 않습니다
const { count, products } = await sdk.collections.preview({
  rules: [
    { field: "category", categoryIds: ["cat_top"] },
    { field: "createdWithinDays", value: 30 },
  ],
});

const collection = await sdk.collections.create({
  title: "이달의 신상 상의",
  slug: "new-tops",
  type: "AUTOMATIC",
  rules: [
    { field: "category", categoryIds: ["cat_top"] },
    { field: "createdWithinDays", value: 30 },
  ],
});

// 조건은 통째로 바꿉니다
await sdk.collections.update(collection.collectionId, {
  rules: [{ field: "discounted", value: true }],
  revision: collection.revision,
});
  • productCount는 지금 조건을 만족하는 판매 중인 상품 수입니다. GET /v1/collections/{collectionId}/products는 그 상품을 기본 정렬 순으로 돌려주고, position은 순위, addedAt은 상품 등록 시각입니다.
  • 스토어프론트 API는 직접 선택과 같은 모양입니다. 정한 순서가 없어 sort=manual은 기본 정렬과 같습니다.
  • 같은 판정을 직접 하려면 SDK 순수 함수 matchesCollectionRules(product, rules, { now, categories })를 사용합니다. 판매량 상위는 판정이 아니라 자르기라 matchesCollectionRules는 그 조건을 통과시키고, 판매 수량을 아는 쪽이 rankBestSelling(products, sales, top)으로 자릅니다.

오류

코드뜻
400 COLLECTION_RULES_REQUIRED조건 자동 컬렉션에 조건이 없습니다
400 COLLECTION_RULES_NOT_ALLOWED직접 선택 컬렉션에는 조건을 둘 수 없습니다
400 COLLECTION_PRODUCTS_NOT_ALLOWED조건 자동 컬렉션을 만들 때 productIds를 줄 수 없습니다
400 COLLECTION_SORT_INVALID조건 자동 컬렉션은 MANUAL 정렬을 사용할 수 없습니다
400 COLLECTION_CATEGORY_NOT_FOUND조건에 상점에 없는 카테고리 id가 있습니다
409 COLLECTION_NOT_MANUAL조건 자동 컬렉션에는 상품을 담거나 뺄 수 없습니다
409 CATEGORY_IN_USE조건 자동 컬렉션이 조건으로 사용하는 카테고리를 지우려 했습니다
409 COLLECTION_SLUG_TAKEN같은 주소의 컬렉션이 있습니다
409 COLLECTION_LIMIT_EXCEEDED상점당 200개를 넘었습니다
409 COLLECTION_PRODUCT_LIMIT_EXCEEDED한 컬렉션에 1,000개를 넘었습니다
409 COLLECTION_CHANGED읽은 뒤 다른 곳에서 바뀌었습니다. 다시 읽어 보내십시오
400 COLLECTION_TYPE_IMMUTABLE유형은 바꿀 수 없습니다
400 COLLECTION_PRODUCT_NOT_FOUND상점에 없는 상품 id가 있습니다
404 COLLECTION_NOT_FOUND컬렉션이 없습니다. 스토어프론트에서는 숨김·기간 밖도 같습니다

이 페이지 목차