---
title: "브라우저 하이픈 사전만 봐도 운영체제를 맞힐 수 있다"
published: 2026-07-22T13:54:32.000Z
canonical: https://jeff.news/article/5040
---
# 브라우저 하이픈 사전만 봐도 운영체제를 맞힐 수 있다

브라우저 지문 추적은 보통 캔버스, 폰트, 웹지엘을 떠올리지만, 이 글은 CSS 자동 하이픈 처리 사전이 운영체제를 노출할 수 있다고 보여준다. macOS의 CoreFoundation 사전과 Windows·Linux 계열의 Minikin 사전이 지원 언어와 줄바꿈 위치에서 달라, 단어 몇 개만 좁은 박스에 넣어도 OS 계열을 구분할 수 있다는 내용이다.

- 브라우저 지문 추적에서 사람들이 잘 안 보는 신호가 하나 있음. 바로 CSS 자동 하이픈 처리임
  - `hyphens: auto`는 긴 단어를 좁은 박스에 넣었을 때 언어별 사전을 보고 줄바꿈 위치를 정함
  - 브라우저에 해당 언어 사전이 없으면 단어는 안 끊기고 한 줄로 넘침
  - 이 차이가 생각보다 날카로워서, 단어 하나와 DOM 높이 읽기 한 번으로 운영체제 계열이 드러날 수 있음

- 예시가 꽤 강함. 진짜 Chrome 150에서 macOS, Windows, Linux를 비교했더니 결과가 갈림
  - 핀란드어 `kansainvälistyminen`은 macOS Chrome에서 hyphenate되지만 Windows와 Linux에서는 안 됨
  - 라틴어 `constitutionalibus`는 macOS Chrome에서는 안 끊기고 Windows와 Linux에서는 끊김
  - 즉 `lang` 속성과 박스 높이만 보면 브라우저가 어느 OS 계열 위에서 도는지 추정할 수 있음

> [!IMPORTANT]
> 이 신호가 까다로운 이유는 텍스트 레이아웃 깊숙한 곳에 있어서 spoofing 스택이 잘 안 건드린다는 점임. User-Agent나 화면 크기처럼 흔히 위장하는 값이 아님.

- 원인은 Chrome이 OS별로 다른 하이픈 엔진을 쓰기 때문임
  - macOS와 iOS는 Apple의 CoreFoundation을 호출함
  - 실제 함수는 `CFStringGetHyphenationLocationBeforeIndex`이고, `/System/Library/LinguisticData/<locale>/hyphenation.dat`에 있는 Apple 사전을 읽음
  - Windows, Linux, Android, ChromeOS는 AOSP의 Minikin을 쓰고, Chrome component updater가 내려주는 `hyph-<locale>.hyb` 패턴 파일을 읽음

- 두 엔진은 지원 언어 목록부터 다름
  - Apple은 21개 로케일을 지원함. 핀란드어, 폴란드어, 카탈루냐어, 루마니아어 등이 macOS 쪽에 있음
  - Minikin은 52개 AOSP 세트를 지원함. 라틴어, 웨일스어, 노르웨이어 뉘노르스크, 슬로베니아어, 바스크어, 에스토니아어 등이 이쪽에 있음
  - 몇 개 언어만 찔러봐도 'Apple 사전인지 Minikin 사전인지'가 갈리고, 그게 곧 OS 계열 신호가 됨

- 더 무서운 건 지원 여부만 다른 게 아니라, 같은 언어에서도 끊는 위치가 다를 수 있다는 점임
  - 체코어, 슬로바키아어, 우크라이나어의 특정 단어에서 Apple 패턴과 AOSP TeX 계열 패턴이 서로 다른 위치를 반환함
  - 탐지기가 단순히 줄바꿈 여부만 보는 게 아니라 break position까지 기록하면 신호 축이 하나 더 생김

- 커스텀 Chromium이나 봇 브라우저는 여기서 두 번 걸릴 수 있음
  - 첫 번째는 component updater를 제대로 돌리지 않아 Minikin 사전 디렉터리가 비어 있는 경우임. 그러면 영어조차 `hyphens: auto`가 동작하지 않음
  - 두 번째는 AOSP `.hyb` 세트를 넣어서 영어는 고쳤지만, macOS라고 주장하면서 실제로는 Minikin처럼 하이픈 처리하는 경우임
  - 이러면 라틴어와 뉘노르스크는 끊기고, 핀란드어와 폴란드어는 안 끊기는 '가짜 macOS'가 됨

> [!WARNING]
> macOS 프로필을 흉내 내려면 단순히 하이픈 사전을 많이 넣는 게 아니라, Apple이 지원하는 21개 로케일만 지원하고 Apple이 거부하는 언어는 똑같이 거부해야 함.

- 글의 하드코어한 부분은 Apple `hyphenation.dat` 역공학임
  - 이 파일은 TeX 패턴 목록이 아니라 serialized CFBurstTrie라는 compiled trie 포맷임
  - 헤더의 `reserved[16]` 필드가 초기화되지 않은 채 디스크에 남아 있어서, 처음엔 포인터가 박힌 메모리 이미지처럼 보였다고 함
  - 실제 본문은 `DiskTrieLevel`, `CompactDiskTrieLevel`, `StringPage` 같은 세 종류의 노드로 구성됨

- Apple 사전의 payload는 Liang hyphenation level을 3비트씩 압축해 담고 있음
  - 일치한 패턴들의 level을 누적하고, 홀수 level인 위치를 하이픈 후보로 반환함
  - 양쪽 최소 2글자 조건도 적용됨
  - 겉으로는 Apple 전용 포맷이지만, 컨테이너를 풀고 나면 나머지는 표준 Liang 방식에 가깝다는 얘기임

- 재구현은 portable C 몇백 줄 규모라고 함
  - 헤더를 파싱하고 trie를 걸으며, sparse level에서는 bitmap과 popcount로 슬롯을 찾고, StringPage에서는 길이와 바이트를 맞춰 terminal entry를 찾음
  - 단어 하나당 시작 위치마다 trie walk를 하므로 대략 마이크로초 단위 비용이라고 설명함
  - UTF-8 key와 code point 기준 break position을 따로 관리해야 그리스어·키릴 문자에서 틀어지지 않음

- 검증은 진짜 macOS Chrome을 DevTools protocol로 돌려 break position을 전부 비교하는 방식임
  - Apple의 21개 로케일 전체에서 byte-exact, break-for-break로 맞췄다고 함
  - 최종 체크도 처음의 probe와 같음. macOS 프로필은 핀란드어와 폴란드어를 끊고, 라틴어와 뉘노르스크는 끊지 않아야 함

- 결론은 단순함. 텍스트 줄바꿈도 fingerprinting 표면임
  - DOM read 한 번으로 결정적인 신호를 얻을 수 있고, coverage split만으로 OS family가 갈림
  - break position까지 보면 공통 지원 언어 안에서도 추가 구분이 가능함
  - 제대로 위장하려면 CoreFoundation 컨테이너 포맷, Liang level 재현, Apple의 정확한 로케일 coverage까지 맞춰야 함. 와, 이건 꽤 집요함

---
## 기술 맥락

- 이 글에서 중요한 기술 선택은 '하이픈 처리 결과를 운영체제 지문으로 본다'는 거예요. 보통 fingerprinting은 캔버스, 폰트, 웹지엘처럼 눈에 띄는 표면을 보는데, 여기서는 CSS 텍스트 레이아웃의 사전 차이를 이용해요.

- 왜 OS가 드러나냐면 Chrome이 모든 플랫폼에서 같은 하이픈 엔진을 쓰지 않기 때문이에요. macOS는 CoreFoundation과 Apple 사전을 쓰고, Windows나 Linux 쪽은 Minikin과 AOSP 사전을 쓰니까 지원 언어와 break position이 자연스럽게 갈라져요.

- 봇 방어 입장에서는 이게 꽤 귀찮은 신호예요. macOS처럼 보이겠다고 User-Agent만 바꾸면, 실제 하이픈 결과는 Linux의 Minikin처럼 나와서 앞뒤가 안 맞거든요. 영어만 동작하게 고치는 식의 부분 수정도 여러 로케일을 찌르면 바로 깨져요.

- Scrapfly 쪽 구현이 어려운 이유는 Apple 사전을 그대로 읽을 수 있는 CoreFoundation이 Linux에 없기 때문이에요. 그래서 `hyphenation.dat`의 CFBurstTrie 구조를 역공학하고, Liang level 적용과 UTF-8 위치 계산까지 맞춰야 진짜 Mac과 같은 결과가 나와요.

- 이 사례는 브라우저 호환성의 반대편을 보여줘요. 사용자에게는 '같은 Chrome'처럼 보여도, 렌더링 엔진 주변의 플랫폼 의존 레이어가 남긴 작은 차이가 자동화 탐지나 프라이버시 문제에서는 꽤 큰 신호가 될 수 있어요.

## 핵심 포인트

- CSS `hyphens: auto`는 언어별 하이픈 사전 유무에 따라 단어 줄바꿈 여부가 달라진다
- macOS Chrome은 Apple CoreFoundation 사전을 쓰고, Windows·Linux·Android·ChromeOS는 AOSP Minikin 사전을 쓴다
- 진짜 macOS처럼 보이려면 Apple의 21개 로케일 범위와 단어별 break position까지 맞춰야 한다

## 인사이트

이건 브라우저 지문 추적이 얼마나 사소한 렌더링 차이까지 파고드는지 보여주는 사례다. 봇 탐지 회피 입장에서는 'User-Agent만 macOS로 바꾸면 끝' 같은 시대가 진작 끝났다는 얘기고, 방어 입장에서는 텍스트 레이아웃도 공격면이라는 걸 봐야 한다.
