[번역] AngularJS Directive 끝내기.

이 포스트는 2015년 8월 12일 NG-NEWSLETTER에 소개된 의 Mastering AngularJS Directives를 번역한 글 입니다.

Directive는 AngularJS 의 꽃이다. Directive는 HTML element와 attribute를 풍요롭게 사용하게 해주며, 재사용 가능하고 테스트 가능하게 해준다. 이 튜토리얼에서는, 여러분께 AngularJS의 directive를 실제 와 비슷한 상황의 예제를 사용하여,  어떻게 사용하는지 보여 드리려고 한다.

본문에서 칭하는 directive는 직접 만든 custom directive를 뜻한다. 이 포스트에서는  ng-repeat ng-show 같은 내장 directive에 대해서 이야기 하지는 않겠다.

  1. Simple Directives
  2. Directive Restrictions
  3. Isolated Scope
  4. Directive Scopes
  5. Directive Inheritance
  6. Directive Debugging
  7. Directive Unit Testing
  8. Directive Scope Testing
  9. Conclusion

당신이 책에 관련한 전자상거래 어플리케이션을 가지고 있다고 생각해보자. 화면의 몇몇 부분에는 책에 대한 세부적인 내용이 들어갈 것이고, 댓글들도 들어갈 것이고, 유져 프로필 페이지, 게시판 등등의 화면이 들어갈 것이다. 책의 세부 사항을 보여주는 위젯은 아래처럼 생겼을 것이다:

Book Widget

이 위젯에는 책 이미지, 타이틀, 설명, 댓글, 그리고 별점이 있다. 이 정보들을 모아서 특정 dom element에 계속 입력하는 일은 생각만해도 끔찍하다. AngularJS directive를 사용해서 위젯화 해보자.

윗 예제에서, directive 함수는 새로운 directive를 만들기 위해서 호출되었다. 이 directive의 이름은  book이다. directive는 object를 return하는데, 이 object에 대해서 이야기를 나눠보자. restrict는 directive의 type을 정의하는데 사용된다. A (Attribute), C (Class), E (Element), and M (coMment). 이렇게 4가지 종류가 있으며, 용례는 아래 표를 참조하자.

Type Usage
A <div book></div>
C <div class=”book“></div>
E <book data=”book_data”></book>
M <!–directive:book –>

scope 는 directive의 scope를 제어한다. 위의 경우에는, data가 “=” scope 형태로 directive의 template에서 사용된다. scope에 관해서는 다음 장에서 더 자세히 설명하겠다. templateUrl은 view에 실제로 보여질 template의 주소이다. 아래 예제처럼 (templateUrl 대신) template을 사용할 수도 있다:

우리의 경우에는, 복잡한 구조의 HTML을 사용할 것이므로, templateUrl을 사용하도록 하겠다.

Directive는 AngularJS project의 JavaScript 파일 내부에 정의하면 된다. HTML 페이지에서 사용할 때는 다음에 나올 Case에 따라서 다르게 사용하면 된다:

Attribute를 사용하면, directive의 이름을 HTML element 안에다가 Attribute로 입력하면 된다. 당신의 웹사이트에 메뉴가 있다고 가정해보자. 이 메뉴에는 사용자 등급에 따라 차등적으로 보이는 항목이 있다고도 가정해보자. 이를 위해 일단 우리는 항목을 보여줄지 안 보여줄지 결정하는 directive를 만들어야 한다. 우리의 HTML 코드는 아래와 같은 모양 일 것이다:

directive의 link function은 무슨 역할을 할까? 쉽게 말해서, link는 directive의 진짜 function이다. 해당 directive에서 수행할 Javascript function을 적으면 된다. directive는 단지 연결된 HTML Template을 렌더링하는 역할만 수행하는것이 아니다. directive element에 function을 붙여서 service를 호출하거나, 값을 계산하거나, (E type directive라면,) directive의 attribute도 읽어올 수 있다.

directive를 HTML element의 class를 통하여 호출하는 방법이다. 만약 위의 directive를 C type으로 작성하였다면,  다음과 같이 적용할 수 있겠다:

굳이 HTML element 안에 뭘 적어서 directive를 불러 올 필요는 없다. AngularJS에서는 directive를 사용해 너만의 HTML element를 만들 수 있다. Directive의 restrict를 “E”로 설정하기만 하면 된다. 우리 웹 페이지에 들어갈 username, avatar, reputation 을 보여주는 위젯을 만들면서 설명하겠다:

HTML 코드는 아래와 같을 것이다:

위의 예제에서, 우리는 custom elements를 만들었고 username, avatar, reputation 을 attribute로 제공하였다.Link function안의 내용을 보자. Element의 attribute를 directive에서 사용할 수 있다. link function의 첫번째 파라미터는 directive의 scope를 가르킨다. 세번째 파라미더는 directive의 attribute를 가르킨다. 무슨 뜻인고 하면, 커스텀 directive의 attribute값들을 attires.attr_name을 사용해서 불러올 수 있다는 것이다. Attribute 값들을 scope의 변수에 넣어주면, template 내부에서 사용할 수 있다.

사실, 이걸 더 짧은 방법으로 만들 수 있지만, 그건 나중에 보자. 이 예제는 기본 개념에 대한 이해와 간단한 용례를 알아보기 위한 것이니까.

이 방법은 거의 안 쓰인다. 그래도 어떻게 쓰는지는 보여주겠다. 웹페이지에서 여러번 쓰일 코멘트 창을 만들어 보며 알아보자. 아래처럼 directive를 만들자:

모든 directive들은 각자의 scope를 갖는다. 또한 당신은 directive 설정할때 데이터 바인딩에 관련해서 세심한 주의를 기울일 필요가 있다. 우리 앱에 장바구니 기능을 추가한다고 가정해보자. 물론 장바구니 페이지에는 이미 장바구니에 포함되어 있는 물건들도 있을것이다. 각각의 아이템마다 수량 필드가 있을것이다. 아래를 보자:

Simple Cart

directive 정의는 다음과 같다:

Directive의 가장 큰 장점은 재사용 가능한 컴포넌트라는 것이다. 또한 추가적인 attribute도 directive에 추가할 수 있다. 그런데, 어떻게 directive(의 Scope) 에 추가적인 값(value)이나, binding, expression을 전달할 수 있을까?

“@” Scope: 이 유형의 scope는 value를 전달받기 위해 사용된다. 새로 만들 위젯에 알림 메세지를 전달해야 한다고 가정해보자:

“&” Scope:  우리는 이제 value와 reference를 directive로 넘길 수 있다. (역자 주, call by value와 call by reference) “&” 스코프는 directive 내로 expression을 전달할 수 있게 해준다. 실제 개발 과정에서, 데이터가 꼬이는걸 막기 위해 expression을 통째로 directive로 보내야 할 때가 있다. 또, 가끔은 directive가 넘어온 expression의 결과가 어떻게 될 지 모른다는 가정 하에 directive를 작성해야 할 때도 있다. 예를 들면, 도서 추천 directive는 사실 추천 알고리즘이 어떻게 구성되어 있는지 전혀 알지 못한다. 이러한 이유로, 도서 추천 directive를 작성할때, 아래와 같은 구조로 작성하게 될 것이다 :

이 directive를 보면, expression이 like속성을 통해 바로 directive의 button으로 전달된다. 이제 controller에서 함수를 정의하고 HTML의 directive로 넘겨줘보자.

이제 템플릿을 보면, 템플릿은 다음과 같을 것이다 :

text box가 디렉티브의 템플릿으로 들어갔고, 이 text box의 값은 like({star: starCount}) 와 같다. star는 controller 함수에서 나왔고, starCount는 textbox에 바인딩 된 값이다.

가끔, 몇몇 directive들에 같은 기능들이 포함되어 있을 때가 있다. 이 경우, 그 기능들을 부모 directive에 모아 놓고, 자식 directive에서 상속해서 사용 할 수 있다.

실생활에서 있을만한 일을 생각해보자. 당신이 어떤 통계 데이터를 책을 클릭 할 때 마다 보여주고 싶다고 하자. 당신은 마우스 클릭 이벤트를 book directive에 추가시킬 수 도 있다. 하지만 이걸 다른 directive에서도 하고 싶을떈 어떻게 해야할까? 이런 경우에는, directive를 아래와 같이 상속받게끔 처리하면 될 것이다:

template 내부에서 directive를 사용할 때, 우리는 directive 자체가 아닌 컴파일 된 버젼만을 볼 수 있다. 디버깅을 할때 우리는 가끔 실제 directive의 모양을 보고 싶을 수 있다. directive의 컴파일 되기 전 버젼을 보기 위해서, 우리는 ng-non-bindable을 사용할 수 있다. 예를 들어, 가장 인기있는 책을 보여주는 위젯을 가지고 있다면, 소스코드는 다음과 같을 것이다:

컴파일 되기 전 directive를 보고 싶다면, 다음과 같은 코드를 사용하면 된다:

충분히 목표를 달성한 것 같지만, 만약 컴파일 된 버젼과 컴파일 되지 않은 버젼을 동시에 보고 싶다면 어떻게 해야 할까? 지금부터 고급 디버깅 옵션이 추가된 custom directive를 작성해보자.

Sample Directive

개발 하는 시점에 이런 디버깅 directive를 사용함으로써 프로젝트를 에러들로부터 지켜낼 수 있을것이다.

아시다시피 당신은 유닛 테스트를 당신이 작성한 코드를 확인하고 잠재적인 버그들로부터 프로젝트를 지키기 위해 매우 중요시 여겨야 한다. 여기서 유닛 테스트에 대하여 자세하게 알아볼 것은 아니지만, directive를 테스트하는 방법에 대해서 몇가지 길을 제시하려고 한다.

나는 Jasmine 을 유닛 테스트을 위해 사용하고, Karma를 유닛 테스트를 실행하기 위해 사용한다. Karma를 사용하기 위해서, (당연하게도) npm을 사용해 Karma를 전역적으로 설치하자. npm install -g karma karma-cli을 통해 설치하면 된다.  물론 Node.js와 npm이 설치되어 있어야 한다. 설치한 후에, 커맨드 라인을 열고, 프로젝트 폴더로 가자. 프로젝트 폴더에서 karma init을 입력하자. 몇가지 질문들이 커맨드 라인에 나타나면, 적당하게 답변해주면 된다.

Karma Test Initialization

나는 개발 툴로 Webstorm을 사용한다. 만약 당신도 Webstorm을 사용한다면, karma.conf.js를 마우스 오른쪽으로 클릭하고 Run karma.conf.js를 선택하자. 이것만 선택해도 karma 설정값에 맞춰서 테스트가 시작된다. 물론 커맨드 라인에 karma start를 입력해서 테스트를 실행할 수도 있다. 지금까지는 테스트 설정에 대한 내용이였고, 이제 테스트에 대한 부분으로 진짜 들어가보자.

우리는 book directive를 테스트 하고 싶다. directive에 책 제목을 넘겨주면, 제대로 컴파일 되어서 book detail view에 입력되어야 한다. 다음을 보자.

이번 세션에서는, booktest directive의 scope를 테스트 할 것이다. 이 directive는 book detail view를 생성한다. 이 detail section을 클릭하게 되면,  viewd라는 scope value의 값이 true로 바뀌게 된다. 우리 테스트에서는, viewed 값이 실제로 잘 변하는지 확인할 것이다. 디렉티브는 다음과 같다 :

모듈화 가능하고 테스트 가능한 웹 프로젝트를 진행하는데 있어서, AngularJS는 널리 쓰이는 가장 좋은 프레임워크 중 하나이다. 그리고 Directive는 AngularJS의 우수한 컴포넌트 중 하나이다. 따라서 당신이 AngularJS의 directive에 대해서 많이 알 수록, 더 모듈화 되고 테스트 가능한 프로젝트를 진행할 수 있다는 말과 같다.

이 튜토리얼에서, 나는 여러분께 실제 생활에서 사용되는 directive에 대해서 보여주려고 많이 노력하였다. directive에 대해서 잘 이해하기 위해서는 스스로 더 노력해야 한다는 사실을 잊지 않았으면 좋겠다. 이 포스트가 AngularJS의 Directive를 이해하는데 도움이 되었길 바라며 마친다.

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.