React 19의 화려한 기능들, 즉 서버 컴포넌트나 Actions의 그늘에 가려져 있었지만, 사용자 경험을 미세하게 다듬는 또 하나의 중요한 개선이 조용히 이루어지고 있었다. 그것은 바로 스타일시트, 폰트, 스크립트 같은 외부 리소스(Asset)의 로딩을 처리하는 방식에 대한 것이었다.
과거에는 이런 리소스들이 HTML의 <head> 태그 안에서 비동기적으로 로드될 때, 종종 예기치 않은 화면 깜빡임 현상을 유발했다.
예를 들어, 페이지의 기본 구조(HTML)와 로직(JavaScript)이 먼저 렌더링된 후, 뒤늦게 CSS 파일이 로드되어 적용된다고 상상해보자. 사용자는 잠시 동안 스타일이 적용되지 않은 날 것의 콘텐츠를 보다가, CSS가 적용되는 순간 화면의 레이아웃과 디자인이 갑자기 확 바뀌는 것을 경험하게 된다. 이를 ‘FOUC(Flash of Unstyled Content)’라 불렀다. 폰트 파일의 경우도 마찬가지였다. 기본 시스템 폰트로 렌더링되었다가, 웹 폰트가 로드되면 글꼴이 바뀌면서 전체 텍스트의 레이아웃이 출렁거렸다.
“이런 작은 깜빡임들이 모여서, 애플리케이션 전체의 완성도를 떨어뜨립니다.”
개발자 경험 팀의 한 엔지니어가 지적했다. “사용자는 왜 그런지 정확히 설명하진 못해도, ‘뭔가 어설프다’는 느낌을 받게 되죠.”
이 문제를 해결하기 위해, React 19는 리소스 로딩을 Suspense의 메커니즘과 통합했다. 이제 React는 특정 리소스가 완전히 로드될 때까지 렌더링을 ‘일시 중단’시킬 수 있는 능력을 갖게 되었다.
이 기능은 <link>나 <script> 같은 표준 HTML 태그에 onLoad와 onError 같은 이벤트 핸들러를 지원함으로써 가능해졌다. React는 이 이벤트들을 활용하여 리소스의 로딩 상태를 추적할 수 있었다.
팀은 이 새로운 기능을 활용하는 몇 가지 API를 도입했다. 예를 들어 preload 함수 같은 것들이었다.
import { preload } from 'react-dom';
function MyComponent() {
// 이 컴포넌트가 렌더링될 때 필요한 CSS 파일을 미리 로드하도록 힌트를 준다.
preload("styles.css", { as: "style" });
return <SomeContent />;
}
이제 React의 렌더링 엔진은 이 styles.css 파일이 완전히 다운로드되고 파싱될 때까지, 해당 컴포넌트의 렌더링을 잠시 멈추고 가장 가까운 Suspense의 fallback(로딩 UI)을 보여줄 수 있었다.
결과적으로,
- FOUC 현상 방지: 스타일시트가 완전히 준비되기 전까지는 콘텐츠를 보여주지 않으므로, 스타일이 입혀지지 않은 화면이 깜빡이는 현상이 사라졌다.
- 폰트 로딩 제어: 웹 폰트가 로드될 때까지 기다렸다가 텍스트를 렌더링함으로써, 폰트 변경으로 인한 레이아웃 쉬프트(Layout Shift)를 방지할 수 있었다.
- 스크립트 의존성 관리: 특정 컴포넌트가 외부 스크립트에 의존하는 경우, 그 스크립트가 로드 및 실행될 때까지 컴포넌트 렌더링을 지연시켜 에러를 막을 수 있었다.
이것은 눈에 잘 띄지 않는 숨겨진 최적화였다. 하지만 이러한 세심한 제어 기능은 웹 페이지의 시각적 안정성을 극적으로 향상시켰다.
Suspense는 이제 데이터 로딩뿐만 아니라, 자바스크립트 코드, 그리고 스타일, 폰트, 이미지 같은 각종 에셋 로딩까지 모두 아우르는, React의 모든 비동기 작업을 위한 통합된 관제탑이 되어가고 있었다. 사용자는 더 이상 어설픈 깜빡임이나 출렁거림 없이, 처음부터 완벽하게 준비된 안정적인 화면을 마주하게 될 터였다.


