Skip to main content

파일명에 'beacon'이 있다고 차단한다고?

· 6 min read
summerz
summerz

요즘 순수 HTML + ES 모듈 + Three.js로, 서버 없이 브라우저에서만 도는 3D 월드 에디터를 만들고 있는데요. 이상하게 아무리 수정해도 아이폰에 반영이 안 되는 거예요.

증상부터 쓰자면 이렇습니다.

  • 맥에서 크롬/사파리, 안드로이드까지 전부 정상.
  • 그런데 아이폰 사파리에서만 예전 로딩 화면에서 멈추는 증상이 사라지지 않음. 심지어 과거 소스 같음.
  • 사이트 데이터 삭제하고, 리부팅 등등 다시 들어가도 똑같음. → 캐시 문제는 아님.

데스크톱 완벽, Android 정상. 아이폰 사파리만 로딩 화면에 고착. 캐시를 지워도, 사파리 데이터를 날려도 같아요.

하필이면 디버깅을 위해 넣은 코드가 살짝 이상해서 발견이 늦긴 했지만, 결론부터 말하면 범인은 내 코드도, 서버도 아니었습니다. 파일 이름이었어요.


beacon 이 뭐라고.

월드에 등대(lighthouse) 기능을 넣을 일이 있어서, 회전하는 빔을 담당하는 스크립트를 자연스럽게 src/beacon.js라고 지었죠. 등표, 등대, 등명대... beacon 이잖아요.

import { Beacon } from './beacon.js';

이게 모든 문제의 시작이었습니다.


디버깅 여정

처음 의심한 건 늘 그렇듯 서비스 워커랑 캐시였습니다. 근데 해당 없었어요. 사이트 데이터를 통째로 지워도 재현되니까, 처음부터 뭔가가 다르게 돌고 있는 거죠.

사실 테일스케일 설정을 의심해서 엄청나게 시간을 많이 썼습니다. 하필이면 테일스케일 설정과 이용 방법을 그 때 즈음에 변경한 게 있어서 그게 문제의 원인이라고 너무 확신을 했던 거죠. 여기서 시간을 제일 많이 썼습니다.

다음으로 서버 접근 로그를 확인했는데, 여기서 단서가 나왔습니다. 아이폰에서 beacon.js를 요청한 기록 자체가 로그에 없더군요. 요청이 서버에 안 온 거예요. 맥 사파리로 접속하면 당연히 로그에 찍히고요. 같은 URL인데 기기에 따라 요청이 아예 안 나간다는 건, 클라이언트 단에서 보내기 전에 뭔가가 가로채고 있다는 뜻입니다.

확인용으로 클라이언트 에러 비콘(/__client-error)을 설치해서 모듈 로드 실패를 감지해봤더니 역시, 아이폰에서만 해당 모듈의 로드가 실패하고 있었습니다. oTL

결론을 말하자면, iOS의 콘텐츠 차단기(광고 차단기). 차단기가 리소스 URL에 "beacon"이라는 문자열이 포함된 것을 잡아낸 겁니다. beacon 하면 추적 비콘(tracking beacon)이 먼저 떠오르니까요. navigator.sendBeacon 같은 API 이름과 겹치는 단어일수록 차단 리스트에 이미 들어가 있을 확률이 높습니다. 차단된 모듈 import는 스크립트 그래프 전체를 실패로 만들고, 그래서 무한 로딩. src/beacon.js는 광고도 아니고 추적기도 아닌데, 이름만으로 희생된 거죠.

파일명을 lighthouse-beam.js 같은 걸로 바꾸고 바로 해결됐습니다.


배운 것

  • 콘텐츠 차단기는 DOM이 아니라 리소스 URL 패턴을 보더라. track, beacon, analytics, ads, pixel, collect, telemetry, fingerprint … 추적 관련 키워드가 담긴 파일·경로는 무고해도 희생될 수 있다.
  • 괜히 근거 없이 다른 애를 의심하지 말고 "서버에 요청이 안 온다 = 클라이언트가 보내기 전에 막혔다"로 인지하고 빨리 확인해야 한다. 네트워크 계층 분할이 디버깅 시간을 결정한다.
  • 방어책으로 에러 비콘(아이러니하게도)을 심어두고, 아무 정보 없는 무한 스피너는 최악의 실패 모드일 수 있다.

오랫동안 "쿠키 때문에 안 되는" 시대를 살았는데, "파일 이름 때문에 안 되는" 시대가 된 줄 몰랐습니다. 변수명은 실행에 영향을 주지 않지만, URL은 코드가 아니라 데이터로 취급되더군요.