유지보수 가능한 Tailwind와 shadcn/ui · 설명

Tailwind와 shadcn/ui의 유지보수성은 소유권에서 시작함

class 수보다 theme, primitive, composition과 page의 변경 권한을 분리해야 하는 이유를 설명합니다.

검증일 근거 자료

이 문서의 역할

이 글은 특정 화면을 고치는 절차가 아니라 구조가 필요한 이유를 다루는 설명 문서

Tailwind CSS를 쓰는 화면이 커지면 긴 className이 가장 먼저 눈에 들어온다. 그러나 class 문자열의 길이는 변경 비용을 직접 설명하지 못한다. 실제 비용은 같은 시각 결정을 몇 군데에서 다시 내려야 하는지, 어느 계층을 고쳐야 하는지 예측할 수 있는지, 변경이 접근성과 제품 동작에 어떤 영향을 주는지에서 발생한다.

문제는 class 수가 아니라 결정의 중복임

bg-white dark:bg-gray-950을 열 곳에서 사용하면 각 호출부가 theme 결정을 소유한다. 문자열을 CSS class 하나로 숨겨도 전역 selector와 cascade가 그 결정을 대신 소유할 뿐이다. 반대로 긴 utility 목록도 한 primitive가 상태, focus와 간격을 함께 관리한다면 변경 위치는 하나로 유지된다.

유지보수 가능한 구조는 "이 값을 어디에 둘 것인가"보다 "누가 이 결정을 바꿀 권한을 갖는가"에 답한다.

변경 질문변경 owner영향
light·dark 실제 색이 바뀌는가theme provider같은 semantic role을 쓰는 모든 UI
공개할 semantic utility가 바뀌는가token adapterTailwind가 생성하는 API
focus·ARIA·범용 시각 상태가 바뀌는가shared primitive모든 제품 consumer
업무 문구와 상태 연결이 바뀌는가product composition해당 제품 흐름
grid와 responsive placement가 바뀌는가page·feature해당 화면 배치

semantic token은 값이 아니라 변경 경계임

primary는 특정 초록색의 별명이 아니라 주 동작이라는 역할이다. 호출부가 bg-primary text-primary-foreground를 사용하면 light·dark 실제 값은 provider로 이동하고, foreground pair와 contrast는 theme 계약에서 함께 검토할 수 있다.

raw palette를 금지하는 목적도 색상 취향을 통제하는 데 있지 않다. 제품 전체의 의미 변화가 page별 색상 교체 작업으로 번지는 것을 막는 데 있다. chart renderer처럼 CSS variable을 쓸 수 없는 경계는 예외로 남기되 owner와 이유를 기록해야 같은 원칙이 유지된다.

shadcn/ui는 라이브러리보다 source 공급자에 가까움

shadcn/ui component는 설치 후 저장소가 소유한다. 이 모델은 제품에 맞는 variant와 접근성 보정을 허용하지만 upstream을 무조건 덮어쓸 수 없게 만든다.

따라서 update의 핵심은 버전을 올리는 일이 아니라 세 종류의 변경을 구분하는 일이다.

  • upstream의 접근성·API 개선은 local source에 병합해야 함
  • 제품에 맞춘 variant와 token 연결은 local 정책으로 보존해야 함
  • 생성 전용 계층이 아니라면 --overwrite가 local 판단을 제거할 수 있음

공용 primitive는 anti-corruption layer로 동작함

앱이 Base UI나 registry 세부 구현에 직접 의존하면 headless library의 API 변화가 제품 코드 전체로 퍼진다. @jongminchung/ui 같은 공용 계층은 접근성, 상태와 범용 variant를 한 번 해석하고 앱에는 안정된 primitive API를 제공한다.

이 경계가 유효하려면 공용 계층은 제품 이름을 몰라야 한다. destructive는 범용 intent이지만 repository-dangercheckout-warning은 제품 의미다. 여러 앱에서 모양이 같아도 변경 이유가 다르면 서로 다른 composition으로 남는 편이 안전하다.

검증은 계층과 같은 방향으로 확장됨

page layout은 formatter, typecheck와 대표 viewport로 확인할 수 있다. 공용 token이나 primitive를 바꾸면 영향이 여러 앱으로 확장되므로 package test, consumer build, keyboard interaction과 light·dark visual까지 검증 범위를 넓혀야 한다.

이 방식은 모든 변경에 최대 검사를 요구하지 않는다. 변경 owner가 넓을수록 증명 범위도 넓어진다는 대응 관계를 만든다.

다음 목적에 맞는 문서로 이동함

결론

Tailwind와 shadcn/ui의 유지보수성은 utility를 감추는 기법보다 변경 권한을 theme, primitive, composition과 page로 분리하는 구조에서 나옴. 이 구조가 있으면 새 요구가 들어왔을 때 수정 위치와 검증 범위를 함께 예측할 수 있음