2 분 소요

🔎 문제 상황

최근 작업 중, 아주 이상한 현상을 발견했습니다.

  • 14인치 / 16인치 노트북에서만 발생
  • 텍스트가 살짝 아래에 있다가 중앙으로 이동하는 느낌
  • 폰트 굵기가 미세하게 달라 보임
  • 애니메이션을 준 적이 없는데도 “움직이는 것처럼” 보임

처음에는 제 눈을 의심했습니다. “이 정도는 그냥 예민한 걸까?”라고 생각했지만, 다시 봐도 분명 움직이고 있었습니다.

특히 고해상도 디스플레이 환경에서만 재현된다는 점이 가장 혼란스러웠습니다.


🧠 원인에 대한 고찰

이 문제를 단순히 “렌더링 이슈겠지”라고 넘기고 싶지 않았습니다. 하나씩 가능성을 좁혀가며 정리해보았습니다.


1️⃣ Subpixel Rendering & Anti-Aliasing

브라우저는 폰트를 픽셀 단위가 아니라 서브픽셀 단위로 렌더링합니다.

고 DPI(2x 스케일링) 환경에서는 0.5px 단위 계산이 발생하고, 브라우저의 반올림 처리 과정에서 초기 레이아웃과 실제 렌더링 위치가 달라질 수 있습니다.

그 결과, 텍스트가 아주 미묘하게 이동하는 것처럼 보일 수 있습니다.

0.5px는 생각보다 강력했습니다.


2️⃣ 폰트 로딩 타이밍 (FOUT / FOIT)

웹폰트를 사용하는 경우:

  1. 시스템 폰트로 먼저 렌더링
  2. 웹폰트 로딩 완료
  3. 폰트 교체

이 과정에서 폰트 메트릭(높이, baseline, 자간 등)이 다르면 텍스트의 위치가 재계산됩니다.

특히 Retina 디스플레이 환경에서는 그 차이가 더 도드라지게 보였습니다.


3️⃣ font-weight 합성 문제

예를 들어 font-weight: 500을 사용했지만 실제 폰트 파일에 500 weight가 없다면 브라우저가 굵기를 합성합니다.

이때:

  • 초기 렌더링
  • 웹폰트 적용 이후

굵기가 살짝 달라 보이며 “변하는 것 같은 느낌”을 줄 수 있습니다.


4️⃣ transform & GPU 개입

의도치 않게 다음과 같은 속성이 들어가 있는 경우:

  • transform
  • translateZ(0)
  • will-change

GPU 레이어로 승격되면서 텍스트 안티앨리어싱 방식이 바뀌고 굵기나 위치가 달라 보일 수 있습니다.


5️⃣ 반 픽셀 중앙 정렬 문제

top: 50% + translateY(-50%) 방식의 중앙 정렬은 컨테이너 높이가 홀수 픽셀일 경우 0.5px 계산이 발생합니다.

이 미세한 차이가 초기 렌더링과 이후 렌더링 간의 차이를 만들 수 있습니다.


🛠 시도한 해결 방법

하나씩 제거해보며 확인했습니다.

✅ 1. 실제 존재하는 font-weight만 사용

합성 weight 제거

✅ 2. line-height 명시적으로 지정

baseline 흔들림 최소화

✅ 3. font-display 전략 조정

swap 사용으로 폰트 교체 시 레이아웃 점프 완화

✅ 4. transform 제거

GPU 개입 가능성 제거

✅ 5. 중앙 정렬을 flexbox로 변경

반 픽셀 계산 최소화


🎯 결과

완벽하게 “이것 때문이다”라고 단정 짓지는 못했습니다.

하지만,

  • 폰트 로딩 전략 개선
  • 합성 weight 제거
  • 반 픽셀 계산 제거

이 세 가지를 조합하면서 현상은 거의 사라졌습니다.

결국, 하나의 원인이라기보다는 여러 렌더링 요소가 겹친 복합적인 문제였던 것 같습니다.


💡 이번 이슈를 통해 배운 점

1️⃣ 미묘한 어색함은 실제 문제일 가능성이 높다

느낌은 틀리지 않았습니다.


2️⃣ 폰트는 단순한 디자인 요소가 아니다

폰트는 다음과 모두 연결되어 있습니다:

  • OS 렌더링 엔진
  • 브라우저 엔진
  • DPI
  • GPU
  • 레이아웃 계산

생각보다 훨씬 복잡한 영역이었습니다.


3️⃣ “반응형”은 너비만의 문제가 아니다

이제는 다음도 함께 확인합니다:

  • devicePixelRatio
  • 디스플레이 스케일링
  • 고해상도 환경 테스트

4️⃣ 정렬은 감각이 아니라 수학이다

0.5px는 존재합니다. 그리고 그 0.5px는 꽤 집요합니다.


🧩 앞으로 주의할 점

  • 웹폰트 사용 시 실제 weight 파일 확인
  • 중앙 정렬에서 translate 남용하지 않기
  • 고 DPI 환경 테스트 필수
  • “이상한데?”라는 감각을 무시하지 않기

🌿 마무리 회고

이번 이슈는 치명적인 버그는 아니었습니다. 하지만 개발자로서 저를 꽤 오래 붙잡아두었습니다.

해결이 완벽하지 않더라도, 원인을 좁혀가며 논리적으로 추적해보는 과정 자체가 성장이라고 느꼈습니다.

프론트엔드는 ‘보이는 영역’을 다루지만, 그 안에서는 우리가 생각하는 것보다 훨씬 많은 계산이 일어나고 있습니다.

다음에 또 이런 미묘한 렌더링 이슈를 만나더라도, 조금은 덜 당황하고, 조금은 더 차분하게 접근할 수 있을 것 같습니다 😊

카테고리:

업데이트:

댓글남기기