서버 컴포넌트 - 웹 스토리지 API 등


03.13(수) ~ 03.14(목)

✨ 정렬 기능

처음 구현한 로직은 먼저 전체 리스트를 불러온 다음, 자바스크립트 함수로 배열을 정렬시켜 목록을 렌더링하게 코드를 작성했다.

그런데 위와 같이 하면 페이지네이션을 구현할 때 상당히 귀찮은 작업을 해야돼서,

애초에 서버에서 정렬된 리스트를 불러오게 바꿨다.

react-query를 사용하면 페이지네이션이나 무한 스크롤 등을 쉽게 구현할 수 있다고 한다.

✨ localStorage is not defined 에러

서버 컴포넌트에서 localStorage에 접근하려고 하면 에러가 나온다.

서버에서는 localStorage가 정의되지 않는다.

그런데, 클라이언트 컴포넌트에서도 단순히 localStorage.getItem() 으로 접근하면 not defined 에러가 나온다.

왜냐하면, 클라이언트 컴포넌트도 일단! 서버에서 먼저 렌더링 되기 때문이다. 그리고 나서 hydration 된다.

hydration: 정적 html을 로드하고나서, js, react를 적용해 interactive한 요소들로 채워지는 과정

그러면 어떻게 localStorage 쓰는데?

1const getSavedNotice = (): Notice[] => {
2  if (typeof window !== 'undefined') {
3    const storedNotices = sessionStorage.getItem('recentNotices');
4    return storedNotices ? JSON.parse(storedNotices) : [];
5  }
6  return [];
7};

서버에서 렌더링 될때는 if문 내에 있는 코드를 실행하지 않는다.

하지만 서버에서 빈 배열을 이용해 렌더링 되고, 이후 클라이언트에서 localStorage에서 가져온 배열로 렌더링 하게 되어 서버에서 보여주는 데이터와 클라이언트에서 보여주는 데이터가 서로 다른 경우 가 되어버렸다. content did not match 오류도 보이게 될 것이다.

해결방법

useEffect를 이용해 서버에서 렌더링을 하지 않게 해서 오류를 해결했다.

하지만 불필요한 렌더링을 발생시켜 성능에 악영향을 미칠 수 있을지도?

next/dynamic Skipping SSR

1'use client';
2
3import dynamic from 'next/dynamic';
4
5type Props = { children: JSX.Element };
6
7const NoSSRRendering = ({ children }: Props) => {
8  return children;
9};
10
11export default dynamic(() => Promise.resolve(NoSSRRendering), {
12  ssr: false,
13});
1<NoSSRRendering>
2	<SomeClientOnlyComponent />
3</NoSSRRendering>

nextjs 공식 문서에 나와있는 SSR에서 pre-rendering을 하고 싶지 않을 때 사용하는 방법이다.

이를 이용하면 static HTML을 보여주는 단계에서는 rendering 되지 않다가, hydration 후에 렌더링 될 것이다.