path
Jin's Lab
코드로 실험하고 기록하는 개발 일지 · J.Lab

Jin's Lab

코드로 실험하고 기록하는 개발 일지. 커리어와 삶의 방향을 탐색하며 기록하는 공간입니다

AdSense

애드센스 봇 감지 오탐으로 멀쩡한 내 광고를 가렸던 이유

J.Lab ·
목차

    최근 내 블로그의 광고 수익이 눈에 띄게 줄어든 이유를 찾다가 기가 막힌 현상을 발견했다. 블로그에 접속하자마자 광고가 아주 잠깐 노출되었다가 순식간에 사라지는 현상이 반복되고 있었다. 처음에는 구글 애드센스 자체의 송출 오류나 일시적인 에러라고 생각했다.

    하지만 원인은 엉뚱하게도 내가 블로그에 직접 적용해 둔 무효 클릭 및 부정 클릭 방지 코드에 있었다. 광고 어뷰징을 막기 위해 작성했던 스크립트가 오히려 정상적인 방문자들의 광고까지 모조리 가리고 있었던 것이다. 치명적인 애드센스 봇 감지 오탐 사건의 서막이었다.

    내 손으로 구현했던 부정클릭 방지 로직의 오작동

    당시 나는 광고 단가를 떨어뜨리는 무효 클릭을 방지하고자 자체적인 botScore 함수를 만들어 사용 중이었다. 이 함수는 접속한 브라우저의 여러 환경 값을 검사하여 봇일 확률을 점수로 환산하는 방식이었다. 기준 점수를 초과하면 봇으로 판단하여 hideAds 함수를 실행했다.

    문제는 이 hideAds 함수가 실행되면 광고 영역에 display none 스타일을 강제로 먹여 버린다는 점이었다. 게다가 세션 스토리지에 플래그를 저장하게 설계하여, 한 번 봇으로 오탐된 사용자는 해당 세션 내내 광고 숨김 상태가 유지되었다. 결과적으로 수많은 실사용자가 광고를 전혀 보지 못하는 상태로 블로그를 서핑하고 있었다.

    자바스크립트 코드에서 에러 경고 플래그가 표시된 모니터 화면의 아이소메트릭 일러스트

    이 무자비한 광고 숨김 필터링의 배후에는 내가 설정해 둔 세 가지 허술한 오탐 휴리스틱 조건이 있었다. 당시에는 정교한 봇 필터링이라고 믿었지만 실제로는 최신 웹 환경과 모바일 인앱브라우저의 특성을 전혀 고려하지 못한 독소 조항들이었다.

    정상 사용자를 봇으로 몰고 간 오탐 휴리스틱 3가지

    첫 번째 문제는 navigator 객체의 플러그인 개수를 검사하는 로직이었다. 예전에는 플러그인이 전혀 없는 환경을 Headless 브라우저로 간주하곤 했다. 하지만 최신 크롬 브라우저 역시 보안과 성능상의 이유로 이제는 빈 배열을 반환하는 경우가 허다하다. 결국 멀쩡한 최신 크롬 사용자들이 모두 봇 점수를 받게 되었다.

    두 번째는 window chrome 객체가 존재하는지 확인하는 검사였다. 구글 크롬이 아닌 브라우저를 잡아내기 위한 조건이었지만, 웨일이나 삼성 인터넷 그리고 수많은 모바일 웹뷰 환경에서는 이 객체가 제대로 정의되지 않는다. 결과적으로 크롬이 아닌 대안 브라우저를 쓰는 사용자들 역시 봇으로 오탐되는 결과를 낳았다.

    세 번째가 가장 결정적이었던 브라우저 크기 검사였다. outerWidth와 outerHeight 값이 0인 경우를 자동화 스크립트로 작동하는 봇으로 판단하도록 설계했었다. 하지만 카카오톡이나 인스타그램 같은 인앱브라우저 환경에서는 이 값들이 종종 0으로 잡히는 치명적인 버그가 존재했다.

    스마트폰 소셜 미디어 앱 내부에서 깨진 광고 영역을 보여주는 모바일 화면 일러스트

    우리나라 모바일 트래픽의 상당수가 카카오톡이나 SNS 링크를 타고 들어오는 인앱브라우저 기반이라는 점을 간과한 대가였다. 인앱브라우저로 접속한 실사용자들은 위의 세 가지 조건에 모두 걸려 봇 점수가 순식간에 3점이나 4점까지 치솟았다. 당연히 코드는 이들을 악성 봇으로 오해하고 광고를 통째로 날려버렸다.

    확실한 자동화 신호만 남기기 위한 스크립트 수정

    상황을 파악하자마자 나는 오탐률이 극도로 높은 이 세 가지 휴리스틱 조건들을 스크립트에서 즉시 제거했다. 대신에 확실하고 명백한 자동화 신호만 감지하도록 코드를 전면 수정했다. 이제는 브라우저가 자동 제어되고 있음을 나타내는 명확한 지표들만 선별하여 점수를 부여한다.

    구체적으로는 webdriver 활성화 여부나 HeadlessChrome 환경 변수를 검사하도록 했다. 또한 phantom 브라우저 흔적이나 domAutomation과 같이 확실하게 조작 도구가 개입한 신호만을 감지 필터로 남겨두었다. 모바일 인앱브라우저를 사용하는 진짜 사용자들은 더 이상 봇으로 분류되지 않게 조치한 것이다.

    성공적인 코드 통합과 디버깅 완료를 나타내는 대시보드 화면의 아이소메트릭 일러스트

    이번 애드센스 봇 감지 오탐 소동을 겪으며 섣부른 보안 스크립트 적용이 얼마나 위험한지 뼈저리게 깨달았다. 보안을 강화하겠다고 추가한 코드가 오히려 내 소중한 광고 노출 기회를 갉아먹는 자충수가 되었기 때문이다. 앞으로는 모바일 웹뷰와 특이 브라우저 환경까지 꼼꼼히 크로스 브라우징 테스트를 거친 후 코드를 반영해야겠다.

    AdSense AdSense Bot Detection In-App Browser JavaScript Web Security
    ← 이전 글
    최근 게시물
    다음 글 →
    이전 게시물
    ≡ 글 목록으로
    소개
    path
    J.Lab

    커리어와 삶의 방향을 탐색하며
    기록하는 공간입니다

    카테고리
    403 Forbidden Error 1 AdSense 1 AdSense Bot Detection 1 AI Automation 1 AI Image Generation 1 ai-automation 2 AI-Prompting 1 AIBlogAutomation 1 AICodeLog 1 AIContentGeneration 1 AIImageGeneration 1 AIWritingErrors 1 API Automation 2 API Retry Design 1 api-automation 1 API-Deprecation 1 api-error 1 api-fallback 1 api-retry-strategy 1 api-troubleshooting 1 APIDebugging 1 APIError 1 APIErrorHandling 1 APIIntegration 1 APITokenRenewal 1 AppsScript 1 appsScriptAutomation 1 AutomatedBlogging 1 automation 1 Automation 2 AutomationTroubleshooting 1 Backoff Algorithm 1 Base64Encoding 1 BatchProcessing 1 blog-automation 1 blog-customization 1 blog-migration 3 Blog-Sorting 1 blog-strategy 1 blog-theme-customization 1 blog-workflow 1 blogautomation 1 BlogAutomation 2 Blogger 4 Blogger API 2 Blogger Automation 1 Blogger SEO 1 blogger-api 3 blogger-automation 1 blogger-error-400 1 blogger-labels 1 blogger-seo 1 blogger-tips 1 Blogger-Tips 1 BloggerAPI 3 BloggerBypath 1 BloggerCustomization 2 BloggerFavicon 1 BloggerTemplate 1 BloggerTemplateEditing 1 BloggerTheme 1 BloggerThemeCustomization 1 BloggerXMLStructure 1 Blogging-Automation 1 BloggingTools 1 BlogQuality 1 BlogSpot 1 BWidgetBIncludable 1 CardClickHandler 1 CDATA 1 clamping-text 1 Code Integration 1 codelog 1 CodeLog 1 codeRefactoring 1 contentsequencing 1 cost-reduction 1 CSSOverlay 1 data-parsing 1 DatabaseDesign 1 DataRecovery 1 DateInjection 1 Debugging 2 dev-journey 1 DeveloperJourney 2 DevJourney 1 display-none-seo 1 dom-manipulation 1 dynamic-menu 1 Error-Handling 1 ErrorHandling 1 Execution Timeout 1 ExecutionLimit 1 exponential-backoff 1 FactChecking 1 FaviconEmbedding 1 Feed-API 1 filesystem 1 Flat Illustration 1 FluxModel 1 FreeAIImage 1 FrontEndDev 1 FrontendTips 1 GAS Blogger API 1 gas-automation 1 gas-optimization 1 gas-trigger 1 GASTimeout 1 gasTriggerManagement 1 GCP Project Linkage 1 Gemini 1 Gemini API 1 gemini-api 1 GeminiAPI 1 GeminiPrompt 1 GeminiPromptEngineering 1 GmailRestrictions 1 Google Apps Script 7 Google Discover 1 google-apps-script 3 Google-Apps-Script 1 google-blogger 1 googleAppsScript 1 GoogleAppsScript 6 googlesapps-script 1 hero-image 1 HTMLWidgetBlogger 1 http-429 1 HuggingFace 1 HuggingFaceAPI 1 ico-generator 1 Image Optimization 1 image-automation 1 image-optimization 1 In-App Browser 1 invalid-argument 1 javascript 3 JavaScript 2 javascript-automation 1 javascript-toc 1 jlab-codelog 1 JLabDevLog 1 json-schema 1 label-length-limit 1 linux 1 meta-description 1 Negative Prompt 1 notion-api 1 notion-database 1 notion-gas-integration 1 NotionAPI 1 NotionAutomation 1 notionintegration 1 NotionIntegration 1 OAuth Scope 1 pagination 1 payload-validation 1 permalink-management 1 PersonaDesign 1 pil-image-processing 1 Pinterest 1 Pollinations 1 Pollinations Flux 1 pollinations-api 1 PollinationsAI 1 PositionAbsolute 1 Prompt Design 1 Prompt Engineering 1 prompt-engineering 1 Prompt-Engineering 1 PromptEngineering 1 publishorder 1 python-favicon 1 queue-stuck 1 RandomDelay 1 rate-limiting 1 Refactoring 1 rfc3339 2 Robots Meta Tag 1 RSS Feed 1 scriptNotFound 1 Search Engine Optimization 2 Search-Engine-Optimization 1 SEO Tips 1 seo-optimization 4 SEO-Optimization 1 seriesmanagement 1 SidebarLinks 1 SNSMarketing 1 SVGIcon 1 table-of-contents 1 TechJournal 1 Template 1 ThreadsAPI 1 tistory-migration 1 transparent-favicon 1 triggerCleanup 1 Troubleshooting 1 unzip 1 URL Slug 1 vanilla-js 1 Web Development 1 Web Publishing 2 Web Security 1 web-development 1 Web-Development 1 web-development-tips 1 web-performance 1 web-scraping 1 WebAccessibility 1 WebDevelopment 3 WebDevelopmentTips 1 WebDevJourney 1 windows 1 WorkflowAutomation 1 XMLParser 1 XMLSpecialCharacters 1 XMLTheme 1 zip 1
    인기 글
    GAS에서 Blogger API 403 오류 완전 정복 — appsscript.json 스코프와 GCP 프로젝트 연결
    GAS에서 Blogger API 403 오류 완전 정복 — appsscript.json 스코프와 GCP 프로젝트 연결
    Google Apps Script 실행 시간 6분 제한 — Gmail 계정 함정과 랜덤 딜레이 설계
    Google Apps Script 실행 시간 6분 제한 — Gmail 계정 함정과 랜덤 딜레이 설계
    Blogger 테마 XML 직접 뜯어봤더니 알게 된 것들
    Blogger 테마 XML 직접 뜯어봤더니 알게 된 것들
    다른 블로그
    IssueLog
    IssueLog
    issuelog.jinbytes.com
    KidStory
    KidStory
    kidstory.jinbytes.com
    IT Story
    IT Story
    jinbytes.com
    © Jin's Lab · J.Lab · All Rights Reserved
    jinbytes.com · Powered by Blogger