이 글은 누구를 위한 것인가
- 위시리스트 기능이 있지만 전환으로 연결하지 못하는 팀
- 위시리스트 데이터를 CRM 마케팅에 활용하고 싶은 PM
- 공유 위시리스트와 선물 기능을 구현해야 하는 개발자
들어가며
위시리스트는 "사고 싶지만 아직 안 샀다"는 명확한 신호다. 이 데이터를 제대로 활용하면 — 가격 인하 알림, 재입고 알림, 기념일 마케팅 — 높은 구매 전환으로 연결할 수 있다.
이 글은 bluefoxdev.kr의 이커머스 CRM 전략 을 참고하여 작성했습니다.
1. 위시리스트 기능 설계
[위시리스트 기능 맵]
핵심 기능:
✅ 상품 추가/제거
✅ 복수 위시리스트 (쇼핑 목록 분류)
✅ 장바구니로 이전
✅ 비로그인 → 로그인 시 병합
알림 트리거:
├── 가격 인하 (N% 이상 내려감)
├── 재입고 (품절이었다가 복귀)
├── 한정 수량 경고 (재고 5개 미만)
└── 오래된 위시리스트 (30일 이상) 리마인더
소셜 기능:
├── 위시리스트 공유 (선물 힌트)
├── 결혼·생일 레지스트리
└── 친구에게 선물하기 (위시리스트에서 바로 구매)
2. DB 및 API 구현
CREATE TABLE wishlists (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id),
name VARCHAR(100) DEFAULT '위시리스트',
is_public BOOLEAN DEFAULT false,
share_token VARCHAR(64) UNIQUE, -- 공유용 토큰
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE TABLE wishlist_items (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
wishlist_id UUID NOT NULL REFERENCES wishlists(id) ON DELETE CASCADE,
product_id UUID NOT NULL,
variant_id UUID,
added_at TIMESTAMPTZ DEFAULT NOW(),
price_at_add DECIMAL(15,2), -- 추가 시 가격 (인하 감지용)
notified_price_drop_at TIMESTAMPTZ,
UNIQUE(wishlist_id, product_id, variant_id)
);
async def check_price_drops_and_notify():
"""가격 인하 감지 및 위시리스트 알림 (배치 작업)"""
# 현재 가격이 추가 시 가격보다 낮은 항목 조회
items = await db.fetch("""
SELECT wi.*, u.email, u.push_token, p.name as product_name, p.current_price, p.image_url
FROM wishlist_items wi
JOIN wishlists wl ON wl.id = wi.wishlist_id
JOIN users u ON u.id = wl.user_id
JOIN products p ON p.id = wi.product_id
WHERE p.current_price < wi.price_at_add * 0.95 -- 5% 이상 인하
AND (wi.notified_price_drop_at IS NULL
OR wi.notified_price_drop_at < NOW() - INTERVAL '7 days')
""")
for item in items:
discount_pct = round((1 - item['current_price'] / item['price_at_add']) * 100)
# 알림 발송
await send_push(item['push_token'], {
"title": f"위시리스트 상품 가격 인하! -{discount_pct}%",
"body": f"{item['product_name']} 가격이 내렸습니다. 지금 구매하세요!",
})
await db.execute(
"UPDATE wishlist_items SET notified_price_drop_at = NOW() WHERE id = $1",
item['id']
)
async def transfer_to_cart(wishlist_id: str, item_ids: list[str], user_id: str):
"""위시리스트 → 장바구니 이전"""
items = await db.fetch(
"SELECT * FROM wishlist_items WHERE wishlist_id=$1 AND id=ANY($2)",
wishlist_id, item_ids
)
for item in items:
await add_to_cart(user_id, item['product_id'], item['variant_id'], 1)
# 옵션: 이전 후 위시리스트에서 삭제
# await db.execute("DELETE FROM wishlist_items WHERE id=ANY($1)", item_ids)
3. 마케팅 자동화 연동
# 위시리스트 데이터 기반 세그먼트 생성
def get_wishlist_segments() -> list[dict]:
return [
{
"segment": "wishlist_high_value",
"description": "위시리스트 총액 50만원 이상",
"query": """
SELECT user_id, SUM(p.current_price) as wishlist_value
FROM wishlist_items wi
JOIN products p ON p.id = wi.product_id
GROUP BY user_id
HAVING SUM(p.current_price) >= 500000
"""
},
{
"segment": "wishlist_abandoned_30d",
"description": "30일 이상 구매 안 한 위시리스트 보유자",
"query": """
SELECT DISTINCT wl.user_id
FROM wishlists wl
JOIN wishlist_items wi ON wi.wishlist_id = wl.id
WHERE wi.added_at < NOW() - INTERVAL '30 days'
AND NOT EXISTS (
SELECT 1 FROM orders o
WHERE o.user_id = wl.user_id
AND o.created_at > NOW() - INTERVAL '30 days'
)
"""
}
]
마무리
위시리스트의 진짜 가치는 상품을 "나중을 위해 저장"하는 것이 아니라, 가장 구매 가능성이 높은 사용자를 식별하는 데 있다. 가격 인하 알림 하나만 잘 구현해도 위시리스트 → 구매 전환율을 크게 높일 수 있다.