사전 렌더링이란?
브라우저의 요청에 미리 렌더링된 HTML을 응답하는 방식으로 SEO 성능이 향상되고 리액트의 CSR의 단점을 효율적으로 보완하는 기술입니다. Next 사전렌더링은 SSR과 SSG 두 가지 방식으로 제공됩니다.
CSR의 단점?

기존 React는 위의 그림과 같은 순서로 유저에게 화면을 제공했습니다.
클라이언트 의존적
유저의 화면에 웹사이트를 보여주는것은 굉장히 많은 과정을 거쳐 이루어지게 됩니다. 이 과정은 HTML 파싱, CSSOM 파싱, 레이아웃 구성, 페인팅 등 이 모든 과정을 클라이언트에 의존하고 있습니다.
CSR의 장단점을 클라이언트와 서버의 입장에서 이해해보기
클라이언트 입장
-
장점
- 빠른 인터랙션
CSR에서는 초기 HTML이 로드된 후, 필요한 자바스크립트를 다운로드한 다음 클라이언트에서 렌더링을 하므로, 이후 페이지 간 전환이 빠릅니다.
- 더 나은 사용자 경험
페이지 전환 시 전체 페이지를 다시 로드하지 않고, 데이터만 갱신하기 때문에 부드러운 네비게이션을 제공합니다.
- 풍부한 UI와 애니메이션
브라우저에서 자바스크립트를 사용해 직접적으로 UI를 조작할 수 있어 복잡한 애니메이션이나 UI 상태 관리를 효율적으로 처리할 수 있습니다.
-
단점
- 초기 로딩 속도
클라이언트가 필요한 모든 자바스크립트를 다운로드하고 실행해야 하기 때문에, 초기 로딩이 느려질 수 있습니다. 특히 자바스크립트 번들이 클 경우 페이지가 느리게 시작됩니다
- SEO 최적화 어려움
CSR은 클라이언트에서 렌더링되기 때문에 초기 HTML에는 콘텐츠가 없고, 이는 검색 엔진 크롤러가 페이지의 콘텐츠를 제대로 인덱싱하지 못할 가능성을 높입니다. 이는 SEO(검색엔진최적화)에 불리할 수 있습니다.
- 자바스크립트 의존성
클라이언트 측에서 자바스크립트를 사용하여 렌더링하기 때문에 자바스크립트가 비활성화된 브라우저나 네트워크 연결 상태가 나쁜 환경에서는 문제가 발생할 수 있습니다.
서버 입장
- 장점
- 부담 감소
서버는 클라이언트에게 HTML을 거의 빈 상태로 전송하고, 이후 클라이언트가 자바스크립트를 통해 콘텐츠를 로드하고 렌더링하기 때문에 서버 부담이 줄어듭니다. 이는 대규모 사용자 요청을 처리할 때 서버 부하를 줄이는 데 도움이 됩니다.
- 스케일링에 유리
CSR은 클라이언트에서 대부분의 작업이 이루어지기 때문에 서버의 리소스를 많이 요구하지 않으므로 더 많은 사용자에게 서비스를 제공할 수 있습니다.
- 단점
- 초기 페이지 전달 비용 증가
서버에서 초기 HTML, CSS, 자바스크립트 파일을 한 번에 전달해야 하므로 초기 페이지 로딩 속도가 느려질 수 있습니다. 특히 대규모 애플리케이션에서는 첫 로딩 시간이 길어질 수 있습니다.
- SEO 문제
서버가 초기 페이지 렌더링을 하지 않기 때문에, HTML을 그대로 제공하면 검색 엔진이 해당 페이지의 콘텐츠를 인식하기 어려워 검색 엔진 최적화에 불리할 수 있습니다. 이를 보완하기 위해 SSR(Server-Side Rendering)이나 하이브리드 방식(Next.js 같은)을 추가적으로 도입하는 경우가 많습니다.
Next JS의 사전렌더링

Next는 리액트 CSR의 장점인 빠른 인터렉션과 더 나은 사용자 경험을 유지하고 단점인 SEO 최적화와 초기 로딩속도를 개선하기위해 위와 같은 방식으로 사용자에게 화면을 제공합니다.
-
FCP 개선
리액트의 치명적인 단점인 초기 로딩 속도를 개선하기위해 서버에서 HTML을 파싱 ( 렌더링 ) 하여 정적인 HTML을 클라이언트에게 먼저 제공합니다. 추 후 해당 페이지에 필요한 JS 코드를 번들링하여 정적인 HTML 파일에 수화 합니다.
-
SEO 개선
리액트의 치명적인 단점인 SEO 최적화의 어려움을 사전에 정적인 HTML을 렌더링함으로 크롤러에게 잘 크롤링될 수 있도록합니다.
-
프리패칭
리액트의 장정인 빠른 인터렉션을 유지하기위해 최초 페이지의 수화가 끝난후에 현재 페이지에 연결된 모든 페이지의 JS 번들을 제공 받아 파싱합니다. 이 후 페이지의 이동은 리액트처럼 자연스럽게 진행됩니다.
단, 프리패칭은 <Link> 컴포넌트를 사용하여 라우팅해둔 페이지만 해당합니다.
아래와 같이 Link가 아닌 프로그래밍 적으로 페이지를 이동시킨다면 따로 프리패치를 해주어야합니다.
const router = useRouter();
const pushUserPage = () => {
router.push('/user')
}
useEffect(()=>{
router.prefetch('/user');
})