Engineering
여기어때 검색 광고: 랭킹 부스팅 구축기
서창균Ocean(오션) / 랭킹추천개발팀여기어때
2025년 11월 7일
원문에서 보기 ↗
안녕하세요 여기어때 랭킹추천개발팀의 오션입니다.
이번에 여기어때에 새로 추가 된 검색 광고에 대해 소개드립니다.
여기어때의 검색 랭킹 시스템은 단순한 정렬 알고리즘이 아닙니다.
수많은 비즈니스 로직과 사용자 경험 요소가 얽혀 있는 꽤나 복잡한 구조의 시스템 입니다.
최근 우리팀은 랭킹 시스템 위에 ‘광고 상품을 통한 랭킹 부스트 기능’을 새로 구현해야 하는 과제를 맡게 되었습니다. 제휴파트너에게 일정 조건하에 더 높은 검색 순위를 제공하는 기능을 만드는 것이었죠.
이번 글에서는 이 기능을 설계하고 구현하는 과정에서 겪은 기술적 고민과 결정 포인트들을 공유하려고 합니다.
“검색 랭킹에 인위적인 조정 요소를 더한다”는 것은 단순히 점수에 +α를 더하는 일이 아닙니다.
검색 품질, 사용자 신뢰, 광고 효율 세 가지 축 사이의 균형을 맞추는 일입니다.
1. 초기 방식: 노출 수 보장
개발 초기 우리는 비즈니스 목표에 맞춰 “광고 상품 구매 시, N%의 랭킹 부스트가 M%의 노출 수 상승을 보장해야 한다”는 가설에서 출발했습니다.
이는 제휴파트너에게 명확한 광고 효과를 제시하기 위한 매력적인 시나리오였습니다.
이 가설을 검증하기 위해, 우리는 목표 노출 수 달성하기 위한 필요 랭킹 스코어를 역산하는 모델을 수립했습니다.
가설 검증
우리가 시도했던 구체적인 로직은 아래와 같았습니다.
- 목표 노출 수 설정
비즈니스 요구사항에 따라, “제휴점 A가 현재보다 10%의 노출 수 상승을 원한다”고 가정했습니다.
현재 노출 수(AS-IS): 820회 (가정)목표 노출 수(TO-BE): 820 X 1.1 = 902회
- 노출 수-랭킹 스코어 관계 모델링
가장 큰 난관은 “902회의 노출을 얻으려면 몇 점의 랭킹스코어가 필요한가?”를 알아내는 것이었습니다.
단순히 두 개의 데이터 포인트로 기울기를 구하는 대신, 모든 제휴점의(노출 수, 랭킹스코어) 쌍을 수집하여, 이 데이터셋에 선형 회귀 모델을 적용했습니다.
이 모델을 통해 노출횟수로 랭킹스코어를 예측하는 함수를 도출했습니다.
- 도출된 방정식 (예시): 랭킹스코어 = aX (노출횟수) + b
- 필요 스코어 예측
이제 이 회귀 모델에 목표 노출 수 902회를 대입하여 필요한 랭킹 스코어를 예측했습니다.
TO-BE Score: aX + b = 804점
- 델타 스코어계산
마지막으로 해당 제휴점의 현재 스코어(AS-IS)를 기준으로 추가해야 할 가중치(Delta Score)를 계산했습니다.
AS-IS Score: 700점Delta Score: 804(TO-BE) - 700(AS-IS) = 104점
이 Delta Score를 해당검색 시 합산해주는 것이 초기 모델의 골자였습니다.
이 모델은 실제 데이터를 검증하는 과정에서 보장하려는 노출 수를 정확히 예측하기 어렵다는 문제가 있었습니다.
테스트 결과 노출 수와 랭킹 스코어 간에는 분명한 상관관계가 존재했습니다. 하지만 예측한 모델의 변동폭이 여전히 컸습니다.
근본적인 원인은 “검색 랭킹의 상대성” 때문이었습니다.
랭킹 스코어 804점의 순위는 절대적이지 않았습니다.
검색어와 입실일에 어떤 다른 제휴점들이 함께 노출되는지에 따라 804점의 실제 순위는 매번 달라졌습니다.
- 시나리오 A (검색어1,주중): 804점 → 순위 5위 상승
- 시나리오 B (검색어2,주말): 804점 → 순위 1위 상승 (혹은 변동 없음)
이는 곧, 우리가 제휴파트너에게 “10% 향상된 노출 횟수”를 일관되게 보장해 드리기 어렵다는 문제로 이어졌습니다.
물론 검색어 및 입실일로 데이터를 모두 세분화하여 각각의 회귀모델을 만들었다면 정확도는 지금보다 훨씬 더 올라갔을 것입니다.
하지만 우리는 노출 수라는 간접적이고 변동성이 큰 지표로 파트너분들과 소통하기보다는 “현재 순위에서 N등 올려드리기”와 같이 직관적인 가치를 제공하는 것이 파트너분들께 더 낫다고 판단했습니다.
이 경험을 통해 우리는 노출수를 예측하는 대신 현재 순위를 기준으로 목표 순위까지 필요한 스코어를 계산하여 주입하는 현재의 2차 모델을 설계하게 되었습니다.

검색어 1의 제휴점 Score의 노출횟수 분포도

검색어 2 의 제휴점 Score의 노출횟수 분포도
2. 새로운 접근: 상승 순위 보장
앞서 노출 수-스코어 선형 모델이 실패한 이유는 랭킹의 상대성 때문이었습니다. 예를 들어 1위 숙소의 랭킹 스코어는 어떤 검색어로 검색했는지에 따라 다르며 동일한 강남역 키워드 내에서도 어떤 입실일(평일인지 주말인지)을 선택했는지에 따라 매번 완전히 달라집니다.
그래서 노출 수처럼 불확실한 결과를 예측하는 대신 제휴파트너들께 “현재 50등이신데, 광고를 하시면 약 25등이 될 수 있습니다”처럼 명확한 순위 상승을 제시하는 방식으로 방향을 바꿨습니다.
즉, 몇 점을 더 준다는 절대적인 개념이 아니라, 현재 50등에서 25등이 되려면 정확히 몇 점이 필요한가?를 계산하는 아키텍처를 설계했습니다.
핵심은 현재 스코어를 기준으로 목표 스코어를 계산하고, 그 차액인 Delta Score를 검색 쿼리에 동적으로 주입하는 것입니다.
이 시스템은 크게 3개의 모듈로 구성됩니다.
1) 데이터 수집 모듈
부스팅을 하려면 먼저 현재 상태(입실일 및 검색어에 따른 제휴점들의 Ranking Score 및 순위)를 정확히 알아야 합니다. 이를 위해 data-collector라는 모듈을 개발했습니다.
- 역할 : 키워드-입실일 검색 조합으로 실제 검색 API를 호출하여, 전체 제휴점 목록의
affiliate_id(제휴점번호),as_is_rank(현재 순위),as_is_score(현재 랭킹스코어)를 수집합니다. - 검색어 선정 : 랭킹을 상승 시키는 기준이 되는 검색어 선정이 중요했습니다. 모든 검색어를 수집할 수는 없으므로, 사용자 행동 로그 분석을 통해 추출한 상위 N개 유의미한 검색어 (ex: 검색 결과 20개 이상)와 각 제휴점의 주소 기반 지역 키워드(시/도, 시/군/구)를 선정하였습니다.
- 실시간성 확보: 랭킹은 실시간으로 변동하므로, 데이터의 최신성이 중요합니다. 실시간 이벤트 기반으로 수집하는 것을 목표로 하지만 5분 단위의 배치를 통해 갱신하도록 하였습니다.
- 저장: 수집된 데이터는 검색어-입실일을 Key로 S3와 같은 스토리지에 적재하였습니다.
2) Delta Score 계산 모듈
1단계에서 수집한 데이터를 기반으로 부스팅에 필요한 Delta Score를 계산합니다.
- 광고 상품을 구매한 제휴점이 목표 순위(
to_be_rank)에 도달하기 위해 필요한to_be_score를 계산합니다. 검색어-입실일을 Key로 제휴점 별as_is_rank,to_be_rank,as_is_score,to_be_score그리고 가장 중요한delta_score (B-A)를 redis에 저장합니다. (이 데이터가 검색 시 쿼리에 주입 됩니다.)
3) 검색 쿼리에 가중치 주입 (검색 API)
사용자가 검색을 요청할 때 2단계에서 계산한 Delta Score를 동적으로 적용합니다.
- Elasticsearch function score 활용 : 우리팀은 검색 엔진으로 Elasticsearch를 사용하며
function_score쿼리는 이 요구사항을 해결하기에 최적이었습니다. - 동작 방식:
- 사용자 검색 요청이 들어오면(
검색어,입실일포함) - 검색 API는 해당 redis에
검색어-입실일에 대한 부스팅 데이터가 있는지 확인합니다. - 데이터가 존재할 경우, 기존의
query에function_score를 동적으로 주입 합니다. functions배열 안에, 부스팅이 필요한 각affiliate_id를filter(term 쿼리)로 지정하고, 2단계에서 계산한delta_score를 가중치로 부여합니다.- 기존 스코어(
score)에delta_score를 합산합니다. (Final_Score = score + delta_score)
/* 실제 쿼리는 더 복잡하지만 예시입니다.
*/
"query": {
"function_score": {
"query": {
/* ... 기존 사용자 검색 쿼리 (필터, 정렬 등) ... */
},
"functions": [
{
"filter": { "term": { "affiliate_id": "제휴점_A" } },
"weight": 120.5 // 제휴점 A의 (B-A) Delta Score
},
{
"filter": { "term": { "affiliate_id": "제휴점_B" } },
"weight": 95.0 // 제휴점 B의 (B-A) Delta Score
}
// ... 부스팅 대상만큼 함수 추가 ...
],
...
}
}
3. 검증: A/B 테스트
실제 사용자에게 적용하기 전 우리는 두 가지를 검증했습니다.
- 순위 상승이 실제로 제휴점의 비즈니스 지표(클릭, 예약)에 긍정적인 영향을 주는가?
- 부스팅이 다른 제휴점들의 노출 기회를 과도하게 빼앗아 전체 검색 생태계 품질을 떨어뜨리지는 않는가?
이를 위해 다음과 같이 A/B 테스트를 설계했습니다.
테스트 설계
- 대상 키워드 : 먼저 GTM 로그 분석을 통해 추출한 상위 N개의 핵심 키워드를 실험 대상으로 한정했습니다.
- 테스트 그룹: 사용자를 3개의 그룹으로 분리했습니다.
- 부스팅 대상 샘플링 : 이 테스트의 핵심 중 하나는 부스팅 대상 제휴점을 공정하게 추출하는 것이었습니다. 만약 상위권 제휴점만 부스팅 한다면 효과가 왜곡될 수 있으므로, 1~10위, 21~30위, 51~70위, 101~150위 등 다양한 랭킹 구간에서 제휴점을 골고루 샘플링하여 각 테스트 그룹에 할당했습니다.
- Group A (Control): 기존 로직 (부스팅 없음)
- Group B (Test 1): 랭킹 상승률 N% 적용
- Group C (Test 2): Group B보다 더 높은 랭킹 상승률 (N + α%) 적용
검증 지표 및 결과
우리는 두 가지 관점에서 지표를 분석했습니다.
- 부스팅 그룹 성과: 부스팅이 적용된 제휴점 샘플군의 클릭률(CTR)과 예약률(CVR)이 Group A(대조군) 대비 유의미하게 증가했는지 확인했습니다.
- 생태계 영향 : 부스팅되지 않은 ‘나머지’ 파트너들의 클릭률과 예약률이 어느 정도 하락하는지(혹은 유지되는지)를 모니터링했습니다.
세부적인 지표는 공개하기 어렵지만, 부스팅을 적용한 Group B, C에서 클릭률(CTR) 및 예약률(CVR)이 A그룹(대조군) 대비 통계적으로 유의미하게 상승하는 것을 확인할 수 있었습니다. 동시에 나머지 파트너들의 지표 하락 폭을 확인하며 우리가 감내할 수 있는 수준인지를 검토할 수 있었습니다.
이 A/B 테스트 결과를 바탕으로 실제 비즈니스 가치를 창출한다는 확신을 얻고 기능 배포를 결정할 수 있었습니다.
4. 남은 과제들
제휴파트너분들을 위한 데이터 제공 방식의 고민
기술적으로 랭킹을 올리는 데는 성공했지만, 이 성과를 “어떻게 효과적으로 보여드릴 것인가?”라는 숙제가 남았습니다.
- 단순히 “전체적으로 순위가 오를 것입니다”라는 두루뭉술한 안내가 아닌, “A키워드에서 N등 상승”, “B키워드에서 M등 상승”처럼 구체적인 리포트를 원하는 니즈를 확인했습니다.
검색어 커버리지 확장
- 상위 N개의 검색어에 포함되지 않는 롱테일 검색어나 신규 인기 검색어에 대해 어떻게 부스팅을 적용할지는 지속적으로 개선해야 할 영역입니다.
아키텍처 효율성 및 확장성 문제
현재의 구조는 검색어-입실일 별로 모든 AS-IS 데이터를 수집하고 Delta Score를 계산합니다. 이 방식은 두 가지 큰 효율성 문제를 안고 있습니다.
- 데이터 볼륨 : 검색어 수 X 입실일 수에 비례하여 처리해야 할 데이터가 폭발적으로 증가합니다. 더 많은 롱테일 키워드까지 부스팅 범위를 넓히기 위해서는, 현재보다 훨씬 더 효율적으로 AS-IS 데이터를 수집하고 계산하는 아키텍처적 개선이 필요합니다.
- 처리 리소스 : 현재는 이 서비스를 이용하는 제휴점 수를 기준으로 5분 이내에 모든 계산 처리가 가능합니다. 하지만 만약 이용하는 제휴점 수가 지금의 10배 또는 100배의 제휴점이 활용한다고 하면 지금의 리소스와 배치 구조로는 실시간 성을 보장하기 어려울 수 있습니다. 더 많은 제휴점이 이 기능을 동시에 사용하더라도 안정적으로 서비스를 제공할 수 있는 구조적 개선을 고민하고 있습니다.
맺음말
검색 랭킹 부스트 기능은 단순히 특정 숙소를 상단에 노출하는 것이 아니라, 기존 검색 품질을 해치지 않으면서 비즈니스 요구사항(Boosting)을 동시에 만족시켜야 하는 도전적인 과제였습니다. 검색 플랫폼을 운영하는 많은 분이 공감하시겠지만, 이 두 가치 사이의 균형점을 찾는 것은 언제나 가장 어려운 숙제입니다.
우리는 현재 두 가지의 과제를 진행하고 있습니다.
- 어떻게 더 효율적으로: 폭증하는 검색어-입실일 조합과 늘어나는 제휴점 수를 감당하기 위해, 데이터 파이프라인을 고도화하고 아키텍처의 확장성을 확보하는 기술적 과제를 해결하고 있습니다.
- 어떻게 더 친절하게: 순위가 올랐다는 사실을 넘어, 파트너님들이 체감할 수 있는 가치 리포트와 미래 순위 예측 데이터를 제공하는 프로덕트적 과제를 풀고 있습니다.
여기어때 검색서비스는 사용자와 제휴파트너 모두가 윈윈(Win-Win)할 수 있는 건강한 생태계를 만드는 것을 목표로 합니다. 이 목표를 위해 저희는 앞으로도 끊임없이 데이터를 분석하고 시스템을 개선하며 다음 단계의 프로덕트를 준비해 나가겠습니다.
긴 글 읽어주셔서 감사합니다.