[Next.js] CSR에서 SSR로 마이그레이션 하기
개요
Next.js 에서 애플리케이션의 성능과 SEO를 개선하기 위해 클라이언트 사이드 렌더링(CSR)에서 서버 사이드 렌더링(SSR)으로 전환한 경험을 공유합니다.
왜 SSR인가?
- 성능: SSR은 서버에서 콘텐츠를 미리 렌더링하여 첫 번째 바이트 시간(TTFB)을 크게 줄일 수 있습니다.
- SEO: 검색 엔진이 미리 렌더링된 페이지를 쉽게 인덱싱할 수 있어 애플리케이션의 검색 엔진 순위가 향상됩니다.
- 사용자 경험: SSR은 초기 로드 시간을 단축하여 전반적인 사용자 경험을 향상시킵니다.
도전 과제
- 데이터 페칭: 서버에서 데이터를 페칭하고 클라이언트에 전달하는 것이 주요 과제 중 하나였습니다.
- 상태 관리: 서버 렌더링된 상태와 클라이언트 렌더링된 상태 간의 일관성을 유지하는 것이 중요했습니다.
- 조건부 렌더링: 특정 컴포넌트가 클라이언트 사이드 상태에 의존하는 시나리오를 처리해야 했습니다.
구현 단계
1. getStaticProps 및 getServerSideProps를 사용한 데이터 페칭
Next.js는 정적 생성(getStaticProps) 및 서버 사이드 렌더링(getServerSideProps)을 제공합니다.
getServerSideProps를 사용하는 예제입니다
export async function getServerSideProps() {
const res = await fetch('https://api.example.com/data');
const data = await res.json();
return {
props: {
initialData: data,
},
};
}
const HomePage = ({ initialData }) => {
return (
<div>
<h1>서버 사이드 렌더링된 페이지</h1>
<pre>{JSON.stringify(initialData, null, 2)}</pre>
</div>
);
};
export default HomePage;
2. React Query를 사용한 상태 관리
서버 상태를 관리하고 캐싱, 페칭, 동기화를 처리하기 위해 React Query를 사용했습니다.
React Query를 SSR과 통합하는 방법입니다
import { Hydrate, QueryClient, QueryClientProvider } from 'react-query';
import { useState } from 'react';
function MyApp({ Component, pageProps }) {
const [queryClient] = useState(() => new QueryClient());
return (
<QueryClientProvider client={queryClient}>
<Hydrate state={pageProps.dehydratedState}>
<Component {...pageProps} />
</Hydrate>
</QueryClientProvider>
);
}
export default MyApp;
// pages/index.js
import { dehydrate, QueryClient, useQuery } from 'react-query';
export async function getServerSideProps() {
const queryClient = new QueryClient();
await queryClient.prefetchQuery('data', async () => {
const res = await fetch('https://api.example.com/data');
return res.json();
});
return {
props: {
dehydratedState: dehydrate(queryClient),
},
};
}
const HomePage = () => {
const { data } = useQuery('data', async () => {
const res = await fetch('https://api.example.com/data');
return res.json();
});
return (
<div>
<h1>React Query와 함께하는 서버 사이드 렌더링된 페이지</h1>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
};
export default HomePage;
반응형
3.로딩 상태를 위한 Skeleton View 구현
데이터를 페칭하는 동안 사용자 경험을 개선하기 위해 Skeleton View를 구현했습니다.
이 placeholder 요소는 콘텐츠가 로드 중임을 시각적으로 나타냅니다.
import styled, { keyframes } from 'styled-components';
const gradient = keyframes`
0% {
background-position: 0% 100%;
}
100% {
background-position: 100% 0%;
}
`;
const SkeletonContainer = styled.div`
display: flex;
flex-direction: column;
align-items: center;
width: 100vw;
height: 100vh;
padding: 20px;
`;
const SkeletonElement = styled.div`
width: ${(props) => props.width || '80%'};
height: ${(props) => props.height || '20px'};
margin-top: 20px;
border-radius: 4px;
background: linear-gradient(
-45deg,
#f0f0f0,
#e0e0e0,
#f0f0f0,
#e0e0e0
);
background-size: 400% 400%;
animation: ${gradient} 1.5s ease-in-out infinite;
`;
const SkeletonView = () => (
<SkeletonContainer>
<SkeletonElement height="50px" />
<SkeletonElement height="200px" />
<SkeletonElement height="200px" />
<SkeletonElement height="50px" />
</SkeletonContainer>
);
export default SkeletonView;
4. Fallback 상태 처리
마지막으로, 메인 페이지를 업데이트하여 데이터 페칭 중에 Skeleton View를 표시합니다.
// pages/index.js
import { useRouter } from 'next/router';
import SkeletonView from '../components/SkeletonView';
const HomePage = ({ initialData }) => {
const router = useRouter();
if (router.isFallback) {
return <SkeletonView />;
}
return (
<div>
<h1>서버 사이드 렌더링된 페이지</h1>
<pre>{JSON.stringify(initialData, null, 2)}</pre>
</div>
);
};
export default HomePage;
결론
우리의 React 애플리케이션에서 CSR에서 SSR로 전환한 것은 성능과 SEO를 개선하기 위한 중요한 단계였습니다. Next.js와 React Query를 활용하여 데이터 페칭과 상태 관리의 도전 과제를 해결할 수 있었습니다. Skeleton View를 구현하여 로딩 상태 동안 사용자가 더 나은 경험을 할 수 있도록 했습니다. 이 전환은 애플리케이션의 효율성을 향상시킬 뿐만 아니라 사용자 경험도 개선했습니다.
참고자료
'React' 카테고리의 다른 글
[Next.js] 다국어 지원과 동적 텍스트 렌더링에 필요한 Trans 컴포넌트 (0) | 2024.08.28 |
---|---|
[React] 브라우저 크기 조정 성능 개선 (0) | 2024.07.28 |
[React] 브레이크포인트를 활용한 반응형 웹 디자인 (0) | 2024.06.01 |
[React] Next.js 관련 면접 질문 및 답변 가이드 (0) | 2023.07.13 |
[React] JWT (JSON Web Tokens)에 대하여 (0) | 2023.07.04 |
댓글