브라우저가 프론트엔드 서버에서 HTML, CSS, JavaSctipy 파일을 받기 전에 프론트엔드 서버에서 먼저 HTML, CSS, JavaSctipy 파일을 그려본다. 이 과정을 Pre-rendering이라 한다. 그 후 브라우저는 프론트엔드 서버로부터 HTML 파일을 받고 렌더링하는데 이때 브라우저에서 렌더링 한 내용과 프론트엔드 서버에서 렌더링한 내용이 서로 다른지 비교한다. 이 과정을 ㅇDiffing이라고 한다. Diffing을 진행한 후 최종적으로 렌더링 하게 되는데 이 과정을 Hydration이라 한다.
const ApolloSetting = ({ children }: IApolloSettingProps) => {
const [accessToken, setAccessToken] = useRecoilState(accessTokenState);
// 렌더링 과정에서 오류 발생 (프론트엔드 서버에는 window가 없다.)
const result = localStorage.getItem("accessToken");
if (result) setAccessToken(result);
return (
<ApolloProvider client={client}>
{children}
</ApolloProvider>
);
};
export default ApolloSetting;
위 같은 과정의 렌더링을 하기 때문에 Pre-rendering 과정에서 window가 없는 프론트엔드 서버에서 위 코드는 오류를 발생시킨다.
따라서 브루우저와 프론트엔드 서버에서의 렌더링을 분리해 줘야 한다. 방법은 다음과 같다.
if (process.browser) {
console.log("브라우저 렌더링");
const result = localStorage.getItem("accessToken");
if (result) setAccessToken(result);
} else {
console.log("프론트엔드 서버 렌더링(yarn dev로 실행시킨 프로그램 내부)");
const result = localStorage.getItem("accessToken");
if (result) setAccessToken(result);
}
if (typeof window !== "undefined") {
console.log("브라우저 렌더링");
const result = localStorage.getItem("accessToken");
if (result) setAccessToken(result);
} else {
console.log("프론트엔드 서버 렌더링(yarn dev로 실행시킨 프로그램 내부)");
const result = localStorage.getItem("accessToken");
if (result) setAccessToken(result);
}
useEffect(() => {
console.log("브라우저 렌더링");
const result = localStorage.getItem("accessToken");
if (result) setAccessToken(result);
}, []);
이 방법에서는 프리렌더링을 무시한다. (componentDidMount 시점)
const ApolloSetting = ({ children }: IApolloSettingProps) => {
const [accessToken, setAccessToken] = useRecoilState(accessTokenState);
useEffect(() => {
console.log("브라우저 렌더링");
const result = localStorage.getItem("accessToken");
if (result) setAccessToken(result);
}, []);
return (
<ApolloProvider client={client}>
{children}
</ApolloProvider>
);
};