<! doctype html >
< html lang = "ko" >
< head >
< meta charset = "utf-8" />
< meta content = "IE=edge" http-equiv = "X-UA-Compatible" />
< meta content = "width=device-width,initial-scale=1.0" name = "viewport" />
< meta content = "no-cache, no-store, must-revalidate" http-equiv = "Cache-Control" />
< meta content = "no-cache" http-equiv = "Pragma" />
< meta content = "0" http-equiv = "Expires" />
< link href = "/favicon.ico" rel = "icon" />
< link href = "/cdn/Pretendard-1.3.9/web/static/pretendard.css" rel = "stylesheet" />
< script src = "/env.js" ></ script >
< script >
// API 서버 preconnect 동적 추가
;( function () {
var apiUrl = (window. __ENV__ && window. __ENV__ . VITE_API_BASE_URL ) || ''
if ( ! apiUrl) return
try {
var origin = new URL (apiUrl). origin
var link = document. createElement ( 'link' )
link. rel = 'preconnect'
link. href = origin
link. crossOrigin = 'anonymous'
document. head . appendChild (link)
} catch (e) {}
})()
</ script >
< title >데이터메이커 시냅스</ title >
</ head >
< body style = " background-color: #1a1f2c; margin: 0; " >
< noscript >< strong >JavaScript를 활성화해주세요.</ strong ></ noscript >
< div id = "app" ></ div >
< script type = "module" src = "/src/main.js" ></ script >
</ body >
</ html >
<! doctype html >
< html lang = "" >
< head >
< meta charset = "utf-8" />
< meta content = "IE=edge" http-equiv = "X-UA-Compatible" />
< meta content = "width=device-width,initial-scale=1.0" name = "viewport" />
< meta content = "no-cache, no-store, must-revalidate" http-equiv = "Cache-Control" />
< link href = " < %= BASE_URL %>favicon.ico" rel = "icon" />
< link href = " < %= BASE_URL %>cdn/Pretendard-1.3.9/web/static/pretendard.css" rel = "stylesheet" />
< title > < %= process.env.BRAND_TITLE || '데이터메이커 시냅스' %></ title >
</ head >
< body style = " background-color: #1e2533; margin: 0; " >
< noscript >< strong >JavaScript를 활성화해주세요.</ strong ></ noscript >
< div id = "app" ></ div >
</ body >
</ html >
항목 main staging 위치 프로젝트 루트 index.html public/index.html템플릿 문법 없음 (정적 HTML) <%= %> (HtmlWebpackPlugin)스크립트 로드 <script type="module" src="/src/main.js">Webpack이 자동 주입 환경변수 env.js 런타임 로드 + preconnectprocess.env 빌드타임 주입배경색 #1a1f2c#1e2533타이틀 하드코딩 환경변수 기반 (BRAND_TITLE)
import { createApp } from 'vue'
import App from '@/app/app.vue'
import store from '@/app/app-store'
import router from '@/app/app-routes'
import i18n from '@/i18n'
import { initSentry } from '@/plugins/sentry'
import { registerPlugins } from '@/plugins'
import { registerComponents } from '@/plugins/components'
const app = createApp (App)
app. use (store)
app. use (router)
app. use (i18n)
initSentry (app, router)
registerPlugins (app)
registerComponents (app)
app. mount ( '#app' )
// Service Worker 등록
if ( 'serviceWorker' in navigator) {
/* ... */
}
import Vue from 'vue'
import App from '@/app/app.vue'
import store from '@/app/app-store'
import router from '@/app/app-routes'
import i18n from '@/i18n'
// Vue 2 플러그인 등록
import VueCompositionAPI from '@vue/composition-api'
import { BootstrapVue } from 'bootstrap-vue'
import VueToast from 'vue-toast-notification'
import VueWorker from 'vue-worker'
import VJsoneditor from 'v-jsoneditor'
import CKEditor from '@ckeditor/ckeditor5-vue2'
import VueFormulate from '@braid/vue-formulate'
Vue. use (VueCompositionAPI)
Vue. use (BootstrapVue)
Vue. use (VueToast)
Vue. use (VueWorker)
Vue. use (VJsoneditor)
Vue. use (CKEditor)
Vue. use (VueFormulate)
// 글로벌 컴포넌트 등록
Vue. component ( 'v-select' , vSelect)
Vue. component ( 'page-header' , PageHeader)
// ... 기타 글로벌 컴포넌트
// Sentry 초기화
Sentry. init ({ Vue, dsn : '...' })
new Vue ({
router,
store,
i18n,
render : ( h ) => h (App)
}). $mount ( '#app' )
핵심 차이점
Vue 3: createApp() + app.use() 체인
Vue 2: new Vue({}).$mount() + Vue.use() 전역 등록
Vue 2에서는 @vue/composition-api 백포트 필요
Vue 2에서는 BootstrapVue, CKEditor 등 추가 플러그인 사용
import { createRouter , createWebHistory } from 'vue-router'
const router = createRouter ({
history : createWebHistory (),
routes : [
... dashboardRoutes,
... annotatorRoutes,
... authRoutes,
{ path : '/:pathMatch(.*)*' , redirect : '/auth/login' }
]
})
// Navigation Guard
router. beforeEach ( async ( to , from , next ) => {
// 인증 및 테넌트 확인
})
import VueRouter from 'vue-router'
const router = new VueRouter ({
mode : 'history' ,
routes : [
... dashboardRoutes,
... annotatorRoutes,
{ path : '*' , redirect : '/auth/login' }
]
})
// Navigation Guard
router. beforeEach ( async ( to , from , next ) => {
// 인증 및 테넌트 확인
})
항목 main staging 생성 방식 createRouter()new VueRouter()History createWebHistory()mode: 'history'Catch-all /:pathMatch(.*)**
import { createStore } from 'vuex'
import createPersistedState from 'vuex-persist'
const store = createStore ({
modules : {
annotator,
imageAnnotator,
pcdAnnotator,
textAnnotator,
audioAnnotator,
videoAnnotator,
promptAnnotator,
dashboard
},
plugins : [ new VuexPersistence ({ /* ... */ }). plugin ]
})
import Vuex from 'vuex'
import createPersistedState from 'vuex-persistedstate'
const store = new Vuex. Store ({
modules : {
annotator,
imageAnnotator,
pcdAnnotator,
textAnnotator,
audioAnnotator,
videoAnnotator,
promptAnnotator,
dashboard
},
plugins : [ createPersistedState ({ /* ... */ })]
})
항목 main staging 생성 방식 createStore()new Vuex.Store()Persistence vuex-persistvuex-persistedstate
import { createI18n } from 'vue-i18n'
const i18n = createI18n ({
legacy : false , // Composition API 모드
globalInjection : true , // $t 템플릿에서 사용 가능
locale : 'ko' ,
fallbackLocale : 'ko' ,
messages : {
/* import.meta.glob('./locales/*.json') */
}
})
import VueI18n from 'vue-i18n'
const i18n = new VueI18n ({
locale : 'ko' ,
fallbackLocale : 'ko' ,
messages : {
/* require.context('./locales', ...) */
}
})
항목 main staging 생성 방식 createI18n()new VueI18n()API 모드 Composition (legacy: false) Options (legacy) 파일 로드 import.meta.globrequire.context