마켓플레이스 셀러 온보딩: 검증·등록·정산 자동화 시스템 설계

이커머스

마켓플레이스셀러 온보딩KYC정산B2B

이 글은 누구를 위한 것인가

  • 마켓플레이스를 운영하거나 구축하려는 이커머스 팀
  • 셀러 신청부터 첫 판매까지의 프로세스를 자동화하고 싶은 팀
  • 셀러 검증과 정산 계좌 등록을 안전하게 처리해야 하는 개발자

들어가며

셀러 온보딩이 복잡하면 좋은 셀러를 잃는다. 반대로 검증이 부실하면 부정 판매자가 들어온다. 셀러 온보딩은 이 두 가지를 동시에 해결해야 하는 어려운 균형점이다.

이 글은 bluefoxdev.kr의 마켓플레이스 운영 가이드 를 참고하여 작성했습니다.


1. 셀러 온보딩 단계

[셀러 온보딩 플로우]

Step 1: 신청 (10분)
  └── 이메일, 사업자 유형 선택
      (개인사업자 / 법인사업자 / 개인)

Step 2: 사업자 검증 (자동, 즉시)
  └── 사업자번호 진위 확인 (국세청 API)
  └── 사업자명 매칭
  └── 통신판매업 신고 여부 확인

Step 3: KYC (1-2 영업일)
  └── 대표자 신분증 업로드
  └── 통장 사본 업로드
  └── 자동 OCR + 수동 검토 (위험 등급 기반)

Step 4: 정산 계좌 등록 (즉시)
  └── 계좌 인증 (1원 송금 인증)

Step 5: 상품 등록 교육 (선택)
  └── 상품 등록 가이드
  └── 금지 품목 안내

Step 6: 첫 상품 등록
  └── 자동 검토 + 수동 검토
  └── 승인 후 판매 시작

2. 사업자 검증 API

import httpx
from dataclasses import dataclass

@dataclass  
class BusinessVerification:
    business_no: str
    is_valid: bool
    business_name: str | None
    status: str  # "active", "closed", "invalid"

async def verify_business_number(business_no: str, business_name: str) -> BusinessVerification:
    """국세청 사업자 진위 확인 API 연동"""
    # 실제: 국세청 공공API (data.go.kr) 사용
    clean_no = business_no.replace("-", "")
    
    async with httpx.AsyncClient() as client:
        response = await client.post(
            "https://api.odcloud.kr/api/nts-businessman/v1/status",
            json={"b_no": [clean_no]},
            headers={"Authorization": f"Bearer {NTS_API_KEY}"},
        )
    
    data = response.json()
    item = data.get("data", [{}])[0]
    
    return BusinessVerification(
        business_no=clean_no,
        is_valid=item.get("b_stt_cd") == "01",  # 01: 계속사업자
        business_name=item.get("b_nm"),
        status="active" if item.get("b_stt_cd") == "01" else "closed",
    )

async def send_micro_deposit(account_no: str, bank_code: str) -> str:
    """정산 계좌 인증: 1원 송금 후 인증 코드 반환"""
    # 은행 API 또는 핀테크 연동 (예: 토스페이먼츠 계좌 실명 확인)
    verification_code = generate_random_code(4)  # 예: "2847"
    
    await bank_transfer_api.send(
        to_account=account_no,
        bank_code=bank_code,
        amount=1,
        memo=f"인증번호{verification_code}",
    )
    
    await cache.set(f"account_verify:{account_no}", verification_code, ttl=3600)
    return verification_code

async def verify_account(account_no: str, user_code: str) -> bool:
    """사용자 입력 코드 확인"""
    stored = await cache.get(f"account_verify:{account_no}")
    return stored == user_code

3. 자동화된 상품 검토

PROHIBITED_KEYWORDS = [
    "의약품", "처방전", "마약", "총기", "불법복제",
    "짝퉁", "레플리카", "가품", "해킹",
]

async def auto_review_product(product: dict) -> dict:
    """상품 자동 검토"""
    issues = []
    
    # 금지 키워드 체크
    text = f"{product['name']} {product['description']}"
    for keyword in PROHIBITED_KEYWORDS:
        if keyword in text:
            issues.append({"type": "prohibited_keyword", "detail": keyword})
    
    # 가격 이상치 감지
    if product['price'] < 100:
        issues.append({"type": "suspicious_price", "detail": "가격이 너무 낮음"})
    
    # 이미지 품질 체크 (AI)
    if product.get('images'):
        quality_score = await check_image_quality(product['images'][0])
        if quality_score < 0.5:
            issues.append({"type": "low_image_quality", "detail": "이미지 품질 불량"})
    
    if not issues:
        return {"status": "auto_approved", "issues": []}
    
    # 심각한 이슈가 있으면 자동 거절
    critical = [i for i in issues if i["type"] == "prohibited_keyword"]
    if critical:
        return {"status": "auto_rejected", "issues": issues}
    
    # 나머지는 수동 검토로
    return {"status": "manual_review_required", "issues": issues}

마무리

셀러 온보딩의 성공 지표는 "신청에서 첫 판매까지의 시간"이다. 이 시간이 길수록 셀러 이탈률이 높아진다. 사업자 검증과 계좌 인증은 자동화하고, 고위험 케이스만 수동 검토로 처리하면 대부분의 셀러를 24시간 내 온보딩할 수 있다.