const onClickLogin = async()=>{
try{
cosnt result = await loginUser({
variables:{
email : email,
password : password
}
})
const accessToken = result.data?.loginUser.accessToken
if(accessToken){setAccessToken(accessToken || "" )
void router.push('/loginsuccess')
localStorage.setItem("accessToken",accessToken)
}
}catch(error){
Modal.error({content : error.message})
}
}
문제가 발생한 코드는 graphql mutation 요청을 통해 로그인을 하고 AccessToken을 발급받은 후 Global state(Recoil)에 저장하고 localStorage에 저장하는 단순한 코드이다.
위 코드를 그대로 실행시키면 localstorage is not defined 오류가 발생한다.
그러나, localStorage나 alert 기능은 웹(브라우저) API이기때문에 브라우저에서 사용할 수 있다.
만약에 위 코드를 리액트 환경(CSR)에서 실행하면 오류없이 정상적으로 동작한다.
여기서 원인을 찾을 수 있었다. Next.js는 서버사이드렌더링(SSR) 환경에서 동작하기 때문에 브라우저 API인 localStorage에 접근할 수 없었던 것이다.
Next.js에서는diffing 과 hydration 과정을 거친 후 화면을 렌더링한다.
이 과정은 흔히 말하는 서버사이드 렌더링과는 살짝 다른개념이다.
이제 오류의 이유를 알 수 있다.
localStorage는 브라우저에만 있는데, 서버에서 먼저 화면을 그려보기 때문에(pre-rendering) 발생하는 오류이다.
이를 해결하기 위해서는
1. if(typeof window !== "undefined") 사용
2. if (process.browser) 사용
3. useEffect를 사용해 렌더링 이후에 실행하는 방법