프로젝트 진행 전 CSS 라이브러리를 선택함에 있어서 첫번째, 팀원들 모두 해당 라이브러리를 사용할 줄 아는가? 였고 두번째는 개발할때 얼마나 편리한가? DX를 생각했었다. 하지만 공부를 하다보니 프로젝트마다 runtime overhead를 고려해서 선택해야한다는것을 알게되었다.
🎈 런타임 오버헤드(runtime overhead) : 오버헤드란 어떤 처리를 위해 들어가는 간접적인 처리 시간을 뜻합니다. 예를 들어 A라는 처리를 단순하게 실행한다면 10초 걸리는데, 안전성을 고려하고 부가적인 B라는 처리를 추가한 결과 처리시간이 15초 걸렸다면, 오버헤드는 5초가 됩니다. 이글에서 런타임 오버헤드는 런타임에 CSS를 생성함으로써 벌어지는 성능하락을 말합니다.
런타임 CSS-in-JS 라이브러리는 실행환경에서 동적으로 스타일을 생성하기 때문에 복잡한 애니메이션을 다룬다면 성능저하가 있을 수 있다.
개발 모드에서는 런타임 도중
<style>
tag에 스타일을 생성해서 삽입한다.
배포 모드에서는 stylesSheet를CSSStylesSheet.insertRule 통해 바로CSSOM에 주입한다.
런타임에 동작하는 CSS-in-JS 라이브러리는 대표적으로 styled-components
와 emotion
이 있다. 제공하는 기능이나 성능은 큰 차이가 없고 사용하는 문법도 @emotion/styled
를 사용한다면 크게 차이가 없다.
차이점이라고 생각한다면 @emotion/react
만 사용한다면 번들크기에서 약간의 이점을 챙길 수 있고 CSS Props 문법을 사용할 수 있다는 점이다. 또한 SSR에서 사용시 별도의 설정이 필요없다는 장점이있다.
🎈 CSS Props를 사용하려면 JSX Pragma 설정 또는 바벨 설정을 변경해야하는 귀찮음이 있다.
제로 런타임 라이브러리 같은 경우 JS
파일에 작성된 CSS를 별도의 .css
파일로 변환 후 브라우저는 해당 스타일을 읽고 웹 페이지에 적용하는 방식으로 작동한다.
( 동적인 스타일에 대응할 수 있는 이유는 css variable을 사용하여 변경되는 항목에 대해 css variable만 변경하여 대응할 수 있기 때문이다. )
대표적인 라이브러리는 styled-components
과 동일한 문법을 사용하는
linaria와 vanilla-extract 등이 있다.
단점으로는 css 파일을 다루기 때문에 플러그인 설치 및 번들러 설정을 건드려야 해서 번거로울 수 있다는 점이다.
런타임에 스타일을 생성하지만 제로 런타임에 근접한 성능을 보장하는 라이브러리들이다. 대표적으로는stitches와 TailwindCSS 가 있다.
예를 들어, 동적 스타일링시, stitches
는 사전에 정의한 variants에 의한 스타일링만 가능하도록 제한하여 성능 이점을 챙겼다. 완전한 동적 스타일이 가능한것은 아니지만 적절한 타협점으로 본다.
또 다른 예는, Tailwind CSS는 사전에 설정한 config를 토대로 HTML,js,ts 등 템플릿을 스캔하고 해당 스타일을 생성한 다음 정적 CSS 파일에 작성하는 방식으로 작동한다.
Tailwind CSS는 이번버전에 번들사이즈가 엄청 커졌는데(원래 컸다.) minify 옵션 및 사용하지 않는 클래스를 제거해주는 기능(Perge CSS)을 통해 사이즈는 매우 감소한다.
단순히 개발 경험을 위해서 선택했던 라이브러리들이 사실은 런타임 동작 유무에 따라 성능차이를 만들고 있었다. 이런 사실을 기억하고 복잡한 스타일을 구현해야하는 프로젝트의 경우 해당 사항을 고려해서 UX 향상을 생각해야겠다.