이 글에서 정리하는 내용
Radix UI와 shadcn/ui를 경쟁 라이브러리처럼 오해해 선택 기준이 흐려지는 상황을 기준으로 원인을 좁히고, 실제 프로젝트에서 어떤 설정과 코드 구조를 확인해야 하는지 정리합니다. 단순 개념 소개가 아니라 오류가 난 순간 바로 확인할 순서와 선택 기준을 중심으로 설명합니다.
- Radix UI와 shadcn/ui는 무엇이 다른가
- 라이브러리를 쓰는 방식과 코드를 소유하는 방식
- 접근성, 디자인 수정, 유지보수 기준 비교
- Next.js와 Tailwind 프로젝트에서 선택 기준
- 처음 시작할 때 추천 흐름
Radix UI와 shadcn/ui는 무엇이 다른가

Radix UI와 shadcn/ui는 같은 층위의 대체재로만 보면 헷갈립니다. Radix UI는 접근성 primitive를 제공하고, shadcn/ui는 Radix 같은 primitive와 Tailwind 스타일을 조합한 컴포넌트 코드를 프로젝트에 가져와 소유하게 하는 방식에 가깝습니다.
먼저 내가 원하는 것이 headless primitive인지, 바로 수정 가능한 완성형 컴포넌트 코드인지 구분합니다. Tailwind 기반으로 디자인을 빠르게 맞추고 싶다면 shadcn/ui가 편하고, 스타일 시스템을 직접 얹을 계획이라면 Radix primitive부터 보는 편이 단순합니다. 관련 흐름은 Tailwind CSS 실무 로드맵도 함께 참고할 수 있습니다.
라이브러리를 쓰는 방식과 코드를 소유하는 방식
Radix UI는 패키지로 설치해 primitive API를 조합하는 방식입니다. shadcn/ui는 CLI로 컴포넌트 파일을 내 프로젝트에 복사하고, 그 코드를 직접 수정하면서 가져가는 방식입니다. 그래서 업데이트와 커스터마이징 책임도 다르게 봐야 합니다.
shadcn/ui 컴포넌트 안에서 Radix primitive를 쓰는 경우가 많기 때문에 둘을 완전히 분리된 선택지로 볼 필요는 없습니다. “Radix를 쓸지 shadcn/ui를 쓸지”보다 “primitive부터 직접 만들지, 이미 조합된 컴포넌트를 가져와 고칠지”가 더 실제적인 질문입니다.
// Radix UI는 primitive를 조합한다
// shadcn/ui는 프로젝트 코드로 복사해 수정한다
import { Dialog } from "@/components/ui/dialog";
위 import는 shadcn/ui 방식의 핵심을 보여줍니다. 컴포넌트가 외부 패키지 안에 숨는 것이 아니라 @/components/ui/dialog 같은 프로젝트 경로에 들어오므로, 팀의 디자인 규칙에 맞춰 코드를 직접 고칠 수 있습니다.
이 방식은 자유도가 높은 대신 “업스트림 업데이트를 자동으로 받는다”는 기대와는 거리가 있습니다. 복사된 컴포넌트는 내 코드가 되므로, 수정 내역과 디자인 토큰을 팀 기준으로 관리해야 합니다.
접근성, 디자인 수정, 유지보수 기준 비교
접근성 primitive와 키보드 상호작용을 직접 조합하고 싶다면 Radix UI가 기준이 됩니다. 반대로 버튼, 다이얼로그, 폼 같은 UI를 빠르게 가져와 Tailwind 클래스와 디자인 토큰을 수정하려면 shadcn/ui가 작업 속도를 줄여줍니다.
상태 스타일을 많이 다룬다면 Tailwind의 data/aria variant와도 연결됩니다. Radix가 노출하는 상태 속성을 Tailwind 클래스로 스타일링하는 구조를 이해하면 shadcn/ui 컴포넌트도 훨씬 덜 낯설게 수정할 수 있습니다. Tailwind CSS 상태 variant 사용법도 함께 볼 만합니다.
Next.js와 Tailwind 프로젝트에서 선택 기준

Next.js와 Tailwind 프로젝트에서 빠르게 일관된 UI를 만들고 싶다면 shadcn/ui로 시작하는 흐름이 현실적입니다. 이미 Tailwind 설정과 path alias가 잡혀 있다면 컴포넌트를 추가하고 바로 프로젝트 스타일에 맞게 수정할 수 있습니다.
반대로 자체 디자인 시스템을 깊게 만들거나 Radix primitive 위에 완전히 다른 스타일 레이어를 얹을 계획이라면 Radix UI를 직접 조합하는 쪽이 맞을 수 있습니다. 어느 쪽이든 접근성 동작을 직접 깨뜨리지 않는지 확인해야 합니다.
처음 시작할 때 추천 흐름
처음 시작할 때는 완성된 화면이 필요한지, primitive 조합 경험이 필요한지부터 정합니다. 빠르게 제품 화면을 만들고 수정할 계획이면 shadcn/ui, 컴포넌트 내부 구조를 직접 설계할 계획이면 Radix UI를 먼저 봅니다.
선택 기준은 “Dialog는 shadcn/ui로 시작 후 디자인 토큰 수정”, “특수한 combobox는 Radix primitive로 직접 조합”처럼 남겨두면 좋습니다. 그래야 팀 안에서 컴포넌트마다 선택 기준이 흔들리지 않습니다.
가능하면 선택 이유를 한 줄로 기록해 두세요. 예를 들어 “프로젝트 UI는 shadcn/ui를 기본으로 사용”, “복잡한 focus 동작은 Radix 문서 기준으로 확인”, “복사한 컴포넌트는 팀 코드로 관리”처럼 남기면 됩니다.
피해야 할 방식은 둘을 경쟁 라이브러리처럼만 보고 한쪽을 무조건 배제하는 것입니다. 실제로는 shadcn/ui 컴포넌트가 Radix primitive를 활용하는 경우가 많으므로, 역할 차이를 알고 쓰는 것이 더 중요합니다.
컴포넌트를 고른 뒤에는 keyboard navigation, focus 처리, disabled 상태, 모바일 터치 동작을 확인합니다. 모양만 맞았다고 끝내면 primitive가 제공하던 접근성 장점을 수정 과정에서 잃을 수 있습니다.
이 글의 핵심은 Radix UI와 shadcn/ui 중 하나가 무조건 더 좋다는 결론이 아닙니다. Radix는 primitive, shadcn/ui는 가져와 수정하는 컴포넌트 코드라는 차이를 이해하고 프로젝트 속도와 소유권 기준에 맞게 고르는 것입니다.
함께 확인하면 좋은 기준
이 글과 관련해 실제 작업에서 같이 확인하면 좋은 기준입니다.
- shadcn/ui Docs: 적용 전 현재 문서의 권장 API, 설정 옵션, 제한 사항이 글의 설명과 맞는지 확인합니다.
- Radix UI Primitives Docs: 적용 전 현재 문서의 권장 API, 설정 옵션, 제한 사항이 글의 설명과 맞는지 확인합니다.
- 비슷한 오류를 구분할 때는 발생 위치, 실행 환경, 재현 조건을 먼저 분리해 확인합니다.
- 프로젝트에 적용할 때는 기존 코드 구조, 의존성 버전, 배포 환경에서 같은 기준이 유지되는지 확인합니다.