실행 시점 스타일 주입과 서버 기본값이 충돌해
styled-components와 emotion은 JavaScript가 실행되며 스타일을 만들어 문서에 넣는 방식이야. 서버 컴포넌트는 자기 코드를 클라이언트로 보내지 않으므로 이 실행 시점 모델을 그대로 사용할 수 없어. 'use client' 경계가 실제 벽이 되는 지점이지.
| 방식 | 서버 컴포넌트 | 클라이언트 컴포넌트 |
|---|---|---|
| CSS Module | 가능 | 가능 |
| Tailwind CSS | 가능 | 가능 |
| styled-components | 불가 | registry와 함께 가능 |
| emotion | 불가 | registry와 함께 가능 |
기존 CSS-in-JS는 registry로 연결해
계속 써야 한다면 클라이언트 style registry로 앱을 감싸고, 서버 렌더링 중 모은 스타일을 응답에 넣어야 해. 작동은 하지만 수집·주입 코드와 실행 시점 비용을 계속 부담하게 돼.
새 프로젝트는 정적 CSS 경로가 단순해
특별한 요구가 없다면 Tailwind나 CSS Module이 서버·클라이언트 어디서나 작동하고 실행 시점 비용도 없어. 기존 투자 때문에 registry를 유지하는 결정과 새로 그 복잡성을 선택하는 결정은 구분해야 해.
기존 CSS-in-JS를 유지한다면 registry의 서버 삽입, hydration 일치, streaming 순서를 실제 production 빌드에서 시험해. 어느 컴포넌트가 client 경계를 요구하는지 목록을 만들고 새 서버 컴포넌트에는 정적 CSS 방식을 기본으로 써. 이동은 화면 단위로 하며 두 시스템의 토큰을 하나로 공유해. 런타임 비용이 있다는 이유만으로 대규모 제품의 스타일을 한 번에 갈아엎으면 회귀 비용이 더 클 수 있어. 이미 안정된 컴포넌트는 유지하고 새 경계부터 다른 기본값을 적용하는 점진적 전환도 가능해. 목표는 유행 교체가 아니라 클라이언트 실행과 유지 책임을 줄이는 거야.
registry가 있는 CSS-in-JS 페이지와 CSS Module 페이지를 production streaming 환경에서 비교해. 첫 HTML의 style, hydration warning, 클라이언트 chunk, route 이동 뒤 중복 style을 확인하고, 기존 화면 한 개만 점진적으로 옮겨 토큰과 시각 결과가 유지되는지 검증해.