Angular.js에서 Controller는 View DOM객체의 표현을 담당한다면 Service 모듈은 View단에 표현되는 NonVisible한 비즈니스 업무 데이터를 담당한다. 이전 블로그까지 모든 데이터 핸들링은 Controller에 담겨 있었는데 이를 Service 모듈로 분리 래팩토링 해보자. 또한 모듈분리를 하면서 $http를 추상화한 $resource를 사용해 보자
1. factory vs service 무엇을 쓸까? (참조)
- <module>.factory는 객체를 new 해서 return 해 주어야 한다.
따라서 별도의 function을 정의하고 해당 펑션을 new해서 return하는 구조일 때 사용
- <module>.service는 function의 내용을 정의하고 new한 객체를 return할 필요가 없다
- <module>.factory 는 공통된 것을 function으로 이미 만들어 놓은 것을 사용할 때. 즉, 공통 모듈 <Module>Svc 에 생성
- <module>.service 는 업무적으로 $resource/$http 이용하여 RESTful API 호출할 때. 즉 업무 모듈 <Module>Biz 에 생성
2. $resource 사용하기
- $resource 객체는 RESTful 클라이언트 애플리케이션 개발을 위한 $http 상위 레벨의 서비스이다
- http에 대한 보다 정교한 header configuration이 가능하다
- resource interceptors 가 있다
- 보다 향상된 promises api를 제공한다
- API
// 사용법
$resource(url[, paramDefaults][, actions]);
// 의미
- url
string 이고, /user/:username 처럼 :<param> 형태로 입력가능하다. 전체 url을 넣어도 됨
- paramDefaults
url parameters object 이고, /path/:verb 일때 파라미터값이 {verb:'greet', name:'dowon'} 이면
url 결과는 /path/greet?name=dowon 으로 간다. @가 앞에 붙으면 전달하는 객체(json)에서 값을 추출하여 대입한다
예)
var User = $resource('/user/:userId', {userId:'@id'});
var user = User.get({userId:123}, function() {
user.abc = true;
user.$save();
});
- actions
object.<object> 이고, $http.config의 action 을 상속받으며 사용자 정의하여 action을 추가할 수 있다.
{action1: {method:?, params:?, isArray:?, headers:?, ...},
action2: {method:?, params:?, isArray:?, headers:?, ...},
...}
- 리턴타입
기본적으로 resource에서 제공하는 action과 사용자 정의 action을 담아서 리턴한다
기본 action)
{ 'get': {method:'GET'},
'save': {method:'POST'},
'query': {method:'GET', isArray:true},
'remove': {method:'DELETE'},
'delete': {method:'DELETE'} };
3. $resource 공통 모듈 만들기
- $resource의 기본 action을 보면 'update': {method:'PUT'} 이 존재하지 않는다. 이를 custom action으로 포함시키고 공통 모듈로 만들어 보자.
- 공통 모듈을 만들기 전에 ngResource를 추가해야 한다. 애플리케이션에 없다는 다음과 과정을 거친다
// bower로 angular resource 설치 및 bower.json에 추가
$ bower install angular-resource --save
// index.html 에 추가
<!-- build:js scripts/core.js -->
<script src="bower_components/jquery/jquery.js"></script>
<script src="bower_components/jquery-migrate/jquery-migrate.min.js"></script>
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<script src="bower_components/angular-resource/angular-resource.js"></script>
<script src="bower_components/angular-cookies/angular-cookies.js"></script>
<script src="bower_components/angular-sanitize/angular-sanitize.js"></script>
<!-- endbuild -->
// ngResource가 필요한 모듈에 추가하기
var DashboardApp = angular.module('DasbhoardApp', [
'ngRoute',
'ngCookies',
'ngResource',
'ngSanitize',
'DasbhoardApp.CommonCtrl',
'DasbhoardApp.RestTestBiz',
]);
- $resource를 이용하여 공통 모듈을 만들어 보자
// common/services/RestfulSvc.js 파일을 생성한다
'use strict';
// 모듈 명칭 정의
var RestfulSvc = angular.module('DasbhoardApp.RestfulSvc', []);
RestfulSvc.factory('RestfulSvcApi', ['$resource', function ($resource) {
/**
* Restful API version. it must be attached the called url.
*/
var prefixUrl = '/api/v1';
/**
* @domain : biz object ex) person
* @key : biz object id ex) persion id is 123
* @action : server action name. if it exist, you can define or not.
* ex) http://www.bennadel.com/blog/2433-Using-RESTful-Controllers-In-An-AngularJS-Resource.htm
*
* add a update action for method of PUT
*/
return $resource(
// 호출하는 url 형식
prefixUrl + '/:domain/:key/:action',
// 호출 url 형식의 :domain :key :action 에 동적으로 받게 되는 파라미터
{
domain: "@domain",
key: "@key",
action: "@action"
},
// 추가 action들 one, all, update
{
one: { method: 'GET', isArray: false },
all: { method: 'GET', isArray: true },
update: {method:'PUT'}
}
);
}]);
4. Controller에 Service 모듈의 서비스 호출하기
- $http 방식을 $resource에 대한 추상 모듈 서비스로 대체한다
- 기존의 RestTestBiz.js의 "RestTestBiz.personCtrl" 컨트롤러 로직을 리팩토링한다
'use strict';
// 의존하는 모듈 주입
var RestTestBiz = angular.module('DasbhoardApp.RestTestBiz', ['DasbhoardApp.RestfulSvc']);
// 사용할 모듈의 서비스 주입
RestTestBiz.controller('RestTestBiz.personCtrl', ['$scope', 'RestfulSvcApi', function ($scope, RestfulSvcApi) {
var bizDomain = 'person';
var load = function () {
console.log('before calling...');
// 사용자 정의 액션 all 호출
RestfulSvcApi.all(
// param key domain의 값인 bizDomain는 @domain에 맵핑된다
{ domain: bizDomain },
// success
function (response) {
$scope.persons = response;
console.log('persons is ', $scope.persons);
},
// error
function (response) {
});
};
load();
$scope.save = function () {
console.log('Save Person : ', $scope.person);
RestfulSvcApi.save(
// 파라미터를 열거하면 하나의 json 객체로 합쳐준다
{ domain: bizDomain }, $scope.person,
function(response) { load(); },
function(response) {}
);
};
$scope.update = function () {
console.log('Update Person : ', $scope.person);
RestfulSvcApi.update(
{ domain: bizDomain }, $scope.person ,
function(response) { load(); },
function(response) {}
);
};
$scope.deletePerson = function(personId) {
console.log('Delete Person : ', personId);
RestfulSvcApi['delete'](
{ domain: bizDomain, key: personId },
function(response) { load(); },
function(response) {}
);
};
}]);
- RestfulSvcApi 와 같은 모듈 서비스를 해주는 추상화 공개 모듈이 존재한다. (참조)
+ Breezejs
* 소스 : https://github.com/ysyun/SPA_Angular_SpringFramework_Eclipse_ENV/tree/feature_angular_service
<참조>
'My Projects > BI Dashboard' 카테고리의 다른 글
[BI Dashboard] 화면을 영역별로 나누어 Routing 하기 (0) | 2013.12.04 |
---|---|
[BI Dashboard] jqGrid 와 Angular.js 연동하기 (0) | 2013.11.28 |
[BI Dashboard] Angular.js 엔터프라이즈 애플리케이션 구조 만들기 (0) | 2013.11.22 |
[BI Dashboard] Angular+Bootstrap을 Windows와 IE8 이상에 적응시키기 (0) | 2013.11.21 |
[BI Dashboard] myBatis에서 Mapper Interface로 고도화하기 (0) | 2013.11.20 |