React ์์ ์คํ์ผ๋ง์ ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์๋ ๊ฐ์ธ์ ์ผ๋ก ๋จ์ฐ styled-components๊ฐ ์๋์ ์ผ๋ก ์ข๋ค๊ณ ์๊ฐํ๋ค.
ํ์ง๋ง Next์์๋ styled-components๊ฐ ์ ๋๋ก ๋์ํ์ง ์์ ์ ์๋ค.
์ค๋ ๊ทธ ์ค๋ฅ๋ค์ ๋ถ์ํด๋ณด๊ณ ์ด๋ป๊ฒ ํ๋ฉด ํด๊ฒฐํ ์ ์๋์ง ์์๋ณด์.
๊ทธ๋ฅ styled-components๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ์ด๋ค ๋ฌธ์ ๊ฐ ์๊ฐ๋์?
Next.js ์ฑ์์ styled-components๋ฅผ ์ฌ์ฉํ๋ฉด ์คํ์ผ์ด ์ ์ฉ๋์ง ์๊ณ ์ผ์ ์๊ฐ ์ดํ์ ์คํ์ผ์ด ์ ์ฉ๋๋ค.
๋ง์น CSS ํ์ผ์ด ๋ก๋๋์ง ์๋ค๊ฐ ๊ฐ์๊ธฐ ๋ก๋๋๋ ๊ฒ ์ฒ๋ผ ๋ณด์ด๋๋ฐ, ์ด๋ UX์์ ๋์ ํ๊ฐ๋ก ๊ฐ์ธ๋ ์ ์๊ณ ์ฌ์ฉ์์๊ฒ ์์ฃผ ๋ถ์พํ ๊ฒฝํ์ ์ ์ฌํ ์ ์๋ค.
์ ๊ทธ๋ฐ ๋ฌธ์ ๊ฐ ์๊ธฐ๋์?
Next๋ ์ฐ์ ๋ชจ๋ ํ์ด์ง๊ฐ Pre-Render ๋๋ค๊ณ ์ง๋ ์๊ฐ์ ๋ฐฐ์ ์๋ค.
์ด๋ฐ Pre-Render์๋ 2๊ฐ์ง Stage๊ฐ ์กด์ฌํ๋๋ฐ,
- Initial Load Stage
- Hydration Stage
๊ฐ๊ฐ์ Stage์ ๋ํด์ ๊ฐ๋ตํ ์ค๋ช ํ์๋ฉด, Initial Stage์์ Staticํ๊ฒ ์์ฑ๋ HTML์ด ๋ ๋๋ ํ, Hydration Stage์์ ๋๋จธ์ง JS ํ์ผ๋ค์ด ๋ก๋๋์ด Sync๋๋ค.
๊ฒฐ๊ตญ ์ฐ๋ฆฌ๊ฐ getStaticProps
๋ getStaticPaths
๋ก SSG๋ฅผ ์ด์ฉํด staticํ HTML์ ๋ง๋ค์ด SSR(SSG) ํ๊ฒฝ์ ๊ตฌ์ถํ๋ค๊ณ ์น๋๋ผ๋ JS์ ์ํด ๋์ ์ผ๋ก CSS๊ฐ ์์ฑ๋๋ CSS-In-Js ๋ฐฉ์์ธ styld-components
๋ SSG ๊ณผ์ ์์ ์์ฑ๋๋ HTML์ ์ฐ๋ฆฌ์ ์ฝ๋๊ฐ ํจ๊ป Build ๋์ง ์๊ฒ ๋๋ค.
์ด๋ฅผ ํ ๋ฌธ์ฅ์ผ๋ก ์ด์ผ๊ธฐ ํ๋ค๋ฉด,
Next.js๋ SSRํน์ SSG๋ฅผ ๊ธฐ๋ณธ์ผ๋ก ์ฌ์ฉํด์ Pre-Rendering ์ ํ๋ฉด์ Initial Load ๊ณผ์ ์์ ๋ฏธ๋ฆฌ HTML์ ๋ก๋ํ๊ณ Hydration ๊ณผ์ ์์ ๋ค๋ฅธ ํ์ผ๋ค์ ๋ก๋ํ๊ธฐ ๋๋ฌธ์ ๋ฐ์ํ๋ค.
๋ก ๋งํ ์ ์๋ค.
์ด๋ป๊ฒ ํด๊ฒฐํ ์ ์๋์?
ํด๊ฒฐ ๋ฐฉ๋ฒ์ Next.js ๊ณต์ ํํ์ด์ง์์ ์ด์ผ๊ธฐํ๋ renderPage
ํจ์๋ก ํด๊ฒฐํ ์ ์๋ค.
๊ณต์ ํํ์ด์ง์์๋ renderPage ํจ์๋ฅผ ์ปค์คํฐ๋ง์ด์งํ๋ ๊ฒ์ ์ค๋ก์ง CSS-in-js ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ ๋๋ง ์ฌ์ฉํ๋ผ๊ณ ๋์์๋ค.
๊ทธ๋ฆฌ๊ณ ์ฐ๋ฆฌ๋ ๋ค์๊ณผ ๊ฐ์ ๋ฐฉ์์ผ๋ก ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ๊ฒ์ด๋ค.
- pages ๋๋ ํ ๋ฆฌ์ Next ์ฑ์ HTML Custom ์ค์ ์ ํ ์ ์๋
_document.js
ํ์ผ์ ์์ฑ ServerStyleSheet
ํจ์๋ฅผ styled-components์์ import ํ์ฌ Globalํ๊ฒ ์ค์ renderPage
ํจ์๋ก ๋ ๋๋ง ์กฐ๊ฑด Customizing.
1. _document.js
ํ์ผ ์์ฑ
pages ๋๋ ํ ๋ฆฌ ์๋์ _document.js
ํ์ผ์ ์์ฑํ๋ค.
next๋ _document.js
ํ์ผ์ Build ์์ ์ env ํ์ผ๋ก ๊ฐ์ฃผํ๊ณ ์๋ตํ๋ค.
import Document, { Html, Head, Main, NextScript } from 'next/document'
class MyDocument extends Document {
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx)
return { ...initialProps }
}
render() {
return (
<Html>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
export default MyDocument
2. ServerStyleSheet
ํจ์ import
_document.js
์์ SC์ ServerStyleSheet
๋ฅผ import ํ๋ค.
// ... ์๋ต
import { ServerStyleSheet } from 'styled-components';
// ... ์๋ต
3. renderPage
ํจ์ ์กฐ๊ฑด ์ถ๊ฐ.
_document.js
์์ renderPage
ํจ์ ์ถ๊ฐ.
import Document from 'next/document';
import { ServerStyleSheet } from 'styled-components';
export default class MyDocument extends Document {
static async getInitialProps(ctx) {
const sheet = new ServerStyleSheet();
const originalRenderPage = ctx.renderPage;
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: App => props => sheet.collectStyles(<App {...props} />)
});
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
)
};
} finally {
sheet.seal();
}
}
}
๊ทธ๋ฆฌ๊ณ ๋ค์ ์คํ์ํค๊ฒ ๋๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์ ์์ ์ผ๋ก styled-components๊ฐ ์ ๋์ํ๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
๋๊ธ