기회가 생겨 Next.js 프레임워크를 사용한 3페이지 정도의 간단한 프로젝트를 작업하게 됐어요.
가입 화면(일반/등록 회원 구분) -> 항목 목록 -> 항목 등록 흐름의 페이지 였어요.
json-server 를 띄우는 형식으로 항목 DB json 파일을 관리하고,
회원 구분과 정보는 js cookie 를 사용해 저장하는 형식입니다.
대부분 문제 없이 작업했는데, Next.js가 처음이라 이해도가 부족해 생긴 이슈가 몇가지 있어 기록합니다.
Next.js 는 SSR 을 지원하는 프레임워크예요.
그래서 컴포넌트가 서버와 클라이언트로 구분돼요.
명시적으로 'use client' 선언을 하지 않으면 서버 컴포넌트로 취급 되며,
클라이언트 컴포넌트를 선언해야 상태관리와 라이프 사이클 로직, 이벤트 핸들러를 사용할 수 있습니다.
이번에 metaData 도 설정해보았는데, metaData 의 경우는 Server 컴포넌트에서만 설정할 수 있었어요.
그래서 page.tsx 를 서버 컴포넌트로 두고, 페이지에 해당하는 클라이언트 컴포넌트는 분리하는 패턴으로 구조를 잡았습니다.
파일 루트 레벨에서 queryClient를 생성하면 모든 요청 간에 캐시가 공유되어, 모든 데이터가 모든 사용자에게 전달됩니다. 이는 성능에 나쁠 뿐만 아니라 민감한 데이터를 유출시킬 수 있습니다.
https://tanstack.com/query/latest/docs/framework/react/guides/ssr
export default function MyApp({ Component, pageProps }) {
// 각 요청마다 고유한 캐시를 보장
const [queryClient] = React.useState(
() => new QueryClient({
defaultOptions: {
queries: {
staleTime: 60 * 1000,
},
},
})
)
return (
<QueryClientProvider client={queryClient}>
<Component {...pageProps} />
</QueryClientProvider>
)
}
파일 레벨에서 queryClient를 생성하면 유저 데이터가 다른 유저에게 보일 수 있어요.
useState를 사용하면 컴포넌트 라이프사이클마다 새 인스턴스를 만들어 방지할 수 있다고 tanstack query 공식 문서에 적혀 있어 참고해서 수정했습니다.
일반적인 프로젝트면 유저정보를 Cookie에 넣지는 않겠지만, 적시적인 구현을 위해 임시로 사용했던 Cookie 에서 오류가 발생했어요.
목록에 대한 스켈레톤을 구현하다 발생한 에러인데,
Cookie 값에 따라 버튼 렌더링 여부를 결정하는 부분이 있어 Cookies.get()이 서버 렌더링 시점과 클라이언트 hydration 시점에 다른 값을 반환했기 때문에 값의 타입을 읽을 수가 없는 문제가 있었어요.
useEffect(() => {
setUserType(Cookies.get(DATA_KEY_USER_TYPE));
}, []);
이 문제는 useState + useEffect로 클라이언트에서만 쿠키를 읽도록 처리해서 해결했습니다.
Next.js 는 하이드레이션 이라는 과정으로 서버에서 미리 렌더링 된 HTML을 브라우저로 전송하고 클라이언트에서 컴포넌트를 재구성해요.
그래서 SEO 최적화가 가능한 건데, 이 때 서버 렌더링 내용과 클라이언트 첫 렌더링 내용이 다르면 에러가 발생하니 이 부분을 주의해야 했습니다.