상품 목록 조회
OnSureLab
광고 상품 목록을 조회합니다. 지하철 상품(type=1)의 경우 역별 도면, 옵션, 가격 데이터가 포함됩니다.
GET
상품 목록 조회
엔드포인트
GET /api/product/ad/list파라미터
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
| lang | string | - | 언어 코드 (기본: ko) |
| productType | string | - | 타입 필터 (콤마 구분, 예: 1,2,4) 0 또는 미입력 시 전체 조회 |
| stations | string | - | 역 필터 (콤마 구분 stationId, 예: 41,42,180) 해당 역에 연결된 상품만 반환 (product_station 기반) |
| limit | number | - | 조회 개수 제한 최대 1000개 |
응답 필드
| 필드 | 타입 | 설명 |
|---|---|---|
| id | number | 상품 고유 ID |
| name | string | 상품명 |
| type | number | 상품 타입 (1=지하철, 2=전광판, 4=단일지하철 등) |
| image / imageSmall | string | 대표 이미지 / 썸네일 URL |
| prices | Price[] | 상품 기본 가격 목록 |
| location | Location | null | 위치 정보 (좌표, 주소) |
| stations | Station[] | 연결된 역 목록 (product_station 기반, 모든 오프라인 상품) |
| saleRate | number | 할인율 (%) |
stations 필드 상세 (모든 오프라인 상품)
| 필드 | 타입 | 설명 |
|---|---|---|
| id | number | 역 ID |
| name | string | 역 이름 (lang에 따라 번역) |
| lines | string[] | 노선 목록 (예: ["2호선", "공항철도"]) |
| costAdjustment | number | 역별 가격 보정값 (원) |
| blueprintImage | string | null | 역 도면 이미지 URL (다국어 지원) |
| options | Option[] | 역 내 광고 옵션 목록 (A1, A2, B1 등) |
| prices | Price[] | 역별 기본 가격 (기간별) |
options 필드
| 필드 | 타입 | 설명 |
|---|---|---|
| id | number | 옵션 ID |
| name | string | 옵션 이름 (예: "A1", "B1") |
| code | string | 옵션 코드 |
| position | { left, top } | 도면 이미지 위 표시 위치 |
| displaySize | string | 디스플레이 사이즈 (예: "1920x1080") |
| designSize | string | 디자인 입고 사이즈 (예: "1920x1080") |
| priceAdjustment | number | 옵션별 가격 보정값 (원) |
가격 계산 방식
최종가격 = stations[].prices[].price (역 기본가)
+ stations[].costAdjustment (역별 보정)
+ stations[].options[].priceAdjustment (옵션별 보정)응답 예시
[
// ── 지하철 상품 (type=1) ──
{
"id": 20,
"name": "홍대입구역 조명광고",
"type": 1,
"image": "https://kr.cafe24obs.com/data/product/20/main.webp",
"imageSmall": "https://kr.cafe24obs.com/data/product/small/20/main.webp",
"prices": [
{ "duration": "7d", "price": 200000, "currency": "KRW" }
],
"location": {
"address": "서울특별시 마포구 양화로 지하 160",
"lat": "37.5571",
"lng": "126.9239"
},
"stations": [
{
"id": 239,
"name": "홍대입구역",
"lines": ["2호선", "공항철도", "경의중앙선"],
"address": "서울특별시 마포구 양화로 지하 160",
"lat": "37.5571",
"lng": "126.9239",
"costAdjustment": 10000,
"blueprintImage": "https://kr.cafe24obs.com/data/.../blueprint.webp",
"options": [
{
"id": 45,
"name": "A1",
"code": "A1",
"position": { "left": 120, "top": 80 },
"displaySize": "1920x1080",
"designSize": "1920x1080",
"priceAdjustment": 10000
}
],
"prices": [
{ "duration": "7d", "price": 200000, "currency": "KRW" },
{ "duration": "14d", "price": 380000, "currency": "KRW" }
]
}
],
"saleRate": 10
},
// ── 일반 상품 (type=2 전광판 등) ──
// product_station에 연결된 역이 있으면 stations에 포함
{
"id": 458,
"name": "강남역 전광판",
"type": 2,
"image": "https://kr.cafe24obs.com/data/product/458/main.webp",
"imageSmall": "https://kr.cafe24obs.com/data/product/small/458/main.webp",
"prices": [
{ "duration": "7d", "price": 350000, "currency": "KRW" },
{ "duration": "14d", "price": 650000, "currency": "KRW" }
],
"location": {
"address": "서울특별시 강남구 강남대로 396",
"lat": "37.4979",
"lng": "127.0276"
},
"stations": [
{
"id": 25,
"name": "강남",
"lines": ["2호선"],
"address": "서울특별시 강남구 강남대로 지하 396",
"lat": "37.4979",
"lng": "127.0276",
"costAdjustment": 0,
"blueprintImage": null
}
],
"saleRate": 0
}
]필터 구조
상품 유형 필터 (productType)
| UI 라벨 | types 배열 |
|---|---|
| 전체 | 1, 2, 3, 4, 5, 7, 8 |
| 지하철 | 1, 4 |
| 전광판 | 2 |
| 버스정류장 | 3, 5 |
| 현수막 | 7 |
| 온라인 | 8 |
역 필터와 상품 유형의 관계
productType과 stations는 독립된 두 축이지만, API 내부 동작에 의해 단방향 의존이 존재합니다.
1. 상품 유형에서 지하철(1,4)을 빼면 → 역 선택 자동 초기화
2. 역을 선택해도 → 상품 유형은 변경되지 않음
API 내부 동작
-- stations 필터가 있을 때의 쿼리 구조
FROM product p
WHERE p.isOpen = 1
AND p.type IN (1,2,3,4,5,7,8)
AND EXISTS (
SELECT 1 FROM product_station ps_filter
WHERE ps_filter.productId = p.id
AND ps_filter.stationId IN (41, 42) -- 합정, 홍대입구
AND ps_filter.isOpen = 1
)
-- EXISTS 서브쿼리로 필터링:
-- → product_station에 해당 역 레코드가 있는 상품만 결과에 포함
-- → product_station 연결이 없는 상품은 제외
--
-- stations 응답: 모든 type에서 product_station 연결이 있으면
-- stations[] 배열에 역 정보가 포함됩니다.
-- (type=1 전용 제한 제거됨)역 선택 시 실제 결과
예시: "전체" + "합정역" 선택
요청: productType=1,2,3,4,5,7,8 & stations=합정역ID
결과: product_station에 합정역이 연결된 상품만 반환
→ type=1(지하철), type=4(단일지하철) — 거의 전부 연결
→ type=2(전광판) — 대부분 연결 (82개 중 79개)
→ type=3,5(버스정류장) — 대부분 연결
→ type=7(현수막) — 대부분 연결 (36개 중 34개)
→ type=8(온라인) — 연결 없음, 제외참고: product_station은 지하철 전용 테이블이 아닙니다. 전광판, 현수막, 버스정류장 등 대부분의 오프라인 상품이 역에 연결되어 있어, 역 필터 시 해당 타입 상품도 함께 반환됩니다. 연결이 없는 상품(온라인 등)만 제외됩니다.
type별 stations 데이터 동작
| 타입 | 목록 API stations | 역 상세 진입 후 | 비고 |
|---|---|---|---|
| type=1 (지하철) | 포함 | 옵션/가격 보강 | 여러 역에 걸친 상품, stations에 옵션(A1,B1...) + 역별 가격 포함 |
| type=4 (단일 지하철) | 포함 | 별도 API로 상세 조회 | 특정 역 전용 상품, stations에 역 정보 포함 |
| type=2 (전광판) | 포함 | 해당 없음 | product_station 연결 기반, 최근접 역 매핑 |
| type=3,5 (버스정류장) | 포함 | 해당 없음 | product_station 연결 기반, 최근접 역 매핑 |
| type=7 (현수막) | 포함 | 해당 없음 | product_station 연결 기반, 최근접 역 매핑 |
| type=8 (온라인) | 빈 배열 | 해당 없음 | 물리적 위치 없음, 역 필터 시 제외 |
type=4 역 상세 조회:type=4 상품의 역/옵션/가격 데이터는 목록 API가 아닌 별도 API로 조회합니다.
GET /api/product/subway/price → 역별 가격
GET /api/product/subway/option → 도면 + 옵션 (A1, A2...)
// 두 API 모두 type=1, type=4를 동일하게 처리