[AngularJS] Directive
AngularJS는 정적인 HTML을 확장하여 동적인 응용프로그램으로써의 웹을 구현할 수 있도록 도와주는 자바스크립트 프레임워크이다.
MVC(MVVM) 아키텍처 기반, 양방향 데이터바인딩, SPA 개발, 모듈화 프로그래밍, 라우팅 시스템 등 단순한 웹 페이지를 응용프로그램으로 승격시키기 위한 다양한 기반 기술을 제공하는데, 이 중 Directive(디렉티브)는 HTML 요소 즉 뷰(View)에 대한 확장기능을 제공하는 AngularJS의 중요한 기능 중 하나다.
Directive를 사용하면, 자신의 응용프로그램에 최적화된 뷰와 기능을 캡슐화하여 재사용 가능한 컴포넌트를 만들 수 있다. 즉 Directive를 통해 HTML 태그 및 특성을 입맛에 맞게 재정의 가능하며 이를 통해 '사용자 정의 뷰'를 제작 및 필요에 의해 재사용할 수 있게 된다.
* AngularJS 내장 디렉티브
- AngularJS 내부적으로 HTML 확장을 위해 많은 디렉티비를 정의하고 있다. AngularJS 적용을 위해 HTML Element에 추가로 부여했던 특성들, na-app, ng-init, ng-model 등이 대표적 내장 디렉티브이다.
내장 디렉티비의 목록은 다음 url에서 확인 가능핟.
- http://www.w3schools.com/angular/angular_ref_directives.asp
* 사용자 정의 디렉티브
- AngularJS 디렉티브를 사용해서 HTML을 확장시킬 수 있다고 했는데, 먼저 간단한 예제부터 살펴보자
<html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script>
var app = angular.module("myApp", []);
app.directive("userdirective", function() {
return {
template : "<h1>사용자 정의 디렉티브</h1>"
};
});
</script>
<body ng-app="myApp">
<userdirective></userdirective>
</body>
</html>
가장 기본적인 형태로 구현된 코드형태이지만, 너무나도 간단하다.
디렉티브 역시, AngularJS의 Module에 추가하는 형태로 구현되며, 사용자 구미에 맞는 새로운 HTML Element를 정의하고 페이지에서 새로운 요소를 사용하고 있다.
기존에 정해진 HTML 요소 외에, 사용자가 원하는 이름을 새롭게 정의하고 사용할 수 있다는 측면에서 AngualrJS가 HTML을 '도메인 특화 언어(domain-specific language)'로써의 기능을 부여했다고 할 수 있다.
* 디렉티브 Naming
- 여기서 한가지 주의할 점이 있는데, 디렉티브 이름을 카멜표기법(단어와 단어사이의 첫 글자를 대문자료 표기)으로 지정했을 땐, 각 단어연결문자로 '-'를 사용해야 한다는 것이다. 즉 다음과 같이 user와 Directive사이에 '-' 문자로 분리해야 한다.
...
<user-Directive></user-Directive>
* 디렉티브 구현 문법
- 앞서 예제에서는 가장 단순한 형태의 디렉티브 사용법을 보여준 것이다. 디렉티브는 다음과 같이 세 가지 구성요소를 기반으로 동작한다.
1) 디렉티브 정의 객체(DDO, Directive Definition Object)
- 디렉티브 구현을 위한 필수요소로, 디렉티브의 HTML 템플릿, scope, 컴파일 주기 등을 설정한 객체를 정의한다. 앞서 예제에서도 리터럴 객체를 리턴하고 있는데, 이것이 바로 DDO이다.
2) 컨트롤러
- AngularJS의 컨트롤러와 동일한 방식으로 동작한다. 디렉티브를 위한 상태와 기능을 정의하고 외부와의 각종 상호작용을 구현한다. DDO와는 달리 반드시 컨트롤러를 정의해야 하는 것은 아니지만, 제대로 된 실무용 디렉티브에서는 필수로 구현해야 할 것이다.
3) 링크
- 디렉티브에서 정의한 DOM을 조작하는 코드를 구현한다. DOM 요소에 발생하는 이벤트를 가로채서 각종 처리를 수행한다. DDO와는 달리 선택요소로 반드시 구현하지 않아도 된다.
이와 같은 구성요소들이 포함된 디렉티브 정의를 위한 뼈대를 살펴보자.
//디렉티브 생성
//필요한 경우, 생성자 함수에 서비스를 주입해서 사용
//ex: function($rootScope, myService, ..., ) .. 이후 컨트롤러에서 사용가능
app.directive("userdirective", function() {
var linker = function(scope, element, attrs){
//DOM 조작에 관한 코드를 구현한다
//scope: 현재 작업중인 디렉티브에 할당된 scope객체.
//컨트롤러함수의 $scope와 동일. 이를 통해 여기서 컨트롤러 함수 호출 가능
//element: 디렉티브가 선언된 요소에 대한 참조를 jQuery 객체로 감싸서 제공
//attr: 디렉티브가 선언된 요소에 정의된 모든 특성을 배열로 제공
};
var controller = function($scope){
//디렉티브의 뷰에서 사용할 비즈니스 로직(상태와 메서드) 구현
//링크함수와 동일한 scope객체 공유
};
return { //DDO객체
restrict: 'A', //이 디렉티브를 HTML요소의 특성(attribute)으로만 사용하도록 제한
controller: controller, //디렉티브의 컨트롤러함수 지정
controllerAs: 'userdirective' //userdirective라는 이름으로 controller 참조
link: linker //링크함수 지정
//이 디렉티브가 HTML Element로 사용될 경우 다음과 같이 템플릿 지정
//template : "<h1>사용자 정의 디렉티브</h1>" //뷰를 위한 HTML 템플릿 지정
};
});
DDO(디렉티브정의객체)에 보면 restrict 속성이 있는데 이것은 해당 디렉티브를 HTML에서 사용할 때 특정 용도로 제한하기 위해 사용한다. 코드예제에서는 'A'라고 지정했는데 이는 HTML요소의 특성(Attribute)로만 이 디렉티브를 사용하도록 제한한 것이다. 다음은 restrict로 지정가능한 옵션이다.
그리고 template로 HTML을 직접 작성했는데, 외부에 이미 존재하는 html 파일을 지정할 수도 있다. * 사용자 정의 디렉티브 샘플
이때는 template 대신 templateUrl: 'directive.html' 형태로 사용한다.
- 이제 디렉티브의 구성요소를 대부분 사용해서 만들어보자
<html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script>
var app = angular.module("myApp", []);
app.directive("mybutton", function(){
var linker = function(scope, element, attrs){
//마우스 over/out 이벤트에 반응하여 투명도를 조절한다
element.bind('mouseover', function(e) {
element.css({'opacity': 0.5});
});
element.bind('mouseout', function(e) {
element.css({'opacity': 1.0});
});
};
var controller = function($scope){
var ctrlMyBtn = this;
ctrlMyBtn.text = "My Button";
ctrlMyBtn.getText = function(){
alert(ctrlMyBtn.text);
}
};
return {
restrict: 'A',
controller: controller,
controllerAs: 'ctrlMyBtn',
link: linker
};
});
</script>
<body ng-app="myApp">
<button mybutton ng-click="ctrlMyBtn.getText();">
{{ctrlMyBtn.text}}
</button>
</body>
</html>
- 예제코드가 그다시 쓸모있는 디렉티브라고는 할 수 없지만, 디렉티브의 구성요소가 어떤식으로 상호작용하여 동작 하는지 파악하기에는 더없이 좋을 것이다.
HTML Element의 특성으로만 사용가능한 디렉터리를 만들고 마우스 오버/아웃에 따른 DOM 투명도 조작과 컨트롤러에 정의된 속성과 메서드와 상호작용하는 예를 보여준다.
결과화면은 다음과 같다.
* 참고자료
- https://docs.angularjs.org/guide/directive
- http://www.w3schools.com/angular/angular_directives.asp