가짜 리뷰는 더 이상 평판 문제에 그치지 않는다. 이제는 미국, 영국, 유럽연합에서 법적인 문제이기도 하며, 리뷰를 호스팅하는 플랫폼들은 수억 건 단위로 가짜 리뷰를 삭제하고 있다. 브랜드, 마켓플레이스, 신뢰 및 안전 팀에게 이는 실질적인 질문을 던진다. 누군가 불만을 제기한 단일 리스팅뿐 아니라 수천 개의 제품에 걸쳐 리뷰 사기를 어떻게 찾아낼 것인가?
이 가이드는 문제의 규모, 캠페인과 일반 고객을 실제로 구분하는 신호들, 가장 유용한 세 가지 신호에 대한 테스트된 코드, 그리고 리뷰 데이터를 책임감 있게 수집하는 방법을 다룬다.
핵심 요약
- 규모가 크다. Google은 2025년 Maps에서 정책을 위반한 리뷰 2억 9,200만 건 이상을 차단 또는 삭제했고, Amazon은 2023년에 의심되는 가짜 리뷰 2억 5,000만 건 이상을 차단했다고 밝혔다.
- 리뷰를 읽는 것만으로는 효과가 없다. 유명한 한 연구에서 가짜 호텔 리뷰를 가려내는 인간 평가자들의 정확도는 53%에서 62% 사이로 거의 우연에 가까웠던 반면, 학습된 분류기는 약 90%에 도달했다.
- 조직적인 캠페인은 행동 흔적을 남긴다. 며칠 사이에 몰리는 리뷰 폭증, 거의 동일한 문구, 다른 활동 이력이 없는 리뷰어 등이 그것이다.
- 신호를 결합하라. 우리 테스트에서 문구 유사성 하나만으로는 잡음이 많았지만, 폭증과 중복 문구 또는 단일 리뷰 계정을 결합하자 심어 둔 가짜 리뷰를 최대 3건의 오탐만으로 모두 잡아냈다.
- 플래그는 사람이 검토할 단서로 취급하고, 리뷰어 데이터는 가명 처리하며, 결과에 따라 조치를 취하기 전에 법적 입장을 확인하라.
문제의 규모
플랫폼들이 직접 공개한 투명성 수치는 규모를 가늠하게 해준다.
| 플랫폼 | 수치 | 기간 |
|---|---|---|
| Google Maps | 정책 위반 리뷰 2억 9,200만 건 이상 차단 또는 삭제; 가짜 비즈니스 프로필 1,300만 건 이상 제거 | 2025년 |
| Amazon | 의심되는 가짜 리뷰 2억 5,000만 건 이상 차단 | 2023년 |
| Tripadvisor | 제출된 3,110만 건 중 사기 리뷰 270만 건; 사기의 54%는 업체가 스스로를 홍보한 것; AI로 생성된 리뷰 214,000건 제거 | 2024년 |
이는 적발된 리뷰 수치일 뿐이다. 이 수치는 사기의 양상이 대체로 어떤 모습인지도 보여준다. Tripadvisor의 경우 절반 이상이 정교한 속임수가 아니라 업체 또는 그와 연관된 사람들에 의한 리뷰 부풀리기였다.
규정이 바뀌었다
이제 세 개의 주요 시장이 가짜 리뷰를 명시적으로 금지하고 있다.
- 미국. 2024년 10월부터 시행된 연방거래위원회(FTC)의 소비자 리뷰 및 보증 규칙은 가짜 리뷰, 긍정적 또는 부정적 리뷰의 구매, 미공개된 내부자 리뷰, 독립적인 것처럼 보이는 업체 운영 리뷰 사이트, 리뷰 억제를 금지하며, 당국이 민사 제재금을 부과할 수 있도록 허용한다.
- 영국. 2025년 4월 6일부터 가짜 리뷰를 제출하거나 의뢰하는 행위, 대가성 리뷰를 숨기는 행위, 오해를 불러일으키는 방식으로 리뷰를 게시하는 행위가 금지되었으며, 리뷰를 게시하는 업체는 가짜 리뷰를 방지하고 제거하기 위한 합리적인 조치를 취해야 한다. 규제 당국은 전 세계 매출의 최대 10%에 해당하는 과징금을 부과할 수 있다.
- 유럽연합. 2022년 5월부터 리뷰를 표시하는 사업자는 해당 리뷰가 실제로 제품을 사용하거나 구매한 고객으로부터 나온 것인지, 그리고 이를 어떻게 확인하는지 밝혀야 하며, 가짜 리뷰를 제출하거나 의뢰하는 행위는 금지된다.
마켓플레이스와 리뷰 게시자에게 이는 탐지를 선택사항이 아닌 컴플라이언스의 일부로 바꾼다. 브랜드에게는 경쟁사가 리뷰를 구매할 경우 대응할 수 있는 경로가 생긴다. 이는 일반적인 정보이며 법률 자문이 아니므로, 개별 상황에 대해서는 변호사와 상담해야 한다.
리뷰를 읽는 것만으로는 왜 효과가 없는가
이 문제에 관한 가장 잘 알려진 학술 연구는 Cornell의 Ott, Choi, Cardie, Hancock이 수행한 것으로, 호텔 리뷰 800건, 즉 진짜 400건과 속이기 위해 작성된 400건으로 구성된 데이터셋을 만들었다. 세 명의 인간 평가자가 이를 분류했다. 그들의 정확도는 각각 53.1%, 56.9%, 61.9%였으며, 그중 두 명은 우연히 맞춘 것과 통계적으로 유의미한 차이가 없었다. 세 명 모두 리뷰를 진짜라고 믿는 쪽으로 편향되어 있었다. 단어 패턴으로 학습된 분류기는 89.8%에 도달했다.
이는 두 가지를 시사한다. 수작업 표본 확인은 대부분의 가짜 리뷰를 놓치게 된다. 그리고 텍스트만 보는 탐지는 2011년보다 지금이 더 어렵다. 모델은 요청에 따라 다양하고 자연스러운 리뷰를 작성할 수 있으며, 이것이 Tripadvisor가 이제 AI로 생성된 리뷰를 별도 항목으로 보고하는 이유이다. 더 신뢰할 수 있는 신호는 행동에 관한 것이다. 리뷰가 언제 도착하는지, 누가 작성하는지, 서로 얼마나 비슷한지가 그것이다.
효과가 있는 신호들
| 신호 | 포착하는 것 | 약점 |
|---|---|---|
| 폭증 | 평소 하루에 2건 정도 받는 제품에 며칠 사이 수십 건의 리뷰가 몰리는 경우 | 세일, 출시, 언론 보도 이후의 정상적인 급증 |
| 거의 동일한 문구 | 단어 일부만 바뀐 정형화된 리뷰 | 진짜 리뷰에서도 흔한 표현; 다양하게 작성된 AI 텍스트 |
| 단일 리뷰 계정 | 단일 캠페인을 위해 만들어진 리뷰어 | 새로 유입된 진짜 고객 |
| 평점 형태 | 세부 내용이 거의 없는 5점 리뷰가 갑자기 몰리는 경우 | 실제로 품질이 좋은 제품 |
| 제품 간 중복 | 동일한 리뷰어들이 한 판매자의 여러 제품에 등장하는 경우 | 충성도 높은 고객 |
| 시장 간 차이 | 한 국가 스토어프론트에서 제품 평점이 크게 다른 경우 | 현지 버전이나 서비스의 실제 차이 |
단일 신호만으로는 신뢰할 수 없다. 폭증은 성공적인 출시일 수 있고, 유사한 문구는 흔한 표현일 수 있다. 캠페인은 대개 여러 신호를 동시에 드러내는데, 이것이 신호를 결합할 때 효과적인 이유이다.
코드
아래 모듈은 이 신호들 중 세 가지와 이를 결합하는 한 가지 방법을 구현한다. 외부 라이브러리는 필요하지 않다. 리뷰는 개인 데이터이고 분석에 이름 자체가 필요하지 않으므로, 분석 전에 리뷰어 이름은 솔트가 적용된 해시로 대체된다.
import hashlib
import re
from collections import Counter, defaultdict
from statistics import median
def pseudonymise(author, salt):
"""Replace a reviewer's name with a stable token, so analysis never needs the name itself."""
return hashlib.sha256((salt + author).encode()).hexdigest()[:12]
def review_bursts(reviews, k=6.0, min_count=5):
"""Flag days whose review count is far above the product's typical day, using a robust baseline."""
daily = Counter(r["date"] for r in reviews)
counts = list(daily.values())
base = median(counts)
spread = median(abs(c - base) for c in counts) or 1
flagged = []
for day, n in sorted(daily.items()):
if n >= min_count and n > base + k * spread:
day_reviews = [r for r in reviews if r["date"] == day]
five_star = sum(r["rating"] == 5 for r in day_reviews) / n
flagged.append({"date": day, "reviews": n, "baseline": base, "five_star_share": round(five_star, 2)})
return flagged
def shingles(text, size=5):
text = re.sub(r"\s+", " ", text.lower()).strip()
return {text[i:i + size] for i in range(max(1, len(text) - size + 1))}
def near_duplicates(reviews, threshold=0.5):
"""Pairs of reviews by different reviewers whose wording overlaps heavily (Jaccard on 5-character shingles)."""
sets = [shingles(r["text"]) for r in reviews]
pairs = []
for i in range(len(reviews)):
for j in range(i + 1, len(reviews)):
if reviews[i]["reviewer"] == reviews[j]["reviewer"]:
continue
overlap = len(sets[i] & sets[j]) / len(sets[i] | sets[j])
if overlap >= threshold:
pairs.append((reviews[i]["id"], reviews[j]["id"], round(overlap, 2)))
return pairs
def one_review_accounts(reviews, history):
"""Share of reviewers in this set who have reviewed nothing else; history maps reviewer to their total reviews."""
reviewers = {r["reviewer"] for r in reviews}
return sum(history.get(x, 1) == 1 for x in reviewers) / len(reviewers)
def suspicious_reviews(reviews, history, threshold=0.5):
"""Combine the signals: a review is suspicious when it sits in a burst and either duplicates
other wording or comes from a one-review account."""
burst_days = {b["date"] for b in review_bursts(reviews)}
duplicated = defaultdict(int)
for a, b, _ in near_duplicates(reviews, threshold):
duplicated[a] += 1
duplicated[b] += 1
return [r["id"] for r in reviews
if r["date"] in burst_days and (duplicated[r["id"]] or history.get(r["reviewer"], 1) == 1)]
폭증 탐지기는 평균과 표준편차 대신 중앙값과 중앙값 절대편차를 사용하므로, 폭증 자체가 그것을 측정하는 기준선을 부풀리지 않는다. near_duplicates의 쌍별 비교는 단일 제품의 리뷰에는 적합하지만, 전체 카탈로그에 걸쳐 사용하려면 먼저 제품이나 판매자별로 리뷰를 그룹화하거나 지역 민감 해싱(locality-sensitive hashing)을 사용해야 한다.
결과는 어땠나
우리는 정답을 미리 알고 있는 구성된 데이터셋으로 이 코드를 테스트했다. 한 제품에 대해 6개월간의 유기적인 리뷰, 하루에 몇 건씩 현실적인 평점과 다양한 문구로 작성된 256건에서 285건, 그리고 3일에 걸쳐 새 계정에서 올라온 정형화된 5점 리뷰 40건으로 이루어진 심어 둔 캠페인을 더했다. 이를 서로 다른 임의의 시드 6개로 실행했다.
| 점검 항목 | 6회 실행 결과 |
|---|---|
| 폭증 탐지로 찾아낸 캠페인 발생일 | 매번 3일 모두; 기준선 2건 대비 하루 13건에서 16건 |
| 결합 규칙으로 잡아낸 심어 둔 리뷰 | 매번 40건 중 40건 |
| 결합 규칙이 잘못 플래그한 진짜 리뷰 | 0건에서 3건 |
| 문구만으로 포착한, 진짜 리뷰가 포함된 유사 문구 쌍 | 27건에서 42건 |
| 다른 리뷰 이력이 없는 리뷰어 비율 | 캠페인 발생일에는 81%에서 100%, 전체 평균은 27%에서 31% |
마지막 두 행이 중요하다. 문구 유사성만으로는 평범한 표현을 공유하는 진짜 고객이 포함된 수십 건의 쌍이 플래그되었다. 폭증과 결합했을 때에만 정밀해졌다. 이것이 따라 해야 할 패턴이다. 하나의 신호가 후보를 지목하고 다른 신호가 그것을 확인하게 하는 것이다.
구성된 테스트는 현실 세계와 다르다. 실제 캠페인은 리뷰를 몇 주에 걸쳐 분산시키고, 텍스트를 다양화하며, 사용하기 전에 계정을 숙성시킨다. 실제로는 더 낮은 재현율을 예상해야 하며, 이미 확인된 사례로 임계값을 조정하고, 모든 플래그를 판정이 아니라 사람이 검토할 단서로 취급해야 한다.
리뷰 데이터 수집
탐지를 위해서는 날짜, 평점, 그리고 이력을 파악할 수 있을 만큼의 리뷰어 맥락이 포함된 리뷰가 필요하다. 이를 수집할 때 중요한 몇 가지가 있다.
- 여러 시장에 걸쳐 수집하라. 같은 제품이라도 국가별 스토어프론트마다 다른 리뷰가 표시되는 경우가 많고, 캠페인은 흔히 하나의 시장을 겨냥한다. 각 국가 내부에서 해당 스토어프론트를 수집하면 현지 쇼핑객이 실제로 보는 내용을 확인할 수 있으며, 이는 고객 리뷰 모니터링에 사용되는 것과 같은 접근 방식이다.
- 이력을 보존하라. 폭증과 단일 리뷰 계정은 시간에 걸쳐서만 측정할 수 있으므로, 일정에 따라 수집하고 수집한 데이터를 보관하라.
- 개인 데이터를 최소화하라. 가능하면 이름 대신 가명 처리된 리뷰어 토큰을 저장하고, 분석에 사용되는 필드만 유지하며, 레지덴셜 프록시와 GDPR에서 다룬 대로 보관 기간을 설정하라.
- 규정 범위 내에서 활동하라. 공개된 리뷰 페이지를 적당한 속도로 수집하고, 각 사이트의 약관을 준수하며, 로그인이 필요한 영역은 건드리지 마라.
리뷰 사기는 혼자 다니는 경우가 드물다. 리뷰를 구매하는 판매자는 흔히 리스팅을 탈취하거나 위조품을 판매하기도 하며, 리뷰 텍스트 역시 다른 AI 생성 콘텐츠와 동일한 수준의 검증이 점점 더 필요해지고 있다. 여러 출처에 걸쳐 이를 운영하는 팀을 위해서는 더 넓은 범위의 워크플로를 대규모 콘텐츠 모더레이션 페이지에서 설명하고 있다.
결론
가짜 리뷰는 흔하고, 이제 가장 큰 시장들에서 명시적으로 불법이며, 읽는 것만으로는 발견하기 어렵다. 캠페인을 드러내는 것은 행동이다. 너무 빠르게 몰리는 너무 많은 리뷰, 서로 지나치게 비슷한 문구, 다른 이력이 없는 계정에서 나온 리뷰가 그것이다.
시간과 시장에 걸쳐 리뷰를 수집하고, 작성자를 가명 처리하고, 서로를 확인할 수 있도록 신호를 결합하며, 누군가 조치를 취하기 전에 플래그된 내용을 사람에게 보내라.
출처 및 참고 자료
- Google, New ways we’re protecting businesses on Maps, 2025년 수치.
- Amazon, How Amazon maintains a trusted review experience.
- Tripadvisor, 2025 Transparency Report.
- Federal Trade Commission, final rule banning fake reviews and testimonials, 2024년 8월.
- Ott, Choi, Cardie and Hancock, Finding Deceptive Opinion Spam by Any Stretch of the Imagination, ACL 2011.
- 구성된 테스트 데이터셋 및 코드, Shifter 작성, 2026년 10월 2일.