pile·
프론트엔드·vercel-blogVercel Blog·

React Wrap Balancer: 이진 탐색으로 텍스트 줄 균형 맞추기

React Wrap Balancer는 웹 제목과 헤딩에서 불균형한 줄 나눔을 방지하는 1kB 미만의 경량 React 라이브러리다. 이진 탐색(binary search) 알고리즘으로 래퍼 너비를 "추가 줄 나눔이 생기기 직전의 최솟값"까지 줄여 텍스트를 균형 있게 배치하며, 4K 디스플레이(3840px)에서도 12번 반복이면 충분하다. 클라이언트 렌더링에선 useLayoutEffect로, SSR에선 인라인 스크립트로 레이아웃 시프트(CLS)를 방지한다.

핵심 포인트
  • 이진 탐색으로 래퍼 너비를 줄 나눔 직전까지 축소한다. 범위를 0~전체 너비로 잡고 반씩 줄여가며 정확한 줄 나눔 지점을 찾는다.
  • 4K 디스플레이(3840px)에서 최대 12번 반복으로 결정 — 이진 탐색의 O(log n) 덕에 화면 너비가 늘어도 반복 횟수는 로그 증가에 그친다.
  • 100개 이하 문자열 처리 시 약 0.25밀리초로 실행되어 렌더링 성능 영향이 없다.
  • CSR은 `useLayoutEffect`로 DOM 페인트 전 동기 실행, SSR은 타이틀 직후 인라인 스크립트로 즉시 실행해 CLS를 방지한다.
  • Next.js 13 App Directory, React Server Components, Streaming SSR에서 최적화 지원. Svelte 포트도 제공.
상세 정리
  • 문제 정의: 웹 제목/헤딩에서 한 줄이 훨씬 짧게 끊기거나 단어 하나만 홀로 내려가는 불균형한 줄 나눔이 가독성을 해친다. CSS만으로는 해결이 어렵다.
  • 핵심 아이디어: 래퍼 너비를 "추가 줄 나눔이 생기기 직전의 최솟값"까지 줄이면 남은 공간에서 텍스트가 자연스럽게 균형 있게 배치된다.
  • 이진 탐색 구현: 래퍼 너비는 0(최소)~전체 너비(최대) 사이에 있다는 걸 안다. 반씩 줄여가며 줄 나눔 발생 지점을 감지하고, 이후 더 작은 단위로 정밀 탐색한다.
  • 4K 디스플레이 12회 반복: 3840px에서 이진 탐색 12회면 약 1px 단위까지 수렴한다. 이진 탐색의 로그 복잡도 덕에 고해상도에서도 성능 저하가 없다.
  • CSR 레이아웃 시프트 방지: `useLayoutEffect` API를 사용해 DOM 페인트 전에 동기 실행하므로 화면에 잘못된 레이아웃이 노출되지 않는다.
  • SSR 처리: SSR 시 인라인 `<script>` 태그를 타이틀 직후에 삽입해 브라우저가 파싱하는 즉시 balancer가 실행된다. Streaming SSR에서도 동작한다.
  • 동적 크기 변화 대응: `ResizeObserver` API로 래퍼 크기 변화(윈도우 리사이즈, 폰트 로드 등)를 감지해 자동으로 재계산한다.
  • 번들 크기: 압축 후 1kB 미만으로 타이틀 렌더링 성능에 실질적 영향이 없다.
  • Next.js 13 최적화: RSC에서 `<Balancer>` 컴포넌트를 직접 사용할 수 있고 Streaming SSR 환경에서도 CLS 없이 동작한다.
왜 읽나제목/헤딩 텍스트 줄 균형을 개선하거나, 이진 탐색 기반 텍스트 레이아웃 최적화 구현 방법이 궁금한 React/Next.js 프론트엔드 개발자에게 알고리즘 원리와 SSR 레이아웃 시프트 방지 기법을 제공한다.
vercel-blog
Vercel Blog 블로그
원문은 여기서 이어서 읽을 수 있어요
원문 읽기
읽음 (0)

이 글과 비슷한

  1. 프론트엔드·여기어때 (GC컴퍼니)여기어때 (GC컴퍼니)·

    항공 프론트엔드 구축기 (7/10): 창구를 하나만 두었습니다

    여기어때 항공 서비스 프론트엔드가 웹과 앱 웹뷰 두 환경에서 동일한 함수 호출로 동작하는 앱 브릿지 추상화 레이어를 설계한 과정을 다룬다. iOS·안드로이드 규약 차이와 "웹에 존재하지 않는 브릿지를 어떻게 호출하나"라는 문제를 단일 추상화 층으로 해결한 구현 사례다.

    요약 이어보기
    #react#typescript#webview+2