Skip to content

앱에 연동

이 페이지는 @platform/vue-debugger를 여러분의 Vue 3 앱 부트스트랩에 붙이는 방법을 다룹니다. 핵심은 main.ts에 몇 줄입니다 — 조건부 동적 import()로 디버거를 지연 로드하고, attachDebugger(app)을 호출하면 끝입니다. 별도 플러그인 등록이나 CSS import는 필요 없습니다.

이 페이지를 마치면 앱을 dev로 띄웠을 때 우측 하단에 톱니(⚙) FAB가 뜨고, Alt+Shift+D로 디버거를 토글할 수 있습니다. 설치가 아직이라면 설치를 먼저 보세요.

어디서 호출하나

디버거는 호스트 앱의 pinia·router를 import하지 않고 런타임에 구조적으로 발견합니다. 따라서 발견 대상이 이미 앱에 등록된 , 그리고 앱이 마운트되기 에 붙여야 합니다.

attachDebuggerapp.use(pinia/router) 뒤, app.mount()에 호출하세요.

  • app.use(...) — 이 순서를 지켜야 Pinia·Router 패널이 인스턴스를 발견합니다. 더 일찍 호출하면 해당 패널이 빈 상태로 뜹니다.
  • app.mount() — 마운트 시점에 디버거가 자리 잡고 있어야 초기 렌더·라우팅·네트워크를 처음부터 기록합니다.

main.ts 전체 예시

아래가 연동의 전부입니다. 부트스트랩을 async function으로 감싸고, 그 안에서 개발/검증 빌드일 때만 디버거를 동적 import()로 불러와 붙입니다.

ts
import { createApp } from 'vue'
import App from './App.vue'

async function bootstrap() {
  const app = createApp(App)
  // app.use(createPinia()) / app.use(router) ... (있다면 먼저)

  // 개발/검증 빌드에서만 디버거를 붙인다 (프로덕션엔 코드가 들어가지 않음)
  if (import.meta.env.DEV || (import.meta.env.MODE === 'staging' && import.meta.env.VITE_DEBUGGER === 'on')) {
    const { attachDebugger } = await import('@platform/vue-debugger')
    attachDebugger(app)
  }

  app.mount('#app')
}
bootstrap()

활성 분기 import.meta.env.DEV || (import.meta.env.MODE === 'staging' && import.meta.env.VITE_DEBUGGER === 'on')이 모든 환경을 한 줄로 처리합니다. 로컬(vite dev)에선 DEVtrue라 자동으로 켜지고, 진짜 프로덕션 빌드에선 두 조건이 정적으로 false가 되어 이 블록과 그 안의 동적 import()가 dead-code로 통째 제거됩니다. 환경별 빌드 설정의 전체 가이드는 환경별 설정을 보세요.

정적 치환 대상만 쓰세요 — 동적 키 접근 금지

분기는 반드시 import.meta.env.VITE_DEBUGGER처럼 정적으로 접근하세요. const f = 'VITE_DEBUGGER'; import.meta.env[f]처럼 동적으로 접근하면 Vite/Rollup이 값을 정적 치환하지 못해 dead-code 제거가 일어나지 않고, 디버거가 프로덕션 번들에 그대로 남습니다. 디버거는 쿠키·스토리지·API 응답을 노출하므로 프로덕션 누출은 보안 사고입니다.

async function으로 감싸나

await import()로 디버거를 지연 로드하려면 await를 쓸 수 있는 컨텍스트가 필요합니다. 이때 main.ts 최상단에 await를 직접 쓰면 안 됩니다(top-level await 금지).

top-level await 함정 — 검증계 빌드가 깨집니다

await import()main.ts 최상단에 직접 쓰면 vite dev(esbuild)에선 동작하지만, vite build의 기본 타깃(es2020 / chrome87…)이 top-level await를 거부해 검증계 빌드가 깨집니다.

반드시 async function bootstrap()으로 감싸고 그 안에서 await 하세요. async 함수 내부의 await는 일반 await라 모든 빌드 타깃에서 안전하고, 동적 import의 프로덕션 dead-code 제거도 그대로 유지됩니다.

(프로덕션은 분기가 정적 false → import() 블록째 제거되어 어차피 await가 남지 않지만, 검증계 빌드를 깨뜨리지 않으려면 감싸는 것이 정답입니다.)

webpack / Vue CLI는 어떻게 다른가

import.meta.env는 Vite 전용입니다. webpack/Vue CLI에는 없으므로 process.env.NODE_ENV로 분기하세요(DefinePlugin이 정적 치환).

ts
async function bootstrap() {
  const app = createApp(App)

  if (import.meta.env.DEV || (import.meta.env.MODE === 'staging' && import.meta.env.VITE_DEBUGGER === 'on')) {
    const { attachDebugger } = await import('@platform/vue-debugger')
    attachDebugger(app)
  }

  app.mount('#app')
}
bootstrap()
ts
// vue.config.js — 빌드 스크립트에 묶인 상수를 정의(셸/CI env로는 켤 수 없게)
// package.json: "build:staging": "vue-cli-service build --mode staging"
// const isStagingBuild = process.env.npm_lifecycle_event === 'build:staging'
// DefinePlugin에 추가: __VDBG_STAGING__: JSON.stringify(isStagingBuild)

declare const __VDBG_STAGING__: boolean

async function bootstrap() {
  const app = createApp(App)

  if (process.env.NODE_ENV !== 'production' || (__VDBG_STAGING__ && process.env.VUE_APP_DEBUGGER === 'on')) {
    const { attachDebugger } = await import('@platform/vue-debugger')
    attachDebugger(app)
  }

  app.mount('#app')
}
bootstrap()

webpack에서 VUE_APP_DEBUGGER 단독 분기는 금지

DefinePlugin은 셸/CI의 VUE_APP_* 환경변수도 정적 치환하므로, NODE_ENV 체크에 VUE_APP_DEBUGGER === 'on'를 OR로만 붙인 분기는 CI에 잔존한 env 하나로 production 번들에 디버거가 실릴 수 있습니다(Vite 쪽 MODE === 'staging' AND 결합과 같은 이유). 위처럼 빌드 스크립트에 묶인 상수(__VDBG_STAGING__)와 AND로 묶고, npx vue-debugger-leak-check <dist>를 CI blocking 게이트로 배선하세요.

실행 — FAB와 단축키

연동을 마치고 앱을 dev로 띄우면 화면 우측 하단에 ⚙ FAB가 나타납니다. 이걸 누르거나 Alt+Shift+D를 누르면 11개 패널을 가진 디버거가 열립니다.

동작방법
디버거 열기우측 하단 ⚙ FAB 클릭
토글(열기/닫기)Alt+Shift+D

CSS import가 필요 없습니다

디버거는 Shadow DOM 안에서 동작하며 스타일을 자동으로 주입합니다. 그래서 별도의 CSS import가 필요 없고, 호스트 앱의 CSS와도 충돌하지 않습니다(:host{all:initial}로 완전 격리). 구조와 격리 원리는 아키텍처를 보세요.

콘솔에 ⚠ @platform/vue-debugger ACTIVE 경고가 보입니다 — 의도된 것입니다

attachDebugger가 활성화되면 콘솔에 끌 수 없는 경고를 남깁니다. dev/검증계에서는 "디버거가 켜졌다"는 정상 신호이니 무시하세요. 이는 심층방어 트립와이어로, 만약 production 콘솔에서 이 문구가 보이면 누출이니 즉시 보안·누출 차단의 게이트를 확인하세요.

FAB·패널이 비어 보일 때

  • FAB가 안 보임attachDebuggerapp.mount() 전에 불렀는지, 분기가 dev에서 true인지 확인하세요.
  • Pinia/Router 패널이 비어 있음attachDebuggerapp.use(pinia/router) 뒤에 호출하세요.
  • 배포 빌드에서 컴포넌트 트리는 보이는데 값이 다 비어 있음__VUE_PROD_DEVTOOLS__ 설정이 빠진 것입니다(환경별 설정 참고).

더 많은 증상과 해결은 문제 해결에 있습니다.

반환 핸들로 제어하기

attachDebugger(app)은 디버거를 프로그래밍 방식으로 제어할 수 있는 핸들을 반환합니다. 직접 호출할 일은 드물지만, 자동화 테스트나 커스텀 트리거를 붙일 때 유용합니다.

ts
const handle = attachDebugger(app)

handle.version    // 디버거 버전 문자열 (예: '0.17.4')
handle.open()     // 패널 열기
handle.close()    // 패널 닫기
handle.toggle()   // 열기/닫기 토글
handle.destroy()  // UI 제거 + 정리, window.__VUE_DEBUGGER__ 해제

반환 타입은 DebuggerHandle | null입니다. **비브라우저 환경(SSR 서버 측 등 window/document가 없는 경우)에선 null**을 반환하며 아무 작업도 하지 않으므로, 별도 분기 없이 안전하게 호출할 수 있습니다.

핸들은 전역에서도 접근할 수 있습니다. 같은 핸들이 window.__VUE_DEBUGGER__에 등록되므로, 콘솔이나 다른 모듈에서 바로 제어하거나 버전을 확인할 수 있습니다.

ts
window.__VUE_DEBUGGER__?.toggle()
window.__VUE_DEBUGGER__?.version   // 정보 탭에서도 동일하게 확인 가능
HMR·중복 부착은 알아서 막습니다

attachDebugger는 이미 window.__VUE_DEBUGGER__가 있으면 새로 만들지 않고 기존 핸들을 그대로 반환합니다. 그래서 HMR로 main.ts가 다시 평가되어도 디버거가 중복 부착되지 않습니다.

다음 단계

  • 옵션(bridges·ignoreUrls·report·maxEntries 등) 전체는 옵션 레퍼런스를 보세요.
  • 검증계·스테이징 등 배포된 빌드에서 디버거를 켜는 법(VITE_DEBUGGER=on, __VUE_PROD_DEVTOOLS__, sourcemap)은 환경별 설정에 있습니다.
  • 전역 beforeEach/beforeResolve 가드 추적이 필요하면 traceGuards를 추가하는 전역 라우터 가드를 보세요.
  • 연동이 제대로 됐는지 확인하려면 설치 검증을 따라 하세요.

개발/검증 환경 전용 인페이지 Vue 디버거 · 진짜 프로덕션엔 코드가 들어가지 않습니다