IT/Angular

[Angular] Pipe 파이프와 사용법 (파일 사이즈 커스텀파이프)

힞뚜루마뚜루 2023. 5. 25. 15:28
728x90

파이프란

보통 애플리케이션이 관리하는 데이터 또는 서버에서 받아오는 데이터는 사용자들에게 실생활에 익숙한 형태가 아닐 수 있다.
예를 들면, 날짜 데이터 같은 경우 Date 함수가 리턴하는 인스턴스를 문자열화하면 아래와 같다.

const today = new Date();
console.log(today.toString()); // Thu May 25 2023 14:00:00 GMT+0900 (KST)

딱보기에도 사용자가 읽기 쉬운 형태는 아니다.

이 때 데이터 자체를 변경하는 것은 다른 side effect가 있을 수 있으므로 화면에 표시하는 형식만 변경하고 싶을 때 사용하는 것이 Pipe 이다. 파이프를 사용하면 마치 스타일 정의하듯 HTML에서 바로 출력 변환이 가능하다.

 

사용법

사용법은 간단하다.

import { Component } from ‘@angular/core’;

@Component({
  selector: ‘app-today’,
  template: `
  <p>Today is {{ today | date }}</p>
  <p>Today is {{ today | date: 'y년 MM월 dd일' }}</p>
 `
})
export class TodayComponent {
	today = new Date();
}

date 파이프를 사용하면 다음과 같이 출력된다.

Today is May 25, 2023
Today is 2023년 05월 25일

대상 값 뒤에 연산자 |  를 붙인 후 원하는 파이프를 지정한다. 예시에서 처럼 콜론(:)을 이용하여 옵션을 지정할 수도 있다.

파이프는 템플릿 내에서만 원하는 형식으로 데이터를 변환하기 때문에 원본데이터 자체는 변경되지 않는다.

 

빌트인 파이프 Built-in Pipe

앵귤러에서는 위에서 쓴 date 파이프와 같은 기본 파이프를 제공한다.

  • DatePipe: 날짜를 원하는 형식으로 변환
  • UpperCasePipe: 문자열을 대문자로 변경
  • LowerCasePipe: 문자열을 소문자로 변경

이 외에도 많은 파이프들이 있는데 자세한 내용과 사용법은 아래 앵귤러 공식문서를 참조하는 게 좋다.

Angular docs - 빌트인 파이프

 

체이닝 파이프 

여러 개의 파이프를 조합할 수도 있다.

import { Component } from ‘@angular/core’;

@Component({
  selector: ‘app-my’,
  template: `
  <p>SlicePipe + UpperCasePipe</p>
  <p>{{ name | slice: 4 | uppercase }}</p>
 `
})
export class MyComponent {
	name = 'hee tistory';
}

빌트인 파이프 중 슬라이스 파이프와 대문자 파이프를 체이닝한 결과이다.

SlicePipe + UpperCasePipe
TISTORY

 

커스텀 파이프

개발자가 직접 파이프를 만들 수도 있다. 

  1. 파이프 클래스를 생성한다.
  2. 생성한 파이프 클래스에는 @Pipe 데코레이터 장식이 필요하며, name 프로퍼티에 식별자를 지정한다.
  3. PipeTransform 인터페이스의 추상메소드 transform 안에 원하는 내용을 구현하면 된다.
  4. 파이프를 module의 declarations에 등록한다.


아래와 같이 pipe 파일을 생성해주고

ng generate pipe file-size

나는 숫자로만 입력된 파일사이즈를 예쁘게 바꿔주는 파이프를 만들었다.

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

@Pipe({
  name: 'fileSize'
})
export class FileSizePipe implements PipeTransform {

  transform(value, option?: object) {

    if(isNaN(value)) return value;
  
    if(typeof value !== 'number') value = Number(value);

    if(value < 0) return value;
    
    const oneMBToByte = 1024 * 1024;
    const oneKBToByte = 1024;

    const isGreaterOneMBToByte = value > oneMBToByte;

    let unit = isGreaterOneMBToByte ? 'MB' : 'KB';

    if (isGreaterOneMBToByte) {
      value = (value / oneMBToByte).toFixed(1)
    } else {
      value = (value / oneKBToByte).toFixed(1)
    }

    return value + ' ' + unit;
  }

}

 

- transform()

transform(value: any, ...args: any[]): any
  • transform 메서드는 변환 대상 값 value와 옵션 args 들을 인자로 받는데 옵션(args)는 Rest 파라미터로 정의되어 있어서 여러 개의 옵션을 파라미터로 전달할 수 있다.

 

이렇게 만든 커스텀 파이프를 이제 모듈의 declarations에 등록하면 완료다. 나는 pipe만 모아놓은 모듈을 따로 만들었다.

//pipes.modules.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FileSizePipe } from './file-size.pipe';

const PIPES = [
  FileSizePipe,
];

@NgModule({
  declarations: [
    ...PIPES,
  ],
  imports: [
    CommonModule
  ],
  exports: [
    ...PIPES
  ]
})
export class PipesModule {}

 

적용은 빌트인 파이프와 같이 동일하게 적용하면 되고 실행결과는 다음과 같다.

import { Component } from ‘@angular/core’;

@Component({
  selector: ‘app-my’,
  template: `
  <p> Size {{size1}} is {{ size1 | fileSize }}</p>
  <p> Size {{size2}} is {{ size2 | fileSize }}</p>
 `
})
export class MyComponent {
	size1: number = 20230525;
    size2: number = 202305;
}
Size 20230525 is 19.28MB
Size 202305 is 197.6KB 

 


[참고]

  • Angular Essentials (루비페이퍼; 이웅모 저)

 

728x90