Vue 3 vite 다중 앱 구성 가이드: 단일 프로젝트에서 여러 애플리케이션 관리하기

반응형

📌 개요

Vue 프로젝트에서 여러 개의 독립적인 애플리케이션을 관리해야 하는 상황이 있습니다. 예를 들어, 관리자용 앱과 고객용 앱을 하나의 코드베이스에서 관리하면서도 별도로 빌드해야 한다면 어떻게 해야 할까요? 이 글에서는 Vite를 사용하여 Vue 3 프로젝트에서 다중 앱을 구성하고 빌드하는 방법을 소개합니다.

🎯 목표

  • App1.vue → 빌드 시 dist/gtc/index.html로 출력
  • App2.vue → 빌드 시 dist/customer/index.html로 출력
  • 공통 컴포넌트와 유틸리티는 재사용
  • 각 앱마다 독립적인 진입점(entry point) 설정

🗂️ 프로젝트 구조

다중 앱 구성을 위한 권장 프로젝트 구조는 다음과 같습니다:

 
my-vue-app/
├── index.html              ← 기본 템플릿 (사용 안함)
├── apps/
│   ├── gtc/
│   │   ├── index.html      ← gtc 전용 템플릿
│   │   └── main.js         ← App1.vue 마운트
│   └── customer/
│       ├── index.html      ← customer 전용 템플릿
│       └── main.js         ← App2.vue 마운트
├── src/
│   ├── App1.vue            ← GTC 앱의 루트 컴포넌트
│   ├── App2.vue            ← Customer 앱의 루트 컴포넌트
│   ├── components/         ← 공유 컴포넌트
│   ├── assets/             ← 공유 에셋
│   └── utils/              ← 공유 유틸리티 함수
├── package.json
└── vite.config.js          ← 멀티 앱 빌드 설정

🛠️ 주요 설정 파일

1. Vite 설정 - vite.config.js

Vite를 사용하여 다중 앱을 구성하기 위한 핵심 설정 파일입니다:

 
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import { resolve } from 'path';

export default defineConfig({
  plugins: [vue()],
  build: {
    rollupOptions: {
      input: {
        gtc: resolve(__dirname, 'apps/gtc/index.html'),
        customer: resolve(__dirname, 'apps/customer/index.html'),
      },
      output: {
        // 출력 파일 커스터마이징 (선택사항)
        // entryFileNames: (chunk) => {
        //   return `assets/${chunk.name}/[name]-[hash].js`;
        // },
        // chunkFileNames: 'assets/js/[name]-[hash].js',
        // assetFileNames: 'assets/[ext]/[name]-[hash].[ext]',
      },
    },
    outDir: 'dist', // 기본 출력 디렉터리
    emptyOutDir: true
  },
  resolve: {
    alias: {
      '@': resolve(__dirname, 'src'), // '@' 별칭 설정
    },
  },
});

2. GTC 앱 진입점 - apps/gtc/main.js

 
import { createApp } from 'vue';
import App1 from '../../src/App1.vue';
// 필요한 경우 앱별 스타일 임포트
import '../../src/assets/styles/gtc.css';

// 앱별 라우터 설정 (선택사항)
// import router from './router';

const app = createApp(App1);

// 앱에 필요한 플러그인 추가
// app.use(router);

app.mount('#app');

3. Customer 앱 진입점 - apps/customer/main.js

 
import { createApp } from 'vue';
import App2 from '../../src/App2.vue';
// 필요한 경우 앱별 스타일 임포트
import '../../src/assets/styles/customer.css';

// 앱별 라우터 설정 (선택사항)
// import router from './router';

const app = createApp(App2);

// 앱에 필요한 플러그인 추가
// app.use(router);

app.mount('#app');

4. HTML 템플릿 - apps/gtc/index.html

 
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="icon" href="/favicon.ico" />
    <title>GTC 애플리케이션</title>
    <meta name="description" content="GTC 관리자용 애플리케이션입니다" />
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="./main.js"></script>
  </body>
</html>

5. HTML 템플릿 - apps/customer/index.html

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="icon" href="/favicon.ico" />
    <title>고객용 애플리케이션</title>
    <meta name="description" content="고객을 위한 서비스 애플리케이션입니다" />
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="./main.js"></script>
  </body>
</html>

🚀 앱별 라우터 설정 (선택사항)

각 앱에 독립적인 라우터를 설정하려면, 다음과 같이 구성할 수 있습니다:

GTC 앱 라우터 - apps/gtc/router.js

 
import { createRouter, createWebHistory } from 'vue-router';

const routes = [
  {
    path: '/',
    name: 'GtcHome',
    component: () => import('@/views/gtc/HomeView.vue'),
  },
  {
    path: '/dashboard',
    name: 'GtcDashboard',
    component: () => import('@/views/gtc/DashboardView.vue'),
  },
  // GTC 앱 전용 라우트
];

const router = createRouter({
  history: createWebHistory('/gtc/'),
  routes,
});

export default router;

Customer 앱 라우터 - apps/customer/router.js

 
import { createRouter, createWebHistory } from 'vue-router';

const routes = [
  {
    path: '/',
    name: 'CustomerHome',
    component: () => import('@/views/customer/HomeView.vue'),
  },
  {
    path: '/products',
    name: 'CustomerProducts',
    component: () => import('@/views/customer/ProductsView.vue'),
  },
  // 고객용 앱 전용 라우트
];

const router = createRouter({
  history: createWebHistory('/customer/'),
  routes,
});

export default router;

🌐 환경 변수 설정

앱별로 다른 환경 변수를 사용하려면, 다음과 같이 설정 파일을 분리할 수 있습니다:

공통 환경 변수 - .env

VITE_API_TIMEOUT=30000
VITE_DEFAULT_LOCALE=ko

GTC용 환경 변수 - .env.gtc

VITE_APP_TITLE=GTC Admin
VITE_API_BASE_URL=https://api.example.com/admin

Customer용 환경 변수 - .env.customer

VITE_APP_TITLE=Customer Portal
VITE_API_BASE_URL=https://api.example.com/customer

📦 빌드 명령어

package.json에 앱별 빌드 스크립트를 추가합니다:

 
{
  "scripts": {
    "dev:gtc": "vite --config vite.config.js --mode gtc",
    "dev:customer": "vite --config vite.config.js --mode customer",
    "build": "vite build",
    "build:gtc": "vite build --mode gtc",
    "build:customer": "vite build --mode customer",
    "preview:gtc": "vite preview --mode gtc",
    "preview:customer": "vite preview --mode customer"
  }
}

📝 빌드 결과

빌드가 완료되면 다음과 같은 디렉터리 구조가 생성됩니다:

dist/
├── gtc/
│   ├── index.html
│   ├── assets/
│       ├── js/
│       ├── css/
│       └── images/
├── customer/
│   ├── index.html
│   ├── assets/
│       ├── js/
│       ├── css/
│       └── images/

💡 추가 팁

공통 컴포넌트 활용

공통 컴포넌트는 src/components 폴더에 위치시키고, 각 앱에서 필요에 따라 임포트하여 사용할 수 있습니다:

 
// 앱별 진입점 파일에서
import BaseButton from '@/components/BaseButton.vue';
import BaseInput from '@/components/BaseInput.vue';

const app = createApp(App1);
// 전역 컴포넌트로 등록
app.component('BaseButton', BaseButton);
app.component('BaseInput', BaseInput);

개발 서버 설정

개발 중에는 주로 한 앱만 작업하게 되므로, Vite 개발 서버를 앱별로 시작할 수 있습니다:

 
# GTC 앱 개발
npm run dev:gtc

# Customer 앱 개발
npm run dev:customer

Monorepo로 확장하기

앱이 더 복잡해지거나 공유 라이브러리가 많아지면 pnpm workspace나 nx를 활용한 monorepo 구조로 전환을 고려해볼 수 있습니다.

🔍 결론

Vue 3와 Vite를 사용하면 하나의 프로젝트에서 여러 앱을 효율적으로 관리할 수 있습니다. 이러한 접근 방식은 코드 재사용성을 높이고, 개발 및 유지보수 비용을 절감하는 데 도움이 됩니다. 앱별로 독립적인 빌드 결과물을 얻으면서도, 공통 컴포넌트와 유틸리티를 공유할 수 있어 일관된 사용자 경험을 제공할 수 있습니다.

이 가이드가 Vue 3에서 다중 앱을 구성하는 데 도움이 되셨기를 바랍니다. 더 복잡한 요구사항이 있다면 모노레포 구조나 마이크로프론트엔드 아키텍처도 고려해볼 수 있습니다.

반응형