shadcn/ui, 디자인 시스템의 소유권을 돌려받다

shadcn/ui, 디자인 시스템의 소유권을 돌려받다

node_modules 안에 갇혀 있던 컴포넌트를 내 프로젝트로 꺼내오는 순간, 디자인-개발 협업의 규칙이 바뀝니다.

shadcn/ui 디자인 시스템 Radix UI Tailwind CSS 컴포넌트 라이브러리 코드 소유권 프론트엔드 개발 디자인 토큰
광고

버튼 하나 고치려고 override 지옥을 헤맨 적 있나요

프론트엔드 개발자라면 한 번쯤 겪어봤을 겁니다. Figma에서 디자이너가 넘긴 버튼의 border-radius6px인데, 쓰고 있는 컴포넌트 라이브러리의 기본값은 4px. MUI라면 sx prop이나 createTheme을 뒤지고, Chakra라면 extendTheme에 들어가 override 체인을 타야 합니다. 그러다 다크 모드에서 hover 색상이 미묘하게 달라서 다시 한번 문서 검색… 이 루프가 끝없이 반복됩니다. 결국 "라이브러리가 나를 쓰는 건지, 내가 라이브러리를 쓰는 건지" 모르겠다는 한탄이 나오죠.

shadcn/ui의 핵심 철학: "코드는 너의 것이다"

shadcn/ui는 이 문제를 정면으로 뒤집습니다. Velog의 정리 글이 잘 짚었듯, 이 도구는 npm 패키지가 아닙니다. npx shadcn@latest add button을 실행하면 Radix UI 프리미티브 + Tailwind CSS로 구성된 button.tsx 소스코드가 @/components/ui/ 디렉토리에 그대로 복사됩니다. node_modules 안이 아니라 내 프로젝트 안에 파일이 생기는 거죠.

사실 이건 "라이브러리를 쓴다"보다 "잘 만들어진 보일러플레이트를 출발점으로 삼는다"에 가깝습니다. 버튼의 padding이 시안과 2px 어긋나면? 파일을 열어 직접 고치면 됩니다. override 문서를 뒤질 필요도, !important 폭탄을 던질 필요도 없습니다.

사용자 입장에서는: 디자인-개발 갭이 줄어든다

예민한 프론트엔드 개발자로서 이 접근 방식이 가장 반가운 지점은 디자인 토큰과의 정합성입니다. shadcn/ui는 초기화 시 CSS 변수 방식(hsl(var(--primary)))을 기본으로 권장하고, components.json에서 베이스 컬러(Slate, Zinc, Stone 등)를 선택하게 합니다. 이건 단순한 색상 선택이 아닙니다. Figma에서 정의한 디자인 토큰을 CSS 변수로 1:1 매핑할 수 있는 구조적 통로가 처음부터 열려 있다는 뜻입니다.

기존 라이브러리들도 테마 커스터마이징을 지원하지만, 그 과정이 createTheme → ThemeProvider → override → variant 같은 추상화 레이어를 거칩니다. Figma Dev Mode에서 뽑아낸 토큰 값을 적용하려면 이 레이어들을 모두 이해해야 하죠. shadcn/ui는 이 중간 계층을 없앱니다. CSS 변수를 바꾸면 끝, 컴포넌트 파일을 열면 끝. "이거 px 단위로 봐야 해요"라는 말이 실제로 통하는 환경이 만들어지는 겁니다.

번들 사이즈, 진짜로 필요한 것만 남긴다

성능 관점에서도 이 모델은 매력적입니다. MUI를 npm install하면 사용하지 않는 DataGrid, Stepper, SpeedDial 등 수십 개 컴포넌트의 코드가 node_modules에 들어옵니다. 물론 tree-shaking이 동작하지만, 완벽하지 않은 경우가 종종 있고요—특히 CSS-in-JS 런타임이 끼어 있으면 Lighthouse 점수에서 TBT(Total Blocking Time)가 눈에 띄게 올라갑니다.

shadcn/ui는 애초에 설치하지 않은 컴포넌트는 프로젝트에 존재하지 않습니다. buttondialog만 추가했으면 그 두 파일만 빌드에 포함됩니다. 번들 사이즈 최적화를 "설정"이 아니라 "구조"로 해결하는 셈이죠. Core Web Vitals에 민감한 프로젝트라면 이 차이가 꽤 체감됩니다.

그렇다면 단점은 없나? 솔직히 말하면…

"코드 소유권"은 양날의 검입니다. 라이브러리 업데이트를 npm update 한 줄로 받을 수 없다는 뜻이기도 하니까요. Radix UI에 접근성 버그 패치가 나왔다면? 직접 확인하고, 내 프로젝트의 컴포넌트 파일에 수동 반영해야 합니다. 팀 규모가 커지면 "누가 이 Button 컴포넌트를 언제, 왜 수정했는지" 추적하는 거버넌스 비용도 생깁니다.

또 하나, Figma에서 볼 때는 괜찮았는데 실제로 구현하면 드러나는 문제가 있습니다. shadcn/ui의 기본 스타일 프리셋(Default, New York)은 훌륭한 출발점이지만, 결국 프로젝트 고유의 디자인 시스템으로 확장하는 건 온전히 팀의 몫입니다. 디자인 시스템 구축 경험 없이 shadcn/ui를 도입하면, 컴포넌트 파일이 제각각으로 수정되어 오히려 일관성이 무너지는 역설이 발생할 수 있습니다.

시사점: "소유권"이라는 키워드가 말하는 것

Dev.to에서 한 프론트엔드 개발자가 자신의 커리어 확장기를 쓰면서 "도구를 목적이 아닌 수단으로 보라"고 했는데, shadcn/ui의 철학과 묘하게 겹칩니다. MUI나 Chakra가 "완성된 집을 임대"하는 모델이라면, shadcn/ui는 "좋은 자재와 설계도를 사서 직접 짓는" 모델입니다. 소유권을 가진다는 건, 유지보수 책임도 함께 가진다는 뜻입니다.

결국 shadcn/ui가 던지는 질문은 이겁니다: "당신의 팀은 컴포넌트 코드를 소유할 준비가 되어 있습니까?" 디자인 토큰 체계가 잡혀 있고, 코드 리뷰 문화가 있고, Tailwind 유틸리티 클래스에 팀원 모두가 익숙하다면—이건 디자인 시스템 구축의 가장 실용적인 출발점이 될 수 있습니다. 그렇지 않다면, 먼저 해결해야 할 숙제가 무엇인지 알려주는 리트머스 시험지가 됩니다.

전망: Copy-Paste 패러다임의 확산

shadcn/ui의 성공은 이미 생태계에 영향을 미치고 있습니다. 유사한 "코드 복사" 모델이 Vue(shadcn-vue)와 Svelte 등으로 퍼지고 있고, Vercel의 v0 같은 AI 기반 UI 생성 도구도 shadcn/ui 컴포넌트를 기본 출력 포맷으로 채택했습니다. Container Queries나 :has() 같은 새로운 CSS 기능이 안정화되면, Tailwind 유틸리티 클래스 기반의 이 접근 방식은 더 강력해질 겁니다.

"사실 이건 flexbox로 해결되지만…"이라며 매일 밤 1px을 잡는 우리 같은 사람들에게, shadcn/ui는 드디어 "내 코드니까 내가 고친다"는 당연한 명제를 디자인 시스템 레벨에서 실현시켜 주는 도구입니다. 다만, 그 자유에는 책임이 따릅니다. 소유권을 돌려받았으니, 이제 잘 관리하는 건 우리 몫입니다.

출처

더 많은 AI 트렌드를 Seedora 앱에서 확인하세요