Reactμμ μ€νμΌμ μ νλ λ°©λ²μ μ¬λ¬κ°μ§κ° μμ΅λλ€. κ·Έ μ€μμ CSS-in-JSλ JavaScriptλ₯Ό μ¬μ©νμ¬ μ»΄ν¬λνΈμ μ€νμΌμ μ μνλ ν¨ν΄μ λλ€. styled-componentsλ emotionκ³Ό κ°μ λΌμ΄λΈλ¬λ¦¬λ€μ΄ μ΄ ν¨ν΄μ ꡬννκ³ μμ΅λλ€. μ΄λ¬ν λΌμ΄λΈλ¬λ¦¬λ€μ ν΄λΌμ΄μΈνΈ μ¬μ΄λ λ λλ§μ μ΅μ νλμ΄ μμ΄, Next.jsμ κ°μ SSR νκ²½μμ μ¬μ©νκΈ° μν΄μλ λͺ κ°μ§ μΆκ°μ μΈ μ€μ μ΄ νμν©λλ€.
μλ² μ¬μ΄λ λ λλ§ μ, μ΄κΈ° HTMLμ μμ±νλ μμ μ λͺ¨λ styled-componentsμ μ€νμΌμ μμ§νμ¬ ν¬ν¨μμΌμΌ ν©λλ€. μ΄λ₯Ό μν΄ ServerStyleSheetλ₯Ό μ¬μ©ν©λλ€:
μ¬κΈ°μ μ¬μ©λ useServerInsertedHTML ν
μ Next.jsμμ μ 곡νλ νΉλ³ν ν
μΌλ‘, SSR κ³Όμ μμ HTMLμ μ£Όμ
ν μ μκ² ν΄μ€λλ€. μ΄λ₯Ό ν΅ν΄ μλ²μμ μμ±λ μ€νμΌμ΄ μ΄κΈ° HTML μλ΅μ ν¬ν¨λ©λλ€.
export const StyledComponentRegistry = ({ children }: PropsWithChildren) => {
const [styleSheet] = useState(() => new ServerStyleSheet());
useServerInsertedHTML(() => {
const styles = styleSheet.getStyleElement();
styleSheet.instance.clearTag();
return <>{styles}</>;
});
if (typeof window !== 'undefined') return <>{children}</>;
return <StyleSheetManager sheet={styleSheet.instance}>{children}</StyleSheetManager>;
};
export default function RootLayout({
children,
}: Readonly<{
children: ReactNode;
}>) {
return (
<html lang="en">
<body>
<StyledComponentRegistry>
{children}
</StyledComponentRegistry>
</body>
</html>
);
}
CSS-in-JS λΌμ΄λΈλ¬λ¦¬λ μ€νμΌλ§λ€ κ³ μ ν ν΄μκ°μ ν΄λμ€ μ΄λ¦μΌλ‘ μ¬μ©ν©λλ€. μλ² μ¬μ΄λ λ λλ§κ³Ό ν΄λΌμ΄μΈνΈ μ¬μ΄λ νμ΄λλ μ΄μ κ³Όμ μμ μ΄ ν΄λμ€ μ΄λ¦λ€μ΄ μΌμΉν΄μΌ νλλ°, μ΄λ λ€μκ³Ό κ°μ λ°©μμΌλ‘ ν΄κ²°λ©λλ€:
const nextConfig = {
compiler: {
styledComponents: {
// κ°λ° νκ²½μμ λλ²κΉ
μ μν ν΄λμ€λͺ
μ¬μ©
displayName: process.env.NODE_ENV === 'development',
// SSR μ§μ νμ±ν
ssr: true,
// λ μμ λ²λ€ μ¬μ΄μ¦λ₯Ό μν μ€μ
minify: true
}
}
};
ServerStyleSheetκ° μλ² μ¬μ΄λμμ μ€νμΌμ μμ§νκ³ , μ΄λ₯Ό μ΄κΈ° HTMLμ ν¬ν¨μν΅λλ€.μ΄λ¬ν μ€μ κ³Ό λ©μ»€λμ¦λ€μ΄ ν¨κ» μλνμ¬ Styled-components λΌμ΄λΈλ¬λ¦¬κ° Next.jsμ SSR νκ²½μμ μ μμ μΌλ‘ λμν μ μκ² ν©λλ€.