Search

멀티 프레임워크 디자인 시스템, 결국 운영 가능한 구조를 선택한 이유

URL
생성 일시
2026/03/10 10:06
최종 편집 일시
2026/03/10 10:06
태그
여기어때
파일과 미디어
|| 안녕하세요. 서비스웹개발팀의 헨비입니다. 이번 글에서는 React와 Vue를 함께 지원하는 디자인 시스템을 직접 만들고 배포/운영하면서, 왜 결국 “모든 것을 동일하게 지원”하는 전략에서 “운영 가능한 범위를 선택하는 전략”으로 전환했는지 정리해보려고 합니다. 처음에는 core + react + vue 구조로 컴포넌트까지 일관되게 제공하는 것을 목표로 했지만, 실제 운영에서는 기능 추가, QA, 배포, 회귀 검증 비용이 빠르게 커졌습니다. 현재는 React 컴포넌트를 운영 축으로 두고, Vue에서는 토큰/스타일/유틸리티 같은 디자인 파운데이션을 중심으로 소비하고 있습니다. 이 전환 과정에서 무엇을 얻고 무엇을 포기했는지, 그리고 비슷한 상황에서 어떤 기준으로 선택해야 하는지 공유하겠습니다. 왜 멀티 프레임워크 디자인 시스템을 시작했나? 서비스웹개발팀은 레거시 Vue 프로젝트와 신규 React/Next.js 프로젝트를 동시에 운영하고 있습니다. 문제는 기술 스택 자체보다, YDS 업데이트를 프로젝트별로 반복 반영하는 운영 비용이 매우 컸습니다. 그래서 특정 당장 프레임워크 통일보다는 프레임워크가 달라도 공통 규칙을 재사용할 수 있는 구조를 먼저 찾았습니다. 검토 기준은 SSR, SEO, 복잡도, 런타임 의존성, 운영 유지비였습니다. 결론적으로 우리 팀 조건에서는 Headless Core + Framework Adapter가 가장 운영 가능한 선택이었습니다. 2. 초기 설계: core + adapter(react/vue) 구조 멀티 프레임워크 환경에서 중복 구현을 줄이기 위해 packages/core, packages/react, packages/vue로 구조를 분리했습니다. core는 디자인 토큰/스타일 유틸리티/headless 로직의 단일 출처로 두었습니다. react, vue는 프레임워크별 렌더링/이벤트/컴포넌트 표면만 담당하는 adapter로 설계했습니다. // core (headless) export function createBoxButton(props) { return { state, bindings } } // React adapter (요약) import { createBoxButton } from "@yeogiforge/core"; export function BoxButton(props) { const { state, bindings } = createBoxButton(props); return ( <button {...bindings} data-state={state}> {props.children} </button> ); } // Vue adapter (요약) <script setup lang="ts"> import { createBoxButton } from "@yeogiforge/core"; const props = defineProps<{ disabled?: boolean }>(); const { state, bindings } = createBoxButton(props); </script> <template> <button v-bind="bindings" :data-state="state"> <slot /> </button> </template> 두 adapter는 같은 core 로직을 공유하고, 프레임워크별 렌더링 표면만 다르게 가져갑니다. 즉, 상태/의미 체계는 core에서 통일하고 UI 연결 지점만 React/Vue에서 분리했습니다. 핵심 의도는 “규칙은 한 곳에서 관리하고, 프레임워크별 연결만 분리”하는 것이었습니다. 초기에는 이 구조가 일관성과 확장성을 동시에 잡는 가장 현실적인 방법이라고 판단했습니다. 문제는 아키텍처 선택 자체보다, 이 구조를 실제 운영하면서 발생한 이중 구현과 동기화