Client-side Rendering (CSR)
React를 사용한 클라이언트 사이드 렌더링 (CSR)에서는 브라우저가 최소한의 HTML 페이지와 페이지에 필요한 자바스크립트를 다운로드 합니다. 그 후 자바스크립트는 DOM을 업데이트하고 페이지를 렌더링하는 데 사용됩니다. 애플리케이션이 처음 로드될 때, 사용자가 전체 페이지를 보기 전에 약간의 지연을 느낄 수 있습니다. 이는 모든 자바스크립트가 다운로드, 파싱 및 실행될 때까지 페이지가 완전하게 렌더링 되지 않기 때문입니다.
페이지가 처음 로드된 후, 같은 웹사이트에서 다른 페이지로 이동할 때는 일반적으로 더 빠릅니다. 필요한 데이터만 가져오면 되고, 자바스크립트가 전체 페이지를 새로 고칠 필요 없이 페이지의 일부를 다시 렌더링할 수 있기 때문입니다.
Next.js에서는 클라이언트 사이드 렌더링을 구현할 수 있는 두 가지 방법이 있습니다.
- 서버 사이드 렌더링 메서드 (
getStaticProps
와getServerSideProps
) 대신에 페이지 내부에서 리액트의useEffect()
훅을 사용합니다. - SWR (opens in a new tab)이나 TanStack Query (opens in a new tab)와 같은 데이터 페칭 라이브러리를 사용하여 클라이언트에서 데이터를 가져옵니다 (권장됨).
다음은 Next.js 페이지 내부에서 useEffect()
를 사용하는 예시입니다.
import React, { useState, useEffect } from 'react'
export function Page() {
const [data, setData] = useState(null)
useEffect(() => {
const fetchData = async () => {
const response = await fetch('https://api.example.com/data')
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`)
}
const result = await response.json()
setData(result)
}
fetchData().catch((e) => {
// 필요에 따라 에러 처리
console.error('An error occurred while fetching the data: ', e)
})
}, [])
return <p>{data ? `Your data: ${data}` : 'Loading...'}</p>
}
위 예시에서, 컴포넌트는 Loading...
을 렌더링하며 시작합니다. 그런 다음 데이터가 불러와지면 다시 렌더링하여 데이터를 표시합니다.
useEffect
에서 데이터를 가져오는 것은 이전 React 애플리케이션에서 볼 수 있는 패턴이지만, 더 나은 성능, 캐싱, 낙관적 업데이트 등을 위해 데이터 페칭 라이브러리를 사용하는 것을 권장합니다. 다음은 클라이언트에서 데이터를 가져오기 위해 SWR (opens in a new tab)을 사용하는 최소한의 예시입니다:
import useSWR from 'swr'
export function Page() {
const { data, error, isLoading } = useSWR(
'https://api.example.com/data',
fetcher,
)
if (error) return <p>Failed to load.</p>
if (isLoading) return <p>Loading...</p>
return <p>Your Data: {data}</p>
}
알아두면 좋은 점:
클라이언트 사이드 렌더링은 SEO에 영향을 줄 수 있음을 유념해야 합니다. 일부 검색 엔진 크롤러는 자바스크립트를 실행하지 않을 수 있기 때문에 애플리케이션의 초기 빈 상태 혹은 로딩 상태만 볼 수 있습니다. 또한 인터넷 연결이나 장치 속도가 느린 사용자들에게는 성능 문제를 일으킬 수 있는데, 전체 페이지를 볼 수 있기 전에 모든 자바스크립트가 로드되고 실행될 때까지 기다려야 하기 때문입니다. Next.js는 애플리케이션에서 각 페이지의 필요에 따라 서버 사이드 렌더링, 정적 사이트 생성 그리고 클라이언트 사이드 렌더링을 조합하여 사용할 수 있는 하이브리드 접근 방식을 권장합니다. App Router에서는 Loading UI with Suspense를 사용하여 페이지가 렌더링 되는 동안 로딩 표시기를 표시할 수도 있습니다.