당근 SEED 문서를 살펴보다가 줄바꿈이 어색한 부분들이 있어서 최소 수정으로 PR을 올려봤다. 몇일 뒤에 리뷰 요청이 달렸고 관련된 다른 PR이 머지되었다. 해당 PR을 살펴보니 [word-break:auto-phrase]라는 속성을 사용하셨더라.
오호 저런 속성이 있었나? 하고 MDN 문서를 가보니 auto-phrase에는 experimental 표시가 붙어 있었고, 브라우저 호환성의 Chrome 설명에는 lang="ja"일때만 적용되며 다른 locale에는 효과가 없다는 설명이 있었다. 또한 문서에서는 auto-phrase has the same effect as word-break: normal except that language-specific analysis is performed to improve word breaks by not placing them in the middle of natural phrases라고 설명한다. 그렇다면 한국어는 ko이고 효과가 없을테니 word-break: normal이 적용되어야 하고, 그렇다면 수정되지 않고 이전과 동일한 상태여야 한다.
또잉 그런데 실제 문서를 보니 정상적으로 수정되어 있었다. normal에서는 우리는 왜 디자인 엔까지 첫줄에 들어가는 반면, auto-phrase에서는 우리는 왜 디자인에서 정상적으로 잘렸다. 일본어만 지원한다면서 ! 왜 한국어 줄바꿈이 달라졌을까 궁금해졌다.
그래서 실제 Chrome 릴리즈를 찾아보기로 했다. (이것도 MDN에 기여할 수 있는 절호의 찬스일 수 있다 키키). 먼저 MDN에 명시되어있는 Chrome 119를 봤다. Chrome은 119에서 auto-phrase를 출시하며 이를 일본어의 자연스러운 문절 경계에서 줄바꿈하는 기능으로 소개했다.
실제로 여기에도 "Currently, Chrome supports this feature only for Japanese, using the BudouX C++ port that uses AdaBoost ML technology.", 그리고 "We plan to support Korean and Chinese in future versions of Chrome"이라면서 아직 일본어밖에 안된다고 하는데.. 근데 한국어도 (사실상) 되는거잖아 !!! 그래서 실제 코드를 봐보기로 했다.
Chromium은 ICU(International Components For Unicode라고 한다)에서 제공하는 코드로 line break을 계산하는데, ICU가 LineBreakiterator를 만드는 부분에 lw=phrase가 일본어와 한국어에서만 지원된다고 명시되어 있다.
반면 실제 분석 엔진을 선택하는 부분에는 phrase breaking은 일본어와 한국어를 지원하지만 ML engine은 일본어만 지원한다고 적혀있다. 그래서 난 음 한국어는 ML engine이 지원되지 않아서 지원되지 않는다고 했나보군이라고 처음에는 생각했다.
근데 이제 생각을 해보자. 한국어는 띄어쓰기가 존재한다. 그리고 띄어쓰기가 사실상 어절을 나누는 기준이다. 반면 일본어나 중국어는 띄어쓰기가 애초에 존재하지 않는다. 그래서 어절을 나눠주는것에 별도의 ML engine이 필요할 수 있다. ML engine은 BudouX를 사용하는데, 이는 일본어를 bunsetsu라는 단위로 나눈다고 한다. 그리고 이것이 언어학적으로 완전히 정확히 같지는 않겠지만 아마 거의 비슷한 느낌인 것 같다 (듀오링고 일본어 1000일에 가까워지는 사람으로써 나뉘어진걸 보면 비슷한 느낌이다).
일본어는 띄어쓰기 없이 이어진 문장에서 자연스러운 경계를 찾아야 하므로 ML engine을 사용해야 하지만 (거의 리버스 엔지니어링) 한국어는 사실상 띄어쓰기 자체가 자연스러운 경계이기 때문에 ML engine이 애초에 필요가 없다는 결론에 도달할 수 있다. 그리고 실제로 BudouX에서도 Korean support?라는 섹션을 두고 "한국어는 대부분 keep-all 쓰면 된다"라고 말하고 있다.
그래서 나는 현재 한국어가 auto-phrase에서 사실상 지원된다라고 보는것이 맞다고 본다. 그래서 일단 MDN에 이슈랑 PR을 올려놨다. 사실상 지원인데 MDN에 일본어만 지원한다는거 보고 안쓰면 아쉽잖아 .. 아 근데 그래서 keep-all이랑은 뭣이 다르냐 하면 ..
keep-all은 구문별로 끊는게 고정이다. 반면 auto-phrase는 구분별로 끊고, overflow될시에는 normal로 fallback해서 다시 끊어준다. 다시말해서 keep-all을 하면서 너무 긴 단어는 중간에 끊어줄 수 있는 기능까지 갖고 있는 것! 내가 keep-all + overflow-wrap: anywhere을 같이 적용한것과 거의 비슷한 효과라고 보면 된다.
차이점이라면 auto-phrase는 기본적으로 hyphens가 추가될 수 있는 기회를 없애서 hyphens: none처럼 동작한다는 것. 그래서 긴 영어 단어가 왔을때 줄바꿈이 되면 보통 hyphens로 이어주는데, 그게 안된다고 한다.
그래서 내가 내린 결론은 이거다. 한국어 (+일본어) / 영어를 같이 다룬다면 이것이 가장 실용적인 선택이 아닐까?
.title {
word-break: normal;
overflow-wrap: anywhere;
text-wrap: balance;
}
.title:lang(ko),
.title:lang(ja) {
word-break: auto-phrase;
}
.title:lang(en) {
hyphens: auto;
}
overflow-wrap: anywhere로 너무 긴 문자열이나 url을 방어하고, text-wrap: balance로 적절하게 위치시키고, 한국어/일본어는 word-break: auto-phrase로 어절 단위로 줄바꿈하고, 영어는 hyphens만 추가해서 긴 단어 줄바꿈시에 hyphens가 들어갈 수 있도록 처리!
아 anywhere이 좋은 이유를 몇가지 더 추가해보자면, 사전에 있는 단어는 hyphens를 추가했을때 잘 동작하지만, 사전에 없는 단어는 넘쳐버린다. 그리고 flex나 grid 안의 텍스트 요소에 별도로 min-w-0을 지정하지 않아도 레이아웃이 깨지지 않는다.
근데 사실 난 처음 auto-phrase를 보고 의미론적으로 줄바꿈해주는건가 했다. 왜냐면 어차피 한국어에서는 keep-all이 어절로 줄바꿈해주는거니까 나는 auto-phrase가 된다면 어절에 더해서 의미론적으로도 줄바꿈을 해줘야 의미가 있는거 아닌가 생각했던 것 같다. 대충 이런 느낌으로.
- 좋은 제품을 만들기 위해 작은
- 불편부터 하나씩 개선합니다
+ 좋은 제품을 만들기 위해
+ 작은 불편부터 하나씩 개선합니다
그래서 내가 직접 BudouX로 만들어봐야겠다 싶었다. 그리고 실제 만들어 본 결과 제한적으로나마 의미가 있는것을 확인했다. 그리고 아예 npm 패키지로 배포해버렸다. 링크는 여기: github, npm. 다음 아티클은 요거 만든 과정을 한번 공유해보겠다 우하하.