CSS와 브라우저

생각한 대로 보이지 않는 속성들과 글로벌 스코프로 이루어지는 선택자들, 그리고 클래스명이 겹쳐도 컴파일 에러가 아닌 자동 오버라이딩이 이루어지는 등 개발자가 예측하기 힘든 다양한 경우들이 CSS 작성을 힘들게 합니다.

특히 가장 문제가 되는 것은, 최근의 컴포넌트 형식의 개발 방법에 비해 CSS는 독립적으로 구성할 수 없다는 점입니다. 브라우저에서의 렌더링 과정에서 CSS를 포함하는 StyleSheet는 Javascript를 포함하는 Script와는 상관없이 과정이 진행되기 때문입니다. (브라우저의 종류와 CSS의 속성에 따라 약간의 차이는 있습니다.)

확실하게 스코프가 나누어지는 컴포넌트 형식의 개발 방법에서 이러한 StyleSheet와 Script의 괴리가 더 큰 혼란을 초래한 것입니다.

CSS in JS

CSS in JS 방식의 라이브러리들은 스코프를 확실히 나눌 수 있게 Javascript를 활용하여 해결합니다.

Javascript 변수로 선언된 CSS 내용을 실제 StyleSheet로 만들고, 랜덤 문자열로 이루어진 클래스명을 만들어 컴포넌트끼리 확실하게 분리될 수 있게 합니다. 게다가, Sass 문법까지 사용 가능하며 변수 사용이 가능하여 기존에 수많은 클래스의 중첩으로 제어하던 부분을 쉽게 제어할 수 있습니다.

이러한 방식은 위에서 서술된 많은 문제를 해결하며 개발자 경험을 향상시킵니다. 😍

또 다른 문제점

하지만 이런 접근은 또 다른 문제점을 야기합니다. StyleSheet의 Script 변환은 그만큼 HTML 파싱에 사용되는 Script의 코드가 늘어났다는 것을 의미합니다. 브라우저의 렌더링이 StyleSheet와 Script로 나누어 병렬처리 되던 것이 오직 Script로 이루어짐에 따라 그만큼 속도가 느려집니다.

또한, CSS가 먼저 제공되어 렌더링 시 형태가 잡혀있는 기존 방식에 비해 컴포넌트가 렌더링 되며 형태가 잡히기 때문에 원형의 모습이 잠깐 노출(FOUC) 됩니다. 이는 사용자 경험을 저하시킵니다.

FOUC(Flash of unstyled content)

스타일 시트가 적용되기 전 마크업 된 그대로의 모습이 잠깐 보이는 현상입니다.

매우 짧은 시간이지만 사용자 경험에 막대한 영향을 끼칩니다.

이러한 문제를 해결하기 위해 빌드 시, 사용하는 스타일을 뽑아서 StyleSheet를 생성해 올려주는 기능이 또 필요합니다. 여기에 SSR의 문제가 겹친다면 문제는 더욱 복잡해집니다. 프레임워크에서 이러한 이슈를 직접 지원하는 경우도 있지만 그렇지 않다면 직접 구현해야 할 것입니다.

마치며

CSS in JS 또한 새로운 문제를 발생시켰습니다. 편의성과 속도라는 두 마리 토끼를 잡으며 개발자와 사용자 모두가 행복한 경우의 수는 존재하지 않는 것일까요.. 😥

저는 @emotion/css를 사용하여 개인 프로젝트 Techblogposts 개발을 진행해 보았는데요, 볼륨이 크지 않아서 그런지 성능 이슈 보다는 개발의 편의성이 더 크게 다가왔습니다. FOUC 문제도 Next.js에서 친절한 예제와 함께 해결 방법을 제공해 주어서 해결할 수 있었습니다. (emotion 홈페이지에서 제공한 잘못된 예제로 삽질하느라 고생한 건 비밀 )

CSS in JS를 선택하여 개발자 경험을 향상시키고 버그의 가능성을 줄일 것인지, CSS를 선택하여 성능의 향상을 기대할 것인지는 결국 또다시 개발자의 선택인 것이라고 느꼈습니다.