어렵게 만든 차트를 react기반 프로젝트에서 재사용할 수는 없을까
개요
현재 nuxt로 만들어진 chartJS기반 컴포넌트를 next 기반 시스템에서 재사용하려는 니즈가 있다.
상세
아쉽게도 당장 내 지식으로는 vue와 react를 같이 쓰는 최선의 아이디어가 없다.
그나마 생각나는건
- 바닐라 자바스크립트로 만들기
- nuxt와 next.js 따로 만들기
- 아예 독립적인 라이브러리로 만들어서 배포하기
이정도인데
1,3은 실제로 해보지 않아서 추상적인 아이디어라고 할 수 있다.
당장 이 요구사항은 해야할 이슈는 아니므로 문제 정의만 해두고 나중에 이 일을 해야 할 상황에 다시 정리해보도록 하자.
해결방안(예비)
1. 바닐라 자바스크립트 기반으로 작성하기
개요
- Vue/React 같은 프레임워크 의존성을 제거하고, Chart.js를 직접 활용해 컴포넌트를 구현.
- 순수 자바스크립트(또는 TypeScript)로 Chart.js 초기화 로직과 DOM 조작을 작성한 뒤, 해당 로직을 Vue나 React 컴포넌트에서 각각 래핑(wrapping)하는 방식.
장점
- 프레임워크 독립성: Vue, React 양쪽에서 똑같이 가져다 쓰기 쉬워짐.
- 유지보수 단순화: 바닐라 코드만 업데이트하면, Vue/React 컴포넌트는 동일 로직을 가져다 써서 재사용.
단점
- 직접 DOM 제어: Vue/React의 데이터 바인딩, 라이프사이클 등을 활용하기 어려워 더 세밀한 DOM 관리가 필요.
- 개발 난이도 증가: Vue/React에 익숙하다면 “바닐라 + Chart.js” 접근은 생소할 수 있음.
- 추가 래퍼(wrapper) 작성 필요: 결국 Vue용 래퍼 컴포넌트, React용 래퍼 컴포넌트를 각각 만들어야 함.
2. Vue와 React 각각 별도 개발(혹은 유지)
개요
- Nuxt(Vue)와 Next(React) 프로젝트에서 동일한 UI/UX를 가진 ChartJS 컴포넌트를 각각 구현/관리.
- 현재 Nuxt용 코드는 그대로 유지하고, React에서는 새롭게 컴포넌트를 작성.
장점
- 프레임워크 친화적: Vue, React 각각의 생태계와 문법에 맞춰 최적화할 수 있음.
- 학습 비용 낮음: 기존 Nuxt 코드를 유지하면서, React 환경에서는 React답게(특히 훅, 라이프사이클, 상태 관리 등) 컴포넌트를 구현.
단점
- 코드 중복 발생: 동일한 로직을 서로 다른 두 코드베이스에서 관리해야 함.
- 유지보수 비용 증가: 기능 수정 시, 두 프레임워크 버전을 모두 반영해야 함.
- 장기적으로 비효율: 컴포넌트가 많아지면 업데이트 부담이 커짐.
3. 독립된 라이브러리(패키지)로 배포
개요
- Chart.js를 사용해 만든 핵심 로직을 하나의 NPM 패키지로 추상화.
- Vue/React 라이브러리로 “래퍼”를 만들어 이 핵심 로직을 각각 가져다 사용하는 구조.
- 예시:
@company/chart-core(바닐라+Chart.js 구현) - Vue 래퍼:
@company/chart-vue - React 래퍼:
@company/chart-react
- 예시:
장점
- 모듈화·재사용성 극대화: “chart-core”라는 단일 소스를 유지하므로, 라이브러리 업데이트 시 Vue/React 쪽도 자동으로 최신화 가능.
- 유지보수 편의성: 하위 레벨 로직(Chart.js 초기화, 업데이트 등)은 한 군데에서 관리.
- 프레임워크 별 최적화 가능: Vue, React 래퍼는 각자의 문법과 상태 관리를 활용해 UX 개선.
단점
- 초기 세팅 복잡도: monorepo(또는 멀티 패키지 구조)를 구성해야 할 수 있음.
- 퍼블리시 자동화 필요: NPM 배포 파이프라인(CI/CD)이 필요하고, 버전 관리도 신경써야 함.
- 학습 비용: 팀에서 npm 패키지를 만들어 배포·관리하는 데 대한 추가 지식 필요.
4. Web Component(Custom Elements)로 래핑
개요
- Vue 코드(또는 바닐라+Chart.js)로 만든 컴포넌트를 Web Component(Custom Element) 규격으로 빌드.
- React 쪽에서는 일반 DOM 태그처럼
<my-chart></my-chart>를 사용하여 삽입. - Vue 3부터는
vue-web-component-wrapper등을 활용하여 Web Component로 변환 가능(단, Nuxt 환경에서의 세팅은 추가 검토 필요).
장점
- 프레임워크 무관한 배포: Web Component이므로 어떤 환경에서든
<my-chart>태그로 사용 가능. - 캡슐화: 컴포넌트 내부 스타일이나 기능을 섀도 DOM으로 격리 가능.
단점
- 학습 난이도: Web Component 생태계와 래핑 방식을 익혀야 함.
- 프레임워크 통합 이슈: React에서 Web Component를 사용할 때, props/이벤트 바인딩 등이 번거로울 수 있음.
- SSR(서버 사이드 렌더링) 난관: Web Component가 클라이언트 사이드에서만 동작할 경우, Nuxt/Next의 SSR과 충돌이 생길 가능성 있음.
5. (참고) Micro-Frontend 접근
개요
- Vue 기반(Chart)과 React 기반(Next)을 각각 독립된 마이크로 프런트엔드로 구성, 런타임 시 통합.
- 단순히 컴포넌트 하나가 아니라 각 프로젝트 일부 모듈을 분리하는 수준으로 커지는 경우 고려 가능.
장점
- 완벽한 독립성: Vue, React 버전 충돌 없이 각 팀/프로젝트가 자유롭게 개발.
- 확장성: 여러 SPA가 합쳐지는 수준에서도 통합 가능.
단점
- 구현 복잡도: Webpack 모듈 연합(Module Federation) 등 지식이 필요하며 설정이 어려움.
- 규모가 큰 프로젝트에만 권장: 단일 컴포넌트를 위해서는 과도한 방식일 수 있음.
권장 시나리오 및 결론
-
신속·단기적으로 “React에서도 같은 UI를 빨리 써야 한다”면
- (2) 각 프레임워크별로 별도 구현을 고려
- 장기적으로 코드 중복이 아쉽지만, 당장 업무를 빠르게 처리 가능.
-
장기 유지보수와 팀 단위 협업이 중요하다면
- (3) 독립 라이브러리(패키지) 형태로 빼는 방식을 추천.
- 가장 유연하면서도 재사용성 높고, Nuxt와 Next 어디에서도 쉽게 import 가능.
-
“진짜” 프레임워크 독립성과 범용성을 원한다면
- (4) Web Component(Custom Element) 고려
- 프레임워크 무관하게 재사용은 가능하나, 이벤트/데이터 바인딩, SSR 등에서 추가 세팅이 필요.
-
프로젝트 규모가 크고 마이크로프런트엔드를 검토 중이라면
- (5) Micro-Frontend 접근도 가능하지만, 단일 컴포넌트 재사용 목적이라면 과도할 수 있음.
추가
-
Proof of Concept(시작 전 검증)
- 새롭게 시도할 접근(특히 웹 컴포넌트, 독립 라이브러리)이라면 간단한 예시를 만들어 POC를 진행해보는 것이 좋.
-
SSR 고려
- Nuxt와 Next 모두 SSR을 사용하는 경우가 많으므로, 서버 렌더링 시 Chart.js 같은 라이브러리가 어떻게 동작하는지 검토가 필요.
-
프로젝트 규모 vs. 유지보수
- 재사용하고자 하는 컴포넌트의 개수, 난이도, 추후 확장 가능성 등을 고려해 “가장 단순한 방법”을 먼저 시도하는 것도 좋은 방법.
- 작은 규모라면 (2)번처럼 “각자 구현”이 빠르고 단순하며, 큰 규모라면 (3)번 방식이 나음.
결론
“가장 단순한 방법은 가장 빠른 결과를 내지만, 장기적으로는 중복코드 관리가 어려워질 수 있다.
반대로 재사용성과 확장성을 극대화하려면 빌드·배포 파이프라인 등 초기 비용이 들 수 있다.”
프레임워크 간 컴포넌트 호환성을 다른 각도로 바라본 시각은 [[KnowledgeBase/Blog/잡다한 글/스벨트를 통해 리액트 더 잘 이해하기]]에서 확인할 수 있다.
댓글
첫 번째 댓글을 남겨보세요.