๋ด๊ฐ ํ์ฌ์์ ๋ค๋ฃจ๊ณ ์๋ ์ ํ์ ํฌ๊ฒ ์ธ ๊ฐ์ง๋ก ๋ถ๋ฅํด๋ณผ ์ ์๋๋ฐ, ๊ทธ ์ค ํ๋์ธ ์ฐ๋ฆฌ ํ์ฌ ์น์ฌ์ดํธ(๋๋ฉํ์ด์ง)๋ NextJS๋ฅผ ๋ฒ ์ด์ค๋ก ํ๊ณ ์๋ค. NextJS ๋์ ์ ๋ฑํ ๋ด๊ฐ ๊ฒฐ์ ํ ๊ฒ์ ์๋๋ฐ, ๋๋ณด๊ณ ์ ํํ๋ผ๊ณ ํ์ด๋ ๊ฐ์ ์ ํ์ ํ์ ๊ฒ์ด๋ค. ์ ์ ๋ค๊ณผ์ ์ค์๊ฐ ์ํธ์์ฉ์ด ๋ฑํ ๋ง์ ๊ฒ์ด ์๋๋ฐ๋ค, ์ ๋ณด ์ ๋ฌ ์์ฃผ์ ํ์ด์ง๋ก ๊ตฌ์ฑ๋์ด ์์ด์...! ํนํ ํ์ฌ ๋ด๋ถ ํฌ๋ฃจ๋ค์ด ์ฌ์ฉํ๋ ์์คํ ์ด ์๋๋ผ, ์ผ๋ฐ ์ ์ ๋ค์๊ฒ ์ฐ๋ฆฌ ํ์ฌ ์ ํ๋ค์ ์๋ฆฌ๋ ๊ฒ์ด ์ฃผ๋ชฉ์ ์ด๊ธฐ ๋๋ฌธ์ SEO์๋ ๋ค๋ฅธ ํ๋ก์ ํธ๋ค ๋ณด๋ค๋ ๋์ฑ ์ ๊ฒฝ์ ์ฐ๊ณ ์๋ค.
๊ทธ๋์์ ํ์ฌ์ ์ ์์ ํ๊ณ , ์ฃผ์ด์ง๋ ํ์คํฌ๋ค์ ์ฒ๋ฆฌํด๋ด๋ ๊ฒ๋ง์ผ๋ก๋ ๋ฐ๋นด์ผ๋ฏ๋ก, ๋ฑํ ์๋ก์ด ๊ธฐ์ ์คํ์ ์ ์ฉํด๋ณธ๋ค๋์ง, ๋ฒ์ ์ ์ ๊ทธ๋ ์ด๋ํ๋ค๋์ง ํ๋ ๊ฐ๋ฐ ํ์คํฌ๋ค์ ์ค์ค๋ก ๋ง๋ค์ด๋ณผ ์๊ฐ์ ๋ชปํ๋ ๊ฒ์ด ์ฌ์ค์ด๋ค. ๊ทธ๋ฌ๋ ๋๋ฆ๋๋ก ํ๋น๋ฉ๋ ๋๊ณ , ํ์ ์ ์ ์ํ ์ง๊ธ์ ํํ์ด ํ๋ก ํธ ๊ฐ๋ฐ์๋ค๋ผ๋ฆฌ ๋ชจ์ฌ, ์ฝ๋ ์ปจ๋ฒค์ ์ ๋ง๋ค๊ณ , ๋ ๊ฐ๋ฐ ํ์คํฌ๋ฅผ ์์ฑํด์, ๋ฆฌ์์ค๊ฐ ์กฐ๊ธ์ฉ ๋จ์ ๋ ํ์คํฌ๋ค์ ์ฒ๋ฆฌํ๊ณ ์๋ค!
๊ทธ ์ค ํ๊ฐ์ง ๋ฒผ๋ฅด๊ณ ์๋ ๊ฒ์ด React์ NextJS๋ฅผ ์ต์ ๋ฒ์ ์ผ๋ก ์ ๊ทธ๋ ์ด๋ ํ๋ ๊ฒ์ด์๋ค.
๊ทผ๋ ๋ง์ผํ
ํ์ผ๋ก๋ถํฐ ํ์ฌ ์น์ฌ์ดํธ์ ๋ฐฐ๋ ์ด๋ฏธ์ง ๋ก๋ฉ์ด ์กฐ๊ธ ๋๋ ค์ก๋ค๋ ์ด์๊ฐ ์ ๋ณด๋์๋ค. ์น์ฌ์ดํธ์์ ์ฌ์ฉํ๋ ๋ฐ์ดํฐ๋ค์ ๊ฐ์ ธ์ค๋ ๋ฐฉ์ ์์ฒด์ ์ฝ๊ฐ์ ๋ฌธ์ ๊ฐ ์์ ๊ฒ์ด๋ผ ์๊ฐ๋๋ ์ด ๋ถ๋ถ์ ๋น์ฅ ๋น ๋ฅด๊ฒ ๋ณํ๋ฅผ ์๋ํด๋ณผ ์ ์๋ ๋ถ๋ถ์ด ์๋๋ผ, ์ฐ์ ํ๋ก ํธ ๊ฐ๋ฐ์๋ค๋ผ๋ฆฌ ์๋ํ ์ ์๋ ๊ฒ๋ค์ ๋ฆฌ์คํธ์
ํด๋ณด์๋ค. ๊ทธ๋ ๊ฒ ํด์ ์๊ฐํด๋ธ ๊ฒ์ด ์ด๋ฏธ์ง ํ๊ทธ์lazy loding๊ณผ async decoding
์ ์ ์ฉํ๋ ๊ฒ์ด์๊ณ , ๋ ํ๋๋ NextJS๊ฐ ์ ๊ณตํ๋ Image ์ปดํฌ๋ํธ๋ฅผ ์ ์ฉํ๋ ๊ฒ์ด์๋ค.
๊ทธ๋์ ๋ํผ Image ์ปดํฌ๋ํธ๋ฅผ ์ ์ฉํ๋ ค๋ ์ฐจ์, Image ์ปดํฌ๋ํธ์ layout ์์ฑ์ fill
๊ฐ์ ๋๊ธฐ๋ ์๊พธ๋ง ์๋ฌ๊ฐ ๋ฐ์ํ๋ ๊ฒ์ด ์๋๊ฐ. ํ์
์คํฌ๋ฆฝํธ๋ก Image์ Props๋ฅผ ์ดํด๋ณด๋, ์๋๋ ๋ค๋ฅผ๊น, layout์ ๋ค์ด์ฌ ์ ์๋ ๊ฐ์ "fill"์ด ์๋ค...? ์๊ฐํด๋ณด๋, ํ์ฌ์ ๋ค์ด์ค๊ณ ๋์ NextJS๋ฅผ ํ ๋ฒ๋ ์
๊ทธ๋ ์ด๋ ํด๋ณธ ์ ์ด ์์๊ณ , ์ฐ๋ฆฌ๋ ํ์ฌ NextJS ๋ฒ์ 10์ ์ฌ์ฉํ๊ณ ์์๋ค.
๋ง์นจ ํ์ฐธ ๋ฐ์๋ค๊ฐ ์กฐ๊ธ ๋ฆฌ์์ค๊ฐ ๋จ๋ ์ ๋ฉฐ์น ์ด์๊ธฐ์, ๋ ๋ฒ ๊ณ ๋ฏผํ ๊ฒ ์์ด ๋ํผ NextJS ๋ฒ์ ์ ๊ทธ๋ ์ด๋๋ฅผ ๊ฒฐ์ฌํ๊ฒ ๋์๋ค!
์์ฃผ ์น์ ํ๊ฒ๋, NextJS๋ Upgrade Guide๋ฅผ ์ ๊ณตํด์ฃผ๊ณ ์๋ค. ๊ฐ์ด๋์ ๋ด์ฉ์ ์ด๊ณณ์ ๋ฐ๋ณตํ ํ์๋ ์์ ๊ฒ ๊ฐ๊ณ ๋ด๊ฐ ๊ฒช์ ์๋ฌ๋ค์ ์์ฃผ๋ก ํฌ์คํ ์ ์ด์ด๊ฐ๋ณด๋๋ก ํ๊ฒ ๋ค!
npm install react@latest react-dom@latest
npm install next@12
์
๊ทธ๋ ์ด๋๋ฅผ ์ํด ์ ๋ ๋ง๋ฒ์ฃผ๋ฌธ์ ํฐ๋ฏธ๋์ ์ธ์น ํ, ์ฐ์ ๋ณ์ผ์ด ์์ ๊ธฐ๋ํ๋ ๋ง์์ผ๋ก npm run dev
๋ฅผ ์คํํ์๋ค.
NextJS ์
๋ฐ์ดํธ ๋๋ฌด ์ฌ์ด๋ฐ! ๋ผ๊ณ ๋ฐฉ์ฌํ๋ ์๊ฐ!
...^^*
์ ์๋ฌ๋ฅผ ๊ตฌ๊ธ๋งํด๋ณธ ๊ฒฐ๊ณผ, next.config.js๋ฅผ ๊ฑด๋๋ ค์ฃผ์ด์ผ ํ๋ค๋ ๊ฒ์ ๋์น๋ก ์๊ฒ ๋์๋ค!
NextJS Upgrade Guide์์๋ SWC๋ฅผ ์ ์ฉํ๋ฉด Babel๋ณด๋ค ์ต๋ 17๋ฐฐ ๋น ๋ฅด๊ณ ... ๋ญ ๊ทธ๋ฐ ์ฅ์ ์ ์๊ฐํ๋ฉฐ
module.exports = {
swcMinify: true,
}
์๋ฐ ์ฝ๋๋ฅผ ์ ์ํด์ฃผ๊ณ ์๋๋ฐ, ์ด๊ฑด ๋ ์ด๊ฒ๋๋ก ์๋ฌ๋ฅผ ๋ฑ๋๋ค...!
๊ฒฐ๊ตญ ๊น๊ณ ๊น์ StackOverflow์ ๋ฐ๋ค๋ฅผ ํค์์ณ ์ฐพ์๋ธ ํด๋ฒ์ ์๋์ ๊ฐ๋ค.
//next.config.js
// [BEFORE] ์ด๋ ๊ฒ ์์ฑ๋์ด์๋ ์ฝ๋๋ฅผ ์๋์ ๊ฐ์ด ๋ฐ๊ฟ!
module.exports = {
webpack(config) {
config.module.rules.push({
test: /\.svg$/,
issuer: {
test: /\.(js|ts)x?$/
},
use: ['@svgr/webpack']
});
return config;
}
};
// [AFTER] issuer ๋ถ๋ถ์ ์ญ์ ํจ!
module.exports = {
webpack(config) {
config.module.rules.push({
test: /\.svg$/,
use: ['@svgr/webpack']
});
return config;
}
};
์ด๋ ๊ฒ ์์ฑํ์๋๋! ์๋์ ๊ฐ์ด ์ฐ์ ๊ฐ๋ฐํ๊ฒฝ์์ ๋ธ๋ผ์ฐ์ ์ ํ์ด์ง๊ฐ ๋ ๋๋ง์ ๋๋ค!
๋ค ๋๋๋ด!!๐ญ๐ญ๐ญ๐ญ ๋ผ๊ณ ๊ฐ๋์ ๋๋ฌผ์ ํ๋ฆฌ๋ ค๋ ์ฐฐ๋. ๋ ๋๋ง๋ ํ์ด์ง๊ฐ ์ด๋๊ฐ ์ด์ํ๋ค๋ ๊ฒ์ ๊ฐ์งํ ๋.
์ด์ฉ์ง ์คํฌ๋กค๋ฐ์ ํฌ๊ธฐ๊ฐ ๋๋ฌด ์งง๊ฒ ๋๊ปด์ง๋ ๊ฒ์ด ์๋๊ฐ.
์ข์ธก์ด ๋ผ์ด๋ธ ํ๊ฒฝ์ ํ์ด์ง๊ฐ ์ ๋๋ก ๋๋๋ง๋ ๋ชจ์ต, ์ฐ์ธก์ด Next ์
๊ทธ๋ ์ด๋ ํ ๊ฐ๋ฐํ๊ฒฝ์์ ํ์ด์ง๊ฐ ๋ ๋๋ง๋ ๋ชจ์ต์ด๋ค.
๋ฌผ๋ก ํ๋์ ๋ด๋ ์คํฌ๋กค๋ฐ ๋ง์ด ๋ฌธ์ ๊ฐ ์๋๋ ๊ฒ์ ์ ์ ์๋ค. ํ์ฌ... ์ด๊ฒ ๋ฌด์จ ์ผ์ด๊ณ ... ํ๋ฉฐ ์คํฌ๋กค์ ๋ด๋ ค๋ณด๋...!
๋์ฒด ์ ํธํฐ ๋ฐ์ ํ์ด์ง๊ฐ ํ ๋ฒ ๋ ๋ฑ์ฅํ๋ ๊ฑด๋ฐ?
๊ฐ๋ฐ์ ๋๊ตฌ๋ก ๋ํผ ๊น๋ณด๋... ํ์ด์ง๊ฐ ๋ ๋ฒ ๋ ๋๋ง๋๊ณ ์๋ ๊ฒ์ด ์๋๊ฐ...!?
๋๋ฌด ์ด์ํด์ NextJS 12 render twice
๋ฑ์ผ๋ก ์ฑํ๊ฒ ๊ตฌ๊ธ๋ง์ ํด๋ณด์์ผ๋, ๋ ํผ๋ฐ์ค๊ฐ ๋๋ฌด ์์๋ค. ๋ ํผ๋ฐ์ค๊ฐ ๋๋ฌด ์์ ๋ ์ญ์คํ๊ตฌ... ์ด๊ฑด NextJS๋ผ๊ธฐ๋ณด๋ค๋ ์ฐ๋ฆฌ ํ๋ก์ ํธ ์ด๋๊ฐ์ ๋ฌธ์ ๊ฐ ์๋ ๊ฒ... ๊ฒธ์ํ ๋ง์์ผ๋ก ๋ค์ ์ฝ๋๋ฅผ ๋๋ฌ๋ณด์๋ค!
๊ทธ๋ฌ๋ค๊ฐ ์์ฌํ ๋งํ ๊ณณ์ด ๋ฐ๋ก ์ด๊ณณ์ด์๋ค!
//_app.tsx
// ์๋ต ํ ์ผ๋ถ ๋ฐ์ท
return (
// ์๋ต
hackleClient ? (
<HackleProvider hackleClient={hackleClient} user={hackleUser}>
<Component {...pageProps} />
</HackleProvider>
) : (
<Component {...pageProps} />
)
// ์๋ต
);
hackle์ ์ฐ๋ฆฌ ํ์ฌ์์ ์ฌ์ฉํ๊ณ ์๋ ๋ง์ผํ ์๋ฃจ์ ํด์ธ๋ฐ, hackleClient๊ฐ ๋ธ๋ผ์ฐ์ ์์ ์คํ๋ ๋๋ง ์ ๋๋ก ์์ฑ๋์ด์ ์์ ๊ฐ์ด ์ฝ๋๋ฅผ ์์ฑํด์ฃผ์๋ค. (hackleClient๋ฅผ ์์ฑํ๊ธฐ ์ํด sdk ๊ณ ์ ํค๋ฅผ ์ฌ์ฉํ๋๋ฐ, ์ด๊ฒ ํ๊ฒฝ ๋ณ์๋ก ์ ์ฅ๋์ด์์ด์...!) ์๋ฌด๋ฆฌ ์๊ฐํด๋ ํ์ด์ง ์ ์ฒด๊ฐ ๋๋ฒ ๋ ๋๋ง๋ ์ด์ ๋ ์ ์ฝ๋๋ฐ์ ์๋ ๋ฏ ํ์ฌ ์ฐ์ ์๋์ ๊ฐ์ด ์ฝ๋๋ฅผ ์์ ํด์ฃผ์๋๋, ๋ง์นจ๋ด ํ์ด์ง๊ฐ ์ ์์ ์ผ๋ก ํ๋ฒ๋ง ๋ ๋๋ง ๋์๋ค.
return (
// ์๋ต
hackleClient ? (
<HackleProvider hackleClient={hackleClient} user={hackleUser}>
<Component {...pageProps} />
</HackleProvider>
) : null
// ์๋ต
);
๊ทธ๋ฐ๋ฐ ์ด๋ ๊ฒ ์์ฑํด๋๊ณ ๋ณด๋... ์๋ฌด๋ฆฌ hackle Client๊ฐ ๋ธ๋ผ์ฐ์ ์์๋ ์ ๋๋ก ์๋ํ ๊ฒ์ด๋ผ ํ์ ํ๋ค ํ๋ค... ๋ง์ผ hackleClient์ ๋ฌด์จ ๋ฌธ์ ๋ผ๋ ์์ ์์๋ ํ์ด์ง ์ ์ฒด๊ฐ ๋ก๋ฉ์ด ๋์ง ์์์ง๋ ๋ชจ๋ฅธ๋ค๋ ์๊ฐ์ ์ข ๋ถ์ํด์ก๋ค. ์ฐ๋ฆฌ ํ์ฌ ํ์ด์ง๊ฐ ์ธ๋ถ ์๋ฃจ์ ์ ์์กด์ฑ์ด ์๊ฒจ์๋ ์ ๋๋ค๋ ํ๋จ์ด์๋ค.
๊ฒฐ๊ตญ hackleClient๋ฅผ useState๋ฅผ ํตํด ์ํ๋ก ๊ด๋ฆฌํด์ฃผ๋ฉด์ ๋ฌธ์ ๋ฅผ ์ผ์ถํด๊ฒฐํ ์ ์์๋ค.
๊ทธ๋ฆฌ๊ณ ๋์ ๋ง์ฃผํ ์๋ฌ์์ ์์์ ํ๋ ๋ง์ ์ฝ์ง์ ์์ผ์ ํ์
ํ ์ ์๊ฒ ๋์๋ค!
(์๋ฌด๋ฆฌ ์ฐ๋ฆฌ ํ๋ก์ ํธ์์ ์ด๋๊ฐ ์ฝ๋๊ฐ ์ด์ํ๊ฒ ์จ์์๋ค๊ณ ํด๋, NextJS ์
๋ฐ์ดํธ ์ด์ ์๋ ํ์ด์ง๊ฐ ๋์์ ๋๋ฒ ๋ ๋๋ง ๋๋ ์ผ์ ์์๋ค...)
์ ์๋ฌ๋ NextJS ๊ณต์ ๋ฌธ์์์๋ ์น์ ํ ์ค๋ช ํด์ค๋ค.
Why This Error Occurred
While rendering your application, there was a difference between the React tree that was pre-rendered (SSR/SSG) and the React tree that rendered during the first render in the Browser. The first render is called Hydration which is a feature of React.
This can cause the React tree to be out of sync with the DOM and result in unexpected content/attributes being present.
๊ณต์ ๋ฌธ์์ ๋ฐ๋ฅด๋ฉด...!
SSR ํน์ SSG๋ฅผ ํตํด ํ๋ฆฌ๋ ๋๋๋ ๋ฆฌ์กํธ ํธ๋ฆฌ์ ๋ธ๋ผ์ฐ์ ์์ ์ฒซ๋ฒ์งธ๋ก ์ดํ๋ฆฌ์ผ์ด์
์ด ๋ ๋๋ ๋, ๊ทธ ์ฌ์ด์๋ ์ฐจ์ด๊ฐ ์กด์ฌํ๋ค๊ณ ํ๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ ์ฒซ ๋ฒ์งธ ๋ ๋๋ง์ด Hydration์ด๋ผ๊ณ ๋ถ๋ฆฌ๋ ๋ฆฌ์กํธ์ ๊ธฐ๋ฅ์ด๋ผ๊ณ ํ๋ค. ์ด ๋๋ฌธ์ DOM๊ณผ์ ์ฑํฌ๊ฐ ๋ง์ง ์๊ฒ ๋ ์๋, ์๋์ง ์์ ์ฝํ
์ธ ๋ ์์ฑ์ด ๋ณด์ผ ์ ์๋ค๊ณ ...
SSR์ ์ ์ ํ์ด์ง๋ฅผ ๋ ๋๋งํ๊ณ js ํ์ผ๋ ๋ฒ๋ค๋งํ ํ์ ํด๋ผ์ด์ธํธ ์ฌ์ด๋๋ก ์ด ๋์ ๋ชจ๋ ๋ด๋ ค์ฃผ๊ฒ ๋๋ค. ๊ทธ๋ฌ๋ ์ด๋ DOM์ ๋์ ์ธ ์ด๋ฒคํธ๊ฐ ์ ์ฉ๋์ง ์์ ๋ฉ๋ง๋ฅธ ์ํ์ด๋ค. ์ด๋ ๋ฉ๋ง๋ฅธ DOM์ html ์ฝ๋์ js๋ฅผ ๋งค์นญํด ์น์ฌ์ดํธ๋ฅผ ๋ธ๋ผ์ฐ์ ์ ๋ ๋๋ง ํ๋ ๊ธฐ์ ์ด ๋ฐ๋ก Hydration์ด๋ค. ๊ทธ๋ฌ๋ ์ด Hydration์๋ ์ด์ฉ ์ ์๋ ๋จ์ ์ด ์กด์ฌํ๋๋ฐ, ๊ทธ๊ฒ์ ๋ฐ๋ก ํด๋ผ์ด์ธํธ ์ธก์์ JS๊ฐ ์คํ๋์ด ํธ๋ค๋ฌ ๋ฑ์ผ๋ก ๋ผ๋๊ฐ ์๋ถ๋ณด์ถฉ ๋๊ธฐ ์ ๊น์ง๋ ํ์ด๊ฐ ๋ก๋๋์์ด๋ ์ ์ ์ ์ํธ์์ฉํ ์ ์๋ค๋ ๊ฒ์ด๋ค.
์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด์ React18์์๋ HTML Streaming๊ณผ Hydration์ ์ ๊ณตํ๋ค. ์์ง ์๋ฒฝํ ์ดํดํ์ง๋ ๋ชปํ์ง๋ง, React v18๋ถํฐ๋ pipeToNodeWritable์ ์ด์ฉํด html์ฝ๋๋ฅผ ์คํธ๋ฆฌ๋ฐ ํ์์ ํตํด ์์ ์ฒญํฌ ํํ๋ก ๋ณด๋ด์ค๋ค๊ณ ํ๋ค. ๋ค์ ๋งํด ํด๋ผ์ด์ธํธ ์ชฝ์์๋ ๋ ๋๋ง ๋น์ฉ์ด ํฐ ์ปดํฌ๋ํธ๋ค์ Suspense๋ก ๊ฐ์ธ์ ๋ถ๋ถ์ ์ด๊ณ ๋ ๋ฆฝ์ ์ผ๋ก ๋ฐ๋ก hydrate๋ฅผ ์์ํ๊ฒ ๋๋ค. ์ฌ์ด๋๋ฐ๋ ๋ค๋น๊ฒ์ด์ ๊ฐ์ด ๋ค๋ฅธ ๊ฒ๋ค๋ณด๋ค ๋น ๋ฅด๊ฒ ์ธํฐ๋์ ์ ์ ๊ณตํด์ผ ํ๋ ์ปดํฌ๋ํธ๋ค์ด๋ผ๋ฉด Suspense๋ก ๊ฐ์ธ๋๋ฉด ๋ ๊ฒ์ด๋ค.
๋ชจ์ชผ๋ก ์์ ๊ฐ์ React v18์ hydration๊ณผ ๊ด๋ จํ ์ ๋ฐ์ดํธ ๋๋ฌธ์ ๊ฒช์๋ ์๋ฌ๋ก ์ง๊ธ์ ํ๋จํ์ฌ, ์ ํค์๋๋ฅผ ์ค์ฌ์ผ๋ก ๊ตฌ๊ธ๋ง์ ํด ์ฝ๋๋ฅผ ๋ค์ ์์ฑํด๋ณด์๋ค!
const App = ({ Component, pageProps }: AppProps) => {
const [domLoaded, setDomLoaded] = useState(false);
// ์๋ต
useEffect(() => {
setDomLoaded(true);
}, []);
// ์๋ต
if (!domLoaded) {
return <></>;
} else {
return (
// ์๋ต
{hackleClient && hackleUser ? (
<HackleProvider hackleClient={hackleClient} user={hackleUser}>
<Component {...pageProps} />
</HackleProvider>
) : (
<Component {...pageProps} />
)}
// ์๋ต
);
}
}
์์์ ์ดํด๋ณธ ์๋ฌ๋ ์ฃผ๋ก window ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ํฌํธํ๊ฑฐ๋ ์๋์ฐ ๊ฐ์ฒด๋ฅผ ๋ฐ๋ก ์ฌ์ฉํ๋ ๊ฒฝ์ฐ์ ๋ฐ์ํ๊ฒ ๋๋๋ฐ, (๋ธ๋ผ์ฐ์ ์์ ์ ์ html๊ณผ js๋ฒ๋ค์ ๋ด๋ ค๋ฐ๊ธฐ ์ ์๋ window ๊ฐ์ฒด๊ฐ ์์ผ๋ฏ๋ก... ๋ณดํต css-in-js ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ๋ง์ด ๋ฐ์ํ๊ฒ ๋๋ค๊ณ ํ๋ค!) useEffect๋ฅผ ํ์ฉํ๋ฉด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ค.
useEffect๋ hydration ๋ ๋ ๋ธ๋ผ์ฐ์ ์์ ํ ๋ฒ ์คํ๋๊ฒ ๋๋๋ฐ, ์ด ์์์ ํน์ ์ํ๋ฅผ ๋ณ๊ฒฝํด์ฃผ๊ณ , ํด๋น ์ํ๋ฅผ ์กฐ๊ฑด์ผ๋ก ๊ฑธ์ด return ๋ฌธ ๋ด๋ถ๋ฅผ ์์ฑํด์ฃผ๋ฉด, ์๋ฒ์์ ๋ ๋๋ง ๋ ๋์์ ์ฑํฌ๋ฅผ ๋ง์ถ ์ ์๊ฒ ๋๋ ๊ฒ์ด๋ค! ํนํ hydration ๋ ๋ ๋ธ๋ผ์ฐ์ ์์ ์คํ๋๋ค๋ ๊ฒ์ ๊ฒฐ๊ตญ ์๋์ฐ ๊ฐ์ฒด๋ฅผ ๋ถ๋ฌ์ฌ ์ ์๋ค๋ ๊ฒ์ ์๋ฏธํ๋ค. ๊ทธ๋ฆฌ๊ณ ๋ ๋ค๋ฅธ useEffect์ ์์กด์ฑ๋ฐฐ์ด์ ์์์ ์ค์ ํ ์ํ์ ๊ฐ์ ๋ฃ์ด์ฃผ๊ณ ํ์ฉํ๋ฉด, ์ฐ๋ฆฌ๋ ํ๋ฆฌ๋ ๋ ๋์์ ์ฑํฌ๋ฅผ ์ ์งํ๋ฉด์๋ ์์ ๋กญ๊ฒ ์๋์ฐ ๊ฐ์ฒด๋ฅผ ํ์ฉํ ์ ์๊ฒ ๋๋ ๊ฒ์ด๋ค! ๐ฅฒ
(๊ทผ๋ฐ ์ด๊ฑธ ํด๊ฒฐ์ด๋ผ๊ณ ์จ๋๊ณ ์ค๋ ์ด๋๋ค๋ ์ค๋ฉด์ ์๊ฐํด๋ณด๋๊น, ์ด๋ฌ๋ฉด SSR์ ์๋ฏธ๊ฐ ์์ด์ง๋๊ฒ ์๋๊ฐ ํ๋ ์๊ฐ๋ ๋ ๋ค. pํ๊ทธ๋ฅผ ๋ฌธ์ ์ผ๋ ๊ฒฝ์ฐ๋ ์๋๋ฐ, ๊ทธ ์ญ์ ์๋ํด๋ด์ผ๊ฒ ๋ค...)
์ฌ์ค ๋๋ถ๋ถ์ NextJS 12 ์ ๊ทธ๋ ์ด๋ ํฌ์คํ ๋ค์ ์ด๋ฌ์ด๋ฌํ New Feature๊ฐ ๋์๊ณ , ์ด๊ฒ๋ค์ ์ ์ฉํด๋ณด์๋ค! ์ ๋ด์ฉ์ธ๋ฐ, ๋๋ ์ ๊ทธ๋ ์ด๋๋ฅผ ํ๊ณ , ์ ๋๋ก ๋ ๋๋ง ๋๊ฒ๋ ๋ง๋ค๊ธฐ ์ํ ์๋ฌ๋ฅผ ํด๊ฒฐํ๋ ๋ด์ฉ์ผ๋ก ์ ๊ทธ๋ ์ด๋ ํ๊ณ ๋ฅผ ๊ฝ ์ฑ์ ๋ค. js/๋ฆฌ์กํธ ๊ฐ๋ฐ์์ด์ง๋ง ๋ฆฌ์กํธ์ ๋ ๋๋ง ๊ณผ์ , ํน์ hydration๊ณผ ๊ฐ์ด ์กฐ๊ธ๋ง ๋ณต์กํ ๊ฐ๋ ์ด ๋์ค๋ฉด ๋ฐ๋ก ๋จธ๋ฆฌ๊ฐ ์ํ์ค๋ ๊ฒ์ด ์ฌ์ค์ด๋ค. ๋งค๋ฒ ์ ๋๋ก ๊ณต๋ถํด์ผ์ง ๋ค์งํ๊ณ ๊ณต์๋ฌธ์๋ฅผ ์ผ๊ณคํ์ง๋ง, ๊ณต์๋ฌธ์ ํน์ ๋ธ๋ก๊ทธ ์๋ฃ๋ค์์ ์ ๊ณตํ๋ ๋ด์ฉ์ ์ฝ๊ณ ์์๋ฉด ์ข ๋์ ๋๋จ์ด์ง ๋ด์ฉ๊ฐ๊ณ ... ๊ทธ๋ ๋ค... ์ด๋ ๊ฒ ์ค๋ฌด์ ๋ง๋ฟ์ ์์ ๋ ์ดํด๋ณด๋ ๊ฒ์ด ๊ทธ๋๋ ๊ฐ์ฅ ํฐ ๋์์ด ๋๋ ๋ฏํ๋ค... ๊ธฐ์ต์๋ ๋ง์ด ๋จ๊ณ .
New Feature๋ ์ด์ ๋ถํฐ ์ ์ฉํ ๋ก ํ๊ฒ ์๋๋ค~
https://nextjs.org/docs/messages/react-hydration-error
https://velog.io/@huurray/React-Hydration-%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC
์ ๋๋ฌด ์ ์ฉํด์
์ ํฌ ํ์ฌ ์น์ฌ์ดํธ์๋ ์ ์ฉํด๋ด์ผ๊ฒ ์ด์
๊ฐ์ฌํฉ๋๋ค! ^.^
์๋
ํ์ธ์. ํตํด์์ ๊ฐ๋ฐ ์ค์ธ ๊ถ์ค๋น์
๋๋ค.
์์ฑํ์ ๋ธ๋ก๊ทธ๊ธ ์ ์ฝ์์ต๋๋ค!
์ด๋ฒ์ ์ ํฌ SDK๊ฐ 11.3.1 ๋ก ์ ๋ฐ์ดํธ ๋๋ฉด์ ๊ธฐ์กด ์ฒ๋ผ ๋ถ๊ธฐ ์์ด ์ฝ๊ฒ ์ฌ์ฉํ์ค ์ ์๋๋ก ์ ๋ฐ์ดํธ ๋์์ต๋๋ค!
props์ supportSSR๋ง ๋ฃ์ด์ฃผ์๋ฉด, ๊ธฐ์กด์ฒ๋ผ ๋ณ๋ ๋ถ๊ธฐ ์์ด ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํด์ง๋๋ก ๋์์ต๋๋ค. :)
Hydrate ๋ฌธ์ ๋ ๋ด๋ถ์ ์ผ๋ก
useLoadableVariation, useLoadableFeature ๋ฅผ ์ถ๊ฐํ์ฌ, isLoading ๊ฐ์ ๋ฐ๋ผ์ ์ค์ ๋ก ์ฌ์ฉํ์๋ ๋ถ๋ถ์์ isLoading ์ด true ์ธ ๊ฒฝ์ฐ์๋ง ๊ฐ์ ํ์ฉํ์ค ์ ์๋๋ก ํ์ฌ SSR ํ๊ฒฝ์์ ๋์ฑ ํธ๋ฆฌํ๊ฒ ์ฌ์ฉํ์ค ์ ์์ต๋๋ค.
๊ฒํ ๋ถํ๋๋ฆฝ๋๋ค. :)
์ ์ฝ๊ณ ๊ฐ๋๋ค!!