mason
mason-log.

GitHub 로그인 중

React Bits에 MasonEffect를 제안하며 배운 것.
mason

masonfe-hyunsu

🐣 1. 개요 : React Bits에 컴포넌트를 제안해 보기.

React Bits에 MasonEffect를 제안해 보라는 메시지
  • React Bits는 애니메이션과 인터랙션을 포함한 React 컴포넌트의 소스 코드를 제공하는 오픈소스 프로젝트다.

  • 이전 포스팅에 달린 의견을 계기로 내가 만든 MasonEffect를 React Bits 방식에 맞춰 제안해 보기로 했다.

  • 처음에는 컴포넌트 하나를 옮기면 될 거라 생각했다. 저장소를 살펴보니 실제 작업은 다음 영역까지 이어졌다.

    • JavaScript, TypeScript와 CSS, Tailwind 조합에 맞춘 4가지 variant

    • jsrepo, shadcn CLI가 읽는 레지스트리

    • 컴포넌트 메타데이터와 문서

    • 프로젝트의 기여 정책

  • 결과적으로 새 컴포넌트는 받아들여지지 않았지만, 코드를 작성하는 일과 오픈소스에 기여하는 일은 다르다는 점을 분명하게 배웠다.

  • 이 포스팅에서는 구현 과정에서 확인한 기술 구조와 기여 절차에서 놓친 부분을 함께 정리해 본다.


👀 2. 코드보다 먼저 확인할 것.

  • 저장소를 fork한 뒤 디렉터리와 기존 컴포넌트의 작성 방식을 먼저 살펴봤다.

  • UI 컴포넌트 저장소는 화면에 보이는 코드만 맞춘다고 끝나지 않는다. 프로젝트마다 다음 기준이 다르다.

    • 지원하는 언어와 스타일 방식

    • 파일명, props, import 규칙

    • 테스트와 반응형 확인 범위

    • 새로운 컴포넌트를 받는지 여부

  • 당시에는 구조 분석부터 시작했지만, 가장 먼저 읽어야 했던 파일은 CONTRIBUTING.md였다.

React Bits GitHub 저장소
  • React Bits의 기여 정책은 기존 컴포넌트 개선과 버그 수정은 받지만, 커뮤니티의 새 컴포넌트는 받지 않는다고 명시하고 있었다.

  • 이 한 줄을 먼저 확인했다면 구현 전에 Issue로 가능 여부부터 물었을 것이다.

오픈소스 기여의 첫 단계는 코드를 쓰는 일이 아니라, 저장소가 어떤 변경을 받고 있는지 확인하는 일이다.

기여를 시작하기 전에는 최소한 아래 순서로 확인하는 편이 안전하다.

  1. README.md에서 프로젝트 목적과 설치 방식을 확인한다.

  2. CONTRIBUTING.md에서 허용하는 기여 범위와 품질 기준을 확인한다.

  3. 기존 Issue와 PR에서 비슷한 제안이 있었는지 검색한다.

  4. 큰 기능은 구현 전에 Issue나 Discussion으로 방향을 맞춘다.

  5. 승인을 받은 뒤 저장소의 브랜치, 테스트, variant 규칙에 맞춰 작업한다.


👍 3. npm 패키지가 아니라 코드를 가져오는 방식.

  • 처음에는 React Bits를 일반적인 npm 컴포넌트 패키지처럼 생각했다.

  • 하지만 React Bits 저장소의 package.jsonprivate: true이며, 사용자는 라이브러리 전체를 의존성으로 설치하지 않는다.

  • 필요한 컴포넌트의 소스 코드만 복사하거나 jsrepo, shadcn CLI로 자신의 프로젝트에 가져온다.

# shadcn 레지스트리를 통해 TypeScript + Tailwind variant 설치
npx shadcn@latest add @react-bits/BlurText-TS-TW

# URL 기반 레지스트리 항목을 직접 지정하는 형태
npx jsrepo@latest add https://reactbits.dev/r/BlurText-TS-TW

Copy-and-own 방식에서는 설치된 파일이 node_modules가 아니라 내 프로젝트 안에 생성된다.

  • 장점

    • 필요한 컴포넌트만 가져올 수 있다.

    • 소스 코드를 서비스 요구사항에 맞게 직접 수정할 수 있다.

    • 사용하지 않는 컴포넌트가 애플리케이션 코드에 포함되지 않는다.

  • 비용

    • 원본 프로젝트의 수정 사항이 자동으로 반영되지 않는다.

    • 가져온 이후의 유지보수와 커스터마이징 책임은 사용자에게 있다.

    • 컴포넌트별 추가 의존성을 직접 확인해야 한다.

일반 npm 패키지도 ESM과 tree shaking을 지원하면 사용한 코드만 번들에 포함할 수 있다. 따라서 이 방식의 핵심을 단순한 용량 절감으로 보기보다는, 컴포넌트 소스의 소유권을 사용자 프로젝트로 옮기는 설계로 이해하는 편이 정확했다.


✌🏼 4. 레지스트리는 어떻게 만들어지는가.

  • React Bits는 컴포넌트 파일을 그대로 공개하는 데서 끝나지 않는다.

  • jsrepo.config.ts가 메타데이터와 각 variant의 소스 경로를 읽고, CLI가 소비할 레지스트리 JSON을 public/r/에 생성한다.

defineComponent({
  title: component.name,
  description: component.description,
  category: component.category,
  variants: component.variants,
});
  • 만들어진 레지스트리 항목에는 다음 정보가 포함된다.

    • 컴포넌트 이름과 설명

    • 설치할 소스 파일

    • 컴포넌트가 요구하는 의존성

    • JS, TS와 CSS, Tailwind 조합을 나타내는 variant

  • 사용자가 CLI 명령을 실행하면 레지스트리 JSON을 읽어 필요한 파일과 의존성을 프로젝트에 반영한다.

React Bits 메타데이터와 레지스트리 생성 흐름

메타데이터 → variant 소스 → 레지스트리 JSON → CLI → 사용자 프로젝트 순으로 이어진다.

이 구조에서는 웹 문서와 설치 결과가 서로 다른 정보를 갖지 않도록 메타데이터를 단일 기준점으로 유지하는 것이 중요하다.


🤟🏻 5. 같은 컴포넌트를 4가지 variant로 관리하는 이유.

React Bits는 언어와 스타일 방식을 두 축으로 조합한다.

src/
├── content/       # JavaScript + CSS
├── tailwind/      # JavaScript + Tailwind
├── ts-default/    # TypeScript + CSS
└── ts-tailwind/   # TypeScript + Tailwind
  • JavaScript와 TypeScript 중 하나를 고른다.

  • 일반 CSS와 Tailwind 중 하나를 고른다.

  • 두 축의 조합으로 JS-CSS, JS-TW, TS-CSS, TS-TW가 만들어진다.

사용자는 자신의 기술 스택에 맞는 코드를 바로 가져갈 수 있지만, 유지보수자는 같은 동작을 네 구현에서 일관되게 관리해야 한다.

  • props와 기본값이 같은가

  • 이벤트와 애니메이션 수명주기가 같은가

  • CSS와 Tailwind 결과가 같은가

  • TypeScript variant의 타입이 실제 런타임 동작과 맞는가

React Bits의 기여 가이드도 기존 컴포넌트를 수정할 때 관련된 4가지 variant를 모두 갱신하도록 요구한다. 지원 범위를 넓히는 선택이 곧 유지보수 비용으로 이어지는 구조였다.


🧢 6. MasonEffect를 옮기며 확인한 기술 지점.

  • MasonEffect 패키지를 새 의존성으로 추가하지 않고, 핵심 로직을 React Bits 컴포넌트 형태로 재구성했다.

  • 여기서 의존성이 없다는 표현은 정확하지 않다. 별도 MasonEffect 패키지를 요구하지 않을 뿐, 애니메이션 구현에 필요한 기존 라이브러리와 브라우저 API는 여전히 사용한다.

  • 컴포넌트 레지스트리에서는 필요한 패키지를 명시해야 CLI가 사용자 프로젝트에 함께 설치할 수 있다.

MasonEffect/
├── component source
├── style source
├── demo
├── metadata
└── registry entry

애니메이션 컴포넌트를 옮길 때는 화면이 보이는지만 확인해서는 부족했다.

  • 수명주기 정리: requestAnimationFrame, 이벤트 리스너, observer를 unmount 시 해제한다.

  • 크기 변화 대응: 컨테이너 resize와 기기 픽셀 비율(DPR)을 고려한다.

  • 입력 변화 대응: text와 옵션 props가 바뀌었을 때 애니메이션 상태를 다시 만든다.

  • 접근성: prefers-reduced-motion 환경에서 움직임을 줄이거나 정적인 대안을 제공한다.

  • SSR 안전성: window, document, canvas 접근은 브라우저에서만 실행한다.

  • variant 동기화: 네 구현의 props와 동작이 달라지지 않게 확인한다.

특히 외부 패키지를 하나 줄였다는 이유만으로 번들 크기와 성능이 자동으로 좋아진다고 단정할 수는 없다. 실제 비용은 애니메이션 루프, DOM 또는 canvas 업데이트, 가져온 하위 의존성을 함께 측정해야 한다.


🫰 7. 메타데이터와 llms.txt.

  • 컴포넌트 메타데이터에는 이름, 설명, 카테고리, 사용 가능한 variant 같은 정보가 들어간다.

  • 이 정보는 레지스트리 구성과 문서 탐색에 사용되고, 별도의 생성 스크립트는 같은 메타데이터를 읽어 public/llms.txt를 만든다.

- [Mason Effect](...): Transforms text into particles...
  CLI: `MasonEffect`.

llms.txt는 사이트의 주요 문서와 컴포넌트 정보를 LLM이 읽기 쉬운 텍스트로 정리하려는 공개 제안이다.

  • 컴포넌트 설명과 문서 링크를 한 파일에서 찾을 수 있다.

  • CLI 식별자와 설치 방법을 에이전트에게 전달할 수 있다.

  • 저장소 구조를 전부 탐색하지 않아도 주요 진입점을 제공한다.

기존에는 robots.txt와 비슷한 역할이라고 이해했지만 둘은 목적이 다르다.

  • robots.txt: 크롤러가 접근할 수 있는 경로에 대한 규칙을 전달한다.

  • llms.txt: LLM을 위한 문서 진입점과 문맥을 제공한다.

llms.txt는 접근을 허용하거나 차단하는 표준이 아니며, 모든 AI 도구가 반드시 읽는 것도 아니다. 그래도 메타데이터를 재사용해 사람이 보는 문서와 에이전트가 읽는 문서를 함께 생성한다는 점은 인상적이었다.


🫵 8. 기여 정책과 제안 타이밍.

  • 구현을 마친 뒤 바로 Pull Request를 보내기보다 먼저 Issue를 등록했다. 이때 기여 가능 범위를 먼저 확인하지 않은 점이 아쉬웠다.

  • MasonEffect에서 영감을 받은 새 컴포넌트가 프로젝트 방향과 맞는지, 별도 의존성을 추가하지 않는 방향이 괜찮은지 물었다.

MasonEffect 컴포넌트 제안 Issue

제안에서 전달하려던 핵심은 다음과 같았다.

I’d love to contribute a lightweight text animation component.
I will not add MasonEffect as a dependency.
Before preparing a PR, does this proposal align with the project?
  • 기능의 출처와 내가 원작자라는 점을 밝혔다.

  • 새 외부 의존성을 추가하지 않을 계획을 설명했다.

  • PR을 열기 전에 maintainer의 방향을 먼저 확인했다.

Issue를 남기며 답변을 기다린 순간

답변은 짧고 명확했다.

React Bits maintainer의 답변

CONTRIBUTING.md에 명시된 대로 현재 React Bits는 커뮤니티의 새 컴포넌트를 받고 있지 않다.

새 컴포넌트를 받지 않는다는 답변을 확인한 순간
  • 이미 구현을 마친 뒤라 아쉬웠지만, 정책은 프로젝트가 유지보수 범위를 통제하기 위한 선택이었다.

  • 새 컴포넌트가 닫혀 있어도 기존 컴포넌트의 버그 수정과 개선은 기여할 수 있다.

  • 답변에는 안내를 이해했고, 정책이 바뀌면 다시 제안하고 싶다는 내용을 남겼다.


😢 9. 마무리 : 기여를 넘어선 경험.

  • 실제 Pull Request로 이어지지는 않았지만 구현 과정에서 React Bits의 배포 구조를 깊게 살펴볼 수 있었다.

  • 가장 크게 배운 것은 기술 구현보다 기여 가능 범위를 먼저 확인하는 순서였다.

  • 함께 기억할 기술적 지점은 다음과 같다.

    • copy-and-own 방식의 컴포넌트 배포

    • JS, TS와 CSS, Tailwind를 조합한 variant 전략

    • 메타데이터를 기준으로 레지스트리와 llms.txt를 생성하는 자동화

    • 애니메이션 컴포넌트의 수명주기, 접근성, SSR 고려

좋은 기여는 코드를 많이 작성하는 것이 아니라, 프로젝트가 원하는 문제를 프로젝트의 방식으로 해결하는 일이다.

이번 작업은 병합된 코드로 남지는 않았다.

대신 저장소를 읽는 순서와 제안의 타이밍까지 포함해 오픈소스 기여의 일부라는 점을 확인했다.

다음에는 CONTRIBUTING.md와 기존 Issue를 먼저 확인하고, 구현 전에 maintainer와 방향부터 맞춰 보려고 한다.


🙂 10. 참고 URL.

이전 글
패키지 배포, 그 이후.

댓글

불러오는 중...
목록으로