bezier-react icon indicating copy to clipboard operation
bezier-react copied to clipboard

코어 라이브러리 변경

Open sungik-choi opened this issue 4 years ago • 8 comments

요약

현재 사용하고 있는 styled-components 를 새로운 라이브러리로 변경-혹은 개선-하면 좋겠습니다.

제안 이유

  • styled-components 는 다른 CSS-in-JS 라이브러리들이 그렇듯 런타임에 className을 생성합니다. 다양한 스타일이 존재하는 화면에서는 오버헤드가 발생할 수 있습니다.
  • 현재 styled-componentsThemeProvidertheme 대신 foundation 을 주입하기 위해, styled 를 Wrapping해서 사용하고 있습니다. styled-components 의 업데이트로 구현이 변경되면 작동하지 않을 문제를 안고 있고, 새로운 API가 생기면 그에 맞게 foundation 을 주입하도록 변경해야하는 등 유지보수가 까다롭습니다.

개선 방안

최근 zero-runtime 을 표방하는 CSS-in-JS 라이브러리들이 많이 등장했습니다. 빌드 타임에 디자인 시스템을 잘 만들기 위한 라이브러리들도 많아서, 이들을 잘 리서치해서 코어 라이브러리를 변경하고자 합니다. 아래와 같았으면 좋겠습니다.

  • 기존 bezier-react의 API에 잘 대응되었으면 좋겠습니다. 마이그레이션에 큰 비용이 들지 않았으면 합니다.
    • 가장 큰 고민입니다. 기존 styled-components 와 대응이 잘 되지 않으면 우리 라이브러리를 사용하고 있는 모든 프로젝트의 거대한 코드베이스를 모두 리팩토링해야 하는데, 너무나도 많은 리소스가 필요합니다. 리소스가 아깝지 않을 정도의 임팩트가 있지 않다면 변경은 지양하고 싶습니다.
  • 꾸준히 메인테이닝되는 라이브러리여야 합니다.
  • DX가 훌륭했으면 좋겠습니다. 타입스크립트가 100% 지원되고, 디자인 시스템을 쉽게 구축할 수 있는 API들이 제공되었으면 좋겠습니다.
  • 성능은 zero-runtime CSS-in-JS 라이브러리들끼리는 큰 차이가 없을 거라, 중요도가 그렇게 높다고 생각하지는 않습니다.

레퍼런스

라이브러리 목록

등의 라이브러리들이 있습니다. 장단점 비교는 코멘트로 작성하겠습니다.

참고할만한 링크

  • https://github.com/Shopify/foundational-design-system-proto/discussions/44
  • https://so-so.dev/web/css-in-js-whats-the-defference/
  • https://itnext.io/how-to-increase-css-in-js-performance-by-175x-f30ddeac6bce

sungik-choi avatar Apr 21 '22 08:04 sungik-choi

styled-components

라이브러리는 그대로 유지하는 방식입니다. 다만 성능 개선을 위해 현재 ThemeProvider를 통해 생성하는 테마 객체를 모두 CSS variable로 변경합니다.

chakra-ui에서 theme token(우리의 경우 foundation)을 CSS variable로 변경하여 얻은 장점을 아래와 같이 설명하고 있습니다.

Chakra UI now converts theme tokens (colors, font sizes, etc) to CSS Custom Properties (also known as "CSS variables").

CSS variables are now supported in all modern browsers, and we think they are useful to:

  • avoid prop interpolations;
  • avoid classname regeneration from emotion;
  • reduce runtime evaluation of token values in Theme context;
  • use theme token outside Chakra's component (embedded forms, markdown content, etc.)
  • CSS Variable을 영리하게 사용하면 불필요한 클래스 네임의 재생성을 막을 수 있습니다(관련 링크, #561). 따라서 런타임 오버헤드도 줄어듭니다.
  • 스타일이 동일하더라도 다른 스타일 컴포넌트라면 클래스 네임을 생성하기때문에, 스타일의 중복을 줄이는 방식으로도 오버헤드를 줄일 수 있습니다(#638, #632, #739 와 연관있습니다. 로우 레벨의 컴포넌트를 만들어야 하는 이유입니다).
  • CSS variable을 사용하기 때문에, foundation을 주입해주기 위해 styled-components를 Wrapping하여 사용할 필요가 없습니다. 레거시 지원을 위해 foundation은 우선 남겨두어야겠지만, CSS variable로 모두 마이그레이션이 이루어진다면 삭제해도 무방합니다.
  • 기존 ev(), border 같은 믹스인은 개별 토큰으로 분리하거나, 컴포넌트의 prop을 통해 사용하도록 변경할 수 있습니다.

장점

  • ✅ 기존 라이브러리를 그대로 이용하기 때문에 마이그레이션 비용이 현저히 적습니다.

단점

  • 🤔 아무래도 디자인 시스템 구축을 고려해서 만들어진 라이브러리들보다 DX가 떨어집니다.
  • ❌ 성능을 신경쓰지 않으면 zero-runtime 라이브러리들보다 런타임에서 성능이 떨어집니다.

총평

라이브러리를 pivot하지 않아, 마이그레이션 비용이 현저히 적기 때문에 가장 마음에 드는 안입니다. CSS variable을 사용할 경우 Intellisense가 잘 동작하도록 해야 합니다. (extension을 만들어보기?! like tailwind css)

sungik-choi avatar Apr 22 '22 04:04 sungik-choi

Stitches

near zero-runtime을 표방하는 라이브러리입니다.

장점

  • ✅ 퍼포먼스가 좋습니다. variants 기반으로, 사용하지 않는 prop interpolation을 방지합니다. (벤치마크 기준 50% 빠르다고 나와있음)
  • ✅ styled-components와 비슷한 다양한 API를 제공합니다.
  • ✅ 100% Typed API
  • ✅ 디자인 시스템 구현에 적합합니다. (토큰, 유틸 등)
  • ✅ 다른 zero-runtime 라이브러리와 다르게 별도의 webpack, babel 설정이 불필요합니다.
  • 🤔 언젠가 도입해보고 싶은 Radix UI와 같은 회사라, 궁합이 좋을 거 같습니다.

단점

  • ❌ API 함수의 '이름'은 비슷하나, Object 방식으로만 스타일링 할 수 있기 때문에 모든 styled를 사용하는 부분에 마이그레이션을 해주어야 합니다.
/* https://stitches.dev/blog/migrating-from-styled-components-to-stitches */
// 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>;
  • ❌ near zero-runtime이기 때문에 다른 라이브러리들보다 성능이 다소 떨어집니다.

총평

다양한 API 제공, 괜찮은 성능, 훌륭한 DX 제공 등 장점이 많지만 마이그레이션이 가장 큰 걱정입니다.

sungik-choi avatar Apr 22 '22 05:04 sungik-choi

emotion

styled-components와 양대 산맥을 이루는 CSS-in-JS 라이브러리입니다. (차이점에 대한 링크) 추가로 테스트 결과 약간의 차이점이 있었는데,

  • emotion 의 경우 스타일이 같다면 동일한 className을 생성합니다. 대신 styled(Something) 과 같이 styled-components에서 사용하는 방식으로 extends할 경우 그 스타일을 merge하여 새로운 className을 생성합니다. css prop 을 통해 스타일링하는 경우도 마찬가지입니다.
  • styled-components 의 경우 스타일이 같아도 다른 className을 생성합니다. 대신 extends할 경우, 이전 className은 유지한 채 extends한 스타일만 새로운 className으로 분리하여 추가합니다.

큰 차이가 있을지는 잘 모르겠네요.

장점

  • ✅ 강력한 css prop을 추가로 사용할 수 있습니다.
  • ✅ tagged template literal, object 스타일링 모두 잘 지원합니다.
  • ✅ styled-components에서 제공하는 API를 모두 제공합니다.
  • ✅ 별도의 설정 없이도 SSR 지원이 가능합니다.
  • ✅ 100% Typed API

단점

  • styled-components 대비 성능 이점은 거의 없다고 알려져 있습니다.
  • jsx 함수를 사용하기 위해 별도의 바벨 설정이 필요합니다.

총평

다양한 API를 지원해줘서 마이그레이션 하는 건 어렵지 않을 거 같습니다. object style을 잘 지원해준다는 장점이 있지만, 굳이 마이그레이션 해야할까..? 라는 생각이 드네요.

sungik-choi avatar Apr 22 '22 05:04 sungik-choi

vanilla-extract

Zero-runtime Stylesheets in TypeScript.

장점

  • ✅ 빌드 타임에 스타일이 모두 생성됩니다.
  • ✅ 100% Typed API
  • ✅ 디자인 시스템 구현에 적합합니다.
  • ✅ 꾸준히 메인테이닝 되고 있습니다.

단점

  • ❌ styled-components와 API가 아예 다릅니다.
  • ❌ 별도의 babel plugin, webpack plugin이 필요합니다.

총평

좋은 라이브러리는 맞지만, 상기한 단점때문에 사용하기가 어려워보입니다.

sungik-choi avatar Apr 22 '22 06:04 sungik-choi

compiled

A familiar and performant compile time CSS-in-JS library for React.

장점

  • ✅ 빌드 타임에 스타일이 모두 생성됩니다.
  • styled, css API 사용 방식이 styled-components와 거의 비슷합니다.
-import styled from 'styled-components';
+import { styled } from '@compiled/react';
  • ✅ 100% Typed API
  • ✅ 꾸준히 메인테이닝 되고 있습니다.

단점

  • ❌ 아직 베타 버전입니다.
  • ❌ 제공하는 API가 적습니다. 디자인 시스템을 구축하기 위한 API가 없습니다.
  • ❌ 별도의 babel plugin, webpack loader가 필요합니다.

총평

손쉬운 마이그레이션에 장점이 있지만, 디자인 시스템 친화적이지 않다는 점과 베타 버전이라는 점이 고민됩니다.

sungik-choi avatar Apr 22 '22 06:04 sungik-choi

linaria

Zero-Runtime CSS in JS

장점

단점

  • ❌ 디자인 시스템을 구축하기 위한 API는 없습니다.
  • ❌ 별도의 babel plugin, webpack loader가 필요합니다.

총평

zero-runtime css-in-js 솔루션 중에선 마이그레이션 비용이 가장 적을 거 같아 최선의 선택지로 보입니다. 테스트 후 성능이 드라마틱하게 좋아진다면 사용해봄직하다고 느꼈습니다.

sungik-choi avatar Apr 22 '22 07:04 sungik-choi

리서치 감사합니다! 🙇‍♂️ 저는 Styled-component를 그대로 사용하는 안이 가장 좋아 보입니다.

가장 큰 이유는 desk가 여전히 styled-component와 scss를 혼용해서 사용하고 있기 때문입니다. 이 상황에서 베지어 라이브러리를 교체하면, 총 세 가지의 css library를 사용하게 되고, 이 세 라이브러리 작동 방식의 충돌 (e.g. 베지어에서는 데스크 테마의 SCSS를 지원하기 위해 themeVars를 만들어 주입하고 있습니다. 이 외에도 여러가지 SCSS 를 위한 코드가 있습니다.)을 해결하는 코드를 작성해야 하며, side-effect가 크기 때문에 기능을 추가할 때에도 항상 염두하고 작성하게 될 것 같습니다.

인터페이스를 거의 비슷하게 사용할 수 있으면서 (마이그레이션 비용 낮음), 제로 런타임으로 큰 효과를 볼 수 있고, maintain 상황도 나쁘지 않은 Linaria를 고려해볼만 하다고 생각하지만, desk 입장에서 현재 SCSS를 안고 가야 하는 상황에 또 새로운 라이브러리를 추가하는 것은 지양해야 할 것 같습니다.

desk에서 SCSS를 모두 없애고 베지어에도 이를 지원하는 코드를 모두 없애는 것이 먼저일 것 같고, 그 다음에 라이브러리 교체를 생각해볼만 한 것 같습니다!

guswnsxodlf avatar Apr 22 '22 08:04 guswnsxodlf

리서치 감사합니다! 🙇‍♂️ 저는 Styled-component를 그대로 사용하는 안이 가장 좋아 보입니다.

👍 저도 같은 고민을 했습니다. 꽤 오랜 기간동안 scss, styled-components, +다른 라이브러리가 혼재된 상황이 될텐데, 관리가 쉽지 않을 거 같단 생각이 들었어요.

sungik-choi avatar Apr 22 '22 08:04 sungik-choi

styled-component를 그대로 사용합니다. CSS Variable에 관련한 별도의 이슈를 생성하고, 이 이슈는 Close합니다.

sungik-choi avatar Nov 09 '22 09:11 sungik-choi