스트리밍(Streaming)
- 서버에서 클라이언트로 어떤 데이터를 보낼 때, 데이터 크기가 너무 크거나 데이터 크기가 커서 빠르게 전송하기 어려울 때 데이터를 잘게 쪼개서 하나하나씩 클라이언트에 보내는 기술
- 랜더링하는데에 오래걸리더라도 로딩바 같은 대체 UI를 보여줌으로써 사용자의 불편을 줄인다.
- Dynamic Page 에 적용하는 것이 올바르다.(Static Page의 경우 렌더링할 때 모든 비동기 작업을 끝내기 때문)
- 페이지 스트리밍보다는, suspense를 사용하는 컴포넌트 스트리밍이 조금 더 유용하게 쓰인다.
페이지 스트리밍
- 적용하고자 하는 'page.tsx' 파일이 존재하는 폴더 내에 'loading.tsx' 파일을 생성해 코드를 작성한다.
// loading.tsx
export default function Loading() {
return <div>Loading...</div>
}
페이지 스트리밍을 사용할 때 주의할 점
- 해당 파일과 같은 폴더 내에 있는 페이지뿐만 아니라, 해당 경로를 포함하는 모든 페이지에서 적용된다.(Layout과 비슷)
- 비동기(async)로 제공하는 페이지에만 적용된다.
- page 파일에만 적용이 가능하다.
- 쿼리스트링만 변경될 때에는 적용되지 않는다.
컴포넌트 스트리밍
- 컴포넌트로 비동기 함수를 감싸주면 해당 함수를 미완성, 로딩 상태로 남겨놓는 것이다.
- 쿼리스트링만 변경될 때에는 적용되지 않는다.
→ 해결법: key 값을 props로 두어 key 값이 변경될 때마다 스트리밍이 적용되도록 함.
- 하나의 페이지 내에서 여러 비동기 함수들을 스트리밍할 때 가장 유용하다
// page.tsx
return (
<Suspense key={q || ""} fallback={<div>Loading...</div>}>
<SearchResult q={q || ""} />
</Suspense>
);
에러핸들링
- 클라이언트 컴포넌트로 설정(서버 컴포넌트든, 클라이언트 컴포넌트든 실행이 되기위해)
- 적용하고싶은 파일과 같은 경로에 파일을 작성하면 된다.
'use client';
import { useRouter } from "next/navigation";
import { useEffect } from "react";
export default function Error({
error,
reset
}: {
error: Error;
reset:() => void
}) {
const router = useRouter();
useEffect(() => {
console.log(error.message);
}, [error])
return <div>
<h3>오류가 발생했습니다.</h3>
<button onClick={() => {
startTransition(() => {
router.refresh(); // 현재 페이지에 필요한 서버 컴포넌트를 다시 불러옴
reset(); // 에러 상태를 초기화, 컴포넌트들을 다시 렌더링
});
}}>다시 시도</button>
</div>
}