ghdtjgus

우리가 결국 완성하고자 하는 디자인 시스템은 shadcn이라고 생각했다.
이는 shadcn이 컴포넌트별로 의존성을 다운로드하는데, 다른 라이브러리들과는 다르게 전체 패키지를 가져오지 않아 상당히 매력적이라고 생각했기 때문이었다.
 
그래서 shadcn에 대해서 깊이 이해하는 시간이 없어서는 안 된다고 생각했고, 이 과정에서 우리가 이때까지 의문이었던 점들을 해결해 나갈 수 있을 것 같다는 생각이 들었다.
shadcn을 가장 우선적으로 파악을 하려고 했는데, shadcn 자체가 radix ui에 상당히 의존적인 라이브러리이기 때문에 radix ui를 분석하고 난 후 shadcn을 분석할 수 있었다.
 
몇 주 안 됐지만 디자인 시스템 리서치를 하면서 가장 신기하고 의미 있었던 시간이 이번 주였던 것 같다.
사실, 이번 주, 다음 주 과제들은 구글링을 해도 나오지 않는다.
깃허브에 들어가서 코드 하나하나, PR 하나하나를 다 뜯어보면서 학습했기 때문에 보다 깊이 학습할 수 있었던 것 같다.
정보가 많지 않아 더 어려웠지만 더 성취감 있었던 것 같다.
 
서론은 여기까지 하도록 하고, radix ui, shadcn ui에 대해서 분석한 점들을 가져와보려고 한다.
 

컴포넌트별로 패키지를 관리해야 하는 이유

일단, 두 라이브러리를 알아보기에 앞서, 컴포넌트별로 패키지를 관리해야 하는 이유를 알아보도록 하자.
이는, 다른 팀원이 열심히 찾아온 자료에 있어서 그걸 들고 와봤다.
 
바로 인프랩 팀의 디자인 시스템 관련 테크 블로그 글이었다.
https://tech.inflab.com/20240224-design-system/#%EB%94%94%EC%9E%90%EC%9D%B8-%EC%8B%9C%EC%8A%A4%ED%85%9C-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0
 
중간쯤 보면 컴포넌트 단위 패키징이라는 내용이 바로 내가 찾는 거였다.
정리하자면, 가장 큰 이유는 버전 관리 측면에서였다.
우리 또한 아래와 같은 이유로 컴포넌트별 패키징이라는 방향으로 가기로 했다.

 

radix ui

radix ui는 headless 방식으로 구현된 라이브러리이다.
내부 구현이 궁금하다면 아래 radix-ui/primitives 레포지토리에 접속해보면 될 것 같다.
https://github.com/radix-ui/primitives
 
우리가 집중한 부분은 radix ui 자체 구현보다는 shadcn과 radix ui와의 관계이다.
그래서 radix ui보다는 radix ui와 shadcn ui와의 관계에, 그보다는 shadcn에 대해 더 집중해서 리서치를 했으니 그 부분을 감안해서 읽으면 좋을 것 같다.
 

shadcn ui

먼저, 나는 shadcn을 radix ui에 의존하는 cli 기반 디자인 시스템이라고 정의했다.
이 이유는 차차 알아보도록 하고, shadcn에서 컴포넌트를 가져와서 사용하는 방식을 먼저 알아보도록 하자.
 
일단 shadcn ui 공식 문서에는 아래와 같이 쓰여있다.

This is NOT a component library. It's a collection of re-usable components that you can copy and paste into your apps.

What do you mean by not a component library?

I mean you do not install it as a dependency. It is not available or distributed via npm.

Pick the components you need. Copy and paste the code into your project and customize to your needs. The code is yours.

Use this as a reference to build your own component libraries.

이 말들이 shadcn의 철학을 가장 잘 나타내는 듯해서 가져오게 되었다.
 
shadcn은 컴포넌트 라이브러리가 아니고, 사용자의 필요에 따라 복사 붙여넣기에 중점을 둔, 즉 사용자 편의를 상당히 생각한 라이브러리이다.
설치가 아닌 복사에 초점을 맞춰서 동작하는 라이브러리라고 할 수 있다.
 
아래 사진은 npm에 배포된 shadcn 관련 캡처본인데, 신기한 것은 컴포넌트 코드를 배포한 것이 아니었다.
그래서 리서치를 하면서 의문이 많이 생겼는데 추후 코드 분석하면서 점점 이해가 되기 시작했다.

 
shadcn에서는 컴포넌트 하나를 사용하고 싶다면 add 명령어를 사용한다.
예시로, 아코디언 컴포넌트를 가지고 오고 싶다면, 아래와 같이 터미널에 입력해주면 된다.

npx shadcn-ui@latest add accordion

 
이 add 명령어는 shadcn 측에서 cli 기반으로 동작하게 하기 위해서 따로 작성한 명령어이다.
실행하면 radix ui 관련 의존성만 설치된다.
그리고, accordion.tsx라는 파일이 생성되고 내부 구현 또한 해당 파일에 그대로 보여진다.
이는 아래 링크에서 확인해볼 수 있다.
https://github.com/ghdtjgus76/shadcn-ui/commit/3bdc8c0f69f5bfae460696014d3218d340eb4211
 
이렇게 하는 이유는 다른 라이브러리와는 다르게 스타일이나 컴포넌트 내부 구현 변경을 용이하게 하기 위한 것이었다.
위에서 언급한 철학과도 상당히 잘 맞는 것을 알 수 있다.
 
shadcn에서 컴포넌트를 가져온다는 것은 radix ui npm 상에 올라간 패키지들을 의존성으로 설치하는 것으로 이해할 수 있었다.
npm에 배포된 radix ui 관련 패키지들을 보면 아래와 같이 여러 패키지들이 배포된 것을 알 수 있었다.

 
이는, radix ui는 컴포넌트별로 npm에 패키지를 배포했고, shadcn에서는 add 명령어를 동작시키면 딱 radix ui npm에 배포된 해당 컴포넌트 패키지만을 다운로드해오는 것이었다.
그래서, npm에 배포된 shadcn 코드에는 컴포넌트가 포함되지 않았던 것이었다.
이렇게 의문이 반 정도는 해결되었다.
 
이제 이 동작들이 다 어떻게 돌아가는건지 더 궁금해졌다.
그래서 여기서 가장 중요한 역할을 하는 add 명령어를 조금 더 찾아봤다.
 
아래 링크는 add 명령어 관련 코드이다.
shadcn은 cli 기반 디자인 시스템이라고 언급했었는데 이 add 명령어 또한 cli 명령어 중 하나이다.
https://github.com/shadcn-ui/ui/blob/main/packages/cli/src/commands/add.ts
 
간단하게 동작을 설명해보자면, add 명령어가 외부 패키지 레지스트리, 여기서는 주로 radix ui에서 컴포넌트를 가져와서 프로젝트에 추가한다.
이를 위해서 fetchTree, resolveTree 함수를 사용해서 컴포넌트의 dependency를 가져오고, execa라는 함수를 통해 패키지 매니저를 호출해서 필요한 dependency들을 설치하게 된다.
 
여기서 또 의문이 생겼다.
그러면 각 컴포넌트별로 dependency가 따로 있을텐데 그건 어디서 볼 수 있는가?
그래서, shadcn의 PR을 다 들여다보며 dependency 관련 내용들을 찾기 시작했다.
 
의문점은 아래 PR을 확인하면서 해결되었다.
https://github.com/shadcn-ui/ui/pull/2219

apps/www/public/registry/index.json에서 각 컴포넌트별 의존성 정보를 확인할 수 있었다.
https://github.com/andrestone/shadcn-ui/blob/9b31619e34f3ecf1afb3540272770cfeef102b76/apps/www/public/registry/index.json
 
위에서 예시로 들었던 아코디언 관련 정보들을 가져왔는데, 내가 아코디언 컴포넌트를 설치했을 때도, @radix-ui/react-accordion 패키지만 설치된 것을 확인할 수 있었다.
즉, add 명령어를 실행하면 registry/index.json 내부에 있는 컴포넌트별 의존성을 찾아서 해당 의존성을 설치해주도록 했던 것이었다.
진짜 신기했다.

 
또 여기서 다른 팀원이 궁금해했던 점이 있었다.
radix ui는 headless 기반으로 동작하는 컴포넌트들이라고 했는데 디자인은 어디서 입히는가?였다.
나도 갑자기 궁금해져서 열심히 찾아봤다.
 
add 명령어를 통해 컴포넌트를 다운 받으면 accordion.tsx 파일이 생성된다고 했었는데, 해당 파일을 살펴보면서 이 의문점을 해결할 수 있었다.
해당 accordion.tsx 파일은 아래 파일과 동일한데, shadcn 측에서 따로 아래와 같이 className을 통해서 디자인을 입히는 것이었다.

 
이제, 조금은 더 이해가 됐지만 아직도 이해가 되지 않는 부분이 있었다.
그러면, add 명령어를 실행시키면 어떻게 컴포넌트 파일이 생성되는 것인지 이해가 되지 않는 부분이 있었다.
 
이 부분은 apps/www/pages/api/components.json이라는 파일을 보면서 확인할 수 있었는데, 아래와 같이 components.json 파일에 모든 컴포넌트 관련 의존성과 파일 내용을 정의해놨던 것이었다.
content에 들어가있는 내용이 바로 우리가 add 명령어를 실행시키면 다운로드되는 파일 내용이었다.

 
즉, 아코디언 컴포넌트 add 명령어를 실행시키면, name이 accordion인 accordion.tsx 파일이 components/ui dir에 생성되고, 해당 content가 accordion.tsx 파일에 담겨있는 것이었다.
 
여기까지만 해도... 정말 많은 걸 알게 됐지만, 해결되지 않는 의문들이 너무 많아서 일단은 우리도 cli 관련 실습을 해보기로 했다.
그렇게 shadcn처럼 cli 관련 실습을 해보고 나면 지금 풀리지 않는 부분들이 해결될 것 같다는 생각이었다.
약간 막막하기는 한데, 재미는 있을 거 같다.
 

+) base ui,  designed ui 둘 다 add 기능을 제공할 것인가?

이 주제를 가지고 약 2시간 반 동안 정말 열띤 토론을 했다.
사실, 이렇게는 shadcn도 하지 않기 때문에 왜 shadcn은 designed ui에만 add 기능을 제공하는지에 대해서 생각해볼 수 있었다.
 
add 기능을 제공한다는 것은 각 컴포넌트별로 파일을 생성할 것인데, base ui, designed ui 둘 다 add 기능을 제공하면, 버전 관리는 어떻게 할 것인가?라는 의문이 있었다.
 
예를 들어보자.
1. A가 base ui 1.0.0 버전 button을 사용하려고 한다. 그래서 add 기능을 통해 button 파일을 생성했다.
2. 이후 button 컴포넌트에 에러가 발생해서 1.0.1 버전 button을 다시 배포해두었다.
3. A가 이제는 designed ui button을 사용하려고 하는데 1.0.1 버전을 사용하려고 add 기능을 통해 button 파일을 생성했다.
A는 한 프로젝트 내에서 버전이 다른 두 버튼을 관리해야 하는 상황이 온 것이다.
 
그래서 우리는 둘 다 add 기능을 제공하기에는 무리가 있다고 생각했다.
결국 shadcn처럼 designed ui에서만 add 기능을 제공하자는 의견으로 수렴하게 되었다.
 

참고 자료

https://github.com/radix-ui
https://www.npmjs.com/search?q=@radix-ui
https://github.com/shadcn-ui
https://www.npmjs.com/package/shadcn-ui
https://ui.shadcn.com/
https://tech.inflab.com/20240224-design-system/#%EB%94%94%EC%9E%90%EC%9D%B8-%EC%8B%9C%EC%8A%A4%ED%85%9C-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0

profile

ghdtjgus

@gugu76

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

검색 태그