Angular ElementRef, TemplateRef, ViewContainerRef에 대해

Jeongkuk Seo
sjk5766
Published in
6 min readDec 22, 2018

AngularJS에서는 DOM을 조작하는 방법을 쉽게 제공하는 장점 덕에 browser 플랫폼에 매우 가까운 단점이 있었습니다. 반면 Angular2 부터는 browser, 모바일, web worker 같은 여러 플랫폼에서 동작하기 위해 platform API와 프레임워크 인터페이스 사이에 여러 추상화 레벨을 두었습니다.

이를 위해 Angular에서는 다양한 type들을 제공하게 되었으며 ElementRef, TemplateRef, ViewRef, ComponentRef, ViewContainerRef 등이 있습니다. 이 중 제목에서 언급했듯이 자주 사용되는 ElementRef, TemplateRef, ViewContainerRef 에 대해 알아보겠습니다.

ViewChild

ElementRef, TemplateRef, ViewContainerRef 를 알아보기 위해 먼저 ViewChild를 알아 보겠습니다. Angular에서 DOM 쿼리를 호출할 수 있는 메커니즘으로 ViewChild와 ViewChildren을 제공하고 있습니다. 이 둘의 차이는 특정 DOM 요소를 가져오느냐 여러 요소를 가져오느냐의 차이입니다. 기본적인 사용법을 보면

@Component({
selector: 'app-root',
template: `<span #elementRef>This is a ViewChild Example</span>`,
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
@ViewChild('elementRef') ef: ElementRef;
ngOnInit() {
console.log(this.ef)
}
}

ViewChild의 기본 사용법은 아래와 같습니다.

@ViewChild([reference from template], {read: [reference type]});

즉, 위 사용법에 의하면 아래 두 코드는 동일합니다.

@ViewChild('elementRef') ef: ElementRef;
@ViewChild('elementRef', {read: ElementRef}) ef: ElementRef;

두 번째 파라미터 read는 항상 필요하진 않습니다. 기본적으로 ElementRef와 TemplateRef는 Angular가 알아서 type을 추론해줍니다. 반대로 나중에 설명할 ViewContainerRef는 type을 추론하지 못하므로 항상 아래와 같이 사용합니다.

@ViewChild('템플릿변수명', {read: ViewContainerRef}) vcr: ViewContainerRef;

ElementRef

ElementRef는 class로 우리가 HTML 표준 태그들을 사용할 때 Component Class에서 해당 type으로 받을 수 있습니다. 예를 들어 <span #s> , <div #d> 등의 HTML 태그와 템플릿 참조 변수(#s, #d)를 사용하면 Component Class에선 다음과 같이 이 둘에 대한 DOM 참조를 얻을 수 있습니다.

@ViewChild('s') span_ef: ElementRef;
@ViewChild('d') div_ef: ElementRef;

TemplateRef

TemplateRef 역시 class로 우리가 <ng-template>을 사용할 경우 Component Class에서 해당 type으로 받을 수 있습니다.

// HTML
<ng-template #ngt> </ng-template>
// Component Class
@ViewChild('ngt') tf: TemplateRef;

ViewContainerRef

ViewContainerRef는 우리가 <ng-container>를 사용할 경우 Component Class에서 해당 type으로 DOM 참조를 얻을 수 있습니다.

// HTML
<ng-container #ngc> </ng-container>
// Component Class
@ViewChild('ngc') vcf: ViewContainerRef;

사용예제

HTML 코드

<div #elementRef> <h1>Hello elementRef</h1> </div><ng-template #templateRef><h1>Hello templateRef</h1></ng-template><ng-container #viewContainerRef><h1>Hello viewtemplateRef</h1></ng-container>

Component Class 코드

@ViewChild(‘elementRef’) ef: ElementRef;
@ViewChild(‘templateRef’) tf: TemplateRef<any>;
@ViewChild(‘viewContainerRef’, {read:ViewContainerRef}) vcr: ViewContainerRef;
ngOnInit() {
console.log(this.ef)
console.log(this.tf)
console.log(this.vcr)
}

위 두 코드의 결과를 보면 아래와 같습니다.

<ng-template> 을 사용한 Hello templateRef 결과가 보이지 않는 것을 알 수 있습니다. 이는 당연하게 ng-template에서 [ngIf]를 사용하지 않을 경우 기본적으로 View에 렌더링 되지 않으므로 정상적입니다.

간단요약

  1. ElementRef, TemplateRef, ViewContainerRef는 Angular에서 다양한 환경에서 어플리케이션을 동작시키기 위해 제공되는 타입이다.
  2. EmelentRef는 HTML 태그, TemplateRef는 ng-template, ViewContainerRef는 ng-container에 대응된다.
  3. 템플릿에서 템플릿 참조 변수를 선언하고 Component Class 에선 템플릿 참조 변수와 ViewChild 데코레이터를 통해 DOM에 대한 참조를 얻을 수 있다.

--

--