4P by GN⁺ 3시간전 | ★ favorite | 댓글 1개
  • Safari와 Firefox는 TikTok, Netflix, Instagram 같은 특정 도메인에서 렌더링과 API 동작을 바꾸는 코드를 배포함
  • Firefox의 about:compat는 사이트별 개입과 토글을 보여주며, 맞춤 CSS·JavaScript 주입과 사용자 에이전트 위장을 수행함
  • Safari의 WebKit은 이를 quirks로 관리하며, PiP 비디오·이미지 정렬·팝오버·스트리밍 접근 문제를 도메인별로 우회함
  • Chrome은 별도 예외 파일이 거의 필요 없는데, 웹이 이미 Chrome 중심으로 만들어져 다른 브라우저가 차이를 보정하기 때문
  • 이런 예외는 로그나 콘솔에 잘 드러나지 않으므로, 개발자는 Firefox와 Safari에서 정기적으로 테스트하고 quirks 파일 포함 여부를 점검해야 함

브라우저 안의 도메인별 예외 처리

  • Safari와 Firefox는 사용자가 방문한 도메인에 따라 렌더링이나 API 동작을 바꾸는 코드를 배포함
  • TikTok, Netflix, Instagram, SeatGuru 같은 사이트가 이런 사이트별 처리의 대상이 됨
  • 관련 소스는 WebKit의 Quirks.cpp와 Firefox의 WebCompat interventions에서 공개적으로 확인 가능함
  • 이 코드는 “특정 도메인이면 다르게 렌더링”하거나 “특정 도메인이면 API 호출을 다르게 처리”하는 방식으로 브라우저 렌더링 엔진에 들어가 있음
  • Chrome은 같은 방식의 예외 파일이 사실상 필요 없으며, 웹이 이미 Chrome 중심으로 만들어진 비대칭이 드러남

Firefox의 about:compat

  • Firefox 주소창에 about:compat을 입력하면 사이트별 개입 목록과 토글 스위치를 볼 수 있음
  • 각 항목은 특정 웹사이트를 위한 맞춤 수정이며, 끄면 사이트가 깨지는 모습을 확인할 수 있음
  • Firefox의 WebCompat system은 특정 도메인에 맞춤 CSS와 JavaScript를 주입함
  • 브라우저를 잘못 감지하는 사이트에는 사용자 에이전트 문자열을 바꿔 전달함
  • 이런 개입은 웹이 고장난 것처럼 보이지 않도록 버그를 덮으며, Mozilla Bugzilla에는 버그 리포트와 사이트 연락 시도까지 추적되어 있음

Safari의 quirks

  • Safari의 WebKit 엔진은 이런 처리를 quirks라고 부르며, Quirks.cpp가 GitHub에 공개되어 있음
  • WebKit 코드에는 Facebook, X, Reddit이 화면 밖으로 스크롤된 <video>를 PiP 모드 여부와 상관없이 일시정지한다는 주석이 있음
  • Safari는 facebook.com, x.com, reddit.com을 감지해 Picture-in-Picture 비디오 처리를 바꿈
  • 사이트의 비디오 코드가 깨져 있어도 해당 회사들이 고치기를 기다리지 않고, 브라우저가 모든 사용자에게 우회 처리를 배포함
  • SeatGuru 관련 주석에는 FIXME: Remove this quirk if seatguru decides to adjust their site.라고 되어 있어, 사이트가 수정되면 예외를 제거할 수 있음을 보여줌
  • 커밋 기록에는 최근 몇 달 사이 여러 사이트별 수정이 들어감
    • Zillow의 floorplan 이미지가 가운데 정렬되지 않는 문제
    • TikTok의 “please upgrade your browser” 메시지 표시 문제
    • Instagram Reels가 재생 중 불규칙하게 크기 조정되는 문제
    • Netflix의 “Episodes and Info” 버튼이 팝오버를 잘못 닫는 문제
    • Twitch가 탭 전환 시 PiP 비디오를 일시정지하는 문제
    • Amazon Prime Video가 Safari 사용자에게 시청을 허용하지 않는 문제

Chrome 중심 웹과 비대칭

  • WebKit의 quirks와 Firefox의 WebCompat은 깨진 사이트를 고치는 데 그치지 않고, Chrome이 “작동한다”의 기준을 좌우하는 상황도 보정함
  • 일반적으로 Chrome이 기능을 배포하면, 시장 지배력 때문에 개발자가 그 기능을 쓰고, 다른 브라우저가 해당 기능을 구현하거나 사이트별 예외로 차이를 덮게 됨
  • Safari와 Firefox가 따라잡을 때쯤에는 이미 예외 처리가 수백만 사용자에게 배포된 상태가 됨
  • WebKit에는 Amazon 비디오 페이지와 여러 스트리밍 서비스에서 Safari가 Chrome인 것처럼 보이게 하는 사용자 에이전트 오버라이드가 포함되어 있음
  • 이런 사이트들은 Chrome 여부를 탐지해 다른 브라우저에 저하된 경험을 제공하므로, WebKit은 Safari 사용자를 보호하기 위해 브라우저 정체성을 속임
  • 현재 Quirks.cpp에는 다음과 같은 가짜 Chrome 사용자 에이전트 문자열이 들어 있음
auto chromeUserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36"_s;
  • Firefox도 같은 방식으로 동작하며, about:compat의 많은 개입은 사이트에 “나는 Chrome”이라고 알리는 사용자 에이전트 위장임
  • Mozilla wiki는 일부 사이트가 브라우저 감지 결과에 따라 “접근을 완전히 차단하거나, 다른 디자인을 표시하거나, 다른 기능을 제공한다”고 밝힘
  • 이런 구조는 피드백 루프를 만듦
    • 개발자는 Chrome 점유율이 높기 때문에 Chrome을 기준으로 만듦
    • 사이트는 Chrome에서 가장 잘 작동함
    • 다른 브라우저에서 버그를 만난 사용자는 사이트가 아니라 브라우저를 탓함
    • 사용자는 Chrome으로 이동하고, Chrome의 지배력은 더 강화됨
  • Chrome이 별도의 quirks 파일을 거의 필요로 하지 않는 이유는 Chrome이 더 잘 설계되어서라기보다, 웹이 이미 Chrome에 맞춰져 있기 때문
  • Chromium 기반 브라우저 사용자가 80%를 넘는 상황에서는 개발자가 Chrome을 먼저 대상으로 삼음
  • 사이트가 Chrome에서 작동하면 배포되고, Safari나 Firefox에서 깨지면 그 문제의 우선순위가 낮아짐
  • Chrome은 예외를 추가하기보다 의제를 설정
  • Chrome이 어떤 동작을 바꾸면 사이트가 그에 맞춰 업데이트되고, 다른 브라우저는 따라가거나 깨짐

명세와 실제 웹 사이의 간극

  • 브라우저 엔지니어들은 현재 명세가 잘 정의되어 있으며, HTML5의 “living specification” 접근이 IE/Netscape 시대의 혼란을 줄였다고 볼 수 있음
  • 문제는 개발자들이 명세에 없는 구현 세부사항에 의존하고, 그 세부사항이 다른 브라우저에서 다르면 비준수 브라우저를 탓한다는 데 있음
  • Chrome의 구현이 모두가 대상으로 삼는 기준이 되면, Chrome의 명세 밖 세부 동작이 사실상의 명세가 됨
  • 2000년대 Internet Explorer 때도 개발자가 IE에 맞춰 사이트를 만들면서 다른 브라우저에서 사이트가 깨졌고, 표준 준수보다 “IE에서 작동”이 우선이 됨
  • 과거에는 웹이 표준을 더 잘 지키면 브라우저 quirks가 사라질 것으로 기대했지만, 실제로는 quirks가 사라진 것이 아니라 Chrome이 아닌 브라우저로 이동한 셈
  • 표준은 브라우저별 코드를 없애기 위해 존재했지만, IE 시대를 빠져나온 뒤 다른 브라우저를 중심으로 같은 구멍이 다시 만들어짐
  • 이제 브라우저별 코드는 지배적인 브라우저가 아니라, 지배적인 브라우저에 맞춰진 웹을 보정하는 비지배 브라우저 안에 들어가 있음

예외 처리는 생각보다 깊다

  • 이런 처리는 단순한 시각적 조정에 그치지 않고, 도메인에 따라 브라우저의 기본 동작을 바꿈
  • WebKit의 목록만 해도 수천 줄에 달하며, 스크롤 동작, 터치 이벤트 처리, 뷰포트 계산, 이미지 MIME 타입 처리까지 포함함
  • Amazon 제품 이미지 확대 기능을 위한 주석에는 다음과 같은 내용이 있음
When panning on an Amazon product image, we’re either touching on the #magnifierLens element or its previous sibling.
  • Safari는 Amazon에 접속했는지 확인한 뒤, 제품 확대 기능을 위해 터치 이벤트를 마우스 이벤트로 변환하는 방식을 바꿈
  • Amazon 사이트가 Safari 기본 동작과 다른 특정 이벤트 동작을 가정하기 때문에, Safari가 Amazon에 대해서만 그 동작을 제공함
  • storage access, 스크롤바 렌더링, 자동 교정 동작, 확대/축소 처리에도 도메인별 quirks가 있음
  • 각 예외는 도메인 검사 뒤에 있으며, 브라우저 실행 파일 안에 컴파일됨

기다리기보다 브라우저가 직접 고치는 이유

  • 브라우저 벤더가 문제 사이트에 연락해 수정을 요청하는 경우도 있으며, 소스 코드에는 outreach 노력이 링크된 필드도 있음
  • 하지만 인기 사이트가 Chrome에서는 작동하고 자사 브라우저에서는 깨지면 사용자는 사이트가 아니라 브라우저를 탓함
  • 제3자에게 버그를 제출하고 몇 주 또는 몇 달을 기다리는 것보다, 다음 날 5줄짜리 우회 처리를 배포하는 편이 브라우저 입장에서는 더 실용적임
  • 누구에게 연락해야 하는지도 분명하지 않을 수 있음
    • 깨진 코드를 작성한 개발자가 이미 회사를 떠났을 수 있음
    • 해당 엔드포인트를 소유한 팀이 책임을 인식하지 못할 수 있음
    • 사이트가 보안 패치만 받는 유지보수 모드일 수 있음
  • 브라우저 입장에서는 즉시, 보이지 않게 고쳐 사용자 문제를 줄이는 선택이 단순함
  • WebKit 엔지니어가 FlightAware quirk 제거 과정을 다룬 글도 있음
  • FlightAware는 CSS transform matrix 문자열을 비교하고 있었고, CSS 명세가 값 직렬화 방식을 바꾸면서 브라우저가 명세를 따르자 사이트가 깨짐
  • 엔지니어들은 flightaware.com을 검사하는 도메인별 코드를 추가했고, 이후 연락이 성공해 FlightAware가 코드를 고치면서 quirk가 제거됨
  • 그 몇 달 동안 Safari 사용자는 브라우저 안의 if문 덕분에 정상적인 경험을 할 수 있었음

개발자가 확인해야 할 것

  • 웹사이트가 자신도 모르게 특별 렌더링 처리를 받고 있을 수 있음
  • 이런 quirk는 오류 로그에 나타나지 않고, 콘솔에도 “브라우저가 실수를 우회 처리 중”이라는 경고를 띄우지 않음
  • 우회 처리는 의도적으로 보이지 않게 동작함
  • Chrome 위주로 테스트하는 사이트는 특히 위험함
  • 사이트가 완벽하게 작동하는 이유가 좋은 코드 때문이 아니라, Chrome의 동작이 개발자의 가정과 맞아떨어지기 때문일 수 있음
  • 다른 브라우저는 사이트를 사용자에게 깨진 채로 보여줄지, 아니면 quirks 파일에 추가할지 선택해야 하는 상황이 됨
  • Firefox와 Safari에서 사이트를 가끔이 아니라 정기적으로 열어봐야 함
  • quirks 파일은 개발자가 정기적으로 그렇게 하지 않았기 때문에 존재함
  • 자신의 도메인이 quirks 파일에 있다면, 브라우저가 우회 처리한 부분을 점검할 필요가 있음
  • 웹은 개발자 개입 없이도 계속 작동했지만, 사용하지 않는 브라우저의 엔지니어가 개발자가 몰랐던 문제를 대신 해결한 상태일 수 있음
Lobste.rs 의견들
  • LLM 잡문 뒤에 흥미로운 이야기가 숨어 있음

    • 안타깝게도 글이 너무 별로라 그 이야기를 찾을 수 없었음. 제목에서 멈췄어도 됐을 글임
    • 이 댓글에 추천을 누른 사람들은 아마 이 글을 스팸으로 신고하는 게 맞을 듯함
    • 선정적으로 몰아가다가 갑자기 브라우저 호환성 우회 정보를 차분히 설명하는 식으로 오락가락해서 꽤 거슬렸음
    • 정중히 말하면, 요즘 근거 없이 “LLM 잡문”이라고 단정하는 댓글이 점점 더 많이 보임. LLM이 글처럼 보이는 건 글로 학습했기 때문이라는 점을 잊은 건가 싶음
      글쓰기 스타일이 마음에 안 들 수는 있고 그 부분은 굳이 다투고 싶지 않지만, 글이 별로라고 해서 반드시 AI가 썼다는 뜻은 아님. AI 이전에도 형편없는 문장은 많았음
    • 이 댓글과 이어진 스레드가 정확히 뭘 문제 삼는지 누가 분명히 말해줬으면 함. 글은 읽기 쉬웠고 유익했는데, 뭐가 문제인지 모르겠음
  • 안타까운 일이고, Google이 웹을 이렇게 많이 좌우하지 않는 세상에 살았으면 좋겠음. “웹”이라는 꿈은 훨씬 더 야심차고, 개인적으로는 영감을 주는 것이었는데 지금처럼 된 게 아쉬움

  • 인용문 블록이 읽기 어려움. 아마 다크 모드 문제일 수도 있음
    우회 방법의 세부 내용을 공유해준 건 유용했음

    • 맞음, 대비가 거의 없음. 라이트 모드에서도 썩 좋지는 않고 다크 모드보다는 약간 나은 정도임. 사이트 만든 사람이 실제로 직접 보지는 않고 그냥 눈감고 코딩한 것 같음
  • “이 사이트들은 Chrome인지 탐지해서 다른 브라우저에는 저하된 경험을 제공한다. 그래서 Safari 사용자가 고생하게 두는 대신 WebKit은 자신이 어떤 브라우저인지 거짓말한다”는 부분은 이 업계 전반에서 반복되는 일처럼 보임
    컴퓨터 제조사들도 드물지 않게 지원하지 않는 운영체제에는 정보를 숨기는 ACPI 펌웨어를 내놓고, 결국 그 운영체제들이 Windows인 척하며 펌웨어를 속이게 만듦

  • 이 글이 AI 문체처럼 읽히는 점이 마음에 들지 않음

  • 여기서 말한 것 말고도 두 가지 피드백 루프가 있음. 하나는 Chrome이 지배적이라 개발자가 Chrome 기준으로 만들고, 그러면 Chrome에서 가장 잘 동작하고, 다른 브라우저에서 문제가 생기면 사용자가 사이트가 아니라 브라우저 탓을 하며 Chrome으로 옮겨가는 루프임
    다른 하나는 사이트가 Firefox에서 깨져 있는데도 사이트 운영자가 통계에 Firefox 사용자가 안 보인다고 말하는 루프임. 사용자 에이전트를 바꾸는 식의 특수 처리가 있어도 이런 일이 생길 수 있음

  • 기억하기로는 고전 Opera(Presto) 가 이런 호환성 계층을 처음 구현하기 시작했음

  • 구현이 곧 명세가 되는 건 이 분야에 널리 퍼진 문제임. 예전 직장에서는 여러 구현체가 생기고 워크플로가 이식 가능해지길 기대하며 적합성 테스트가 있는 워크플로 언어를 썼음
    핵심 문제는 완전한 이식성을 만들 경제적 유인이 낮다는 데 있음. 자기 구현체에 부가 기능을 넣어 사람들이 계속 그 제품에 머물게 만들고 싶어짐
    또 위원회식으로 소프트웨어 만들 시간은 없으니 새 기능을 앞서 만들어 넣고 싶어짐
    구현이 명세가 되는 건 우리가 인간 사회에 살기 때문임

  • 새 일이 아님. 소수 브라우저들은 특정 사이트용 해킹을 늘 갖고 있었고, 예전에는 그 대상이 IE였음. 대안은 사이트가 깨진 채로 남는 것뿐이었음
    수십 년 전 웹 개발자들은 IE에서만 동작하는 사이트를 만들고 “이 사이트를 쓰려면 IE를 쓰라”고 했고, 지금은 같은 일이 Chrome으로 반복되는 중임. Chrome이 맞는지 틀린지는 중요하지 않음. 사이트가 Chrome에서만 동작하고, 다른 브라우저가 그 사이트에서 Chrome의 동작을 보장하지 않으면 사람들은 “이 브라우저가 깨졌다”고 말하고 Chrome으로 옮겨감
    정말 궁금한데, 사람들이 Gecko와 WebKit이 원칙 때문에 이런 사이트를 깨진 채로 놔둬야 한다고 생각하는 건지, 아니면 모두가 Chrome만 쓰고 다른 브라우저는 쓰지 말아야 한다고 생각하는 건지 모르겠음. 특정 사이트용 해킹의 대안은 그 둘뿐임

  • Firefox와 Safari가 사용자 에이전트로 Chrome인 척하는 건 웃기다고 봄
    그런데 Chrome의 사용자 에이전트 문자열에는 Mozilla 브라우저인 척하고 Apple 브라우저인 척하던 화석 같은 흔적이 남아 있음
    이 코드 한 줄에는 지질학적 층이 쌓여 있음:

    auto chromeUserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36"_s;