Hydration
서버에서 생성한 HTML은 단순 마크업이므로 사용자 인터렉션이 불가능하다.
따라서 React 는 이벤트리스너, 상태관리와 같은 클라이언트 로직을 전달받은 HTML과 통합하여 애플리케이션으로 작동할 수 있도록 한다. 이과정을 `Hydration` 이라 한다.
다시 설명하면,
서버에서 생성한 HTML을 클라이언트에게 전달하고,
클라이언트는 전달받은 HTML에 이벤트리스너와 상태관리와 같은 클라이언트 로직을 연결시킨다. 이것이 `Hydration`이다.
이때 중요한건 연결하는 과정인데,
React는 Element와 로직 정보가 담긴 가상 DOM 을 생성한 뒤 이를 전달받은 HTML과 비교한다.
즉, 서버와 클라이언트 렌더링 결과가 같은 경우에만 `Hydration`을 수행할 수 있다.
function App() {
const name = (() => {
/* 서버 환경인 경우, 객체에 접근하지 못하도록 수정 .. */
if ( isServer() ) {
return null;
}
return new URL(location.href).searchParams.get(name);
})();
/* 유저의 이름을 화면에 출력한다 ..*/
return <div>{name}</div>
}
서버환경일 땐 null 을 리턴하고, 클라이언트 환경이면 브라우저 location객체에서 파라미터 정보를 가져오는 코드이다.
이 코드를 실행하면, 아래와 같은 에러가 난다.
Unhandled Runtime Error Text content does not match server-rendered HTML
위의 `Hydration` 을 이해한다면 에러원인을 알아낼 수 있다.
서버에서는 name 변수의 값은 항상 null 이지만, 클라이언트에서는 쿼리파라미터가 존재하면 그 파라미터값이 name 변수값이 된다.
즉, 서버와 클라이언트는 각각 다른 결과물을 렌더링 하게 되면서 Hydration을 수행할 수 없는 상태가 되어버리는 것이다.
// 서버
<div>{null}</div>
// 클라이언트
<div>{'김토스'}</div>
해결방안
Hydration Mismatch 를 해결하기 위해선, 서버와 클라이언트의 렌더링 결과물이 같아야 한다.
import { useRouter } from 'next/router';
function App() {
const name = useRouter().query.name;
return <div>{name}</div>
}
다행히도, 위의 코드에서 Next.js 의 `useRouter() hook` 을 사용하면 예외처리 없이도 서버,클라이언트 어느 환경에서든 동일한 결과값을 보장받을 수 있다.
// 서버
<div>{'김토스'}</div>
// 클라이언트
<div>{'김토스'}</div>
이처럼 서버와 클라이언트 양측에 동일한 결과를 보장하는 코드를 `isomorphic` 하다고 표현한다.
'🌳Frontend > etc' 카테고리의 다른 글
쿠키, 세션 (2) | 2023.09.10 |
---|---|
[Web] Gzip 압축으로 사이트를 최적화해보자 (0) | 2023.09.06 |
[FE] Next.js SSR 환경에서 흔히 겪는 에러 Server Error XXX is not defined. This error happened while generating the page. (0) | 2023.09.04 |
[FE] 토스가 정의하는 컴포넌트의 역할과 분리 기준 (0) | 2023.09.03 |
[FE] 실무에서 바로 쓰는 Frontend Clean Code (0) | 2023.09.03 |