본문으로 건너뛰기
Kabkee.github.io
뒤로 가기

Vue 2 + BootstrapVue: Bootstrap CSS를 scoped로 격리하기 (::v-deep + SCSS)

2021년 2월, Vue 2 + BootstrapVue + Vue CLI(vue-loader 15) 환경에서 작성한 글이다. 2026년 기준으로 달라진 점은 다음과 같다.

  • Vue 2는 2023년 12월 31일에 지원이 종료됐다. BootstrapVue도 Vue 2·Bootstrap 4 기반이라, Vue 3에서는 BootstrapVueNext를 쓴다.
  • Vue 3에서는 ::v-deep 대신 :deep() 을 쓴다. 예: .main-wrapper :deep(.btn) { ... }
  • 아래 코드의 ~bootstrap/... 경로 표기는 webpack(Vue CLI) 전용이다. Vite에서는 ~ 없이 bootstrap/... 로 쓴다.

목차

목차 펼치기

scoped 스타일을 쓰는 이유

여러 라이브러리의 CSS를 규칙 없이 한 사이트에 불러오면, 스타일이 서로 충돌하거나 겹쳐서 원하는 결과를 얻기 어렵다. 프로젝트나 컴포넌트마다 scoped 스타일을 쓰면 이런 문제를 막을 수 있다.

상황: 기존 사이트의 Bootstrap 버전

LOOK360은 Bootstrap 3를 기반으로 만들어졌고, 관리자 화면 일부에만 Bootstrap 4를 쓰고 있었다.

사이트가 쓰는 CMS(kimsq 1.2)는 Bootstrap 3를 그대로 불러오면 레이아웃이 심하게 깨져서, Bootstrap CSS에 접두사(prefix)를 붙인 버전을 따로 만들어 쓰고 있었다.

왜 Vue 컴포넌트에 Bootstrap을 scoped로 넣어야 했나

Vue로 만든 화면을 기존 레거시 코드 대신 넣거나, 그누보드·kimsq 같은 CMS 안에서 쓰면 문제가 생긴다. Vue 쪽 Bootstrap CSS가 전역으로 적용되면 CMS의 기존 스타일과 충돌하고 겹친다. 그래서 Vue 컴포넌트 안에서만 Bootstrap이 적용되도록 범위를 묶어야 했다.

방법

  1. vue-loader에 SCSS 전처리기를 설치한다 (vue-loader 문서). Vue CLI라면 프로젝트를 만들 때 함께 설치할 수 있다.
  2. deep 선택자를 쓴다 (vue-loader 문서). scoped 스타일은 빌드할 때 컴포넌트의 요소에 data-v-xxxx 같은 속성을 붙이고, CSS 선택자에도 그 속성을 붙여서 범위를 제한한다. deep 선택자 안에 Bootstrap CSS 전체를 넣으면 Bootstrap의 모든 규칙이 이 컴포넌트 범위로 제한된다.
  3. SCSS의 deep 선택자 블록 안에서 Bootstrap CSS를 import한다 (참고한 글).
<style scoped lang="scss">
.main-wrapper ::v-deep {
  @import "~bootstrap/dist/css/bootstrap.min";
}
</style>

이렇게 하면 Bootstrap의 .btn 같은 규칙이 .main-wrapper[data-v-xxxx] .btn 형태로 컴파일되어, .main-wrapper 안에서만 적용된다.

주의사항

정리

Bootstrap CSS나 BootstrapVue CSS를 전역으로 불러오면 기존 CMS의 레이아웃이나 레거시 코드가 깨질 수 있다. 기존 사이트 안에 Vue 화면을 넣을 때는 scoped 스타일로 범위를 묶어 이를 막는다.

SCSS의 deep 선택자 블록 안에서 Bootstrap CSS를 import하면, Bootstrap에 정의된 CSS 전체를 scoped로 묶을 수 있어서 충돌 문제가 사라진다.

참고자료


이 글 공유하기:

이전 글
Axios withCredentials를 위한 PHP CORS 설정 (Preflight·다중 Origin)
다음 글
Electron에서 Axios로 받은 파일이 깨질 때: ipcMain에서 저장하기