심화 가이드
템플릿

흐름 제어

Angular 템플릿은 조건에 따라 엘리먼트를 표시하거나, 감추거나, 반복하는 흐름 제어 블록 기능을 제공합니다.

조건에 따라 표시하기: @if, @else-if, @else

@if 블록은 표현식 결과가 참으로 평가될 때 내용물을 표시합니다:

      
@if (a > b) {  <p>{{a}} is greater than {{b}}</p>}

판단할 조건이 여러개라면 @else if 블록이나 @else 블록을 자유롭게 활용하면 됩니다.

      
@if (a > b) {  {{a}} is greater than {{b}}} @else if (b > a) {  {{a}} is less than {{b}}} @else {  {{a}} is equal to {{b}}}

표현식 계산 결과를 변수로 저장하기

@if 블록에서 조건문 판단에 사용한 데이터는 블록 안쪽에서 재사용할 수 있도록 변수로 할당해 둘 수 있습니다.

      
@if (user.profile.settings.startDate; as startDate) {  {{ startDate }}}

조건문에 사용하는 표현식이 길다면 이 방식이 유용합니다.

내용 반복하기: @for

@for 블록은 콜렉션을 순회하면서 블록 안에 있는 내용물을 반복해서 렌더링합니다. 이 때 콜렉션은 JavaScript 이터러블(iterable)이라면 어떤 것이라도 가능하며, Angular는 특히 Array를 다루는 성능에 최적화되어 있습니다.

@for 루프 블럭은 이렇게 사용합니다:

      
@for (item of items; track item.id) {  {{ item.name }}}

Angular @for 블록은 JavaScript의 continuebreak 같이 흐름을 제어하는 구문은 지원하지 않습니다.

@for 블록을 사용할 때 왜 track을 지정해야 하나요?

track 표현식은 Angular가 데이터와 DOM 노드의 관계를 파악하는 용도로 사용합니다. Angular가 이 관계를 파악할 수 있으면 데이터가 변경되었을 때 DOM 연산을 최소화하면서 성능을 최적화할 수 있습니다.

그래서 데이터 콜렉션을 반복할 때 애플리케이션의 렌더링 성능을 최적화하려면 track 구문을 효율적으로 작성해야 합니다.

track 표현식에는 개별 항목을 고유하게 구분할 수 있는 필드를 지정하세요. 보통은 iduuid와 같은 값을 사용할 것입니다. 고유하게 식별할 수 있는 필드가 없다면, 추가로 마련하는 것을 강력하게 권장합니다.

값이 변경되지 않는 정적 콜렉션이라면 인덱스 값을 표현하는 $index를 사용하는 것도 좋습니다.

값이 변경되는 것을 필드로 식별할 수 없다면 identity를 활용할 수도 있습니다. 이 방식은 삼중 등호 연산자(===)를 기준으로 참조값이 같은지 판단합니다. 이 방식은 가능한 한 사용하지 않는 것이 좋습니다. Angular가 데이터와 DOM 노드를 제대로 매칭할 수 없으면 렌더링 성능이 크게 저하될 수 있습니다.

@for 블록 내부에서 사용할 수 있는 변수

@for 블록에서 사용할 수 있는 내부 변수가 몇가지 있습니다:

변수 의미
$count 콜렉션의 전체 개수
$index 현재 반복되는 인덱스 값
$first 현재 반복되는 항목이 첫번째 항목인지 여부
$last 현재 반복되는 항목이 마지막 항목인지 여부
$even 현재 반복되는 항목이 짝수번째인지
$odd 현재 반복되는 항목이 홀수번째인지

이 변수들은 그대로 사용할 수 있지만, let 을 사용해서 다른 이름으로 사용할 수도 있습니다:

      
@for (item of items; track item.id; let idx = $index, e = $even) {  <p>Item #{{ idx }}: {{ item.name }}</p>}

이렇게 내부 변수를 다른 이름으로 지정하는 방식은 @for 블록이 중첩되어 있을 때 특히 유용합니다.

콜렉션이 비어있을 때 - @empty 블록 사용하기

@for 블록 뒤에는 @empty 블록을 사용할 수 있습니다. 그러면 @for 블록에서 순회하는 콜렉션에 항목이 하나도 없을 때 @empty 블록이 화면에 표시됩니다:

      
@for (item of items; track item.name) {  <li> {{ item.name }}</li>} @empty {  <li aria-hidden="true"> There are no items. </li>}

여러 조건 중 하나 표시하기: @switch 블록

@if 블록은 대부분의 경우에 사용할 수 있지만, 조건이 여러개라면 @switch 블록을 사용하는 것도 고려할 만 합니다. @switch 블록은 JavaScript switch 구문과 아주 비슷합니다.

      
@switch (userPermissions) {  @case ('admin') {    <app-admin-dashboard />  }  @case ('reviewer') {    <app-reviewer-dashboard />  }  @case ('editor') {    <app-editor-dashboard />  }  @default {    <app-viewer-dashboard />  }}

이 때 조건문은 삼중 등호 연산자(===)로 비교합니다.

@switch 블록은 다음 블록으로 연결되지 않습니다. breakreturn 같이 흐름을 제어하는 구문은 존재하지 않습니다.

@default 블록을 사용할 수 있습니다. 이 블록은 매칭되는 @case 블록이 없을 때 표시됩니다.

@default 블록이 없으면서 @case 블록 중 어느것도 매칭되지 않으면, 아무것도 렌더링되지 않습니다.