본문 바로가기

FrontEnd

소프트웨어 엔지니어링 관점에서 바라본 CSS-in-js vs Tailwind CSS

반응형

소프트웨어 엔지니어는 항상 확장성과 재사용성을 찾습니다.

해당 기능들은 관심사의 분리 / 합성을 통해 구현됩니다.

위 두 가지 관점에서 Styled Component(Css-in-js 대표)와 Tailwind CSS를 비교해 봅니다.

Styled Components가 확장성 / 재사용성을 구현하는 방법

주 : 몇몇 경우 타입스크립트를 이용한 타입 안전성을 제공하기 위한 hack이 필요합니다.

1. ThemeProvider

마크업 구조, 컴포넌트를 변경하지 않으면서 디자인 토큰만 변경하기 위한 추상화 방법.

css 변수를 직접 임포트해도 되긴 됩니다.

https://styled-components.com/docs/advanced#theming

const Button = styled.button`
  color: ${props => props.theme.fg};
  border: 2px solid ${props => props.theme.fg};
  background: ${props => props.theme.bg};

  font-size: 1em;
  margin: 1em;
  padding: 0.25em 1em;
  border-radius: 3px;
`;

2. Variant (Props)

https://stitches.dev/docs/variants#adding-variants

해당 방법을 가장 잘 사용하는 stitches.js의 예시를 가져옴

여러 CTI를 하나로 프롭으로 뭉쳐 디자인의 변형을 제공.

* 클래스명을 사용하지 않음

const Button = styled('button', {
  // base styles

  variants: {
    color: {
      violet: {
        backgroundColor: 'blueviolet',
        color: 'white',
        '&:hover': {
          backgroundColor: 'darkviolet',
        },
      },
      gray: {
        backgroundColor: 'gainsboro',
        '&:hover': {
          backgroundColor: 'lightgray',
        },
      },
    },
  },
});

() => <Button color="violet">Button</Button>;

3. CSS variables

마크업은 그대로 두고 CSS 선언에 바인딩된 값을 바꾸는 방식으로 사용

참고 : https://itchallenger.tistory.com/592

function Backdrop({ opacity, color, children }) {
  return (
    <Wrapper
      style={{
        '--color': color,
        '--opacity': opacity,
      }}
    >
      {children}
    </Wrapper>
  )
}
//

4. CSS helper function

css를 관심사에 따라 잘 잘라서 합성할 수 있음

https://styled-components.com/docs/api#css

import styled, { css, keyframes } from 'styled-components'

const pulse = keyframes`
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
`

const animation = props =>
  css`
    ${pulse} ${props.animationLength} infinite alternate;
  `

const PulseButton = styled.button`
  animation: ${animation};
`

5. 캡슐화

테일윈드의 유틸리티 클래스만으로 구성하기 어려운게

아래와 같은 컨텍스트 기반 CSS임

스타일드 컴포넌트를 활용하면 컨텍스트에 영향받는 자기자신의 CSS를 해당 컴포넌트 내에 전부 캡슐화할 수 있음.

해당 방법은, 레이아웃을 포함한 컴포넌트가 좀 더 구체적인 컴포넌트라서,

추상적인 자식 컴포넌트의 스타일을 오버라이딩 한다는 관점에서 생각하면 별로이고

CSS의 캡술화 관점에서 생각하면 더 나은 방법인것 같음.

 

// TextLink.js
import { Wrapper as AsideWrapper } from '../Aside'
const TextLink = styled.a`
  color: var(--color-primary);
  font-weight: var(--font-weight-medium);
  ${AsideWrapper} & {
    color: var(--color-text);
    font-weight: var(--font-weight-bold);
  }
`;

6. 합성

compoition을 이용해 가장 제너럴한 TextLink, Div 등의 컴포넌트를 확장.

프로젝트 내의 모든 TextLink는 해당 컴포넌트를 사용해야 함.

즉, TextLink 컴포넌트가 단일 진실 원천(SSOT)임

(물론 컴포넌트 제약 관점에서 그렇다는거지 실제로 디자인 요구사항의  SSOT는 디자인 토큰임)

import TextLink from '../TextLink';
const SpookyTextLink = styled(TextLink)`
  font-family: 'Spooky Font', cursive;
`;

스타일드 컴포넌트 명은 최대한 스타일을 반영하며 일반적으로 만들어야 함.

예를 들어 BioArticleText 이런건 컨텐츠 컨텍스트가 반영되어 재사용성이 떨어짐.

컨텐츠, 컨텍스트, 컴포넌트(ex 카드 컴포넌트)에 대한 정보를 스타일드 컴포넌트에서 제거히야 합성 및 재사용성이 용이함.

Tailwind CSS가 확장성 / 재사용성을 구현하는 방법

테일윈드 CSS는 클래스명이라는 간접 계층을 두어 디자인 세부사항과, 마크업 구조가 독립적으로 진화할 수 있도록 함.

마크업(컴포넌트)은 스타일에 대한 정보와 스트럭처(구조)에 대한 정보가 반영되는 것이 당연하다는 멘탈 모델에서 온 것임

(이는, 스타일드 컴포넌트도 마찬가지며 렌더링 관심사까지 컴포넌트에 함께하면 리액트가 됨)

테일윈드 : 디자인 토큰과 마크업의 간접 계층

1. configuration

디자인 토큰을 이용해 설정을 바꿀 수 있음.

클래스명 API는 동일함

마크업(구조, 클래스명 포함)을 그대로 두고 스타일 변경

https://garden.mirahi.io/how-to-use-the-color-tokens-from-your-design-system-directly-in-tailwind-css/

 

How to use the Color Tokens from your Design System directly in Tailwind CSS

Find out how to use your design system's color tokens directly in Tailwind CSS, and how to keep those token colors updated in all Figma components and your code.

garden.mirahi.io

2. 스타일은 반드시 클래스명

스타일드 컴포넌트의 프롭스, 버라이언트는 마크업에 반영됨(탬플릿을 통한 추상화)

Tailwind CSS는 반드시 클래스명 기반으로 디자인의 관심사를 처리함.

const ConfirmButton = (props) => {
  const { className, ...rest } = props;
  return (
    <button
      className={classnames(
        'bg-black text-red-400',
        className,
      )}
      {...rest}
    ></button>
  );
});

 

3. 유틸리티 퍼스트 프레임워크 : (횡단 관심사 / 합성)

각 디자인 관심사를 클래스명으로 잘게 분리하여 합쳐서 사용 (예제는 trivial하므로 생략...)

  • Text sizes, colors, and weights
  • Border colors, widths, and positions
  • Background colors
  • Flexbox utilities
  • Padding and margin helpers

추가로 tailwind의 장점은 css를 최대한 thin하게 유지할 수 있다는 것임.
스타일드 컴포넌트는 컴포넌트의 증가 > 스타일 규칙의 증가임.

tailwind css는 큐레이팅된 css 규칙 룰 셋을 유지할 수 있음.

마치며 : 컴포넌트와 API

스타일드 컴포넌트, 테일윈드 CSS로 만드는 아토믹 컴포넌트는

데이터, 컨텍스트에 독립적인 것이 좋음.

대신 아토믹한 컴포넌트를 감싸는 컴포넌트를 하나 만들어서,

해당 컴포넌트에서 데이터에 대한 관심사를 처리하여,

하위 컴포넌트에 바인딩(렌더링)하는 로직을 따로 처리하는게 좋음

 

이를 통해 데이터, 컨텍스트, 통합에 대한 관심사에서 

렌더링, 마크업 구조, 스타일에 대한 관심사를 분리할 수 있음.

참고 : 

https://itchallenger.tistory.com/594

 

Styled-Components(CSS-in-js) 잘 활용하기

원문 보기 :https://www.joshwcomeau.com/css/styled-components/ The styled-components Happy Path styled-components is a wonderfully powerful styling library for React, and over the years I've learned..

itchallenger.tistory.com

https://fe-developers.kakaoent.com/2022/220303-tailwind-tips/

 

Tailwind CSS 사용기

카카오엔터테인먼트 FE 기술블로그

fe-developers.kakaoent.com

https://itchallenger.tistory.com/779

 

왜 Tailwind CSS를 사용해야 할까? 유틸리티 퍼스트 CSS를 이용한 확장성

Tailwind CSS 창시자가 Tailwind CSS를 만들게 된 배경을 살펴봅니다. 원문입니다 : https://adamwathan.me/css-utility-classes-and-separation-of-concerns/ CSS Utility Classes and "Separation of Concerns"..

itchallenger.tistory.com

 

반응형