VueJS에 CSS를 스타일을 적용하는 방법 중 편리한 Scoped CSS 기능에 대하여 알아보고 관련된 예제를 만들어 봅니다.

! VueJS에서 Scoped CSS는?
Vue를 사용하는 프로젝트는 다수의 컴포넌트를 사용하여 하나의 앱을 구현하게 됩니다. 이 경우 각각의 컴포넌트에 선언된 스타일이 의도하지 않거나 실수에 의하여 다른 컴포넌트에 영향을 줄 수 있겠죠. 이처럼 오직 특정 컴포넌트에만 고유의 스타일을 선언하기 위한 방법으로 vue-loader가 제공하는 scoped 방법을 사용할 수 있습니다.
<style scoped>
.my-component {
  color: red;
}
</style>

위 예제의 1번 라인에 적용된 style 태그의 scoped 속성이 바로 scoped style을 적용하기 위해 필요한 방법입니다. 그럼 scoped는 어떻게 적용되는걸까요?

@ Scoped style은 어떻게 동작하는가?
우선 컴포넌트 동작 방식을 알아야합니다... 컴포넌트는 생성될 경우 태그에 data-로 시작하는 고유의 속성값을 가지게 됩니다 위 예제인 myComponent 역시 특정한 값을 가지는 속성값을 가지게 되는데 scoped를 적용할 경우 해당 css 스타일은 해당 속성값이 자동으로 적용됩니다. 즉 scoped를 입력하면 아래와 같이 AFTER의 결과로 스타일이 적용됩니다.
// Before
.my-component {
  color: red;
}

// After
.my-component[data-a31h23f] {
  color: red;
}

아래의 코드처럼 특정 컴포넌트에만 적용 가능하도록 data-a31h23f라는 이름의 어트리뷰트가 생성되었죠. 이 data-a31h23f는 컴포넌트 내부의 모든 엘리먼트에 적용되어 나타납니다. 이제 해당 컴포넌트에 적용된 모든 style css는 이 속성이 있는 경우에만 적용되게 됩니다. 쉽고 간단하지만 매우 편리한 기능이죠.

하지만 예외상황도 존재합니다. 바로 컴포넌트 하위의 컴포넌트 또는 slot을 사용하는 경우가 대표적입니다. 아래에서 알아봅니다.


! 자식 컴포넌트에 스타일 적용하기, ::v-deep
컴포넌트는 부모와 자식처럼 계층 구조를 가지게 되고 위의 myComponent 내부에는 다른 여러 개의 컴포넌트가 사용될 수 있을 것입니다. 예를들어 AComponent, BComponent라고 생각해봅니다.

<MyComponent>
  <span>123</span>
  <AComponent>
    <h3>test</span>
  </AComponent>
  <BComponent>
  </BComponent>
</MyComponent>

모두 MyComponent 하위에 있지만 span 태그와 달리 하위 컴포넌트는 data-a31h23f처럼 속성값이 생기지 않습니다. 그런 이유로 당연히 scoped 스타일도 적용되지 않을 수 있죠... <slot>으로 추가된 요소 역시 적용되지 않습니다... 그럼 scoped style을 MyComponent에서 사용할 수 없을거라 생각하겠지만 방법이 있습니다. ::v-deep를 사용하면 됩니다.


# ::v-deep 사용하기 및 예제
아시는 분은 이미 아시겠지만 먼저 비슷한 몇 가지가 존재합니다. /deep/ 또는 >>> 또는 ::v-deep이죠. 가장 먼저 >>>은 언제 사용할까요? sass를 사용하지 않는다면 >>>를 사용하는데 동작은 /deep/ 또는 ::v-deep과 동일합니다. 하위 컴포넌트에서 scoped style을 사용할 수 있게해주죠!

그리고 ::v-deep과 /deep/ 역시 현재는 동일하게 동작하지만 /deep/은 deprecated되었으므로 ::v-deep을 사용하는 것이 좋습니다. 아래는 폰트 색을 적용한 간단한 예제입니다.

@ MyComponent.vue
<MyComponent>
 ...
</MyComponent>

<style scoped lang="scss">
span {
  color: red;
}
::v-deep {
  h3 {
    color: blue;
  }
}
</style>

위 예제에서는 하위 컴포넌트인 Acomponent 내부의 h3에 scoped style을 적용하기 위해서 ::v-deep을 사용한 예제코드입니다. 이처럼 사용해야 하위에서도 color: blue;라는 스타일이 정상 동작하게 됩니다.


여기까지 VueJS 앱에서 사용하는 scoped css에 대하여 간략하게 알아보았습니다.