AngularJS에 대해 어떻게 생각하시나요? 그냥 webpage를 만드는 Front-end 단의 JavaScript Framework 정도로 생각하시나요? AngularJS는 클라이언트의 브라우져에서 SPA(Single Page Application)를 구현하기 위한 프레임워크입니다. Webpage를 만드는 것이 아니라 SPA의 A처럼 애플리케이션을 만드는 프레임워크라는 것이지죠. Adobe의 Flex 프레임워크와 대비하여 생각해도 되지 않을까 합니다. AngularJS로 개발한다면 새로운 관점에서 바라보아야 합니다. Angular Way의 길에 들어오세요
1. 페이지를 디자인 하지 말고 DOM(Document Object Model) 조작을 통해 페이지를 변경하라
- "나는 몇개의 DOM 조각을 가지고 있다 이것을 가지고 뭔가 동작하는 것을 만들고 싶다"라는 생각에서 AngularJS는 출발한다
- 완성하고 싶은 것이 있으면 애플리케이션 아키텍쳐 디자인을 한 다음 마지막에 화면 디자인을 한다
2. AngularJS 와 함께 jQuery 에 대해서 말하지 마라
- AngularJS를 사용하면 jQuery 를 바탕으로 개발하는 것은 배제하길 바란다. Angular Way를 가라~~
- jQuery 플러그인을 AngularJS에서 사용하기 위해 $apply를 남발하여 코드를 꼬아 놓지 말자. jQuery 플러그인 대부분은 약간의 코드조각으로 AngularJS에서 재작성되어 질 수 있다 (Directive로 만들어서 사용하기)
3. 아키텍쳐라는 단어를 항상 생각하라
- SPA (Sinlge Page Application)는 application 이다. webpage가 아니다. 서버사이드 개발과 똑같이 생각하라
- 따라서 모듈화 하고 확장성 있고 테스트 가능하게 개발해야 한다
3-1. 화면은 공식적으로 표현되는 것
- jQuery 경우를 보자
<ul class="main-menu">
<li class="active">
<a href="#/home">Home</a>
</li>
<li>
<a href="#/menu1">Menu 1</a>
<ul>
<li><a href="#/sm1">Submenu 1</a></li>
<li><a href="#/sm2">Submenu 2</a></li>
<li><a href="#/sm3">Submenu 3</a></li>
</ul>
</li>
<li>
<a href="#/home">Menu 2</a>
</li>
</ul>
// JavaScript
$('.main-menu').dropdownMenu();
- 위의 경우를 단순한 AngularJS의 Directive로 표현한다. 이렇게 하면 jQuery처럼 HTML과 Javascript를 분리할 필요가 없고 해당 <ul> HTML 태그가 dropdown-menu임을 바로 알 수 있다.
<ul class="main-menu" dropdown-menu>
...
</ul>
- 애플리케이션 개발시 반은 jQuery 반은 AngularJS 스타일로 - half jQuery, half AngularJS - 절대로 절대로 개발하지 말라.
- 디자인을 하지 말고, Markup을 해라. 즉, 아키텍쳐링을 하고 그 다음에 디자인을 하라.
3-2. Data Binding
- DOM을 조작(첨부,삭제)하는데 있어서 Two Way Binding을 적극적으로 사용하라
- jQuery 의 경우를 보자 : append하고 delete 하는 조작들을 넣어야 한다.
$.ajax({
url: '/myEndpoint.json',
success: function ( data, status ) {
$('ul#log').append('<li>Data Received!</li>');
}
});
<ul class="messages" id="log">
</ul>
- AngularJS 를 보자 : $scope를 통하여 controller와 view 간의 데이터가 삭제 되거나 첨부되는 것을 보다 쉽고 깔끔하게 처리해 준다
// controller 코드
$http( '/myEndpoint.json' ).then( function ( response ) {
$scope.log.push( { msg: 'Data Received!' } );
});
// html 코드
<div class="messages">
<div class="alert" ng-repeat="entry in log">
{{ entry.msg }}
</div>
</div>
3-3. 모델객체와 화면과 분리되어 있다
- $scope를 통하여 view와 controller간 모델역할을 수행한다
- 이 방법은 view와 완전 독립적이어서 separation of concern을 유지하고 테스트 가능하게 만들준다
3-4. 관심의 분리 (SoC, separation of concern)
- 아키텍쳐링을 하여 개발하면 관심 영역별로 분리하여 유지할 수 있다
- 화면(view)은 공식적인 표현되는 것이고, 모델(model)은 데이터를 대표하며, 업무를 수행하는 서비스를 갖게된다
- 이것은 3-5에서 이야기하는 DI와도 연관이 있다
3-5. 의존성 주입 (DI, Dependency Injection)
- 코드안의 하드코딩된 부분을 제거하고 의존관계에 있는 모듈을 다양한 방법으로 전달해 준다
- AngularJS에서는 펑션의 파라미터로 넘겨준다. 이를 통해 테스트시에 서버를 직접 호출할 필요없이 필요한 목서비스(mock service)를 전달하여 테스트를 할 수도 있다
4. 항시 TDD 하라
- Test Driven Development 를 수행하라
- jQuery로 테스트 할 때는 항시 테스트 화면을 만들어 해야 제대로 된 테스트 수행이 가능해진다. 그러나 AngularJS는 그렇지 않다
- 내부에 사용되는 기능을 모듈로 분리해 개발하고 DOM조작에 대해서 테스트하고 애플리케이션과 통합할 수가 있기 때문이다
- 그것은 관심의 분리(SoC) 방식으로 개발하기 때문에 TDD가 AngularJS에서 가능한 것이다
- 예를 보자
// HTML : when-active라는 AngularJS Directive(지시자)
<a href="/hello" when-active>Hello</a>
// Test Script : Karma를 보자. DOM을 조작하여 화면을 이동시킨 후 true, false인지 체크한다
it( 'should add "active" when the route changes', inject(function() {
var elm = $compile( '<a href="/hello" when-active>Hello</a>' )( $scope );
$location.path('/not-matching');
expect( elm.hasClass('active') ).toBeFalsey();
$location.path( '/hello' );
expect( elm.hasClass('active') ).toBeTruthy();
}));
// Script : 정상적으로 라우팅이 되면 active class 첨부, 아니면 삭제
.directive( 'whenActive', function ( $location ) {
return {
scope: true,
link: function ( scope, element, attrs ) {
scope.$on( '$routeChangeSuccess', function () {
if ( $location.path() == element.attr( 'href' ) ) {
element.addClass( 'active' );
}
else {
element.removeClass( 'active' );
}
});
}
};
});
5. Directive(지시자)는 패키징된 jQuery가 아니다
- Directive안에서 DOM 조작을 하라. 하지만 jQuery 스타일은 배제하라
- Directive는 template을 가지고 있는 widget과 유사하다. 이를 통해 SoC를 보여주고 있고, 테스트를 가능하게 한다
- jQuery 스타일의 버튼토글 코딩을 보자 : AngularJS Directive안에 아래와 같이 jQuery 스타일의 DOM 조작을 수행하지 말라
.directive( 'myDirective', function () {
return {
template: '<a class="btn">Toggle me!</a>',
link: function ( scope, element, attrs ) {
var on = false;
$(element).click( function () {
if ( on ) {
$(element).removeClass( 'active' );
}
else {
$(element).addClass( 'active' );
}
on = !on;
});
}
};
});
- Angular Way 방식의 버튼코글 : ng-show, ng-class, ng-binding 과 같은 Directive를 통해 DOM 조작을 수행하라
.directive( 'myDirective', function () {
return {
scope: true,
template: '<a class="btn" ng-class="{active: on}" ng-click="toggle()">Toggle me!</a>',
link: function ( scope, element, attrs ) {
scope.on = false;
scope.toggle = function () {
scope.on = !$scope.on;
};
}
};
});
- Directive는 jQuery같은 펑션의 집합이 아니다. Directive는 HTML의 확장이다. 이는 HTML안에 우리가 수행하고 싶은 무언가를 넣고 싶은데 못 할 경우에 Directive를 만들어야 하는 것이다. 그래서 HTML의 일부로서 사용하는 것이다.
Angular Way에서 jQuery 방식을 사용하지 말고 포함조차 시키지 말아라.
- View === AngularJS의 Directive가 포함된 HTML이다
- Model === $scope를 통하여 Controller에서 Two way binding을 자동 수행한다
- View와 Controller를 통하여 표현과 행위를 분리한다 (SoC)
- AngularJS 애플리케이션 접근법
Step 1) Model을 먼저 생각하고 Service를 만든다
Step 2) Model이 표현될 View에 대해 생각해 보고 template을 만들고, 필요하면 자동 모델 바인딩되는 Directive도 만든다.
Step 3) 각 View 를 Controller에 연결한다 (ng-view and routing, ng-controller)
<참조>
- 원문 : Think in AngularJS
- AngularJS의 상속에 대한 이해 (그림포함)
'AngularJS > Concept' 카테고리의 다른 글
[AngularJS] Service 종류 이해하기 (0) | 2013.08.22 |
---|---|
[AngularJS] $watch, $apply, $digest 개념잡기 (0) | 2013.08.21 |
[AngularJS] 웹 애플리케이션 견고하게 만드는 방법 (0) | 2013.04.27 |
[AngularJS] 개발자 가이드 - 06. 모듈 (0) | 2013.04.11 |
[AngularJS] 개발자 가이드 - 05. 지시자(Directives) (0) | 2013.04.11 |