Styled component 에서 Tailwind CSS 로

styled-components 신봉자이던 내가 Tailwind로 넘어온 이유


tailwind-visual.png

프론트엔드 개발을 처음 제대로 시작했을 때, 나는 styled-components를 굉장히 좋아했다.

당시 React 생태계에서는 CSS-in-JS가 굉장히 인기 있었고, 특히 styled-components는 “현대적인 React 스타일링 방식”처럼 느껴졌다.

무엇보다 좋았던 건:

  • CSS가 분리 된 깔끔해 보이는 JSX
  • 컴포넌트 단위 스타일링
  • props 기반 동적 스타일링

이었다.

// Button.tsx
<Button>
  Click me!
</Button>


// Button.style.ts
const Button = styled.button`
  padding: 8px 12px;
  border-radius: 8px;
  background: black;
  color: white;
`;

당시의 나는 이렇게 CSS가 완전히 분리 된 코드가 굉장히 “잘 구조화된 코드” 라고 느꼈다.

반면에 Tailwind를 처음 봤을 때는 거부감이 있었다.

<button className="px-4 py-2 rounded-md bg-black text-white">

이걸 보고 처음 든 생각은:

“JSX가 너무 지저분한데?”

였다.

className 안에 수많은 클래스가 나열된 모습은 가독성을 해치는 것처럼 느껴졌고, 심지어 과거에 많이 사용되던 Bootstrap과 비슷해 보여, 한때 발전했던 프론트엔드 스타일링 방식이 다시 과거로 돌아가는 듯한 인상마저 받았다.

시간이 지나면서 생각이 바뀌기 시작했다.

프로젝트 규모가 커지고, 협업이 많아지고, 디자인 시스템과 성능을 신경 쓰기 시작하면서 조금씩 다른 문제들이 보였다.

“깔끔한 JSX”가 꼭 유지보수하기 좋은 건 아니었다

styled-components를 오래 사용하다 보면 이런 코드가 점점 많아진다.

const Container = styled.div``
const Wrapper = styled.div``
const Inner = styled.div``
const Content = styled.div``

처음에는 JSX가 깔끔해 보여서 좋다. 그런데 시간이 지날수록 다른 문제가 보이기 시작했다.

네이밍 비용

styled-components의 가장 큰 숨은 비용은 모든 스타일에 이름을 붙여야 한다는 것이다.

CSS로는 그냥 div 하나면 끝나는 영역도, styled-components에서는 반드시 컴포넌트 이름을 정해야 한다. 그런데 의미 있는 이름을 매번 짓는 건 생각보다 어렵다.

실제로 동료 개발자들과 “이거 이름 뭘로 지을까요…” 와 같은 간단한 고민을 자주 나누곤 했다.

컨텍스트 스위칭 비용

이름 문제와 별개로, 스타일을 수정할 때마다 시선이 여러 번 이동한다.

  1. JSX 확인
  2. styled component 정의 찾기
  3. 다시 스타일 코드로 이동

이 과정을 반복하게 된다.

반면 Tailwind는 스타일이 JSX 근처에 그대로 존재한다.

<button
  className="
    px-4 py-2
    rounded-md
    bg-black text-white
  "
>
  저장하기
</button>

처음에는 className이 길어 보여도, 익숙해지니 오히려 읽는 속도가 훨씬 빨랐다.

Tailwind 를 활용한 컴포넌트 패턴화

예전에는 Tailwind가 단순히 “className 덕지덕지 붙이는 방식”이라고 생각했다.

그런데 실제로 사용해보니 생각보다 훨씬 구조적이었다.

특히:

  • clsx
  • cva
  • tailwind-variants

같은 도구와 함께 사용하면 컴포넌트 패턴화가 잘 된다.

const buttonVariants = cva(
  "rounded-md px-4 py-2 font-medium",
  {
    variants: {
      variant: {
        primary: "bg-black text-white",
        secondary: "bg-zinc-100 text-black",
      },
    },
  }
);

type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {
  variant?: "primary" | "secondary";
};

function Button({ variant = "primary", className, ...props }: ButtonProps) {
  return (
    <button
      className={cn(buttonVariants({ variant }), className)}
      {...props}
    />
  );
}

결국 중요한 건 “스타일을 어디에 적느냐” 보다, “얼마나 일관된 규칙으로 관리되느냐” 에 가까웠다.

런타임 이점

프로젝트 규모가 커질수록 스타일 시스템의 런타임 비용도 신경 써야 한다.

styled-components는 런타임에서 CSS를 생성하고 <style> 태그를 주입하는 방식이다. 즉, 컴포넌트가 렌더링될 때 스타일 처리 과정도 함께 발생한다.

반면 Tailwind는 대부분의 스타일이 빌드 타임에 미리 생성된다.

<button className="px-4 py-2 rounded-md bg-black text-white">

브라우저는 이미 만들어진 CSS 클래스를 바로 사용하기만 하면 된다.

결국:

  • 스타일 생성 비용 감소
  • 런타임 오버헤드 감소
  • 예측 가능한 CSS 구조
  • 디버깅 단순화

같은 장점이 생긴다.

특히 최근 프론트엔드 생태계는:

  • RSC(Server Components)
  • SSG
  • Astro Islands Architecture
  • Edge Rendering

처럼 “클라이언트 런타임을 최대한 줄이는 방향” 으로 가고 있다.

그런 흐름 속에서 Tailwind의 빌드 타임 기반 접근은 굉장히 자연스럽게 느껴졌다.

그 외의 이점들

shadcn/ui 와의 궁합

Tailwind를 쓰면서 가장 인상적이었던 건 shadcn/ui 같은 생태계의 등장이었다.

shadcn/ui 라이브러리는 버전에 종속되지 않고, 컴포넌트가 내 코드의 일부가 되므로, 자유롭게 수정할 수 있다.

Tailwind 클래스로 되어 있으니, 디자인 시스템에 맞춰 튜닝도 간편하다.

styled-components 기반 컴포넌트 라이브러리를 쓰면 “스타일을 override하는 방법” 을 매번 고민해야 했다. 하지만, Tailwind + shadcn 조합에서는 그냥 className을 바꾸면 끝이다.

훨씬 직관적이고 간편하게 커스터마이징이 가능해졌다.

AI와의 시너지

Tailwind는 LLM 챗봇 서비스로 다루기에 훨씬 적합한 형태다.

스타일이 마크업과 한 파일에 있으니, AI가 전체 컨텍스트를 한 번에 본다. 별도의 styled component 정의 파일을 찾아다닐 필요가 없다.

styled-components를 쓰는 프로젝트에서 AI에게 컴포넌트를 만들어 달라고 하면, 매번 네이밍 컨벤션이 들쭉날쭉하다. Wrapper인지 Container인지 Box인지. 반면 Tailwind는 그런 결정을 할 필요 자체가 없다.


Style 도구에 대한 생각

나는 여전히 styled-components가 잘못된 도구라고 생각하지 않는다. 동적 테마가 핵심인 프로젝트 혹은 이미 잘 굴러가고 있는 코드베이스라면 굳이 갈아엎을 이유가 없다.

다만 예전엔 “코드가 깔끔해 보이는가” 가 중요한 기준이었다면, 지금은 “수정할 때 얼마나 빨리 도달할 수 있는가”, “런타임 비용이 얼마나 드는가”, “팀과 AI가 같은 규칙 위에서 일할 수 있는가” 같은 것들을 더 보게 됐다.

마무리

styled-components를 쓰는 내내 네이밍, 컨텍스트 전환에 대한 불편함을 느끼고 있었음에도, 불편함에 대한 비용을 인식하지 못하고 있었다. 익숙한 방식이었기 때문에, 당연한 비용이라고 생각했다.

Tailwind를 공부하는 과정에서야 이를 비용으로 인식할 수 있었다. 앞으로 새 도구를 익힐 때 왜 이런 접근이 등장했고, 어떤 문제를 풀고 있는가 에 대해서 집중하는 자세를 가져야 할 것 같다.