[Angular2] 지시자(Directive)

참고: angular2에 대한 연재는 여기를 참조해 주세요. 틀린 부분이나 의견, 피드백은 언제든지 환영합니다.

지시자에 대하여

오늘 다룰 개념은 Angularjs를 사용해 보신 분들은 적어도 한 번쯤은 들어보았을 지시자(Directive)입니다. 지시자에 대한 설명은 먼저 용어의 의미에서 출발해 보기로 합니다. 지시자 본래의 단어 Directive를 네이버에서 검색할 때 제일 처음 나오는 사전적 정의는 다음과 같습니다.

(공식적인) 지시[명령]

A directive is an official instruction that is given by someone in authority.

마찬가지로 네이버 한국어 사전에서 지시의 의미를 찾아보면 “1. 가리켜 보임, 2. 일러서 시킴. 또는 그 내용” 등으로 나오네요. 여기서 우리가 관심 갖는 의미는 2번째에 해당된다고 볼 수 있습니다.

정리하면, 어휘의 의미에서 접근했을 때 지시자라는 개념은 “어떠한 대상에게 일련의 명령을 수행하게 함”으로 다듬어 정의할 수 있습니다. 그리고 이 의미는 Angular 프레임워크 맥락에서도 동일합니다. Angular 프레임워크에서 의미하는 지시자는 “DOM을 다루기 위한 모든 것”이라 정의할 수 있습니다.

그럼 다음의 예를 통해서 조금 더 익숙한 곳에서부터 Angular가 수행하는 지시자의 역할을 살펴보기로 합니다.

지시자가 아닌 간단한 형태의 Component를 보여드렸습니다. Component 소스를 다시 꺼내 든 이유는 Component 역시 지시자이기 때문입니다. 위에서 정의한 지시자의 정의와 Component의 역할을 생각하면 Component가 왜 지시자인지 이해할 수 있습니다. Component도 화면의 렌더링과 사용자의 이벤트 처리 등 DOM을 다루기 때문에 지시자입니다.

Component는 Angular에서 중요한 컨셉 중 하나입니다. 그러므로 지시자의 일부로 다루기 보다는 독립적으로 구분해서 보는 이해하는 것이 좋습니다. 따라서 앞으로 지시자를 이야기 할 때 넓은 의미로는 Component를 포함하지만 협소한 의미로 이야기할 때는 Component를 제외하고 이야기 하도록 합니다.

그렇다면 좁은 의미로 볼 때, 지시자에는 어떤 것들이 있을까요? 구조 지시자(Structural directive)와 속성 지시자(Attribute directive)가 있습니다. 이 지시자들은 HTML의 태그 안에 속성에 선언하여 사용합니다. 세부적으로 각각 어떤 역할을 하는지 확인해 봅시다.

 

구조 지시자(Structural Directive)

구조 지시자는 DOM 요소를 추가하거나 삭제하는 등 화면의 구조를 변경할 때 사용하는 지시자입니다. 대표적인 구조 지시자에는 ngIf, ngFor가 있습니다. ngIf 지시자는 불리언 값을 입력 받아 true일 경우 ngIf가 선언된 DOM을 보여주고 false이면 제거해주는 용도의 지시자입니다. 반면 ngFor는 배열 형태의 모델을 반복해서 DOM에 표현할 때 사용하는 지시자입니다. 아래 공식매뉴얼의 간단한 예제를 살펴봅시다.

설명한 정의와 같이 구조 지시자는 DOM을 직접 조작하는데 사용하는 지시작입니다. angular에서 제공하는 기본 구조 지시자로도 어플리케이션 개발이 충분하지만, 필요에 따라 자신만의 구조지시자를 만들수도 있습니다. 이에 대해서는 나중에 다시 다루어 보도록 합니다.

angularjs에서는 지시자는 태그명, 속성, 클래스명, 주석까지 총 4가지로 표현되어 사용할 수 있었습니다. angularjs의 태그명을 사용한 지시자가 angular에서는 Component에 해당하고, angularjs의 속성 지시자가 angular에서는 협의의 의미의 지시자에 대응한다고 볼 수 있습니다.

 

속성 지시자(Attribute Directive)

속성지시자는 지시자가 선언된 DOM의 모습이나 동작을 조작하는데 사용하는 지시자입니다. 조작할 DOM에 미리 정의한 속성 지시자를 마킹하듯이 태그 안에 속성으로 선언하면 해당 DOM이 지시작에서 정의한 대로 동작하게 됩니다. 다음의 예를 한 번 봅시다.

이 예제는 DOM요소의 class에 ‘my-new-class’를 추가하는 ‘my-selector’라는 속성지시자를 선언한 것입니다. 따라서 필요에 따라 ‘my-new-class’란 클래스를 추가할 DOM에 다음과 같이 ‘my-directive’를 속성 중 하나로 선언해 주면 됩니다.

속성 지시자는 명칭에서 알 수 있듯이 DOM의 속성과도 직접 연관된 지시자입니다. 장황한 설명보다 다음의 예제가 그 역할을 충분히 설명할 수 있습니다.

예제를 보면 []를 사용하여 단방향 바인딩으로 우변의 모델 값을 직접 반영하고 있다는 것을 알 수 있습니다. 예제와 같이 기존 DOM의 속성에 접근하기 위한 용도에도 속성지시자가 사용되며 지난 시간에 설명한 바인딩도 속성 지시자의 일부가 됩니다.

 

Component와 지시자의 관계

오늘 소개했던 지시자와 Component는 Angular 프레임워크의 기둥과도 같은 중요한 개념입니다. 위에서 설명한 바와 같이 사실 Component도 지시자의 이야기 했습니다. 실제로 @Component 데코레이터는 @Directivetemplate이 포함된 확장된 형태로 구현되어 있습니다. 넓은 의미의 지시자는 DOM을 다루는 데 필요한 모든 것이기 때문에 우리가 만들 어플리케이션은 지시자들을 조합하여 구성하게 됩니다. HTML template을 포함한 Component와 구조/속성 지시자들을 활용하여 새로운 Component를 만들고, 또 이렇게 만들어진 Component 들을 조합하여 하나의 완성된 어플리케이션을 구축하는 것입니다. 따라서 지난 시간에 설명한 Component의 트리의 개념을 지시자를 포함해서 생각하면 다음과 같이 표현할 수 있습니다.

컴포넌트 트리 참조

위 그림을 보면 여러 지시자와 Component를 조합하여 새로운 Component를 부모로 가질 수 있지만 지시자는 부모가 될 수 없다는 점을 알 수 있습니다.

종합예제

그럼 한 번 지금까지 간단하게 살펴 보았던 컴포넌트, 데이터바인딩과 오늘 배운 내용들을 종합한 간단한 예제를 작성해 보기로 합니다. 예제는 초간단 Todo 리스트입니다. 먼저 작동 예제를 살펴봅시다.

예제의 시작점은 app.component.ts의 AppComponent 입니다.

AppComponent를 구성하기 위해서 TodoInputComponent와 TodoListComponent가 필요합니다. 따라서 13번 라인과 같이 metadata의 directives 에 해당 자식 컴포넌트들을 선언해야 합니다. 만약 자식 Component나 지시자를 사용하지만 directives안에 선언해 두지 않으면 어플리케이션 로딩 시 스크립트 오류가 발생합니다.

이번엔 한 번  TodoListComponent를 봅시다.

  • TodoListComponet도 metadata를 보면 TodoItemComponent를 자식 컴포넌트로 갖고 있음을 directives를 통해서 알 수 있습니다.
  • 10번 라인에서는 todos 배열의 값을 구조지시자를 활용하여 반복해서 todo-item을 표현하고 있습니다.

TodoItemComponent의 소스를 읽어 봅시다.

  • 8번 라인을 보면 PriorityDirective를 자식으로 포함하고 있음을 알 수 있습니다.
  • 7번 라인의 template  을 보면 todo-priority 라는 속성지시자를 추가했음을 확인할 수 있습니다.
  • 또한 7번 라인에서 todo 모델의 값을 사용자에게 보여주기 위해서 getTodoItemContent라는 함수를 사용했는데 다음에 “파이프”를 설명하면서 이를 좀 더 깔끔하게 처리하는 법을 소개하겠습니다.

본 예제의 PriorityDirective의 역할은 아주 간단합니다. 해당 속성지시자가 선언된 DOM의 요소에 ‘priority-grp’이라는 클래스를 추가하는 일을 합니다. 소스에서 확인해 볼까요?

소스를 보면 설명하지 않은 내용들이 많긴 하지만 일단은 무시하고 여기서는 9번라인이 todo-priority 속성 지시자가 선언된 DOM 요소에 ‘priority-grp’ 클래스를 넣는 부분이라고만 확인합시다.  지시자에 대한 자세한 활용은 다음 시간에 이야기 하기로 합니다.  (또한 constructor 안에 선언된 두 파라미터와 관련된 의존성 주입입니다. 역이 다음에 다루기로 합니다.)

 

정리하며

오늘 설명한 지시지에 대한 개념은 지난 시간의 Component와 함께 Angular 기반 어플리케이션의 뼈대를 세우는 중요한 역할을 합니다. 컴포넌트 관점에서 template이 있는 Component가 지시자와 다른 Componen를 자식으로 포함할 수 있지만 지시자는 다른 자식을 가질 수 없다는 것을 설명했습니다.

Angular2 글 목록보기