선물 추천 서비스를 운영하면서 사용자에게 제공되는 상품 리스트를 유심히 살펴보던 중 너무 유사한 상품들이 연속적으로 추천되는 현상을 발견했다. 겉보기에 상품 제목은 조금씩 다르지만 실제로는 같은 브랜드의 동일 라인업이거나 용량/옵션만 다른 거의 동일한 상품들이었고 이로 인해 추천 결과가 단조롭고 반복적이라는 인상을 주고 있었다. 이 문제는 사용자 경험에 큰 영향을 미치는 요소였다. 사용자 입장에서는 “추천이 다양하지 않다”, “뭘 봐도 비슷한 것만 나온다”는 불만족으로 이어질 수 있기 때문에 중복되거나 유사한 상품을 자동으로 걸러내는 로직이 꼭 필요하다고 판단했다. 단순히 브랜드나 카테고리 기준으로 중복을 제거하는 방법도 고려했지만 이 방식은 너무 단편적이었다. 같은 브랜드라도 전혀 다른 상품일 수 있고 다른 브랜드더라도 본질적으로 동일한 상품일 수도 있기 때문이다. 결국 핵심은 “제목 자체를 어떻게 비교할 것인가”였고 여기서 두 가지 기능을 도입하게 되었다
extractBaseTitle
jaccardSimilarityByWords
상품 제목은 판매처마다 다르게 포맷팅되며 다양한 노이즈 요소를 포함한다. 예를 들어 [정품]
, (화이트)
, 200ml
, -
, •
등은 상품의 본질과 상관없는 정보지만 제목을 분리하거나 비교하는 데 방해가 된다. 따라서 다음과 같은 과정을 거쳐 제목을 최대한 본질적인 키워드만 남기는 방식으로 전처리했다.
public static String extractBaseTitle(String title) {
return title
.replaceAll("\\[[^\\]]*\\]", "") // [정품], [BTS 에디션] 등 대괄호 제거
.replaceAll("\\([^)]*\\)", "") // (화이트), (옵션 선택) 등 소괄호 제거
.replaceAll("[-_•·|]", " ") // 특수 구분자 -> 공백
.replaceAll("\\d+(호|mm|ml|g|kg|cm|개|세트|pack|팩)?", "") // 단위 포함 숫자 제거
.replaceAll("[^가-힣a-zA-Z0-9 ]", "") // 나머지 특수문자 제거
.replaceAll("\\s{2,}", " ") // 다중 공백 정리
.trim()
.toLowerCase(); // 소문자 통일
}
입력: [정품] 록시땅 핸드크림 (화이트) 30ml - 프랑스 정품 • 감성
출력: 록시땅 핸드크림 프랑스 정품 감성
정규화된 제목들끼리 유사도를 판단하기 위해 자카드 유사도(Jaccard Similarity)를 활용했다. 이는 두 문자열을 단어 단위로 나눈 후 교집합과 합집합의 비율을 통해 유사도를 계산하는 방식이다.
public static double jaccardSimilarityByWords(String title1, String title2) {
Set<String> words1 = new HashSet<>(List.of(title1.split("\\s+")));
Set<String> words2 = new HashSet<>(List.of(title2.split("\\s+")));
Set<String> intersection = new HashSet<>(words1);
intersection.retainAll(words2);
Set<String> union = new HashSet<>(words1);
union.addAll(words2);
return union.isEmpty() ? 0.0 : (double) intersection.size() / union.size();
}
예시 비교
록시땅 핸드크림 프랑스 정품 감성
프랑스 정품 감성 록시땅 크림
4/5 = 0.8
자카드 유사도가 0.8
이상이면 사실상 거의 동일한 상품이므로 하나만 추천 리스트에 포함하도록 했다.
이번 개선 작업을 통해 추천 리스트에 포함되는 상품들의 다양성을 높이고 사용자 경험을 해치는 유사 상품 중복 노출 문제를 줄일 수 있었다. 특히 상품 제목을 정규화하여 본질적인 키워드만 남기고 자카드 유사도를 기준으로 중복 여부를 판단함으로써 같은 브랜드의 유사 상품이 연속 추천되는 문제를 상당 부분 개선할 수 있었다. 유사도가 0.8
이상인 상품은 하나만 추천되도록 필터링하면서 결과적으로 추천 품질이 더 좋아졌다는 피드백도 확인할 수 있었다.
다만 모든 키워드 조합을 수동으로 테스트하기 어려운 만큼 일부 상황에서는 여전히 유사 상품이 걸러지지 않을 가능성도 존재한다. 이 부분은 향후 더 정교한 필터링 조건 등을 고민해보며 계속 개선해나가야 될 거 같다.