Angular essentials - 디렉티브

  • SUNGMIN SHIN
  • 10 Minutes
  • 2018년 9월 18일

Angular essentials

(https://book.naver.com/bookdb/book_detail.nhn?bid=13761643)


08. 디렉티브


8.1 디렉티브란?

디렉티브(Directive, 지시자)는 DOM의 모든 것(모양이나 동작 등)을 관리하기 위한 지시(명령)로 HTML 요소 또는 어트리뷰트의 형태로 디렉티브가 사용된 요소에게 무언가를 하라는 지시(Directive)를 전달한다.

디렉티브는 애플리케이션 전역에서 사용할 수 있는 공통 관심사를 컴포넌트에서 분리하여 구현한 것으로 컴포넌트의 복잡도를 낮추고 가독성을 향상시킨다.
(컴포넌트도 뷰를 생성하고 이벤트를 처리하는 등의 DOM을 관리하기 때문에 큰 의미에서는 디렉티브로 볼 수 있다.)

컴포넌트는 뷰를 구성하는 독립적인 구성요소로서 다른 컴포넌트에 직접적인 관심을 두지 않지만 디렉티브는 보편적이며 애플리케이션 전역에서 공통으로 사용 가능한 고유의 관심사를 기능으로 구현한다.
(즉 컴포넌트는 뷰 단위의 관심사를 가지고 있다고 하면 디렉티브는 DOM 요소의 공통 기능에 관심을 갖는다.) 디렉티브는 단일 책임 원칙(Single Responsibility, Principle)에 의해 복합적인 기능보다는 여러 요소에서 공통적, 반복적으로 사용될 하나의 기능을 명확히 구현하는 것이 바람직하다.

디렉티브는 컴포넌트와 달리 뷰를 가지고 있지 않기 때문에 자식을 가질 수 없다. 다시 말해 컴포넌트는 자식 컴포넌트, 디렉티브. 파이프, 서비스등을 조합하여 뷰를 만들지만 디렉티브는 부모가 될 수 없고 컴포넌트에 의해 사용될 뿐이다.

디렉티브는 DOM 요소 또는 어트리뷰트와 유사하게 의미를 갖는 이름으로 표현된다. 이때 로직은 드러나지 않으며 단지 디렉티브를 순서에 맞게 배치한다. 이를 ‘선언형 프로그래밍(Devalarative Programming)이라고 한다.

디렉티브는 @Directive 데코레이터로 장식된 클래스로 디렉티브의 설정 정보가 기술된 메타데이터를 인자로 전달받아 디렉티브를 생성한다.

정리

  1. 디렉티브는 애플리케이션 전역에서 사용할 수 있는 공통 관심사를 컴포넌트에서 분리하여 구현한 것
  2. 뷰를 구성하는 독립적인 구성요소로 애플리케이션 전역에서 공통으로 사용 가능한 고유의 관심사를 기능으로 구현
  3. 디렉티브는 복합적인 기능보다는 여러 요소에서 공통, 반복적으로 사용될 하나의 기능을 명확히 구현하는 것이 바람직하다.


8.2 디렉티브의 종류

Angular는 아래와 같이 3가지 유형의 디렉티브를 제공한다.

  1. 컴포넌트 디렉티브(Component Directive)
    컴포넌트의 템플릿을 표시하기 위한 디렉티브로 @Component 데코레이터의 메타 데이터 객체의 selector 프로퍼티에서 임의의 디렉티브 이름을 정의한다.
  2. 어트리뷰트 디렉티브(Attribute Directive)
    어트리뷰트 디렉티브는 DOM 요소의 어트리뷰트로 사용하여 해당 요소의 모양이나 동작을 제어한다. ngClass, ngStyle과 같은 빌트인 디렉티브가 있다.
  3. 구조 디렉티브(Structual Directive)
    구조 디렉티브는 DOM 요소를 반복 생성(ngFor), 조건에 의한 추가 또는 제거(ngIf, ngSwitch)를 통해 DOM 레이아웃을 변경한다.

이 외에 사용자 정의 디렉티브가 있는 데 이 것은 사용자가 직접 정의하는 디렉티브이다.


8.3 사용자 정의 어트리뷰트 디렉티브

8.3.1 사용자 정의 어트리뷰트 디렉티브 생성

angular CLI를 통해 추가하는 경우 아래와 같이 입력

1
ng generate directive 디렉티브명

예제에서는 ‘textBlue’라는 이름으로 아래와 같이 생성합니다.

1
ng generate directive textBlue

그리고 생성된 디렉티브를 아래와 같이 수정합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// text-blue.directive.ts
import { Directive, ElementRef } from '@angular/core';

// 1 - 디렉티브의 식별자를 @Directive 메타데이터 객체의 selector 프로퍼티에 지정
@Directive({
selector: '[text-blue]'
})

export class TextBlueDirective {
// 2 - 생성자 함수에 주입된 ElementRef는 컴포넌트의 호스트 요소를 반환
constructor(
el: ElementRef
) {
el.nativeElement.style.color = 'blue';
}
}


디렉티브는 모듈에 둥록하여야한다. @NgModule 데코레이터의 메타데이터 객체의 declarations 프로퍼티에 생성한 디렉티브를 추가 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
// app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core'
import { AppComponent } from './app.component.ts';
import { TextBlueDirective } from './text-blue.directive';

@NgModule({
declarations: [ AppComponent, TextBlueDirective ],
imports: [ BrowserModule ],
providers: [],
bootstrap: [ AppComponent ]
})
export class AppModule {}


디렉티브를 모듈에 등록하면 컴포넌트에서 사용할 수 있다. textBlue 디렉티브를 p 요소에 아래와 같이 적용해보자. (이때 textBlue 디렉티브가 선언된 요소(P)는 어트리뷰트 호스트 요소가 된다.)

1
2
3
4
5
6
7
8
9
10
// app.component.ts
import { Component } from '@angular/core';

@Component({
selector: 'app-root',
template: `
'<p textBlue>textBlue directive</p> <!-- 여기서 p가 어트리뷰트 호스트 요소 -->
`
})
export class AppComponent {}

(‘text-blue.directive.ts’ 참고)
1 - 디렉티브는 @Directive 데코레이터로 장식된 순수한 자바스크립트 클래스이다. @Directive 데코레이터의 메타 데이터 객체에 디렉티브에 필요한 정보를 설정한다. selector 프로퍼티에는 CSS셀렉터 문법과 동일하게 디렉티브가 적용되는 조건을 설정할 수 있다.

selector 프로퍼티 설명
selector: ‘foo’ foo 요소(element)에 디렉티브가 적용
selector: ‘.foo’ .foo 클래스가 선언된 요소에 디렉티브 적용
selector: ‘[foo]’ foo 어트리뷰트가 선언된 요소에 디렉티브가 적용
selector: ‘[foo=bar]’ foo 어트리뷰트의 값이 bar로 선언된 요소에 디렉티브가 적용
selector: ‘:not(foo)’ foo 요소가 아닌 모든 요소에 디렉티브가 적용
selector: ‘foo, bar’ foo 또는 bar 요소에 디렉티브가 적용

디렉티브는 selec