
yarn add styled-components styled-reset @types/styled-components babel-plugin-styled-components
styled-reset 혹은 styled-normalize를 설치할 수 있다.styled-components, @types/styled-components, babel-plugin-styled-components를 설치한다.// theme.ts (내부 스타일 요소는 예시입니다.) import "styled-components"; // declare module "styled-components" { export interface DefaultTheme { flex: (direction: string, justify: string, align: string) => string; // colors: { black: string; white: string; }; } }
theme 파일의 인터페이스 타입을 styled-component의 모듈로 지정해준 후 export 한다.// theme.ts (내부 스타일 요소는 예시입니다.) import { DefaultTheme } from "styled-components"; // const flex = (direction = "row", justify = "center", align = "center") => { return ` display: flex; justify-content: ${justify}; align-items: ${align}; flex-direction: ${direction}; `; }; // const colors = { black: "#0E0E0E", white: "#000000", }; // const theme: DefaultTheme = { flex, colors, }; // export default theme;
styled.d.ts 파일에서 export한 DefaultTheme로 theme의 타입을 지정한다.//GlobalStyle.ts (내부 스타일 요소는 예시입니다.) import { createGlobalStyle } from "styled-components"; import { reset } from "styled-reset"; // const GlobalStyle = createGlobalStyle` ${reset} * { box-sizing: border-box; } `;
// .babelrc { "presets": ["next/babel"], "plugins": [ [ "styled-components", { "ssr": true, "displayName": true, "preprocess": false } ] ] }
Nextjs는 최초 SSR 이후 부분적으로 CSR(클라이언트 사이드 렌더링)을 하게 되는데, 이때 server에서 생성되는 class 해시값과 client에서 생성하는 class 해시값이 달라 충돌로 인해 문제가 발생한다. 때문에 babel-plugin-styled-components 및 .babelrc 파일을 설정하도록 하자. (설치 및 파일을 설정했음에도 계속 위와 같은 에러가 발생하다가 npm install을 통해 전체 모듈을 설치해주니 다시 정상적으로 제기능을 하였다.)import Document, { DocumentContext } from "next/document"; import { ServerStyleSheet } from "styled-components"; // export default class MyDocument extends Document { static async getInitialProps(ctx: DocumentContext) { 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(); } } }
Next.js는 Pre-rendering을 통해 Initial load 과정에서 미리 HTML, CSS 등 정적인 요소들을 먼저 렌더링 한 후 JS 파일을 로드하며 Hydration이 이루어진다.
위와 같은 이유로 인해 css-in-js의 경우, 스타일 요소 또한 늦게 로딩이 된다. (내 경우 아예 로드가 되지 않았다 .. 왜 그런지 이유는 못찾았음..) 이러한 문제점은 next.js 공식문서에서 제공하는 renderPage를 통해 해결할 수 있다. 즉, index.html 파일에 css-in-js 형식으로 작성된 스타일 요소들을 주입시켜줌으로써 스타일이 뒤늦게 적용되는 문제를 해결할 수 있다.
styled-component 공식문서 에서는 심지어 코드 샘플을 예제로 제공하고 있으며, 적용을 통해 정상적으로 스타일링이 HTML 요소에 적용됨을 확인할 수 있었다.

// _app.tsx import type { AppProps } from "next/app"; // import theme from "../src/styles/theme"; import { ThemeProvider } from "styled-components"; import { GlobalStyle } from "../src/styles/GlobalStyles"; // export default function MyApp({ Component, pageProps }: AppProps) { return ( <ThemeProvider theme={theme}> <GlobalStyle /> <Component {...pageProps} /> </ThemeProvider> ); }