CSS-in-JS와 Tailwind CSS 유지보수와 성능 관점에서의 비교

웹 개발을 하다 보면 항상 고민하게 되는 스타일링 방식은 바로 CSS-in-JS와 Tailwind CSS입니다. 

저는 두 가지 방식을 모두 실무 프로젝트에 적용해 보았고, 각각의 장단점을 뼈저리게 경험했는데요. 

오늘은 많은 개발자분들이 고민하시는 유지보수성과 성능이라는 두 가지 핵심 관점에서 CSS-in-JS와 Tailwind CSS을 비교해 보려고 합니다.

어떤 방식이 내 프로젝트에 더 맞을지 고민이셨다면 이번 글이 작은 힌트가 되었으면 좋겠습니다.


CSS


2. 개발 생산성과 유지보수성에서 나타나는 결정적인 차이

처음 CSS-in-JS 방식을 접했을 때는 정말 신세계였습니다. Styled Components나 Emotion 같은 라이브러리를 사용하면 자바스크립트 변수나 상수를 스타일 코드 안에서 그대로 쓸 수 있거든요.

제가 직접 해보니 프론트엔드 개발자 입장에서 이보다 직관적일 수는 없었습니다.

컴포넌트의 상태에 따라 배경색을 바꾸거나 크기를 조절해야 할 때, 별도의 클래스명을 복잡하게 조합할 필요 없이 스타일 정의 내부에 삼항 연산자나 props를 바로 주입하면 끝이었으니까요.

게다가 스타일이 컴포넌트 단위로 캡슐화되기 때문에, 다른 파일의 CSS와 클래스명이 겹쳐서 디자인이 깨지는 이른바 '스타일 오염' 걱정이 완전히 사라진다는 게 가장 큰 장점이었습니다.

프로젝트 규모가 커져도 내가 수정하는 컴포넌트의 스타일만 보면 되니 심리적인 안정감이 아주 높았습니다.

반면 Tailwind CSS는 접근 방식이 완전히 다릅니다. 미리 정의된 유틸리티 클래스를 HTML 태그에 직접 나열하는 방식이죠. 처음에는 코드가 너무 지저분해 보이고 외워야 할 클래스명이 많아서 거부감이 들기도 했습니다.

하지만 이 방식에 익숙해지고 나니 유지보수 측면에서 예상치 못한 강력한 장점을 발견할 수 있었습니다. 바로 '스타일 코드를 찾아 헤매는 시간'이 사라진다는 점입니다.

CSS-in-JS는 스타일을 수정하려면 컴포넌트 파일 하단이나 별도의 스타일 파일로 이동해서 코드를 확인해야 합니다. 반면 Tailwind CSS는 HTML 마크업 구조를 보는 동시에 스타일을 바로 읽고 수정할 수 있습니다.

새로운 팀원이 프로젝트에 합류했을 때도, 스타일 가이드라인을 공유하거나 복잡한 CSS 구조를 설명할 필요 없이 공식 문서의 클래스명만 알면 누구나 동일한 규칙으로 일관성 있게 코드를 작성할 수 있어서 협업 관점의 유지보수성이 대단히 뛰어났습니다.


3. 런타임과 빌드타임 성능이 가져오는 반전

성능 관점으로 넘어가면 두 기술의 명암이 더욱 확실하게 갈립니다. 이 부분은 프로젝트의 사용자 경험과 직결되기 때문에 기술 스택을 정할 때 가장 신중하게 따져봐야 하는 영역입니다.

우선 CSS-in-JS의 가장 큰 아킬레스건은 런타임 오버헤드입니다. 브라우저가 자바스크립트 코드를 실행하는 시점에 스타일을 동적으로 계산하고, 이를 다시 HTML의 스타일 태그로 주입하는 과정을 거치게 됩니다.

사용자가 버튼을 클릭해서 컴포넌트의 상태가 바뀔 때마다 자바스크립전 엔진은 새로운 스타일을 연산하고 적용하느라 바빠집니다.

화면에 보여줄 컴포넌트가 몇 개 없을 때는 체감이 안 되지만, 수백 수천 개의 데이터가 들어간 복잡한 대시보드나 리스트 화면에서는 이 과정 때문에 미세한 화면 버벅임이나 렌더링 지연이 발생할 수 있습니다.

특히 서버 사이드 렌더링 환경에서 런타임 CSS-in-JS를 사용하려면 서버에서 생성된 스타일을 클라이언트에 동기화하는 추가적인 설정과 과정이 필요해서 초기 로딩 속도 측면에서도 불리한 점이 있습니다.

여기에 반해 Tailwind CSS는 성능 면에서 압도적인 우위를 점합니다. Tailwind CSS는 런타임에 아무런 연산을 하지 않습니다.

빌드하는 시점에 내가 사용한 유틸리티 클래스만 쏙쏙 골라내서 하나의 순수한 static CSS 파일로 컴파일해 주기 때문입니다.

브라우저는 그저 이미 완성된 가벼운 CSS 파일 하나만 다운로드해서 읽으면 되므로, 자바스크립트 연산으로 인한 병목 현상이 아예 발생하지 않습니다.

실제로 프로젝트를 빌드해 보면 전체 CSS 파일 용량이 수십 킬로바이트 수준으로 매우 작게 유지되는 것을 볼 수 있습니다.

초기 페이지 로딩 속도가 중요하고, 저사양 기기나 모바일 환경에서도 부드러운 화면 전환을 보장해야 하는 서비스라면 성능 관점에서는 Tailwind CSS가 훨씬 유리한 선택이 될 수밖에 없습니다.


4. 직접 경험하며 느낀 가독성과 코드 비대화 문제

기술의 장점만 보고 도입했다가 나중에 후회하기 쉬운 포인트가 바로 가독성과 장기적인 코드 관리 문제입니다. 이 부분은 개발자마다 성향 차이가 극명하게 갈리는 영역이기도 합니다.

Tailwind CSS를 쓰면서 가장 힘들었던 순간은 복잡한 반응형 디자인이나 다크 모드, 그리고 다양한 가상 선택자를 한 번에 적용할 때였습니다.

하나의 태그 안에 수십 개의 클래스명이 길게 늘어서다 보니, 나중에는 HTML 태그 구조가 한눈에 들어오지 않고 코드가 옆으로 끝없이 길어지는 현상이 생겼습니다.

물론 컴포넌트 단위로 쪼개서 관리하면 어느 정도 완화되지만, 마크업 자체가 비대해지는 느낌은 지우기 어려웠습니다.

또한 복잡한 조건부 스타일링을 구현할 때는 clsx나 tailwind-merge 같은 외부 라이브러리의 힘을 빌려 클래스 문자열을 동적으로 조합해야 하는데, 이 과정이 생각보다 매끄럽지 않고 코드가 지저분해지는 원인이 되기도 했습니다.

반대로 CSS-in-JS는 코드가 정말 깔끔하게 정돈됩니다. 마크업 영역에는 가독성 좋은 컴포넌트 이름만 남겨두고, 세부적인 스타일은 아래로 격리하기 때문에 전체적인 코드의 가독성이 아주 훌륭합니다.

변수나 테마 시스템을 활용한 디자인 시스템 구축도 유연하게 대처할 수 있어서 대규모 엔터프라이즈 레벨의 웹 애플리케이션을 정교하게 다듬을 때는 CSS-in-JS가 주는 코드 구조의 깔끔함이 큰 위안이 되었습니다.


5. 내 프로젝트에 맞는 최선의 스타일링 선택 기준

두 기술 모두 훌륭한 도구이며 대세로 자리 잡은 이유가 확실하기 때문에, 무조건 한쪽이 옳다고 단정 지을 수는 없습니다. 내가 만들고자 하는 서비스의 성격과 팀의 구성원 성향에 따라 선택의 기준을 가져가는 것이 좋습니다.

동적인 인터랙션이 엄청나게 많고, 자바스크립트 데이터와 테마 변수를 유연하게 결합해야 하며, 코드의 깔끔한 구조와 캡슐화를 최우선으로 생각한다면 여전히 CSS-in-JS는 매력적인 선택지입니다.

런타임 오버헤드가 걱정된다면 최근 등장하고 있는 컴파일 타임(Zero-runtime) CSS-in-JS 라이브러리를 대안으로 검토해 보는 것도 좋은 방법입니다.

만약 서비스의 초기 로딩 속도가 무엇보다 중요하고, 동적 연산이 적은 정보성 페이지나 커머스 사이트이며, 스타일 코드 작성을 빠르게 끝내고 비즈니스 로직에 집중하고 싶다면 Tailwind CSS를 적극 추천드립니다.

특히 스타일링에 대한 개인의 취향을 타지 않고 누구나 정해진 규칙대로 빠르게 코드를 읽어 내려갈 수 있다는 점은 협업 속도를 끌어올리는 데 엄청난 무기가 됩니다.

저 역시 프로젝트의 목적에 따라 매번 다른 선택을 내리곤 합니다.

기술의 트렌드를 무조건 쫓기보다는 우리 팀의 현재 상황과 서비스가 마주한 성능 병목이 어디에 있는지를 면밀히 파악하고 도구를 선택하는 안목이 가장 중요한 것 같습니다.

여러분도 현재 진행 중인 프로젝트의 특성을 고려하셔서 최선의 선택을 내리시길 바랍니다.


이런 기술적인 비교와 고민의 과정이 담긴 글이 비슷한 고민을 하시는 개발자분들께 조금이나마 도움이 되었으면 좋겠습니다.

Post a Comment

다음 이전