Files
2nd/10_Wiki/Topics/Architecture/Styled_Components.md
T
Antigravity Agent f8b21af4be Wiki cleanup: error-doc removal, dedup merge, link normalization
10_Wiki/Topics 대규모 정리:
- 오류 캡처/미완성 stub 문서 227개 제거
- 교차폴더 중복 43클러스터 병합 (63파일 → redirect)
- 링크명 정규화: 깨진 링크 수정·redirect 직결·개념 매핑 ~2,400건
- 카테고리 MOC 6개 신규 생성
- Graph 섹션 미해결 related-keyword 링크 10,058건 제거

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 23:52:15 +09:00

5.5 KiB

id, title, category, status, canonical_id, aliases, duplicate_of, source_trust_level, confidence_score, verification_status, tags, raw_sources, last_reinforced, github_commit, tech_stack
id title category status canonical_id aliases duplicate_of source_trust_level confidence_score verification_status tags raw_sources last_reinforced github_commit tech_stack
wiki-2026-0508-styled-components Styled Components 10_Wiki/Topics verified self
styled-components
CSS-in-JS
none A 0.9 applied
react
css-in-js
frontend
styling
2026-05-10 pending
language framework
typescript react

Styled Components

매 한 줄

"매 CSS 의 component 의 안에 — 매 tagged template literal 로 매 React component + style 의 atomic unit". Glen Maddern, Max Stoiber (2016). 매 CSS-in-JS 의 reference. 2026 매 styled-components v6+ 가 매 React Server Components 의 partial 지원 — 매 RSC native era 에서 매 Tailwind / vanilla-extract / CSS Modules 의 challenge.

매 핵심

매 mechanic

  • 매 tagged template literal: ``styled.button`color: red```.
  • 매 runtime 의 unique class name 의 generation, 매 stylesheet 의 inject.
  • 매 props-based dynamic styling: ${props => props.primary ? '#0070f3' : '#fff'}.

매 features

  • Theming: ThemeProvider context.
  • as prop: 매 polymorphic element.
  • Extending: ``styled(Button)`...```.
  • Animations: keyframes helper.
  • Global styles: createGlobalStyle.

매 응용

  1. React design system (Material-like component lib).
  2. Theme switcher (dark mode).
  3. Per-component style isolation.

💻 패턴

Basic styled component (TypeScript)

import styled from "styled-components";

const Button = styled.button<{ $primary?: boolean }>`
  padding: 8px 16px;
  border-radius: 6px;
  border: none;
  cursor: pointer;
  background: ${(p) => (p.$primary ? "#0070f3" : "#eee")};
  color: ${(p) => (p.$primary ? "#fff" : "#222")};
  &:hover { opacity: 0.9; }
`;

export default function App() {
  return <Button $primary>Buy</Button>;
}

Theme + ThemeProvider

import { ThemeProvider, DefaultTheme } from "styled-components";

const dark: DefaultTheme = { bg: "#111", fg: "#eee", accent: "#0af" };
const light: DefaultTheme = { bg: "#fff", fg: "#111", accent: "#06c" };

const Card = styled.div`
  background: ${(p) => p.theme.bg};
  color: ${(p) => p.theme.fg};
  padding: 16px;
`;

export default function App() {
  const [mode, setMode] = useState<"light" | "dark">("dark");
  return (
    <ThemeProvider theme={mode === "dark" ? dark : light}>
      <Card>Hello</Card>
    </ThemeProvider>
  );
}

Extending another styled component

const Base = styled.button`padding: 8px; border-radius: 4px;`;
const Danger = styled(Base)`background: #e00; color: white;`;

as polymorphic prop

const Box = styled.div`padding: 16px;`;
<Box as="section" /> // renders <section>
<Box as={Link} to="/x" /> // renders react-router Link

Keyframes animation

import styled, { keyframes } from "styled-components";
const pulse = keyframes`
  0% { transform: scale(1); }
  50% { transform: scale(1.1); }
  100% { transform: scale(1); }
`;
const Pulser = styled.div`animation: ${pulse} 1s infinite;`;

Global styles

import { createGlobalStyle } from "styled-components";
const Global = createGlobalStyle`
  body { margin: 0; font-family: Inter, sans-serif; background: ${(p) => p.theme.bg}; }
`;

css helper for shared mixin

import { css } from "styled-components";
const truncate = css`
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
`;
const Title = styled.h2`${truncate} font-size: 24px;`;

Next.js 14+ App Router (RSC) — 매 'use client'

"use client";
import styled from "styled-components";
export const Button = styled.button`color: red;`;
// app/layout.tsx — registry pattern for SSR
import StyledRegistry from "./StyledRegistry";
export default function Root({ children }) {
  return <html><body><StyledRegistry>{children}</StyledRegistry></body></html>;
}

매 결정 기준

상황 Approach
React SPA, 매 dynamic theming heavy styled-components / emotion
React Server Components 의 native vanilla-extract / CSS Modules / Tailwind
Utility-first, design system Tailwind CSS v4
Build-time zero-runtime vanilla-extract / Linaria
Component lib for distribution CSS Modules + tokens

기본값 (2026): 매 새 React project — Tailwind 의 default. styled-components 의 dynamic + theme heavy app 에 still-valid.

🔗 Graph

🤖 LLM 활용

언제: dynamic prop-based styles 의 heavy, theme switching 의 first-class, existing CSS-in-JS app. 언제 X: 매 RSC-first new app — runtime cost + 'use client' boundary 의 friction. 매 Tailwind / vanilla-extract 의 prefer.

안티패턴

  • Inline style prop interpolation 의 every render: 매 className thrash 의 perf hit. 매 attrs / static class 의 사용.
  • No $ prefix on props: 매 DOM warning (unknown attribute). 매 transient prop 의 사용 — $primary.
  • createGlobalStyle 의 multiple instances: 매 conflict.
  • SSR without registry: 매 FOUC. Next.js registry 의 setup.

🧪 검증 / 중복

  • Verified (styled-components.com docs v6, 2025; Next.js 14 App Router CSS-in-JS guide).
  • 신뢰도 A.

🕓 Changelog

날짜 변경
2026-05-08 Phase 1
2026-05-10 Manual cleanup — styled-components v6 + RSC era guidance