Frameworks, Platforms and Libraries/Vue.js
Vue application with React component
iam102
2023. 10. 8. 16:09
현재 회사에서 운영 중인 세 개의 application 중 두 개의 application의 경우 React, 남은 하나의 application는 Vue.js 기반이었습니다. 운영 중인 Vue.js 기반의 application을 React로 포팅할려는 니즈가 있었지만 한 번에 빅뱅 하기엔 시간이 부족하여 점진적으로 React로 포팅하고 신규 기능 페이지의 경우는 미리 React로 구성하기로 했습니다. 그렇다 보니 기존 Vue.js 기반의 application에 React component를 띄워야 했고 이때 사용한 방식을 포스팅하고자 합니다.
react → vue 변환 모듈
※ Vue는 Class Component 형태로 작성되었습니다.
ReactDOMClient의 createRoot()를 통해 렌더링 되는 DOM의 위치를 Vue.js 기반의 application으로 향하게 합니다.
// glue.tsx
import React from 'react';
import { createRoot } from 'react-dom/client';
// import { Provider } from 'react-redux';
// import { store } from './store';
import './styles/index.scss';
export function mount(
targetNode: HTMLElement,
component: React.FunctionComponent,
) {
const reactElement = React.createElement(component);
const root = createRoot(targetNode!);
root.render(reactElement);
// 필요에 따라 store도 임시로 연결할 수 있습니다.
// root.render(<Provider store={store}>{reactElement}</Provider>);
return root;
}
// Bridge.ts
// react => vue
import { Component, Vue } from 'vue-property-decorator';
import { Root } from 'react-dom/client';
import { mount } from './glue';
@Component({
name: 'Bridge',
})
export default class extends Vue {
reactRoot: Root | null = null;
setComponent(component: React.FunctionComponent) {
this.reactRoot = mount(this.$el as HTMLElement, component);
}
beforeDestroy() {
this.reactRoot?.unmount();
}
}
적용
// Component.tsx
function Component() {
return <div>Vue application with React component</div>;
}
export default Component;
// ComponentBridge.vue
<template>
<div></div>
</template>
<script lang="ts">
import { Component } from 'vue-property-decorator';
import Component from './Component';
import Bridge from './Bridge';
@Component({
name: 'ComponentBridge',
})
export default class extends Bridge {
mounted() {
this.setComponent(Component);
}
}
</script>
router를 통해 ComponentBridge 페이지를 보면 정상적으로 출력이 됩니다.
후기
Vue.js 기반의 application을 당장 React로 빅뱅 할 시간이 부족하여 신규 기능 페이지만이라도 미리 React로 구성하기 위해 사용한 방식이었습니다. 하나의 application에서 두 개의 프론트엔드 프레임워크가 공존하는 건 좋지 않지만 이러한 방식을 통해 점진적으로 포팅할 수 있었습니다. 그래도 역시나 빠른 시일 내에 완전히 포팅을 완료해야겠습니다.