Published on

hydrate가 무엇인가요?(react, next.js)

Authors
  • 테크버킷
    Name
    테크버킷
    Twitter

서론

hydration failed because the initial ui does not match what was rendered on the server

Text content does not match server-rendered HTML

next.js 프로젝트를 다루다 보면 발견할 수 있는 에러입니다.최근에 next.js 프로젝트에서 hydrate와 관련된 에러를 많이 보게 되면서, 이 개념에 대해 좀 더 자세히 자세히 알고 싶어서 정리를 하게 되었습니다.

hydrate란?

리액트와 Next.js에서 "hydrate"는 서버에서 렌더링된 HTML 마크업에 기반하여 클라이언트 측에서 자바스크립트 이벤트와 상태를 연결하는 과정을 말합니다.이를 통해 초기 로딩 시 클라이언트에서 즉시 상호작용이 가능하고, 이후에는 일반적인 리액트 애플리케이션처럼 동작할 수 있습니다.

hydrate이 없다면 서버측에서 렌더링된 HTML을 무시하고 클라이언트 측에서 불필요하게 새로 렌더링을 해야 할 것입니다. 하지만 Hydrate을 통해 이러한 과정을 효율적으로 처리하게 됩니다.

리액트 App이 렌더링되는 과정

리액트 애플리케이션은 기본적으로 클라이언트 렌더링 방식으로 실행됩니다. 서버로부터 빈 페이지를 받고, 모든 렌더링이 브라우저에서 발생합니다.

반면에 Next.js와 같은 프레임워크에서는 서버에서 렌더링된 HTML을 클라이언트로 보내고, 클라이언트에서는 해당 HTML을 가져와 자바스크립트 이벤트와 상태를 연결합니다.

이런 방식을 서버 사이드 렌더링(SSR)이라고 합니다. 이런 과정은 Next.js에서는 "hydrate"라는 메서드로 이루어집니다.

hydrate는 서버에서 렌더링된 HTML을 가져와 기존 클라이언트에 이미 존재하는 마크업과 일치시키기 위해 사용됩니다.

기존 마크업은 서버에서 렌더링될 때 생성되고, 클라이언트에서는 기존 마크업과 일치하는 컴포넌트를 찾아 이벤트 처리 및 상태 업데이트를 연결합니다.

이렇게 하면 초기 로딩 시 사용자는 이미 렌더링된 컨텐츠를 볼 수 있으며, 자바스크립트 이벤트와 상태 관리를 통해 동적인 상호작용을 제공할 수 있습니다.

이러한 과정을 순서대로 정리하면 이렇습니다.

  1. 서버에서는 Next.js를 사용하여 리액트 애플리케이션을 렌더링하고, 생성된 HTML을 클라이언트로 전송합니다.
  2. 클라이언트에서는 전송된 HTML을 가져와서 기존 마크업과 일치시킵니다.
  3. 일치하는 컴포넌트를 찾아 해당 컴포넌트의 이벤트 처리 및 상태 업데이트를 활성화합니다.
  4. 클라이언트에서는 이제 일반적인 리액트 애플리케이션처럼 동작하며, 상호작용과 상태 변화에 따라 UI를 업데이트할 수 있습니다.

리액트의 Hydration 문서 또는 The Perils of Hydration 에서 더 자세한 내용을 확인할 수 있습니다.

게시판 렌더링 예시

서버 측에서 Next.js로 렌더링된 페이지가 있고, 이 페이지에는 게시판이 포함되어 있다고 가정해 봅시다. 이 HTML은 클라이언트로 전송되고, 클라이언트에서는 hydrate를 사용하여 초기 상태와 이벤트 처리를 설정합니다.

1. 서버 렌더링

  • 서버에서는 Next.js를 사용하여 페이지를 렌더링하고, 게시판의 데이터를 가져옵니다.
  • 렌더링된 페이지의 마크업과 데이터는 HTML로 생성되어 클라이언트로 전송됩니다.

접속하면 서버는 게시판의 데이터를 가져와 새 게시판을 HTML로 렌더링합니다. 렌더링한 HTML을 클라이언트로 전송합니다.

2. 클라이언트 hydrate

  • 클라이언트에서는 서버에서 전송받은 HTML을 가져옵니다.
  • 클라이언트에서는 리액트와 Next.js를 초기화하고, hydrate를 실행합니다.
  • hydrate는 가져온 HTML과 클라이언트 측에서 생성되는 컴포넌트의 마크업을 일치시킵니다.

클라이언트는 서버에서 전송받은 HTML을 화면에 보여줍니다.유저는 화면에서 게시글을 볼 수 있게 됩니다. (이때, 클라이언트 측에서 hydrate가 수행됩니다)

3. 컴포넌트 매칭 및 이벤트 처리

  • hydrate는 일치하는 컴포넌트를 찾아 이벤트 처리와 상태 업데이트를 활성화합니다.
  • 예를 들어, 게시판 목록을 표시하는 컴포넌트를 찾을 수 있습니다.
  • 클라이언트에서는 해당 컴포넌트의 이벤트 처리기를 등록하고, 사용자의 상호작용에 대응하여 UI를 업데이트합니다.

클라이언트 측에서는 전송받은 HTML을 분석하여 기존에 렌더링된 마크업과 일치하는 컴포넌트를 찾습니다. 예를 들어, 게시글 목록을 보여주는 컴포넌트를 찾을 수 있습니다. 이 컴포넌트에는 클릭 이벤트나 상태 업데이트와 관련된 로직이 포함될 수 있습니다. 즉, 클라이언트에서는 해당 컴포넌트의 이벤트 핸들러를 등록하고, 필요한 경우 상태를 업데이트하여 동적으로 UI를 조작할 수 있게 됩니다.

4. 동적 상호작용

  • 초기 렌더링 후에는 클라이언트에서 동적인 상호작용을 제공할 수 있습니다.
  • 예를 들어, 사용자가 게시글을 클릭하면 해당 게시글의 세부 정보를 가져와 UI를 업데이트할 수 있습니다.
  • 또는 사용자가 새로운 게시글을 작성하면 클라이언트에서 http 요청을 통해 서버에 데이터를 전송하고, UI에 새로운 게시글을 추가할 수 있습니다.

클라이언트 측에서는 매칭된 컴포넌트를 기반으로 사용자의 클릭 등의 이벤트에 응답하여 새로운 데이터를 가져오거나 상태를 업데이트하여 UI를 동적으로 변경할 수 있습니다.

정리

다시 정리하면, hydrate는 서버 렌더링된 HTML을 가져와 클라이언트에서 리액트 애플리케이션을 초기화하고, 상호작용 가능한 동적인 UI를 제공하는 과정을 의미합니다. 이와 같이 hydrate를 사용하면 초기 로딩 시에는 서버에서 렌더링된 HTML을 가져와서 빠르게 사용자에게 보여줄 수 있습니다. 이후에는 클라이언트에서 동적인 상호작용을 제공하고, 서버와의 데이터 통신을 통해 UI를 업데이트할 수 있습니다. 이를 통해 사용자는 빠른 초기 로딩과 원활한 상호작용을 경험할 수 있습니다.

문제가 되는 경우

hydrate가 잘 못 되면 어떻게 될까요? hydration이 실패했다는 메시지는 왜 나오는걸까요. hydrate를 사용하려면 서버에서 렌더링된 HTML과 클라이언트에서 생성되는 컴포넌트의 마크업이 일치해야 합니다. 일치하지 않는 경우에는 에러가 발생할 수 있습니다.

Next.js의 공식 문서의 Text content does not match server-rendered HTML에서도 이 문제를 따로 다루고 있습니다. 이 문서에서는 window의 유무에 따라 렌더링하는 경우, p 안에 div를 중첩시키는 경우를 흔히 발생하는 문제로 소개하고 있습니다. 이러한 경우에 서버 사이드에서 렌더링한 html과 클라이언트 사이드에서 렌더링한 html이 일치하지 않게 되어 hydrate가 실패하게 됩니다.

관련 개념

hydrate를 이해하기 위해 필요한 관련 개념들을 소개합니다. 기본적인 용어이긴 하지만 이해를 돕기 위해 간단히 정리하였습니다.

  1. 리액트(React) 페이스북에서 개발한 UI 라이브러리로, 컴포넌트 기반의 사용자 인터페이스를 구축하는 데 사용됩니다. hydrate는 리액트 애플리케이션에서 서버에서 생성된 HTML과 클라이언트에서 생성되는 컴포넌트를 일치시키는 데에 활용됩니다.

  2. 리액트 돔(React DOM) 리액트 애플리케이션을 브라우저에 렌더링하는 데 사용되는 리액트의 패키지입니다. hydrate는 ReactDOM.hydrate() 메서드를 사용하여 클라이언트 측에서 hydrate를 수행합니다. ReactDOM.render() 메서드는 새로운 마운트를 수행할 때 사용됩니다.

  3. 서버 사이드 렌더링(Server-Side Rendering, SSR) 리액트 애플리케이션을 서버에서 초기 렌더링하여 HTML을 생성하는 접근 방식입니다. hydrate는 서버 사이드 렌더링과 관련하여 서버에서 생성된 HTML과 클라이언트 측의 리액트 애플리케이션을 연결합니다.

  4. 클라이언트 측 렌더링(Client-Side Rendering, CSR) 리액트 애플리케이션의 초기 렌더링 및 상호작용이 클라이언트 측에서 이루어지는 접근 방식입니다. CSR은 서버에서 렌더링된 HTML을 가져와 클라이언트에서 자바스크립트를 사용하여 애플리케이션을 초기화합니다. hydrate는 CSR과 관련하여 초기 상태 및 이벤트 처리를 설정하고 클라이언트 측에서 동적인 UI를 제공합니다.

  5. 초기 상태(Initial State) 리액트 애플리케이션의 상태의 초기 값입니다. hydrate를 사용하여 클라이언트에서 초기 상태를 설정하고, 이후에는 상태를 업데이트하여 UI를 동적으로 변경할 수 있습니다.

  6. 이벤트 처리(Event Handling) 사용자의 상호작용에 대응하기 위해 클라이언트에서 이벤트 핸들러를 등록하고 관리하는 과정입니다. hydrate를 사용하여 클라이언트에서 이벤트 처리를 활성화하고, 이벤트가 발생하면 해당 이벤트에 대한 처리를 수행할 수 있습니다.