[ Troubleshooting🛠️ ] Next.js 서버사이드 렌더링에서 styled-components 적용하기
1. 문제 발생❓
Next.js와 styled-components를 함께 사용할 때, 페이지 새로고침 시 스타일이 적용되지 않는 문제가 발생했습니다. 이로 인해 사용자가 페이지를 새로고침할 때마다 스타일이 없는 콘텐츠가 잠시 표시되는 깜박임 현상(FOUC - Flash of Unstyled Content)이 발생했습니다.
2. 원인 추론 🔎
이 문제는, styled-components가 기본적으로 클라이언트 측에서 런타임에 스타일을 주입하는 방식으로 작동하기 때문에 발생했습니다. Next.js의 서버 사이드 렌더링(SSR) 환경에서는 이러한 동적 스타일 주입이 자동으로 이루어지지 않아 초기 HTML에 스타일이 포함되지 않았습니다.
3. 해결 과정 📋
문제 해결을 위해 두 가지 주요 설정을 적용했습니다:
1. _document.tsx 파일 생성 및 설정
Next.js의 커스텀 Document를 생성하여 서버 사이드 렌더링 시 styled-components의 스타일을 HTML에 포함시키도록 했습니다.
import Document, {
Html,
Head,
Main,
NextScript,
DocumentContext,
DocumentInitialProps,
} from "next/document";
import { ServerStyleSheet } from "styled-components";
import { AppProps } from "next/app";
export default class MyDocument extends Document {
static async getInitialProps(
ctx: DocumentContext
): Promise<DocumentInitialProps> {
const sheet = new ServerStyleSheet();
const originalRenderPage = ctx.renderPage;
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp:
(App: React.ComponentType<AppProps>) => (props: AppProps) =>
sheet.collectStyles(<App {...props} />),
});
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
),
};
} finally {
sheet.seal();
}
}
render() {
return (
<Html>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
2. .babelrc 파일 생성 및 설정
Babel 설정을 통해 styled-components가 서버 사이드 렌더링을 지원하도록 구성했릅니다
{
"presets": ["next/babel"],
"plugins": [["styled-components", { "ssr": true, "displayName": true }]]
}
+ 추후 yarn dev 실행하였더니
✔ Console Ninja extension is connected to Next.js, see https://tinyurl.com/2vt8jxzw
▲ Next.js 14.0.4
- Local: http://localhost:3000
Disabled SWC as replacement for Babel because of custom Babel configuration ".babelrc" https://nextjs.org/docs/messages/swc-disabled
✓ Ready in 1333ms
Using external babel configuration from /Users/jigong/Development/music-player/.babelrc
⚠ It looks like there is a custom Babel configuration that can be removed:
⚠ Next.js supports the following features natively:
⚠ - 'styled-components' can be enabled via 'compiler.styledComponents' in 'next.config.js'
⚠ For more details configuration options, please refer https://nextjs.org/docs/architecture/nextjs-compiler#supported-features
⨯ ./node_modules/next/dist/client/next-dev.js
Error: Cannot find module 'babel-plugin-styled-components'
프로젝트에 제가 .babelrc 파일을 만들어줘서 Next.js의 기본 SWC 컴파일러 대신 Babel을 사용하려 했습니다. .babelrc가 babel-plugin-styled-components 를 참조하고 있지만, 이 패키지가 설치되어 있지 않았습니다. Next.js는 경고 메세지를 통해 위와 같은 오류 메세지를 알려주고 있습니다.
⚠ It looks like there is a custom Babel configuration that can be removed:
⚠ Next.js supports the following features natively:
⚠ - 'styled-components' can be enabled via 'compiler.styledComponents' in 'next.config.js'
Next.js 14 버전에서는 styled-components를 지원하기 위해 별도의 Babel 설정이 필요하지 않습니다. 오히려 Next.js의 내장 컴파일러를 사용하는 것이 더 효율적입니다.
- .babelrc 파일을 제거했습니다.
- next.config.js 파일에 styled-components 지원을 추가했습니다:
/** @type {import('next').NextConfig} */
const nextConfig = {
compiler: {
styledComponents: true,
},
// 기존 설정 유지
};
module.exports = nextConfig;
이 변경 후 성공적으로 프로젝트가 실행되었습니다!!
4. 결론 ❤🔥
위의 두 개의 설정을 적용한 후, 페이지 새로고침 시에도 styled-compoennts로 작성 스타일이 즉시 적용되어 FOCU 문제가 해결되었습니다. 이제 서버에서 렌더링된 HTML에 스타일이 포함되므로 사용자 경험이 크게 향상되었습니다.