728x90
아래는 **host-maestro-monorepo**를 루트로 하는 pnpm 모노레포 구성부터,
Host와 remoteMaestro 두 패키지를 만들고,
Host에서 Remote 컴포넌트를 가져와서 사용하는 과정을 순서대로 정리한 내용입니다.
1. 폴더 구조 & 초기 설정
1) 모노레포 루트 폴더 만들기
mkdir host-maestro-monorepo
cd host-maestro-monorepo
2) pnpm init
루트에서 pnpm init을 통해 **루트의 package.json**을 생성합니다.
pnpm init
루트 package.json 예시
{
"name": "host-maestro-monorepo",
"private": true,
"version": "1.0.0",
"scripts": {
// "install": "pnpm install", // ← (무한루프 방지를 위해 제거!)
"dev:host": "pnpm --filter host dev",
"dev:remote": "pnpm --filter remoteMaestro dev",
"build:all": "pnpm build -r --filter './packages/*'"
}
}
- 주의: "scripts": { "install": "pnpm install" }는 넣지 않습니다(무한 루프 발생).
3) pnpm-workspace.yaml
packages: - "packages/*"
- 모노레포로 인식할 경로를 지정: packages 폴더 하위의 모든 디렉터리를 워크스페이스 패키지로 삼음.
4) TypeScript / ESLint(옵션)
- **루트(host-maestro-monorepo)**에 tsconfig.json, .eslintrc.js 등을 둬서 전체 규칙을 적용할 수 있습니다.
- (옵션) 여기서는 간단히 생략하거나, 다음과 같은 최소 설정을 둘 수 있음:
// tsconfig.json
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"strict": true,
"skipLibCheck": true
},
"exclude": [
"node_modules"
]
}
2. 패키지 생성 (Host, remoteMaestro)
폴더 구조
host-maestro-monorepo
├── packages
│ ├── host
│ │ ├── package.json
│ │ ├── vite.config.ts
│ │ ├── index.html ← Vite용 HTML
│ │ └── src
│ │ ├── App.vue
│ │ ├── main.ts
│ │ └── router.ts
│ └── remoteMaestro
│ ├── package.json
│ ├── vite.config.ts
│ ├── src
│ │ ├── HelloRemote.vue
│ │ ├── RemoteApp.vue
│ │ ├── main.ts
│ │ └── index.ts
├── package.json ← 모노레포 루트
├── pnpm-workspace.yaml ← 모노레포 설정
└── tsconfig.json ← (옵션)
2-1) packages/host 설정
a) host/package.json
{
"name": "host",
"version": "1.0.0",
"scripts": {
"dev": "vite",
"build": "vite build"
},
"dependencies": {
"vue": "^3.3.0",
"vue-router": "^4.0.0"
},
"devDependencies": {
"vite": "^4.5.0",
"@vitejs/plugin-vue": "^4.0.0",
"typescript": "^4.5.0"
}
}
- "name": "host" 로 정의 (이 패키지의 이름)
- Vue, Vite, TypeScript 등을 설치
b) host/vite.config.ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [vue()],
server: {
port: 3000
}
});
- 호스트 앱을 3000 포트로 띄우는 설정 예시
c) host/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Host App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
- Vite가 이 HTML을 기준으로 앱을 로드
d) host/src/main.ts
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
const app = createApp(App);
app.use(router);
app.mount('#app');
e) host/src/router.ts
import { createRouter, createWebHistory } from 'vue-router';
import App from './App.vue';
const routes = [
{
path: '/',
name: 'Home',
component: App
}
];
export default createRouter({
history: createWebHistory(),
routes
});
f) host/src/App.vue
<template>
<div>
<h1>This is Host App</h1>
<router-view />
</div>
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue';
const title = ref('Hello from Host App!');
onMounted(() => {
console.log(title.value);
});
</script>
<style scoped>
h1 {
color: steelblue;
}
</style>
2-2) packages/remoteMaestro 설정
a) remoteMaestro/package.json
{
"name": "remoteMaestro",
"version": "1.0.0",
"main": "src/index.ts", // ← export할 엔트리 (중요)
"scripts": {
"dev": "vite",
"build": "vite build"
},
"dependencies": {
"vue": "^3.3.0"
},
"devDependencies": {
"vite": "^4.5.0",
"@vitejs/plugin-vue": "^4.0.0",
"typescript": "^4.5.0"
}
}
- name: "remoteMaestro"`
- main: "src/index.ts"` 를 지정 → 이 파일에서 내보낸 것이 패키지의 기본 export가 됨.
b) remoteMaestro/vite.config.ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [vue()],
server: {
port: 3001
}
});
- 리모트 앱을 3001 포트에서 실행
c) remoteMaestro/index.html (Vite용, Remote 단독 실행 시 필요)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Remote Maestro</title>
</head>
<body>
<div id="remote-app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
d) remoteMaestro/src/main.ts
import { createApp } from 'vue';
import RemoteApp from './RemoteApp.vue';
const app = createApp(RemoteApp);
app.mount('#remote-app');
- 리모트 앱 실행 시, #remote-app에 마운트
e) remoteMaestro/src/RemoteApp.vue
<template>
<div>
<h2>Remote App</h2>
<HelloRemote />
</div>
</template>
<script setup lang="ts">
import HelloRemote from './HelloRemote.vue';
</script>
<style scoped>
h2 {
color: darkmagenta;
}
</style>
f) remoteMaestro/src/HelloRemote.vue
<template>
<p>{{ message }}</p>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const message = ref('Hello from Remote Component!');
</script>
<style scoped>
p {
font-size: 18px;
}
</style>
g) remoteMaestro/src/index.ts
// remoteMaestro의 "main" 엔트리
export { default as HelloRemote } from './HelloRemote.vue';
export { default as RemoteApp } from './RemoteApp.vue';
- 이렇게 export 해줘야, Host 쪽에서 import { HelloRemote } from 'remoteMaestro'; 형태로 사용 가능
3. Host에서 Remote 컴포넌트를 가져오기
3-1) Host가 remoteMaestro를 의존성으로 추가
Host 패키지(packages/host/package.json) 안에서 remoteMaestro를 직접 명시해줄 수 있습니다.
단, Monorepo Workspace 의존성을 사용하기 위해서는 루트에서 아래처럼 해주는 것이 보통입니다:
a) Host의 package.json
{
"name": "host",
"version": "1.0.0",
"scripts": { ... },
"dependencies": {
"vue": "^3.3.0",
"vue-router": "^4.0.0",
// "remoteMaestro": "workspace:*" ← 추가
"remoteMaestro": "workspace:*"
},
"devDependencies": {
"vite": "^4.5.0",
"@vitejs/plugin-vue": "^4.0.0",
"typescript": "^4.5.0"
}
}
- 이렇게 remoteMaestro를 의존성으로 지정하면,
pnpm이 node_modules/remoteMaestro를 모노레포 내부에서 심볼릭 링크해 줍니다.
b) pnpm install
루트(host-maestro-monorepo) 폴더에서:
pnpm install
- 이제 host/node_modules/remoteMaestro가 연결됨.
c) Host에서 import
host/src/App.vue (또는 다른 컴포넌트)에서:
<template>
<div>
<h1>This is Host App</h1>
<HelloRemote />
</div>
</template>
<script setup lang="ts">
import { HelloRemote } from 'remoteMaestro';
</script>
- 이렇게 하면, remoteMaestro/src/index.ts에서 export된 HelloRemote가 정상적으로 import됩니다.
4. 실행 & 확인
4-1) 의존성 설치
# 루트에서
cd host-maestro-monorepo
pnpm install
- 모든 하위 패키지(Host, remoteMaestro)의 의존성을 한 번에 설치
4-2) Host 실행
pnpm dev:host
- scripts에 "dev:host": "pnpm --filter host dev"를 넣어뒀다면, 이 명령어로 Host 앱이 켜짐
- http://localhost:3000 에 접속 (만약 Vite 서버에서 port: 3000이 지정되어 있다면)
4-3) Remote 실행 (옵션)
pnpm dev:remote
- 만약 Remote를 개별로 띄워서 http://localhost:3001 에서 확인하고 싶다면.
5. 만약 404가 뜨거나 import ... from 'remoteMaestro'가 안 될 때
- index.html 누락: Vite는 index.html이 필수(Host, Remote 각각).
- **루트에서 "scripts.install"**이 무한 루프를 일으키는지 체크 (지워야 함).
- Workspace 의존성 설정이 제대로 되었는지:
- Host package.json에 "remoteMaestro": "workspace:*" 추가했는지?
- remoteMaestro/package.json에 "name": "remoteMaestro", "main": "src/index.ts" 명시했는지?
- pnpm install 후에 다시 pnpm dev:host를 실행해보는지?
이 과정을 정확히 지키면, Host에서 remoteMaestro의 컴포넌트를 원활히 가져올 수 있게 됩니다.
6. (참고) Module Federation 방식으로 “동적” 로드하기
위의 방식은 정적 import(빌드 시점)이며, 실제로는 Module Federation을 사용하여 런타임에 remoteEntry.js를 불러와서 모듈을 가져오는 시나리오도 있습니다.
- 그때는 Webpack (또는 Vite) Module Federation Plugin을 설정하고,
- Remote 쪽에 exposes, Host 쪽에 remotes를 명시해야 합니다.
- 예) import('remoteMaestro/HelloRemote') 로 동적 import.
이 부분은 MFE(Micro Frontend) 구현 시 별도의 설정 작업이 필요합니다.
결론
- 폴더 구조: host-maestro-monorepo 루트 / packages/host / packages/remoteMaestro.
- pnpm-workspace.yaml: packages/* 지정.
- Host와 remoteMaestro 각각 package.json, vite.config.ts, index.html 세팅.
- remoteMaestro는 "name": "remoteMaestro", "main": "src/index.ts"로 export 포인트 설정.
- Host에서 "remoteMaestro": "workspace:*" 의존성을 추가하여 가져오기.
- pnpm install 후 pnpm dev:host 실행 → App.vue 에서 import { HelloRemote } from 'remoteMaestro'; 테스트.
결과물
728x90
'Vue 실습' 카테고리의 다른 글
[모듈 페더레이션]mhome과 remote2를 연결하여 모듈 페더레이션 by vue.cofig.js (0) | 2024.12.31 |
---|---|
[모듈 페더레이션과 모노레포 구성] vite(host) + webpack(remote)로 모둘 페더레이션 구성 - 1 (0) | 2024.12.29 |
[vue.js] components을 이용한 동적 렌더링 - 1 (1) | 2024.12.07 |
[vue.js] vue 개념 라이프 사이클 관련 개념 정리 (0) | 2024.11.28 |
vue 에서 yup을 사용하여 유효성 검사하는 방법 정리 (0) | 2024.09.06 |