[ Angular 2: Pipes ] 파이프 개념 및 활용

Pipes 는 데이타를 출력할 때 시각적인 형식을 변형하여 나타낼 수 있도록 해준다. Built-in Pipes 는 이미 Angular 2 에서 지정해놓은 것들인 반면, 필요에 따라 우리가 Custom Pipes 를 만들어 사용할 수도 있다.

Pipes Example

 

myValue = 'lowercase';

<p>{{lowercas}}</p>

‘lowercase’라고 출력된다.

myValue = 'lowercase';

<p>{{ myValue | uppercase }}</p>

‘LOWERCASE’ 라고 출력된다. ‘|’ 다음에 나오는 ‘uppercase’ 는 Angular 2가 지정해놓은 Built-in Pipes 중 하나이다.

다양한 Built-in Pipes  살펴보기

링크를 클릭하면 위 페이지로 이동하여 pipe 리스트를 확인할 수 있다.

Custom Pipes Example 1

다음과 같이 명령프롬프트에서 실행하면, pipe 파일이 생성된다.

$ ng generate pipe {{pipe_name}}
//또는
$ ng g p {{pipe_name}}

입력한 수의 두배값을 출력하는 pipe를 만들어보자. 다음과 같이 입력하면, src/app/double.pipe.ts 파일이 생성된다.

$ ng g p double

생성된 파일을 아래와 같이 편집하자.

double.pipe.ts

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'double'
})
export class DoublePipe implements PipeTransform {

  transform(value: any, args?: any): any {
    return value*2;
  }

}

value 값을 받아서 2를 곱한 후 돌려주는 기능을 한다. 이 기능을 html 파일에서 아래와 같이 적용해보자.

app.component.html

<div class="pipes">
  <h2>Custom Pipe</h2>
  <input type="text" #input (keyup)="0">
  <p>{{input.value | double}}</p>
</div>

여기서 keyup 이벤트 리스너는 0이라는 Dummy 값을 돌려준다. 즉, 아무 기능도 하지 않지만, Input 필드에 값을 입력하면 p태그 안의 Input 값이 함께 업데이트될 수 있도록 하는 일종의 Hack이다.

$ ng serve

숫자를 입력하면 두배값을 실시간으로 출력하는 것을 볼 수 있다.

Custom Pipes Example 2

음식 이름이 나열된 array value 가 있다고 치자. [‘Milk’,’Bread’,’Beans’] 이 중에서 ‘ea’가 포함된 것들만 출력하는 Pipe 를 만들어보자. 다음을 명령프롬프트에서 실행하면 filter.pipe.ts 파일이 생성된다.

$ ng g p filter

filter.pipe.ts

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'filter'
})
export class FilterPipe implements PipeTransform {

  transform(value: any, args?: any): any {
    if (value.length==0) {
      return value;
    }
    let resultArray = [];
    for (let item of value){
      if (item.match('^.*'+args[0]+'.*$')){
        resultArray.push(item);
      }
    }
    return resultArray;
  }

}

app.component.ts 파일에서 array value 를 설정하자.

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  values = ['Milk','Bread','Beans']
}

app.component.html 에서 적용시켜보자.

<div class="pipes">
  <ul>
    <li *ngFor="let item of values | filter:'ea'">{{item}}</li>
  </ul>
</div>

ng serve 로 실행해본다. 예상대로 ea를 포함한 값만 표시된다. 이 예제를 약간 변형하여 impure pipe 을 구현해보자.

Impure Pipe

Angular 2 의 Change Detection 은 Primitive 타입이 변하거나 Reference 자체가 변할 때만 실행된다. 위 value 값은 reference 이기 때문에 그 뒤에 있는 Object 가 변하더라도 Angular 2가 감지하지 못한다. 다음과 같이 app.component.html 을 변경해보자.

<div class="pipes">
  <input type="text" #newItem>
  <button (click)="values.push(newItem.value)">Add Item</button>
  <ul>
    <li *ngFor="let item of values | filter:'ea'">{{item}}</li>
  </ul>
</div>

이렇게 변경하고 브라우저에서 실행해보면, Input 필드에 어떤 값을 넣더라도 적용이 되지 않는 것을 확인할 수 있다. value 가 reference 이기 때문에 그렇다. 이럴 때는 impure pipe 을 사용해야한다. 간단하다. 다음과 같이 filter.pipe.ts 파일의 @Pipe 디렉티브 안에 pure:false 를 추가해준다.

...
@Pipe({
  name: 'filter',
  pure: false
})
...

이제 의도한 대로 입력한 값에 ea 가 포함되어 있다면 리스트가 업데이트 되는 것을 확인할 수 있다. impure pipe 를 사용하면 퍼포먼스에 악영향을 미칠 수 있음을 명심하자.

Async Pipe

Observable 이나 Promise 의 결과값 반영은 Async Pipe 으로 구현해야 한다.

app.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  asyncValue = new Promise((resolve,reject)=>{
    setTimeout(()=>resolve('Data is here!'),2000);
  });
}

여기서 asyncValue 값이 2초 후에 전달되도록 설정했다. html 파일에서 어떻게 받아와야할까?

app.component.html

<div class="pipes">
  <h2>Async pipe</h2>
  <p>{{asyncValue}}</p>
</div>

단순히 변수를 불러오는 것으로는 브라우저 창에 [Object Object] 라는 이상한 문구가 표시된다. 다음과 같이 고쳐보자.

<div class="pipes">
  <h2>Async pipe</h2>
  <p>{{asyncValue | async }}</p>
</div>

이렇게 하면 브라우저 창에서 2초 후에 값이 정상적으로 표시된다.

 

댓글 남기기