Next.js로 기존 프로젝트를 마이그레이션하면서 가장 많이 놓치는 파일이 loading.tsx입니다. 단순히 "로딩 스피너를 보여주는 파일" 정도로 인식하고 넘어가기 쉽지만, 실제로는 React Suspense와 결합된 스트리밍 렌더링의 진입점 역할을 하는 핵심 파일입니다.
loading.tsx는 단순한 스피너가 아니다
App Router에서 loading.tsx를 만들면 Next.js는 내부적으로 해당 경로의 page.tsx를 <Suspense> 바운더리로 감쌉니다.
<Suspense fallback={<Loading />}>
<Page />
</Suspense>
즉, loading.tsx는 Suspense의 fallback이며, 이 경계가 있어야 서버에서 HTML을 부분적으로 스트리밍할 수 있습니다. 파일 하나가 단순한 UI가 아니라 렌더링 아키텍처 전체의 동작 방식을 바꾸는 스위치인 셈입니다.
없으면 어떤 일이 벌어지나
1. 모든 데이터를 기다린 뒤에야 첫 바이트가 나간다
서버 컴포넌트에서 fetch나 DB 쿼리가 일어날 때, Suspense 바운더리가 없으면 서버는 모든 데이터가 준비될 때까지 HTML 응답을 보내지 않습니다.
예를들면 블로그 목록 페이지라면 다음과 같은 상황이 발생합니다.
- 포스트 목록 쿼리: 300ms
- 카테고리 카운트: 150ms
- 사이드바 인기글: 200ms
가장 느린 쿼리(300ms)가 끝날 때까지 사용자는 완전히 흰 화면을 보게 됩니다. TTFB(Time To First Byte)가 그대로 300ms+ 깎이는 것입니다.
2. LCP 악화
LCP(Largest Contentful Paint)는 뷰포트에서 가장 큰 콘텐츠가 렌더링되는 시점입니다. 스트리밍 없이는 헤더/네비게이션 같은 정적 영역조차 데이터 페칭이 끝날 때까지 표시되지 않습니다.
loading.tsx를 통해 스트리밍을 활성화하면 레이아웃과 스켈레톤이 즉시 내려가므로, 체감 LCP가 크게 개선됩니다.
3. INP 악화 가능성
데이터 로딩 중 사용자가 다른 링크를 클릭하거나 상호작용을 시도해도, 페이지 전체가 블로킹된 상태라면 반응이 늦습니다. 스켈레톤이 먼저 뜨면 네비게이션과 인터랙션이 즉시 가능해지므로 INP(Interaction to Next Paint)에도 유리합니다.
4. 네비게이션 피드백 부재
App Router에서 <Link>로 페이지 이동 시, 새 페이지의 데이터가 준비되는 동안 사용자는 아무 피드백도 받지 못합니다. 링크를 눌렀는데 화면이 그대로라면, 사용자는 "눌린 건가?" 하며 다시 클릭하게 됩니다. loading.tsx가 있어야 즉각적인 네비게이션 피드백이 가능합니다.
적용했을 때 좋은점
1. 스트리밍 SSR 활성화
가장 큰 이점입니다. 서버는 레이아웃과 스켈레톤을 먼저 플러시하고, 데이터가 준비되는 대로 실제 콘텐츠를 이어서 내려보냅니다. 네트워크 워터폴이 개선되고, 사용자는 "뭔가 일어나고 있다" 는 시그널을 즉시 받습니다.
2. 체감 성능 향상
실제 로딩 시간이 똑같더라도, 스켈레톤이 먼저 뜨는 것만으로 체감 속도가 눈에 띄게 빨라집니다. 이는 수많은 UX 연구에서 반복적으로 검증된 결과입니다. 흰 화면 2초 vs 스켈레톤 2초는 사용자 입장에서 완전히 다른 경험입니다.
3. Core Web Vitals 지표 개선
- LCP: 정적 영역이 먼저 그려지므로 개선
- FCP(First Contentful Paint): 스켈레톤 자체가 첫 콘텐츠가 되므로 크게 개선
- CLS(Cumulative Layout Shift): 스켈레톤 크기를 실제 콘텐츠와 맞추면, 콘텐츠가 들어올 때 레이아웃 시프트가 거의 발생하지 않음
4. 레이아웃은 유지된 채로 콘텐츠만 교체
loading.tsx는 해당 세그먼트에만 적용되므로, 상위 layout.tsx의 헤더/네비게이션/사이드바는 계속 렌더링된 상태를 유지합니다. 페이지 간 이동 시에도 레이아웃이 깜빡이지 않고, SPA 같은 부드러운 전환 경험을 제공합니다.
loading.tsx를 쓰지 않는 것은 React 18 서버 컴포넌트의 가장 큰 성능 이점을 스스로 포기하는 것과 같습니다. 데이터 페칭이 일어나는 모든 라우트 세그먼트에 최소한의 스켈레톤이라도 추가해두는 것이 바람직합니다.
