황총무의 실험실

🎨
기술 이야기

Next.js App Router + styled-components SSR 삽질기

2025-07-05

문제: FOUC(Flash of Unstyled Content)

Next.js App Router에서 styled-components를 그냥 사용하면 페이지가 처음 로드될 때 스타일이 적용되지 않은 날것의 HTML이 잠깐 보이는 현상(FOUC)이 발생합니다. 이는 styled-components가 클라이언트에서 스타일을 생성하기 때문입니다.

해결: StyledComponentsRegistry

Next.js 공식 문서에서 권장하는 방식은 ServerStyleSheet를 활용한 Registry 패턴입니다. SSR 시점에 스타일을 수집해서 HTML의 <head>에 주입하는 방식이죠.

// lib/registry.tsx
'use client';
import { useServerInsertedHTML } from 'next/navigation';
import { ServerStyleSheet, StyleSheetManager } from 'styled-components';

export default function StyledComponentsRegistry({ children }) {
  const [sheet] = useState(() => new ServerStyleSheet());
  
  useServerInsertedHTML(() => {
    const styles = sheet.getStyleElement();
    sheet.instance.clearTag();
    return <>{styles}</>;
  });
  
  return (
    <StyleSheetManager sheet={sheet.instance}>
      {children}
    </StyleSheetManager>
  );
}

추가 최적화: compiler 옵션

next.config.ts에서 styled-components compiler를 활성화하면 빌드 타임에 스타일을 처리해 성능이 개선됩니다. displayName도 자동으로 추가되어 디버깅이 편해집니다.

// next.config.ts
const nextConfig = {
  compiler: {
    styledComponents: true,
  },
};

교훈

App Router와 styled-components의 조합은 설정이 까다롭지만, 한 번 잡아놓으면 이후에는 매우 편리합니다. 테마 시스템과 결합하면 일관된 디자인 토큰 관리가 가능하고, TypeScript와의 궁합도 좋습니다.

황총무의 실험실