Next.js
Next.js loading.tsx가 바로 보이지 않을 때 확인한 짧은 튜토리얼
loading.tsx를 만들었는데 전환 중 화면이 그대로여서 Suspense 경계와 캐시를 확인한 방법을 적었다.
loading.tsx를 추가했는데도 화면이 조용했다
상품 목록 페이지에 app/products/loading.tsx를 만들었지만 링크를 눌렀을 때 기존 화면이 잠깐 그대로였다. loading 파일이 망가진 줄 알았는데, 실제로는 데이터 fetch가 캐시되어 서버가 거의 즉시 응답하고 있었다. 기다릴 시간이 없으면 로딩 UI도 눈에 띄지 않는다.
경로와 파일 위치부터 맞춘다
loading.tsx는 같은 route segment의 page.tsx를 감싸는 Suspense 경계가 된다. 예를 들어 목록 페이지라면 구조는 아래처럼 둔다.
app/
products/
page.tsx
loading.tsx
export default function Loading() {
return <p aria-live="polite">상품을 불러오는 중입니다.</p>
}
처음에는 app/loading.tsx 하나만 두고 특정 목록의 스켈레톤이 보일 것을 기대했다. 전역 파일은 전체 경로 전환에 쓰일 수 있지만, 화면 모양이 다른 페이지에는 segment 가까이에 둔 파일이 훨씬 분명했다.
테스트용 지연과 실제 원인을 구분한다
로딩 UI 자체를 시험할 때만 임시 지연을 넣었다. 운영 코드에 남기면 안 된다.
async function getProducts() {
const response = await fetch('https://api.example.com/products', {
cache: 'no-store',
})
if (!response.ok) throw new Error('목록을 가져오지 못했습니다')
return response.json()
}
cache: 'no-store'는 문제를 확인하기 위한 만능 해법이 아니다. 자주 바뀌지 않는 목록까지 매 요청마다 서버에서 받게 만든다. 나는 데이터 갱신 주기를 정한 뒤 revalidate를 쓰거나, 사용자별 데이터만 동적으로 처리하는 기준으로 바꿨다.
전환을 직접 관찰하는 방법
브라우저 개발자 도구에서 Network의 요청 시간을 throttling으로 늘리고, <Link>로 이동했을 때와 주소를 새로 열었을 때를 각각 봤다. prefetch된 경로는 체감이 다를 수 있다. 에러 UI가 필요한 경우에는 error.tsx도 같은 segment에 별도로 둔다.
마무리로 확인할 것은 세 가지다: loading 파일이 정확한 경로에 있는지, 실제 요청이 기다릴 만큼 느린지, 캐시 정책이 서비스 요구와 맞는지. 로딩 화면이 안 보인다고 해서 곧바로 캐시를 끄는 선택은 하지 않게 됐다.