-
리액트 스타일 라이브러리 (StyledComponents, Stitches, Tailwind) 비교web 2023. 6. 14. 03:32
리액트에서 컴포넌트를 스타일링할 때 사용할 수 있는 방식은 굉장히 다양하다. 일반적인 CSS, Sass, CSS Module, styled-components 등 다양한 스타일 방식이 존재한다. 그동안에는 가장 선호된다는 스타일 라이브러리인 styled-components를 많이 이용해왔는데, 리액트 스타일 라이브러리 중에서도, StyledComponents, Stitches, Tailwind에 대해 알아보고 비교해보고자 한다.
Styled Components
스타일드 컴포넌트란 '컴포넌트 이름을 쓰듯 스타일을 지정하는 것'을 의미한다. 스타일드 컴포넌트는 자바스크립트 파일 안에 스타일을 선언하는 방식이다. 이러한 방식을 CSS-in-JS라고 부르고, 이런 방식의 라이브러리는 정말 많지만 CSS-in-JS라이브러리 중에서 개발자들이 가장 선호하는 방식은 styled-components라고 한다.
스타일드 컴포넌트는 리액트의 컴포넌트 시스템에 대해서 CSS스타일링을 향상시키기 위한 고민의 결과이다.
공식 문서에 따르면, 스타일드 컴포넌트는 아래와 같은 기능을 제공한다.
- 자동으로 크리티컬 CSS 처리: styled-components는 페이지에서 렌더링된 컴포넌트를 추적하고 해당 스타일만 자동으로 삽입한다. 코드 분할과 결합되면 사용자가 필요한 최소한의 코드만 로드한다.
- 클래스 이름 버그 없음: styled-components는 스타일에 대해 고유한 클래스 이름을 생성하기때문에, 중복, 겹치거나 철자 오류에 대해 걱정할 필요가 없다.
- CSS 쉽게 삭제: 코드베이스에서 클래스 이름이 어디에서 사용되는지 알기 어려울 수 있습니다. styled-components는 모든 스타일링이 특정 컴포넌트와 연결되기 때문에 명확하게 보여준다. 컴포넌트가 사용되지 않고(도구를 통해 감지 가능) 삭제되면 해당 컴포넌트의 모든 스타일도 함께 삭제된다.
- 단순한 동적 스타일링: 프롭스나 전역 테마에 기반하여 컴포넌트의 스타일을 쉽고 직관적으로 조정할 수 있습니다. 수십 개의 클래스를 수동으로 관리할 필요가 없다.
- 편안한 유지 관리: 컴포넌트에 영향을주는 스타일을 찾기 위해 서로 다른 파일을 찾아야하는 일은 없습니다. 따라서 코드베이스의 크기에 관계없이 유지 관리는 매우 쉽다. 자동 벤더 프리픽싱: CSS를 현재 표준에 맞게 작성하고 styled-components가 나머지 처리를 자동으로 처리하도록 할 수 있다.
스타일드 컴포넌트는 아래와 같은 코드로 작성한다.
// The Button from the last section without the interpolations const Button = styled.button` color: #BF4F74; font-size: 1em; margin: 1em; padding: 0.25em 1em; border: 2px solid #BF4F74; border-radius: 3px; `; // A new component based on Button, but with some override styles const TomatoButton = styled(Button)` color: tomato; border-color: tomato; `; render( <div> <Button>Normal Button</Button> <TomatoButton>Tomato Button</TomatoButton> </div> );
이 때, TomatoButton처럼 Button스타일드 컴포넌트를 상속받아 사용할 수도 있다.
// Create an Input component that'll render an <input> tag with some styles const Input = styled.input<{ $inputColor?: string; }>` padding: 0.5em; margin: 0.5em; color: ${props => props.$inputColor || "#BF4F74"}; background: papayawhip; border: none; border-radius: 3px; `; // Render a styled text input with the standard input color, and one with a custom input color render( <div> <Input defaultValue="@probablyup" type="text" /> <Input defaultValue="@geelen" type="text" $inputColor="rebeccapurple" /> </div> );
스타일드 컴포넌트에서도 props를 내려줄 수 있는데, 이 때 transient props를 이용해서 내려줄 수 있다. transient props란 $로 시작하는 props를 사용하는 이유는 발생하는 warning을 없애주기 위함이다. 그냥 props로 내려주게 되면, props가 정의되지 않았다는 warning이 뜨는데, transient props는 DOM에서 인식하지 않고, 스타일드 컴포넌트에서만 사용할 수 있도록 하는 방법이다.
import styled from "styled-components"; export default function App() { return <UrgentMessage>현재 세일 중입니다!</UrgentMessage>; } function Message({ children, ...delegated }) { return <p {...delegated}>받은 메세지: {children}</p>; } const UrgentMessage = styled(Message)` background-color: pink; `;
뿐만 아니라, 스타일드 텀포넌트는 커스텀 컴포넌트와 일반 컴포넌트가 혼합 가능하다. 여기서의 delegated를 콘솔에 찍어보면,
{ className: 'OwjivF' }
위와 같이 나올텐데 이는 스타일드 컴포넌트가 동작되는 원리와 연결되어있다.
스타일드 컴포넌트가 렌더링되면, 임의의 클래스네임이 생성되고, Tag변수로 클래스네임이 prop으로 렌더링된다.
즉, 아래의 코드처럼 리액트가 렌더링되면 아래와 같은 코드로 변환이 된다는 것이다.
//리액트 import styled from "styled-components"; export default function App() { return ( <> <ContentImage alt="해맑게 웃고 있는 누렁이" src="https://images.unsplash.com/photo-1543466835-00a7907e9de1" maxWidth="200px" /> <ContentImage alt="해맑게 웃고 있는 누렁이" src="https://images.unsplash.com/photo-1543466835-00a7907e9de1" /> </> ); } const ContentImage = styled.img` display: block; margin-bottom: 8px; width: 100%; max-width: ${(p) => p.maxWidth}; `; //렌더링된 DOM <style> .JDMLk { display: block; margin-bottom: 8px; width: 100%; max-width: 200px; } .oXyedZ { display: block; margin-bottom: 8px; width: 100%; } </style> <img alt="해맑게 웃고 있는 누렁이" src="https://images.unsplash.com/photo-1543466835-00a7907e9de1" class="sc-bdzxRM JDMLk" /> <img alt="해맑게 웃고 있는 누렁이" src="https://images.unsplash.com/photo-1543466835-00a7907e9de1" class="sc-bdzxRM oXyedZ" />
Stitches
Stitches도 styled-components와 마찬가지로, CSS-in-JS 라이브러리의 일종이다. 스타일드 컴포넌트에 비해 빠른 런타임을 가지고 있다는 장점이 있다.
stitches는 아래와 같이 styled-components와 유사한 형식으로 작성할 수 있다.
const StitchesDiv = styled("div", { // 공통영역 border: "none", borderRadius: "9999px", padding: "10px 15px", fontSize: "13px", });
또한 stitches는 스타일드 컴포넌트와 다르게 props를 내려주는 방식이 보다 쉽다. stitches에서는 props나 theme을 불러오지 않고, variants기능을 이용한다.
// styled-components const Button = styled.button` ${(props) => props.color === 'violet' && ` background-color: 'blueviolet' `} ${(props) => props.color === 'gray' && ` background-color: 'gainsboro' `} `; // Stitches const Button = styled('button', { variants: { color: { violet: { backgroundColor: 'blueviolet' }, gray: { backgroundColor: 'gainsboro' }, }, }, }); () => <Button color="violet">Button</Button>;
tailwind
tailwind는 atomic css인데, 이는 미리 정의된 className을 조합해서 스타일링하는 방식이다. tailwindcss가 정해놓은 클래스 이름을 가져다가 쓰면 되기 때문에, 네이밍에 대한 고민을 하지 않아도 된다는 큰 장점이 있다. 또한 반응형 페이지를 만들기 쉽고 커스터마이징하기 좋다는 장점 또한 존재한다.
tailwind는 아래와같이 주어진 네이밍으로 class를 지정해서 스타일링을 해준다.
<div class="p-6 max-w-sm mx-auto bg-white rounded-xl shadow-lg flex items-center space-x-4"> <div class="shrink-0"> <img class="h-12 w-12" src="/img/logo.svg" alt="ChitChat Logo"> </div> <div> <div class="text-xl font-medium text-black">ChitChat</div> <p class="text-slate-500">You have a new message!</p> </div> </div>
비교
스타일링을 하는 여러가지 방식이 존재하는 만큼 사용성도 각각 다르다. styled-components는 가장 보편적으로 이용되는 스타일 라이브러리이고, stitches는 스타일드 컴포넌트보다 속도가 빠르며, tailwind는 클래스이름을 외우면 편리하고 반응형이 쉽다는 장점이 있다. 스타일 라이브러리의 각 장점을 생각해서 사용하면 좋을 것 같다.
참고자료
https://styled-components.com/docs
https://medium.com/@probablyup/introducing-transient-props-f35fd5203e0c
https://www.zigae.com/styled-components-abstract/
https://so-so.dev/web/css-in-js-whats-the-defference/
'web' 카테고리의 다른 글
[ 모던 리액트 : Deep Dive ] - 01장 리액트 개발을 위해 꼭 알아야 할 자바스크립트 (2) 2023.12.06 [ 리액트 ] 데이터를 효과적으로 관리하는 방법에 대하여 - 리액트 쿼리와 커스텀 훅 (0) 2023.07.21 리액트의 데이터 관리 React Query vs Asynchronous Recoil (7) 2023.05.08 리액트 반응형 완벽 구현하기 (1) 2023.04.23 프리티어 오류 해결하기 (1) 2023.04.16