Search
Duplicate
🖌️

[React] emotion과 styled-component의 차이

간단소개
팔만코딩경 컨트리뷰터 (Library DB (속성)에 관계됨)에 관계됨
ContributorNotionAccount
주제 / 분류
React
태그
Scrap
8 more properties

emotion과 styled-component

1. 사용빈도 및 트렌드?

위 사이트에서 npm패키지들의 트렌드를 손쉽게 파악할 수 있다. 실제로 emotion과 styled-components 중 어떤 패키지를 많이 사용하는지 알아봅시다.
emotion이 v10에서 v11이 되면서 @emotion/core 에서 @emotion/react로 package rename이 이루어졌다. 하지만 아직 v10을 사용하는 개발자들이 있어서 두 패키지를 모두 포함해서 비교해 보았습니다.
두 패키지 모두 많은 개발자들에게 사랑받는 것을 확인할 수 있었습니다. 2022년 기준으로 emotion이 @emotion/core와 @emoiton/react를 합쳤을 때, styled-components보다 2배정도 많은 다운로드 수를 가지고 있습니다.

2. 코드에서의 차이

실제로 코드에선 어떤 차이가 있을지 알아보자. 우선 두 패키지를 모두 설치합니다. styled-components를 Typescript에서 사용하려면 @types/styled-components 패키지를 추가로 설치해주어야 합니다.
yarn add styled-components @emotion/react yarn add -D @types/styled-components
Shell
emotion을 사용할 때 추가 사항 아래의 pragma line을 파일 최상단에 추가해주어야 합니다.
/** @jsxImportSource @emotion/react */
TypeScript
.tsconfig.json 에는 아래와 같이 되어있어야 합니다.
{ "compilerOptions": { ... "jsx": "react-jsx", "jsxImportSource": "@emotion/react", } }
JSON
위 코드에서 @emotion/react로 작성했을 때, 특이한 점이 하나 있습니다. 순서상으로는 container가 먼저 적용되고 button이 추후에 적용될 것이라고 생각했는데, foreground color를 바꿔주는 버튼을 누르니 버튼내부의 color도 수정되었습니다.
찾아보니 같은 css속성이 있다면, 가장 최근에 변경된 속성으로 덮어씌워진다고 합니다.
@emotion/react에서 중복된 css속성이 있을 때, 최신 css속성으로 덮어씌워지는 장면
styled-components에서는 적용된 순서가 바뀌지 않는다
@emotion/styled emotion에도 styled API가 있어서 styled-components와 동일한 형태로 개발을 진행할 수 있기 때문에, 코드상의 비교는 무의미 합니다. 실제로 styled API를 활용하면 위와 같은 문제가 발생하지 않습니다.

3. 디버깅

css-in-js패키지들을 사용하면 class를 hash로 만들어서 class name을 겹치지 않도록 만들어줍니다. html태그가 몇개 없고 아주 작은 사이즈의 서비스라면 보는데 크게 어렵지 않습니다. 하지만 쉽지도 않습니다. 아래 사진을 보면, class name으로 판단이 불가능해서 내용을 보고 코드를 역으로 추적해야 합니다.
그래서 각 패키지들은 이러한 디버깅에 도움을 줄 수 있는 방법을 제공합니다.

1) emotion

emotion에서는 label태그를 활용해서 간단하게 해결할 수 있습니다. css 내부에 label 태그를 활용해서 디버깅 창에 원하는 이름이 나올 수 있게 할 수 있습니다. css-hash-label 과 같은 형태로 label이 나타나게 됩니다.
const container = (props: Props) => css` label: container; background: ${props.bgColor}; padding: 20px; & * { color: ${props.fgColor}; } `;
TypeScript

2) styled-components

Babel Macro를 활용하면 개발 버전에서 class name을 조금 더 자세하게 표현할 수 있습니다.
create-react-app을 활용해서 만든 프로젝트라면, styled-components/macro를 import해서 손쉽게 적용할 수 있습니다. 개발버전에서는 파일이름_컴포넌트이름_해쉬와 같은 형태로 보이게 됩니다.
import styled from 'styled-components/macro';
TypeScript

4. 패키지 의존성 및 번들 사이즈 확인해보기!

1) 패키지 의존성

Left : styled-component Right : emotion
yarn info "package name" "key"
TypeScript
위 명령어를 활용해서 각 패키지가 어떤 의존성을 가지고 있는지 확인할 수 있다. styled-components가 조금 더 많은 의존성을 가지고 있습니다. 공통된 라이브러리도 있었고, styled-components에서는 emotion api를 사용합니다.
yarn why "package name"
TypeScript
yarn why명령을 활용하면 패키지 사이즈를 확인할 수 있습니다. 빌드결과물이 아니기 때문에 큰 영향력 없는 비교이지만, 패키지 자체의 사이즈는 emotion이 조금 더 작았습니다.

2) 번들 사이즈

결론

신입 개발자 지원을 위해 회사들의 채용공고를 보면서 emotion을 쓰는 회사가 대부분이여서 차이가 궁금해서 포스팅을 시작했습니다. 포스팅을 하면서 느낀점은 굳이 나눠서 공부할 필요는 없다고 느꼈습니다. 두 패키지 모두 최근까지 지속적으로 업데이트 지원을 하고있고 성능상의 차이가 크게 없었습니다.
처음엔 global style과 두 패키지의 타입에 대한 차이를 다루려고 했으나 추후 팀에서 사용하는 기술 스택에 맞춰서 추가적으로 학습하면 된다고 생각했습니다. 하지만 포스팅 과정에서 yarn, webpack bundle analyzer, babel, 디버깅 과정에 대한 학습과 고민을 할 수 있어서 좋은 경험이였습니다.

Reference