ng-template과 ng-container

Jeongkuk Seo
sjk5766
Published in
7 min readDec 16, 2018

Angular에서 제공하는 ng-template과 ng-container는 HTML 렌더링을 위해 사용됩니다. 이 둘은 개별로 사용할 수도 있고 조합해서 사용할 수 있습니다. 이 둘의 특징과 언제 사용해야 하는지 정리하겠습니다.

ng-template

ng-template은 우리가 알게 모르게 내부적으로 항상 사용되고 있습니다. 한 번이라도 div 태그에 *ngIf를 아래와 같이 써봤다면 말입니다.

<div *ngIf=”true”> Hi </div>

위 코드는 Angular에 의해 아래와 같이 변환됩니다. 정확히는 *ngIf를 처리할 때, 아래와 같이 변경하는 거죠.

<ng-template [ngIf]=”true”>
<div> Hi </div>
</ng-template>

Angular가 내부적으로 처리하는 것 말고 우리가 어떻게 ng-template을 쓸 수있는지 이해하기 위해 특징 먼저 살펴보겠습니다.

ng-template은 기본적으로 view에 렌더링 되지 않습니다. 단순히 보이지 않는게 아니라 DOM에서도 존재하지 않습니다. 우리가 단순히 ng-template을 사용하면 그 내용은 주석처리가 됩니다. 아래와 같이 HTML을 작성하면,

<ng-template> Hi </ng-template>

크롬에서 개발자 도구로 다음과 같이 확인됩니다.

ng-template을 view에 보여주기 위해 두 가지 방법이 있습니다. ngIf 구조 디렉티브를 사용하거나 템플릿 참조 변수를 사용하는 방법입니다.

<! — ngIf 사용 →>
<ng-template [ngIf]=”true”> ngif </ng-template>
<br><! — 템플릿 참조 변수 사용 →>
<div *ngIf=”true; then templateReferenceVariable”></div>
<ng-template #templateReferenceVariable>
template reference variable
</ng-template>

위 코드의 결과는 아래와 같으며 ng-template가 view에 렌더링 될 수 있는 조건(구조 디렉티브, 템플릿 참조변수)이 추가되면 ng-template과 관련된 주석이 추가됩니다.

여기서 한 가지, ng-template에서 ngIf 구조 디렉티브를 사용한 코드를 다시 보겠습니다.

<ng-template [ngIf]=”true”> ngif </ng-template>

우리가 구조 디렉티브를 사용할 경우 보통은 *ngIf와 같이 사용하는데 ng-template 에서는 [ngIf]와 같이 사용해야 합니다. *ngIf 문법을 사용하면 적용되지 않습니다. 가령 우리가 아래와 같이 코드를 작성하면,

<ng-template *ngIf=”true”> Hi </ng-template>

Angular가 위 코드를 아래와 같이 변경하여 처리합니다.

<ng-template [ngIf]="true">
<ng-template> Hi </ng-template>
</ng-template>

외부 ng-template은 true라도 내부의 ng-template은 조건 값이 없으므로 렌더링 되지 않습니다. [ngIf]와 같은 문법은 기존의 *ngIf, *ngFor와 같은 문법과는 사용방법이 다르기 때문에 Angular에서 권장하지 않습니다. 만약 ng-template을 사용하여 view에 렌더링 할지 말지를 결정해야 한다면 템플릿 참조 변수를 사용하는 것이 좋습니다.

ng-container

ng-container는 Angular 그룹 요소로 ng-template과 두 가지 차이점이 있습니다. 우선 ng-container는 항상 view에 렌더링 됩니다.

<ng-container > Hi </ng-container>

두 번째 차이점은 *ngIf 구문을 사용합니다. 따라서 위에서 ng-template에서는 템플릿 참조 변수를 사용하라고 했지만, 동일하게 ng-container에서 *ngIf로 표현할 수 있습니다.

<ng-container *ngIf=”true” > Hi </ng-container>

ng-container는 언제 쓰는 걸까요? 가령 우리가 *ngIf나 *ngFor 같은 Angular 구조 디렉티브를 사용할 때, HTML 태그가 필요한 순간이 있습니다. 보통 그런 경우 우리는 <div> 나 <span> 태그를 사용합니다.

// app.component.html
<div *ngIf=”isClicked”> 버튼이 눌림!! </div> // (*)
<button (click)=”changeStatus()”>button </button>
// app.component.ts
export class AppComponent {
isClicked = false;
changeStatus() {
this.isClicked = !this.isClicked;
}
}

위 코드는 html의 버튼을 클릭하면 component 클래스의 isClicked 변수를 변경해서 버튼이 눌림!! 문자열을 보여주는 코드입니다. 이때 주석 (*)코드의 div 태그는 순전히 *ngIf를 위해 사용한 태그입니다. 자, 이게 실제 제품에서 이런 용도로 수 많은 div 태그가 존재하고 설상 가상으로 div 태그에 css를 적용하기 시작했습니다. 이럴 경우 DOM 이 매우 복잡해져 디버깅이 어려워지고 문제가 발생할 경우 쉽게 원인을 찾기 힘듭니다.

이런 경우 Angular에서는 ng-container를 쓰는게 더 좋은 방법입니다. Angular는 ng-container를 DOM에 넣지 않기 때문에 css나 layout에 영향을 미치지 않습니다.

<ng-container *ngIf=”isClicked”> 버튼이 눌림!! </ng-container>
<button (click)=”changeStatus()”>button </button>

이 외에도 HTML 태그에 두 개 이상의 구조 디렉티브(*ngIf ,*ngFor) 를 사용할 수 없으므로 이 때 역시 ng-container를 사용할 수 있습니다.

*ngIf와 *ngFor을 사용할 때 안좋은 예

<div *ngFor=”let item of items”>
<div *ngIf=”item.id”>
{{item.name}}
</div>
</div>>

*ngIf와 *ngFor을 사용할 때 좋은 예

<ng-container *ngFor="let item of items">
<div *ngIf="item.id">
{{item.name}}
</div>
</ng-container>

ngTemplateOutlet

ng-container에서 ngTemplateOutlet 구조 디렉티브를 이용하여 다음과 같이 사용할 수 있습니다.

<ng-container *ngTemplateOutlet=”template”></ng-container> 
<ng-template #template> Hello!</ng-template>

ngTemplateOutlet 디렉티브를 이용하면 동일한 템플릿을 중복해서 사용할 수 있습니다. 가령 회사 로고이미지를 템플릿 여러곳에서 보여준다고 할 경우 아래와 같이 사용할 수 있습니다.

--

--