한 투숙객이 당신의 호텔을 찾아 웹사이트를 확인한 다음, 다른 사이트에서 같은 객실을 더 저렴하게 발견합니다. 그 투숙객은 그곳에서 예약하고, 당신은 수수료를 지불하며, 투숙객은 당신의 웹사이트가 예약할 곳이 아니라는 것을 알게 됩니다. 이런 일이 파트너가 일반 대중에게 판매할 의도가 없던 요금을 유출했기 때문에 벌어진다면, 당신 자신의 재고가 당신을 저가로 공격하는 데 쓰이고 있는 것입니다.
레이트 패리티 모니터링은 호텔과 여행 브랜드가 이런 일이 어디서, 어느 시장에서, 어떤 채널을 통해 벌어지는지 알아내는 방법입니다. 이 가이드는 규칙이 바뀐 지금 패리티가 무엇을 의미하는지, 대부분의 패리티 점검이 왜 거짓 경보를 내는지, 그리고 동일한 것끼리 비교하는 검증된 코드를 다룹니다.
핵심 요약
- 패리티는 더 이상 온라인 여행사가 유럽 대부분 지역에서 호텔에 강제할 수 있는 것이 아닙니다. 이제는 주로 호텔 자신의 이해관계, 즉 자사 객실로 인해 저가로 공격당하지 않는 문제가 되었습니다.
- 저가 판매는 대개 호텔이 계약을 맺은 적 없는 사이트에 유출된 도매 요금이나 패키지 요금이 나타나면서 발생하며, 주요 여행사 자체에서 비롯되는 경우는 드뭅니다.
- 가격은 투숙객이 실제로 예약하는 시장에서 확인해야 합니다. 같은 객실이라도 쇼핑객이 어디에 있는지에 따라 다른 가격, 통화, 세금 표시 방식으로 보여질 수 있습니다.
- 동일한 상품만 비교해야 합니다. 같은 날짜, 객실, 식사 조건, 취소 조건을 갖추고 세금을 포함하고 통화를 환산한 상태여야 합니다. 저희가 구성한 예시에서, 지름길 점검은 5건의 경보를 울렸고 그중 3건은 거짓이었습니다. 정규화된 점검은 정확히 2건의 실제 저가 판매만 찾아냈습니다.
- 저가 판매는 조사의 시작으로 다뤄야 합니다. 어떤 파트너의 요금이 유출되었는지 찾아낸 다음, 계약이나 유통 설정을 수정하십시오.
지금 레이트 패리티가 의미하는 것
과거에는 온라인 여행사들이 호텔에게 다른 어느 곳에서도 그보다 더 나쁘지 않은 가격을 제공하도록 요구했습니다. “넓은(wide)” 패리티 조항은 모든 채널을 포괄했고, “좁은(narrow)” 조항은 호텔 자체 웹사이트만 포괄했습니다. 유럽 대부분 지역에서 두 조항 모두 폐지되었습니다.
- 독일. 연방 카르텔청은 2015년 Booking.com의 좁은 최저가 조항을 금지했으며, 연방 대법원은 2021년 5월 이 조항이 경쟁법을 위반한다고 확인했습니다.
- 유럽연합. 2024년 9월, 유럽사법재판소는 플랫폼 가격 패리티 조항이 넓든 좁든 원칙적으로 경쟁법 적용을 면제받는 부수적 제한으로 취급될 수 없다고 판결했습니다.
- 디지털시장법(Digital Markets Act). Booking.com은 2024년 5월 게이트키퍼로 지정되었고 2024년 11월까지 이를 준수해야 했습니다. 이 법에 따라 패리티 조항은 Booking.com에 대해 금지되므로, 호텔 및 다른 공급자들은 자사 웹사이트와 다른 채널에서 더 나은 가격과 조건을 포함해 다른 가격과 조건을 제시할 수 있으며, Booking.com은 수수료 인상이나 목록 삭제와 같이 동일한 효과를 내는 조치를 취할 수 없습니다.
- 그 밖의 지역. 프랑스, 이탈리아, 오스트리아, 벨기에, 스위스를 포함한 여러 국가가 자국법에서 숙박 플랫폼의 패리티 조항을 제한했습니다.
이는 일반적인 정보이며 법률 자문이 아닙니다. 규칙은 국가와 계약에 따라 다르므로, 자사 계약에 대해서는 법률 전문가와 상담하시기 바랍니다.
실질적인 결과는 패리티의 입장이 뒤바뀌었다는 것입니다. 이제 호텔은 대개 자체 사이트에서 여행사보다 낮은 가격을 자유롭게 책정할 수 있으며, 많은 호텔이 그렇게 하고 싶어 합니다. 그래도 여전히 알아야 할 것은, 누군가 자사의 직접 판매가보다 낮은 가격으로 자사 객실을 판매하고 있는지, 그리고 어떻게 그렇게 하는지입니다.
저가 판매는 어디서 비롯되는가
| 출처 | 발생 방식 | 모니터링에서 드러나는 것 |
|---|---|---|
| 유출된 도매 요금 | 패키지에 번들로 포함되도록 설계된 순수 요금이 단독 객실로 재판매됨 | 메타서치에서 흔히 발견되는, 직접 판매가보다 낮은 낯선 사이트들 |
| 패키지 분리 판매 | 투어 운영사의 호텔+항공 결합 요금이 분리되어 객실로만 판매됨 | 어떤 공개 채널도 제시해서는 안 될 만큼 낮은 가격 |
| 회원 및 모바일 요금 | 채널이 로그인 사용자나 앱 사용자에게 더 낮은 가격을 보여줌 | 특정 기기나 세션에서만 나타나는 가격 차이 |
| 통화 및 시장별 가격 책정 | 채널이 쇼핑객의 국가나 통화에 따라 다르게 가격을 책정함 | 일부 시장에서만 나타나고 다른 시장에서는 나타나지 않는 저가 판매 |
| 오래되었거나 잘못 입력된 요금 | 요금 변경이 모든 채널에 반영되지 않음 | 특정 날짜에만 짧게 나타나는 가격 차이 |
이 중 일부만 누군가의 잘못이며, 일부만 전화 한 통으로 해결할 수 있습니다. 모니터링은 이들을 구분할 수 있을 만큼 충분한 세부 정보를 보여주어야 합니다.
단순한 패리티 점검이 거짓 경보를 내는 이유
패리티 점검은 단순해 보입니다. 여러 사이트에서 같은 호텔을 찾아 가격을 비교하면 됩니다. 하지만 이런 식으로 하면 대시보드가 실제가 아닌 경보로 가득 차고, 정작 실제 경보는 놓치게 됩니다. 흔한 이유는 다음과 같습니다.
- 다른 상품. 환불 불가 요금이나 객실만 포함된 요금은 조식이 포함된 유연한 요금에 대한 저가 판매가 아닙니다.
- 세금 표시. 미국 쇼핑객에게 보여지는 많은 사이트는 세전 가격을 표시하는 반면, 대부분의 유럽 사이트는 세금을 포함합니다. 같은 총액이라도 몇 퍼센트 더 저렴해 보일 수 있습니다.
- 통화. 서로 다른 환율로 환산하거나, 애초에 통화를 넘나들며 비교하는 것만으로도 그 자체로 1~2퍼센트의 차이가 생깁니다.
- 시장. 미국에서 보여지는 채널 가격은 독일에서 보여지는 당신의 직접 판매가와 비교할 수 없습니다. 각 시장은 그 시장 자체와 비교해야 합니다.
- 날짜 및 투숙 인원. 체류 기간과 투숙객 수가 다르면 동일한 1박 요금이라도 총액이 달라집니다.
코드
아래 모듈은 견적이 동일한 조건으로 동일한 상품을 판매할 때만 비교하고, 세금 표시와 통화를 정규화하며, 각 채널을 동일한 시장에 표시된 직접 판매가와 비교하여 그 차이를 보고합니다. 객실 코드는 각 채널의 표현 방식에서 매핑한 자체 정규화 코드를 사용해야 합니다. 채널마다 같은 객실을 다르게 설명하기 때문입니다.
from collections import defaultdict
from dataclasses import dataclass
from decimal import ROUND_HALF_UP, Decimal
@dataclass(frozen=True)
class Quote:
channel: str # "direct", or the name of the OTA or metasearch listing
market: str # where the shopper was, e.g. "DE" or "US"
hotel: str
check_in: str
nights: int
room: str # your own normalised room code, not the channel's wording
board: str # "room-only", "breakfast", ...
refundable: bool
price: Decimal # total for the stay, exactly as displayed
currency: str
taxes_included: bool
def product_key(q):
"""Two quotes are only comparable when they sell the same thing on the same terms."""
return (q.hotel, q.check_in, q.nights, q.room, q.board, q.refundable)
def comparable_total(q, fx_to_base, hotel_tax):
"""Total price in the base currency with the destination's taxes included."""
amount = q.price if q.taxes_included else q.price * (1 + hotel_tax[q.hotel])
return (amount * fx_to_base[q.currency]).quantize(Decimal("0.01"), ROUND_HALF_UP)
def find_undercuts(quotes, fx_to_base, hotel_tax, tolerance=Decimal("0.01")):
"""Compare every channel with the direct rate shown to the same market, and report cheaper offers."""
groups = defaultdict(list)
for q in quotes:
groups[(product_key(q), q.market)].append(q)
undercuts, unmatched = [], []
for (key, market), group in groups.items():
direct = [comparable_total(q, fx_to_base, hotel_tax) for q in group if q.channel == "direct"]
if not direct:
unmatched.extend(q for q in group)
continue
best_direct = min(direct)
for q in group:
if q.channel == "direct":
continue
total = comparable_total(q, fx_to_base, hotel_tax)
gap = (best_direct - total) / best_direct
if gap > tolerance:
undercuts.append({"channel": q.channel, "market": market, "hotel": key[0], "check_in": key[1],
"direct": best_direct, "channel_total": total, "gap": round(gap, 3)})
return sorted(undercuts, key=lambda u: u["gap"], reverse=True), unmatched
여기서 두 가지 설계 선택이 중요합니다. 세금은 호텔별로 적용되는데, 이는 세금이 쇼핑객의 국가가 아니라 목적지에 속하기 때문입니다. 그리고 비교 가능한 직접 판매 조건이 없는 견적은 폐기하지 않고 따로 반환됩니다. 당신이 직접 판매하지 않는 상품을 판매하는 채널이 있다는 것 자체가 하나의 발견이기 때문입니다.
실제 적용 예시
저희는 하나의 호텔과 하나의 숙박 기간에 대해, 독일, 미국, 영국의 쇼핑객에게 표시된 10건의 견적으로 구성된 데이터셋에 이 모듈을 테스트했으며, 그중 두 건의 실제 저가 판매를 의도적으로 심어두었습니다. 이는 가상의 가격을 사용한 예시일 뿐, 실제 호텔이나 채널을 측정한 결과가 아닙니다.
| Check | Alerts raised | Real undercuts found | False alarms |
|---|---|---|---|
| 지름길: 동일 시장 내 표시 가격과 직접 판매가 비교 | 5 | 2 | 3 |
| 정규화: 동일 상품, 세금 포함, 단일 통화 | 2 | 2 | 0 |
3건의 거짓 경보는 전형적인 사례들입니다. 세전 가격을 표시했지만 실제로는 패리티가 맞았던 미국 목록, 환불 불가 요금, 그리고 객실만 포함된 요금입니다. 정규화된 점검은 뒤의 두 건을 비교 불가능한 것으로 제외하고 별도로 목록화했습니다. 환산 후 직접 판매가보다 0.5% 낮았던 영국 목록은 1%의 허용 오차 이내에 머물렀는데, 이는 통화 환산만으로도 생길 수 있는 정도의 차이입니다.
견적 수집하기
패리티 모니터링의 품질은 투숙객이 실제로 보는 것을 수집하는지에 달려 있습니다.
- 투숙객의 시장에서 조회하기. 채널과 메타서치 결과는 방문자의 국가에 따라 달라지므로, 중요한 각 시장 내부에서 수집해야 합니다. 항공사와 호텔이 출발 국가에 따라 다르게 가격을 제시하는지에 대한 저희 테스트는 이것이 선택 사항이 아닌 이유를 보여줍니다.
- 세션을 일관되게 유지하기. 프록시의 지역, 시간대, 로케일 일치시키기에서 다룬 것처럼 언어, 통화, 시간대를 해당 시장에 맞춰야, 세션 도중 채널이 다른 시장의 가격으로 전환하지 않습니다.
- 기기를 별도로 확인하기. 모바일 및 앱 요금은 데스크톱 요금과 다를 수 있으므로, 투숙객이 둘 다 사용하는 경우 양쪽 모두 테스트해야 합니다.
- 전체 조건을 기록하기. 대표 가격만이 아니라 식사 조건, 취소 정책, 투숙 인원, 세금 포함 여부를 기록해야 합니다. 표시되는 숫자 또한 로케일별 가격, 숫자, 날짜 정규화하기에서 설명한 것처럼 로케일에 맞춰 파싱해야 합니다.
- 내일만이 아니라 여러 날짜를 표본으로 삼기. 유출은 종종 특정 미래 날짜에만 나타나므로, 다양한 도착 날짜와 숙박 기간을 포괄해야 합니다.
- 정중하게 수집하기. 검색 결과를 마구 요청하기보다 일정에 따라 합리적인 범위의 날짜를 확인하고, 각 사이트의 이용 약관을 준수해야 합니다.
같은 수집 방식은 더 일반적으로 항공편 및 호텔 가격 스크래핑의 기반이 되며, 저희 여행 사용 사례에서는 팀들이 이를 여러 숙박시설에 걸쳐 어떻게 운영하는지 다룹니다.
경보에서 해결까지
저가 판매 경보는 작업의 끝이 아니라 시작입니다.
- 확인하기. 동일한 시장에서 해당 제안을 다시 확인하고, 예약 경로가 실제로 그 가격으로 끝나는지 확인합니다.
- 추적하기. 테스트 예약이나 결제 단계에 표시되는 요금 코드와 공급자를 확인하면 대개 어떤 파트너의 요금이 유출되었는지 알 수 있습니다.
- 출처에 조치하기. 도매 계약을 강화하거나, 파트너가 받는 요금을 변경하거나, 영향을 받는 날짜에 대해 채널을 닫습니다.
- 시간에 따라 추적하기. 파트너와 시장별로 저가 판매를 기록합니다. 반복적으로 유출하는 파트너는 모니터링 문제가 아니라 상업적 논의의 대상입니다.
결론
레이트 패리티는 이제 여행사들이 강제하는 조항이 아니라, 호텔 스스로 묻는 질문이 되었습니다. 누군가 내 객실을 나보다 더 싸게 팔고 있는가? 이 질문에 신뢰성 있게 답하려면 투숙객이 실제로 예약하는 시장에서 가격을 수집하고, 세금과 통화를 정규화한 상태로 동일한 상품만 비교해야 합니다.
그렇게 하면 패리티 경보는 드물고 실제적인 것이 됩니다. 그렇게 하지 않으면 대시보드는 세금 표시와 환불 불가 요금으로 가득 차고, 예약을 갉아먹는 유출된 요금은 그 소음 속에 묻혀버립니다.
출처 및 참고 자료
- 유럽사법재판소, 사건 C-264/23, Booking.com 관련 보도자료, 2024년 9월 19일.
- Bundeskartellamt, 연방 대법원, Booking.com의 좁은 가격 패리티 조항의 위법성 확인, 2021년.
- 유럽위원회(European Commission), Booking, 이제 디지털시장법을 준수해야 함, 2024년 11월.
- Shifter가 구성한 테스트 데이터 및 코드, 2026년 10월 3일.