용어정리
- TTV(Time To View): 유저가 사이트를 볼 수 있는 타이밍
- TTI(Time To Interact): 유저가 인터렉트 할 수 있는 타이밍
- SEO(Search Engine Optimization): 검색 엔진 최적화. → 홈페이지가 검색엔진에 더 잘 노출되어 더 많은 유저가 접속할 수 있도록 합니다.
렌더링 방식
CSR: Client Side Rendering

동작 방식
- 서버에서 브라우저로 응답(빈 HTML(<div id=”root”>만 있음) + 연결된 JS 링크(리액트 코드))을 보냅니다.
- 브라우저에서 (연결된)JS를 다운로드 받습니다.
- 브라우저가 JS(리액트) 코드를 실행합니다.
- 페이지가 보이고 상호작용 할 수 있습니다.(TTI === TTV)
특징
- 클라이언트에서 전적으로 웹 렌더링(라우팅, 연산 등)을 책임집니다.
- 깜빡임 없이 부드러운 페이지 전환이 가능합니다.
- 페이지 렌더링을 위한 HTTP 통신이 필요없습니다.
- 첫 페이지 로딩이 느립니다.
- 전체 페이지 리소스를 한번에 불러오기 때문입니다.
- SEO 대응이 어렵습니다.
- 미리 html을 만들어 두는 것이 아니라, 요청에 따라 html을 동적으로 생성하기 때문입니다.
사용 시 체크리스트
- [ ] 검색엔진에 노출되지 않아도 되는(않아야 하는) 페이지인가?
- [ ] 유저와의 인터렉션이 잦은가?
- [ ] 화면 업데이트 / 렌더링이 잦은가?
- [ ] 초기 로딩속도 보다 부드러운 사용자 경험이 중요한가?
SSR: Server Side Rendering

동작 방식
- 서버는 렌더링할 준비가 된 HTML을 응답으로 브라우저에게 보냅니다.
- 브라우저는 페이지를 렌더링하고 이 때 페이지를 볼 수 있습니다.(TTV)
- 브라우저가 JS를 다운로드 받습니다.
- 브라우저가 React를 실행합니다.
- 페이지와 상호작용 할 수 있습니다.(TTI)
특징
- 브라우저가 서버에 페이지를 요청하면 서버에서 요청에 따라 구성된 HTML을 전송(렌더링) 합니다.
- 서버에서 매번 동적으로 페이지를 렌더링하기 때문에 서버 부하, 비용이 높아집니다.
- 페이지 전환시 깜빡임이 있어 부자연스럽습니다.
- 첫 페이지 로딩이 빠릅니다.
- CSR과 달리, 해당 요청의 HTML과 스크립트만 불러오기 때문입니다.
- SEO 대응이 가능합니다.
- 데이터가 매핑된 html이 pre-rendering되기 때문입니다.
사용 시 체크리스트
- [ ] 검색엔진에 노출되지 않아도 되는(않아야 하는) 페이지인가?
- [ ] 유저와의 인터렉션이 잦은가?
- [ ] 화면 업데이트 / 렌더링이 잦은가?
- [ ] 초기 로딩속도 보다 부드러운 사용자 경험이 중요한가?
SSG: Static Site Generation
동작 방식
- SSR과 동일하게 서버로부터 완성된 HTML을 받아옵니다.
- SSR과 다른 점은 HTML 파일 생성시점이 ‘요청’이 아닌 ‘빌드 타임’ 입니다.
특징
- build 시 고정된 데이터들을 모두 담은 정적 html 파일을 생성하여 재활용합니다.
- pre-render에 필요한 페이지의 개수만큼 정적파일이 생성됩니다.
사용 시 체크리스트
- [ ] 적용하려는 페이지에 업데이트가 없는가?
- [ ] 생성되는 정적파일의 개수가 너무 많지는 않은가?
ISR: Incremental Static Regeneration
동작 방식
- SSG에서 revalidate 옵션을 추가한 방식입니다.
- build 후 변하지 않는 SSG와는 달리, ISR은 설정에 따라 자동으로 데이터를 revalidate(재검증 및 업데이트)하고, rebuild합니다.
사용 시 체크리스트
- [ ] 적용하려는 페이지에 업데이트가 적은가?
Next.js에서 렌더링 방식 별 데이터 가져오기 예시
CSR
const Csr = () => {
const [users, setUsers] = useState([]);
useEffect(() => {
async () => {
const res = await fetch("url");
const users = await res.json();
setUsers(users);
};
}, []);
return (
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
};
export default Csr;
SSR
const Ssr = ({ users }) => {
return (
{/* CSR과 동일 */}
);
};
export const getServerSideProps = async () => {
const res = await fetch("api");
const users = await res.json();
return {
props: {
users,
},
};
};
export default Ssr;
SSG
const Ssg = ({ users }) => {
return (
{/* CSR과 동일 */}
);
};
export const **getStaticProps** = async () => {
{/* SSR과 동일 */}
};
export default Ssg;
ISR
const Isr = ({ users }) => {
return (
{/* CSR과 동일 */}
);
};
export const getStaticProps = async () => {
{/* SSR와 동일 */}
return {
props: {
users,
**revalidate: 10, // revalidate 속성을 준다는 점만 SSG와 다름**
},
};
};
export default Isr;
[참고자료]
'Next.js' 카테고리의 다른 글
| Optimistic UI(with SWR) 적용기 (0) | 2024.04.15 |
|---|---|
| 프로젝트 ‘공책’의 렌더링 (CSR vs SSR) (1) | 2024.04.15 |
| Next/Image (0) | 2024.04.13 |