2026년 10월 7일 기준으로 Shifter는 Oxylabs와 Bright Data보다 많은, 가장 큰 규모의 실시간 미국 IP 풀을 보유하고 있으며, 비용은 그 일부에 불과합니다.Shifter는 이제 가장 많은 미국 라이브 IP 풀을 보유하고 있습니다

벤치마크 보기

지식

공익 가격 모니터링: 검증을 견디는 증거 수집하기

소비자 단체, 저널리스트, 컴플라이언스 팀이 할인 주장을 검증하기 위해 가격을 모니터링하는 방법과 소매업체가 반박할 수 없는 증거를 수집하는 방법.

Priya Nair

2026년 10월 11일 · 8 분 소요

“Was 89.99, now 59.99”는 소매업계에서 가장 오래된 주장 중 하나이며, 동시에 가장 조작하기 쉬운 주장이기도 하다. 몇 주간 가격을 올린 뒤 원래 가격으로 “인하”하면 그만이다. 소비자 단체, 언론, 규제 당국, 그리고 소매업체 자체의 컴플라이언스 팀도 모두 이를 적발하기 위해 가격을 모니터링한다. 하지만 이러한 조사 결과는 소매업체가 반박할 때 버텨낼 수 있어야 의미가 있으며, 소매업체는 실제로 반박한다.

이 가이드는 가격 전략이 아닌 책임 규명을 위한 가격 모니터링을 다룬다. 할인 표시에 관한 규정이 무엇인지, 검증을 견뎌내는 가격 증거를 어떻게 수집하는지, 그리고 할인 주장을 그 이면의 가격 이력과 대조해 검증하는 코드를 다룬다.

이는 일반적인 정보이며 법률 자문이 아니다. 규정은 국가마다 다르므로, 의혹을 제기하거나 민원을 제출하려는 사람은 먼저 법률 자문을 구해야 한다.

할인 표시에 관한 규정

대부분의 관할권에서는 오해의 소지가 있는 기준가격 표시를 기만적인 상업 관행으로 다룬다. 유럽연합은 여기서 한 걸음 더 나아가 구체적이고 검증 가능한 규정을 두고 있다.

  • 유럽연합. 2022년 5월 28일부터 가격 인하를 공고할 때는 종전 가격을 표시해야 하며, 이는 인하 전 최소 30일 동안 사업자가 적용한 최저가로 정의된다. 회원국은 빠르게 상하는 상품, 30일 미만으로 판매되는 제품, 그리고 점진적으로 커지는 인하에 대해서는 다른 규정을 둘 수 있다. 2024년 9월, EU 사법재판소는 소매업체 Aldi Süd가 연루된 사건에서 백분율로 광고되거나 프로모션성 “가격 하이라이트”로 표시된 인하 역시 세일 직전 가격이 아니라 이 30일 최저가를 기준으로 측정되어야 한다고 판결했다.
  • 영국. 오해를 유발하는 가격 비교는 불공정 상업 관행에 해당하며, 2025년 4월부터 경쟁시장청(Competition and Markets Authority)은 법원을 거치지 않고도 소비자법 위반 여부를 직접 결정하고 기업에 벌금을 부과할 수 있다.
  • 미국. 연방거래위원회(Federal Trade Commission)의 기만적 가격 표시 방지 지침(Guides Against Deceptive Pricing)은 종전 가격이 상당 기간 동안 일반 대중에게 정기적으로 제공되었던 실제이고 진정한 가격일 때만 비교의 정당한 근거로 인정한다.

EU 규정은 “이 할인이 진짜인가?”라는 질문을 산술 문제로 바꾸기 때문에 모니터링에 가장 유용하다. 세일 전 30일 동안의 최저가를 찾아 비교하면 된다. 이는 가격 이력이 있어야만 가능하므로, 모니터링은 검증하려는 세일보다 훨씬 전에 시작해야 한다.

가격 증거가 버텨내려면 무엇이 필요한가

조사 결과에 직면한 소매업체는 결론보다 먼저 데이터를 문제 삼는다. 증거는 뻔한 반박을 미리 답해둘 때 버텨낸다.

반박무엇이 답이 되는가
”데이터가 틀렸다.”URL, UTC 타임스탬프, 해시값과 함께 캡처된 원본 페이지로, 원본에서 가격을 다시 확인할 수 있게 한다
”며칠을 놓쳤다.”각 구간의 커버리지를 함께 보고하는 일별 관측, 커버리지가 너무 낮으면 판정하지 않음
”그건 다른 상품이었다.”모든 관측치와 함께 기록되는 안정적인 상품 식별자(SKU, EAN 또는 소매업체 자체 ID)
“그건 다른 지역의 가격이었다.”가격이 적용된 위치, 매장, 또는 배송 우편번호를 기록하고 일정하게 유지함
”그건 회원 전용 또는 앱 전용 가격이었다.”로그아웃 상태에서 수집한 공개 가격, 페이지에 표시된 조건을 함께 기록함
”최악의 사례만 골랐다.”분석 전에 정의된 방법론과 표본, 나쁜 결과만이 아니라 모든 결과를 보고함

일별 수집은 대부분의 모니터링보다 여기서 더 중요하다. 온라인 가격에 관한 연구에 따르면 주간 샘플링으로도 대형 소매업체의 정기적인 가격 변동 대부분을 포착할 수 있지만, 가짜 기준가격은 단 1주일 안에 숨을 수 있다. 온라인 가격이 얼마나 빨리 변하는가에 관한 우리의 조사가 수집 주기를 자세히 다룬다. 스크린샷부터 해싱, 타임스탬프에 이르는 캡처 측면은 온라인 목록에서 법정 증거 구축하기와 동일한 원칙을 따른다.

할인 주장 검증하기

아래 함수는 상품의 일별 가격 이력과 공고된 인하율을 받아 EU 규정과 같은 방식으로 검증한다. 누락된 날이 너무 많으면 판정을 거부하고, 커버리지를 기록해 독자가 증거가 얼마나 완전했는지 확인할 수 있도록 한다. 두 번째 함수는 각 관측치를 타임스탬프와 원본 페이지의 해시값과 함께 저장한다.

import hashlib
from datetime import datetime, timedelta, timezone


def evidence_record(url, raw_body, price, currency):
    """One observation, stored so that anyone can later check what was seen and when."""
    return {
        "url": url,
        "captured_at": datetime.now(timezone.utc).isoformat(timespec="seconds"),
        "sha256": hashlib.sha256(raw_body).hexdigest(),
        "price": price,
        "currency": currency,
    }


def lowest_prior_price(history, start, days=30, min_coverage=0.8):
    """Lowest observed price in the `days` before `start`, if we watched closely enough.

    history: {date: price} from daily observations.
    Returns (price, coverage); price is None when too many days are missing to say.
    """
    window = [start - timedelta(days=d) for d in range(1, days + 1)]
    seen = [history[d] for d in window if d in history]
    coverage = len(seen) / days
    if coverage < min_coverage:
        return None, round(coverage, 2)
    return min(seen), round(coverage, 2)


def check_discount(history, start, sale_price, shown_prior=None, shown_percent=None):
    """Compare an announced reduction with the lowest price in the 30 days before it."""
    prior, coverage = lowest_prior_price(history, start)
    result = {"start": start.isoformat(), "sale_price": sale_price, "lowest_30d": prior,
              "coverage": coverage, "findings": []}
    if prior is None:
        result["findings"].append("not enough observations before the sale to judge")
        return result
    real_percent = round(100 * (prior - sale_price) / prior, 1)
    result["real_percent"] = real_percent
    if sale_price >= prior:
        result["findings"].append("no real reduction: the sale price is not below the 30-day low")
    if shown_prior is not None and shown_prior > prior:
        result["findings"].append(f"shown prior price {shown_prior} is above the 30-day low {prior}")
    if shown_percent is not None and shown_percent > real_percent + 0.5:
        result["findings"].append(f"claims {shown_percent}% off, but it is {real_percent}% off the 30-day low")
    return result

다음은 같은 세일 날짜에 올라온 세 가지 예시 할인 상품이다(가상의 이력이며 실제 소매업체가 아니다).

from datetime import date, timedelta

from discounts import check_discount

sale = date(2026, 11, 27)


def daily(prices_before_sale):
    """Daily observations for the days before the sale, oldest first."""
    n = len(prices_before_sale)
    return {sale - timedelta(days=n - i): p for i, p in enumerate(prices_before_sale)}


offers = {
    "kettle":  (daily([49.99] * 40), 39.99, 49.99, 20),
    "blender": (daily([59.99] * 25 + [89.99] * 15), 59.99, 89.99, 33),
    "toaster": (daily([34.99] * 30 + [29.99] * 10), 27.99, 34.99, 20),
}
for name, (history, price, shown_prior, shown_percent) in offers.items():
    result = check_discount(history, sale, price, shown_prior, shown_percent)
    print(name, result["lowest_30d"], f"{result['real_percent']}%", result["findings"] or "ok")
kettle 49.99 20.0% ok
blender 59.99 0.0% ['no real reduction: the sale price is not below the 30-day low', 'shown prior price 89.99 is above the 30-day low 59.99', 'claims 33% off, but it is 0.0% off the 30-day low']
toaster 29.99 6.7% ['shown prior price 34.99 is above the 30-day low 29.99', 'claims 20% off, but it is 6.7% off the 30-day low']
  • **주전자(kettle)**는 전체 기간 동안 49.99였고 39.99에 판매된다. 20% 할인 주장은 정확하다.
  • **블렌더(blender)**는 대부분의 기간 동안 59.99였다가 마지막 15일 동안 89.99로 올랐고, 33% 할인을 내세워 다시 59.99로 “인하”되었다. 30일 최저가 대비로는 전혀 인하되지 않았다. 이것이 전형적인 패턴이다.
  • **토스터(toaster)**는 실제로 인하되었지만 주장된 것보다 폭이 작다. 세일 전 10일 동안 이미 29.99였으므로 27.99는 20%가 아니라 6.7% 할인이다.

80%라는 커버리지 임계값은 판단의 문제다. 시작하기 전에 하나를 정해 모든 상품에 동일하게 적용하고, 결과와 함께 보고해야 한다.

모니터링 프로젝트 진행하기

  1. 표본을 먼저 정의한다. 세일 시즌이 시작되기 전에 소매업체, 카테고리, 상품을 선정하고 그 이유를 기록한다. 가격을 본 후에 표본을 정하면 선택적 취사(cherry-picking)라는 비판을 받기 쉽다.
  2. 일찍 시작한다. EU 검증에는 세일 전 최소 30일간의 이력이 필요하다. 공백에 대비해 6주 전부터 시작한다.
  3. 공개 가격을 수집한다. 로그아웃 상태로, 고정된 위치에서, 소매업체 자체의 상품 페이지를 이용한다. 수집한 위치를 기록해 둔다. 가격과 프로모션은 종종 지역별로 다르다.
  4. 모든 것을 캡처한다. 모든 관측치에 대해 원본 페이지, 파싱된 가격, 증거 기록을 보관한다. 저장 비용은 저렴하지만, 놓친 하루는 복구할 수 없다.
  5. 발표 전에 확인한다. 플래그가 붙은 가격을 원본 페이지에서 수작업으로 다시 확인한다. 명백해 보이는 위반 사례 중 상당수는 파싱 오류, 다른 변형 상품, 또는 묶음 상품으로 밝혀진다.
  6. 사업자에게 반론 기회를 준다. 언론과 소비자 단체는 보통 조사 결과를 발표하기 전에 소매업체에 전달한다. 응답을 통해 확인하지 못했던 지역별 가격처럼 정당한 설명이 드러나는 경우도 있다.
  7. 방법론을 공개한다. 표본, 날짜, 수집 주기, 커버리지 임계값, 그리고 전체 결과를 보고한다.

책임감 있게 수집하기

공익 목적의 모니터링도 여전히 데이터 수집이며, 동일한 원칙이 적용된다. 공개된 가격을, 쇼핑객이 직접 열어볼 수 있는 상품 페이지에서, 로그인 없이, 적절한 속도로 수집한다. 개인정보는 데이터셋에서 완전히 배제한다. 가격 증거에는 상품과 가격만 있으면 되며, 리뷰어나 고객 정보는 필요 없다. 나머지 내용은 웹 스크래핑 모범 사례에서 다룬다.

가격이 국가별로 다른 경우, 각 시장 내부에서 수집해 현지 쇼핑객이 보는 가격을 그대로 확인해야 한다. 국가 타겟팅이 가능한 레지덴셜 프록시가 이를 대규모로 수행하는 일반적인 방법이며, 각 시장에 대해 위치를 고정하는 것은 수집 주기만큼이나 중요하다.

자주 묻는 질문

가격 인하에 관한 30일 규정이란 무엇인가?

유럽연합에서는 가격 인하 공고 시 종전 가격을 표시해야 하며, 이는 인하 전 최소 30일 동안 사업자가 적용한 최저가를 의미한다. EU 사법재판소는 2024년 백분율 인하 역시 이 가격을 기준으로 계산되어야 한다고 확인했다.

할인이 가짜인지 어떻게 알 수 있나?

세일 전 최소 30일간 상품의 가격을 매일 추적한다. 세일 가격이 그 기간의 최저가보다 낮지 않거나, 주장된 할인율이 그 최저가 대비 실제 인하율보다 크다면, EU 규정상 그 할인 표시는 오해의 소지가 있을 가능성이 높다.

세일 전 얼마나 오래 가격을 모니터링해야 하는가?

EU 검증을 위해서는 최소 30일이며, 실제로는 며칠이 누락되어도 구간이 불완전해지지 않도록 약 6주 정도가 적당하다.

가격 모니터링 증거를 민원에 사용할 수 있는가?

원본 페이지, 타임스탬프, 상품 식별자, 가격이 적용된 위치, 공개된 방법론 등으로 잘 문서화되어 있다면 민원을 뒷받침할 수 있다. 민원을 제출하거나 의혹을 공개하기 전에 법률 자문을 구해야 한다.

결론

가짜 할인은 만들기 쉽지만, 적절한 데이터만 있으면 검증하기도 쉽다. EU의 30일 규정은 할인 주장을 가격 이력과의 비교로 바꾸므로, 모니터링은 세일보다 훨씬 전에 시작해야 한다. 고정된 위치에서, 로그아웃 상태로 매일 수집하고, 모든 관측치의 원본 증거를 보관한다. 데이터가 부족할 때는 판정을 거부하고, 모든 결과를 수작업으로 확인하며, 방법론을 공개한다. 이렇게 수집된 증거는 무시하기 어렵다.

출처 및 참고자료

시작할 준비가 되셨나요?

205M개 이상의 IP, 195개 이상의 국가를 지원하는 Shifter의 레지덴셜 프록시를 $0.10/GB부터 이용해보세요.

시작하기