Angular에서 부모 컴포넌트에서 정의한 스타일을 자식 컴포넌트나 전체...

Angular에서 부모 컴포넌트에서 정의한 스타일을 자식 컴포넌트나 전체...

Angular를 사용하여 프로젝트를 진행하다 보면 부모 컴포넌트에서 정의한 스타일을 자식 컴포넌트나 아니면 전체 스타일에 적용해야 할 때가 있습니다.

이럴 때 사용할 수 있는 것이 바로 @Component의 옵션 중 하나인 encapsulation에 적용하는 ViewEncapsulation 입니다.

ViewEncapsulation에 대해 설명하기 전에 Shadow DOM에 대해 알아야할 필요가 있습니다. 왜냐하면 ViewEncapsulation이 가능한 이유가 바로 이 Shadow DOM 때문입니다.

간단히 설명하자면 Shadow DOM은 HTML 요소들을 캡슐화할 수 있도록 제공합니다. 그래서 Shadow DOM을 사용하면 마크업, 스타일과 behavior들이 적용된 요소에 범위가 지정되며 다른 DOM 노드들과 충돌하지 않게 됩니다.

Angular 컴포넌트는 아래의 3가지로 구성됩니다.

컴포넌트 클래스 템플릿 스타일

이 3가지가 결합되어 애플리케이션에서 재사용 가능한 Angular 컴포넌트를 만들게 됩니다. 그리고 이 컴포넌트를 만들 때 Shadow DOM의 장점을 활용합니다.

만약 브라우저에서 Shadow DOM을 지원하지 않는다고 해도 Angular 자체 내에서 Shadow DOM을 흉내내기 때문에 문제가 없습니다.

Angular는 Shadow DOM을 흉내내고 스타일을 캡슐화하기 위해 ViewEncapsulation Type 3개를 제공합니다. (기본 값은 Emulated 입니다.)

Emulated : Shadow DOM 없음, 스타일 캡슐화, value는 0 None : Shadow DOM 없음, 스타일 캡슐화 없음, value는 2 ShadowDom : Shadow DOM, 스타일 캡슐화, value는 3

이 3개의 값의 차이를 비교하기 위해 아래와 같은 예시 코드가 있다고 가정하고 ViewEncapsulation의 값을 각각 적용해 보겠습니다.

// app.module.ts import { NgModule } from ‘@angular/core’; import { AppComponent } from ‘./app.component’; import {ChildComponent } from ‘./child’; import { BrowserModule } from ‘@angular/platform-browser’; @NgModule({ bootstrap: [AppComponent], declarations: [AppComponent, ChildComponent], imports: [BrowserModule], }) export class AppModule {} // app.component.html This is app(parent) // app.component.ts import { Component, ViewEncapsulation } from ‘@angular/core’; @Component({ selector: ‘my-app’, styleUrls: [‘./app.component.scss’], templateUrl: ‘./app.component.html’, encapsulation: ViewEncapsulation.Emulated }) export class AppComponent {} // app.component.scss h1 { color: red; } // child.component.html This is child

Emulated

Shadow DOM을 사용하지 않고 스타일을 캡슐화하기 때문에 app 컴포넌트에 적용된 h1 스타일이 child 컴포넌트에 적용되지 않습니다.

이 옵션을 사용하면 Angular는 실제 Shadow DOM을 생성하지 않고 흉내만 냅니다. 그렇기 때문에 브라우저에서 Shadow DOM을 지원하지 않아도 컴포넌트에 대한 스타일 캡슐화가 가능합니다.

개발자 도구에서 Elements를 확인해 보시면 아래와 같이 나타날 것입니다.

h1[_ngcontent-c60] { color: red; } This is app(parent) … // 이하 생략

None

Shadow DOM, 스타일 캡슐화 둘 다 사용하지 않기 때문에 부모 컴포넌트에(app) 있는 h1 스타일이 자식 컴포넌트에(child)도 적용된 것을 확인할 수 있습니다.

개발자 도구를 확인해 보시면 h1 스타일 DOM의 head 부분에 정의되어 있는 것을 확인할 수 있습니다.

h1 { color: red; } … // 이하 생략

None은 Shadow DOM도 적용되지 않고 스타일 캡슐화도 적용되지 않기 때문에 모든 DOM 노드 스타일에 영향을 줄 수 있으므로 주의가 필요합니다.

ShadowDom

Shadow DOM을 사용하고 스타일을 캡슐화 하므로 부모 컴포넌트(app)에 있는 h1 스타일이 자식 컴포넌트(child)에도 적용된 것을 확인할 수 있습니다. 왜냐하면 child 컴포넌트가 app 컴포넌트 안에 있기 때문에 같이 캡슐화되었기 때문입니다.

#shadow-root h1 { color: red; } This is app(parent) This is child

ShadowDom의 경우 브라우저가 Shadow DOM을 지원하지 않을 경우 오류가 발생하므로 주의가 필요합니다.

from http://clap-yeon.tistory.com/58 by ccl(A) rewrite - 2021-11-25 11:00:48