광고 차단 확장 프로그램이 이벤트 배너를 숨긴 이유

커버 이미지

특정 사용자에게만 이벤트 배너가 노출되지 않는 현상이 보고되었습니다. 일반적인 테스트 환경에서는 재현되지 않았지만, 원인을 추적한 결과 광고 차단 확장 프로그램이 CSS 클래스명을 기준으로 요소를 숨기고 있었습니다.

이 문제는 이벤트 배너 컴포넌트에서 발생했습니다. 이 컴포넌트는 사이트의 다양한 이벤트 배너를 사용자에게 보여주는 역할을 담당하고 있었습니다. 그런데 일부 사용자들에게서 "배너가 안 보입니다"라는 CS가 올라오기 시작했습니다. 일반적인 테스트 환경에서는 재현되지 않았지만 원인을 추적한 결과, 사용자 브라우저에 설치된 광고 차단 확장 프로그램이 배너를 숨기고 있음을 확인했습니다.

필터링 규칙과 CSS 클래스명의 충돌

이번 이슈의 핵심은 서비스 코드 자체의 오류보다, 광고 차단 확장 프로그램이 ad-banners라는 클래스명을 광고 요소로 해석하고 있었다는 점이었습니다. 문제를 해결하려면 확장 프로그램이 어떤 기준으로 요소를 식별하고 차단하는지부터 이해할 필요가 있었습니다.

광고 차단 확장 프로그램의 작동 원리

AdGuard나 AdBlock 같은 광고 차단 확장 프로그램들은 사용자가 웹사이트를 방문할 때 웹 페이지의 로딩 과정에 개입합니다. 이들은 광고 서버로의 요청을 가로채거나, 웹 페이지를 구성하는 HTML 요소와 CSS 스타일을 분석하여 광고로 의심되는 콘텐츠를 제거하거나 숨기는 방식으로 작동합니다. 단순히 광고 이미지만 가리는 것이 아니라, 특정 스크립트의 실행을 막거나, HTML 구조 자체를 조작하여 광고 요소를 페이지에서 완전히 배제하기도 합니다.

필터링 목록: 광고 차단의 설계도

광고 차단 확장 프로그램이 어떤 요소를 차단할지 결정하는 기준은 바로 필터링 목록(Filtering Lists)입니다. 이 목록은 광고로 식별되는 URL, 스크립트 경로, 그리고 HTML 요소 및 CSS 클래스 등의 패턴을 포함하고 있습니다. EasyList는 가장 널리 사용되는 필터링 목록 중 하나로, 전 세계 커뮤니티에 의해 지속적으로 업데이트되며 새로운 광고 기술에 대응하고 있습니다.

filter image

예를 들어, 필터링 목록에는 ##.ad-banners와 같은 규칙이 포함될 수 있습니다. 이 규칙은 웹 페이지에서 ad-banners라는 클래스 이름을 가진 모든 요소를 차단하라는 지시입니다. 광고 차단기는 이 목록에 있는 규칙과 웹 페이지의 요소를 대조하여 일치하는 경우 해당 요소를 로드하지 않거나 숨김 처리합니다.

CSS 클래스 선택자와 예상치 못한 부작용

CSS 클래스 선택자는 웹 개발에서 특정 HTML 요소에 스타일을 적용하기 위해 광범위하게 사용됩니다. <div class="my-component">처럼 HTML 요소에 class 속성을 부여하고, CSS에서 .my-component와 같은 형식으로 해당 클래스를 선택하여 스타일을 정의합니다. 이는 웹 페이지의 디자인과 구조를 유연하게 관리하고 재사용성을 높이는 데 필수적인 개념입니다.

하지만 이번 이슈에서 우리는 클래스 이름이 단순히 시각적인 목적을 넘어, 광고 차단기와 같은 외부 도구에 의해 특정 요소를 식별하는 데 사용될 수 있음을 확인했습니다. 우리의 이벤트 배너 컴포넌트가 사용하고 있던 ad-banners라는 클래스명은 불행히도 EasyList와 같은 필터링 목록에 '광고'로 인식될 수 있는 패턴으로 포함되어 있었던 것입니다. 즉, 우리가 의도한 것은 단순한 '이벤트 배너'였지만, 외부의 기준에서는 '광고'로 오인되어 차단되고 있었던 셈입니다.

구현 포인트: 클래스명 충돌 해소

문제의 원인을 파악하고 나니 해결책은 의외로 간단했습니다. ad-banners라는 클래스명이 필터링 목록에 걸렸다면, 이 클래스명을 광고 차단기가 탐지할 수 없는 다른 이름으로 변경하면 되는 것이었습니다.

src/components/ui/banners/EventBanner.vue 파일에서 사용되던 클래스명을 line-banners로 변경하기로 결정했습니다. 이 변경은 EventBanner.vue 컴포넌트의 템플릿과 <style> 블록에 걸쳐 이루어졌습니다.

Before: 필터링 규칙에 걸린 ad-banners

아래 코드는 클래스명 변경 전의 EventBanner.vue 컴포넌트의 일부입니다. ad-banners라는 클래스명이 <template>div 요소와 <style> 블록에 적용되어 있었습니다.

<template>
  <!--
    EventBanner 컴포넌트의 템플릿 구조입니다.
    bannerData의 길이에 따라 배너를 렌더링할지 결정합니다.
    'ad-banners' 클래스가 직접적으로 광고 차단 필터링 목록에 포함되어 문제의 원인이 되었습니다.
  -->
  <div
    v-if="bannerData?.length"
    class="ad-banners"
    :class="{
      'is-empty': status === 'success' && bannerData?.length === 0,
    }"
  >
    <!-- 
      실제 배너 콘텐츠가 여기에 들어갑니다.
      예시: 이미지 슬라이더, 이벤트 링크 등
    -->
    <div class="banner-content">
      <img src="/assets/event-banner-image.png" alt="이벤트 배너" />
      <p>놓칠 수 없는 특별한 이벤트!</p>
    </div>
  </div>
</template>

위 코드는 EventBanner.vue 컴포넌트의 템플릿과 스타일 부분입니다. ad-banners라는 클래스명이 HTML 요소에 적용되어 있었고, 이 이름이 광고 차단 확장 프로그램의 필터링 규칙에 걸려 배너 노출이 차단되었습니다. 특히 v-if 조건부 렌더링은 데이터 유무에 따라 컴포넌트 노출을 제어했지만, 클래스명 자체가 문제였기 때문에 데이터가 있더라도 최종적으로 브라우저에서 렌더링되지 않았습니다. <style> 블록에서는 이 클래스에 대한 기본적인 레이아웃과 디자인이 정의되어 있었고, @include media-query를 통해 반응형 디자인도 고려하고 있었습니다.

After: line-banners로 클래스명 변경

다음은 클래스명을 line-banners로 변경한 후의 코드입니다. 코드의 기능적인 변화는 전혀 없지만, 클래스명 변경만으로 문제를 해결할 수 있었습니다.

<template>
  <div
    v-if="bannerData?.length"
    class="line-banners"
    :class="{
      'is-empty': status === 'success' && bannerData?.length === 0,
    }"
  >
    <div class="banner-content">
      <img src="/assets/event-banner-image.png" alt="이벤트 배너" />
      <p>놓칠 수 없는 특별한 이벤트!</p>
    </div>
  </div>
</template>

변경된 코드는 템플릿의 class 속성과 <style> 블록 내의 선택자만 ad-banners에서 line-banners로 바뀌었을 뿐, 나머지 로직이나 스타일은 모두 동일합니다. 이 단순한 변경으로 광고 차단 확장 프로그램의 필터링을 성공적으로 우회할 수 있었고, 배너는 모든 사용자에게 정상적으로 노출되기 시작했습니다.


결과 및 시사점

클래스명을 ad-banners에서 line-banners로 변경한 후, 특정 사용자에게 발생하던 이벤트 배너 미노출 문제는 재현되지 않았습니다.

영향받은 사용자 규모

전체 사용자의 25~30%가 광고 차단 확장 프로그램을 사용하고 있었고, 이 중 상당수에게 배너가 노출되지 않고 있었습니다. 클래스명 수정 후 배너 노출률이 눈에 띄게 올랐고, 매주 5~8건 들어오던 관련 CS는 완전히 사라졌습니다. 이벤트 배너가 프로모션 전환율에 직결되는 요소인 만큼, CSS 클래스명 하나를 바꾼 것치고는 꽤 큰 비즈니스 임팩트를 회복한 셈이었습니다.

이 과정에서 다음과 같은 시사점을 확인했습니다.

  1. 광고 차단 확장 프로그램의 동작 방식 이해: 사용자 브라우저의 확장 프로그램이 웹 요소에 어떤 영향을 미칠 수 있는지 고려해야 합니다. EasyList와 같은 필터링 목록의 존재와 작동 방식을 이해하는 것이 중요합니다.
  2. 클래스명 선정의 신중함: UI 컴포넌트의 클래스명은 단순히 스타일링을 위한 것이 아니라, 외부 도구에 의해 특정 요소를 식별하는 '표지판' 역할을 할 수 있습니다. 클래스명 선정 시 기능적인 의미와 함께 잠재적인 외부 영향까지 고려해야 합니다.
  3. 임시방편과 근본적인 해결책 사이: 이번 클래스명 변경은 즉각적인 문제 해결에는 효과적이었지만, 일종의 '우회 전략'입니다. 필터링 목록은 지속적으로 업데이트되므로, 장기적으로는 SSR 강화나 동적 콘텐츠 구성 등 근본적인 해결책을 검토할 필요가 있습니다.

참고 자료