@senspond

>

개발>프론트 엔드

NextJs - Text content did not match. Server : "A" Client: "B" 오류 해결

등록일시 : 2023-12-07 (목) 12:23
업데이트 : 2023-12-07 (목) 12:43
오늘 조회수 : 5
총 조회수 : 663

    NextJs - Text content did not match. Server : "A" Client: "B" 오류 를 만나고 해결한 방법을 정리

    문제 발단

    RgbitCode 블로그를 Nextjs 로 개발하면서 만나게 되었던 오류이다.


    테마 기능을 적용하면서 브라우저 콘솔에 다음과 같은 오류가 발생하였다.



    NextJS 는 서버사이드랜더링(SSR)을 지원하는 프레임워크이다. 기본적으로 Next.js는 모든 페이지를 사전 랜더링(pre-rendering)하게 된다. 이것은 Next.js가 미리 각 페이지별로 HTML을 생성한다는 것을 의미하며, 클라이언트 측의 자바스크립트로 모든 것을 수행하는 대신. 사전 랜더링을 통해 성능과 SEO가 향상될 수 있다.


    오류 원인

    서버에서 사전 랜더링한 HTML 과 클라이언트에서 랜더링한 HTML이 서로 불일치 하기 때문에 발생하였기 때문이다.



    해결 방법

    서버에서 사전랜더링 한 HTML과 클라이언트가 랜더링한 HTML가 일치되도록 클라이언트,서버간 상태를 공유할 수 있도록 구현을 하거나

    서버에서 랜더링을 하지 않고 클라이언트에서만 랜더링 하도록 컴포넌트를 작성하면 된다. 여기서는 오류를 무시하거나 클라이언트에서만 랜더링 되도록 하는 방법으로 정리해보았다.


    suppressHydrationWarning 로 무시하기

    • 에러로그를 출력을 하지 않도록 해버리는 방법이다. 문제를 발생시키는 컴포넌트에 suppressHydrationWarning를 달아주면 된다. 그러나 에러로그를 무시해버리는 방법이기에 권장되는 방법은 아니다.

    <Component suppressHydrationWarning />


    useEffect 를 사용하는 방법

    • useEffect를 사용해 client에서만 랜더링 되도록 만드는 방법이다.

    export default function Home() {
        const cook = new Cookies();
        const [session, setSession] = useState();
        
        // `setCookie` and `deleteCookie` code here
    
        useEffect(() => {
            setSession(cook.get("key"));
        }, []);
    
        return (
            <div className={styles.container}>
                <button onClick={() => setCookie()}>Save Cookie</button>
                <button onClick={() => deleteCookie()}>Delete Cookie</button>
                {session ? <>I'm in</> : <>I'm out</>}
            </div>
        );
    }

    next dynamic import(ssr : false)

    • nextjs 에서 지원하는 dynamic import {ssr : false} 를 통하는 방법이다. 구성요소가 서버에 포함되지 않고 클라이언트 측에서만 동적으로 로드되도록 만드는 것이다.

    const Home = dynamic(
        () => import('../components/Home'),
        { ssr: false }
    )


    필자가 적용한 방법

    'use client';
    
    import dynamic from 'next/dynamic';
    
    type Props = { children: JSX.Element };
    
    const NoSSRRendering = ({ children }: Props) => {
      return children;
    };
    
    export default dynamic(() => Promise.resolve(NoSSRRendering), {
      ssr: false,
    });

    필자는 위와 같은 공통 컴포넌트를 구현하고 서버에서 사전랜더링이 필요하지 않은 컴포넌트에는 다음과 같이 감싸주기로 했다. 이런 오류를 만날때마다 또 반복적인 코드를 작성하는것이 귀찮기 때문이었다.



    참고문헌

    이글은 아래 링크의 글을 참고하여 작성되었습니다.

    https://stackoverflow.com/questions/66374123/warning-text-content-did-not-match-server-im-out-client-im-in-div

    senspond

    안녕하세요. Red, Green, Blue 가 만나 새로운 세상을 만들어 나가겠다는 이상을 가진 개발자의 개인공간입니다.

    댓글 ( 0 )

    카테고리내 관련 게시글

    현재글에서 작성자가 발행한 같은 카테고리내 이전, 다음 글들을 보여줍니다

    @senspond

    >

    개발>프론트 엔드

    • [현재글] NextJs - Text content did not match. Server : "A" Client: "B" 오류 해결

      NextJs - Text content did not match. Server : "A" Client: "B" 오류 를 만나고 해결한 방법을 정리
        2023-12-07 (목) 12:23
      1. 제이쿼리(JQuery) AJAX 요청 문법 정리

        제이쿼리(JQuery) AJAX 요청 문법 정리한 글입니다
          2023-10-30 (월) 01:57
        1. NextJs 에서 동적으로 Sitemap 만드는 방법

          이번 글에는 React 기반으로 만들어진 NextJs 프레임워크에서 동적으로 Sitemap 만드는 방법에 대해서 정리해보고 현재 발견한 문제점에 대해서 적어보려고 합니다.
            2024-01-03 (수) 05:33
          1. NextJs 프로젝트에 Jest 테스트 프레임워크 적용하기

            Jest는 메타(구 페이스북)가 유지보수하는 재스민(jasmine) 위에서 빌드되는 테스팅 프레임워크입니다. 이 글은 NextJs 프로젝트에 Jset 프레임워크를 적용하는 방법을 정리해봅니다.
              2024-01-19 (금) 11:32