Let's kick it

[React 5일차]Next.js App Router에서 중첩 레이아웃의 HTML 구조 오류 해결하기 본문

트러블 슈팅 기록

[React 5일차]Next.js App Router에서 중첩 레이아웃의 HTML 구조 오류 해결하기

bloggerddori 2025. 5. 14. 20:19

오류 메세지

In HTML,  cannot be a child of . This will cause a hydration error.

 

[src/app/layout.js] - 루트 레이아웃

 

[src/app/chap01/layout.js] - 오류 발생 코드 (수정 전)

 

원인 분석

Next.js App Router에서는 HTML 문서의 구조가 매우 중요합니다. 특히 <html><body> 태그는 전체 애플리케이션에서 오직 한 번만 정의되어야 합니다.

이 오류는 루트 레이아웃(src/app/layout.js)에서 이미 <html><body> 태그를 정의했는데, 중첩 레이아웃(src/app/chap01/layout.js)에서 또 다시 이 태그들을 사용했기 때문에 발생했습니다.

결과적으로 HTML 구조가 다음과 같이 중첩되는 문제가 발생합니다:

<html> (루트 레이아웃에서)
  <body> (루트 레이아웃에서)
    <html> (중첩 레이아웃에서) - 문제 발생!
      <body> (중첩 레이아웃에서) - 문제 발생!
        ...
      </body>
    </html>
  </body>
</html>

이런 구조는 HTML 명세에 위배되며, React가 클라이언트 측에서 렌더링(hydration)할 때 서버에서 생성된 HTML과 일치하지 않아 오류가 발생하게 됩니다.


[src/app/chap01/layout.js] - 수정 후 코드

해결 방법

이 문제의 해결책은 간단합니다. 중첩 레이아웃인 src/app/chap01/layout.js에서 <html><body> 태그를 제거하고, Redux Provider만 반환하도록 수정하면 됩니다.

Next.js App Router에서는 루트 레이아웃(src/app/layout.js)에서만 <html><body> 태그를 정의해야 하며, 하위 레이아웃에서는 이러한 태그를 사용하지 않아야 합니다. 이렇게 수정하면 HTML 구조가 정상적으로 구성되어 hydration 오류가 해결됩니다.

수정 전과 후의 코드를 비교해보면, 단순히 태그를 제거하는 것만으로도 오류가 해결된 것을 확인할 수 있습니다.


배운 점

이 문제를 해결하면서 Next.js App Router의 레이아웃 구조에 대해 더 깊이 이해하게 되었습니다:

  1. 레이아웃 계층 구조: Next.js App Router에서는 레이아웃이 중첩될 수 있지만, HTML 문서의 기본 구조(<html>, <body>)는 최상위 루트 레이아웃에서만 정의해야 합니다.
  2. Hydration의 중요성: React의 hydration 과정은 서버에서 렌더링된 HTML과 클라이언트에서 렌더링하려는 구조가 일치해야 합니다. 구조가 일치하지 않으면 오류가 발생합니다.
  3. 오류 메시지의 이해: "In HTML, <html> cannot be a child of <body>"라는 오류 메시지는 HTML 구조가 잘못되었음을 명확히 알려줍니다.

이러한 경험은 Next.js로 개발할 때 레이아웃 구성의 중요성과 HTML 구조를 올바르게 유지해야 한다는 점을 상기시켜 줍니다. 특히 Redux와 같은 상태 관리 라이브러리를 통합할 때는 적절한 위치에 Provider를 배치하는 것이 중요합니다.