adSense 900*70


AngularJs - Proviers (Value, Factory) JavaScript

AngularJs - Proviers

Providers

원문 - AngualrJs Guide

Application은 서로 협력하는 여러 객체들의 구성 및 조합으로 이루어져있습니다. 이런 객체들을 실제로 생성하여(인스턴스화) 서로서로를 연결시켜 함께 작동하도록 해야 Application이 잘 작동 할 수 있는 것이죠. AngularJs에서는 이런 객체들을 인스턴스화하고 injector service에 의해 자동으로 서로를 연결시켜 잘 작동하도록 합니다.

주입자(injector)는 아래와 같은 두 종류의 객체들을 생성합니다.

  • services (서비스 객체들)
  • specialized objects (특정 목적에 맞게 구현된 객체들)

Specialized object들은 Angular Framework API에 맞게 구현되고 작동합니다. 이런 객체들에는 다음과 같은 객체들이 있습니다.

  • controllers
  • directives
  • filters
  • animations

그런데 주입자(injector)가 특정 객체(들)을 생성하기 위해서는 어떻게 생성을 해야 하는지를 알아야 합니다. 그래서 개발자가 주입자(injector)가 객체를 생성할 수 있도록 하는 일종의 레시피를 등록하여야 합니다. 등록할 수 있는 방법에는 다섯가지가 있고 이중에 가장 범위가 넓고 포괄적인 방법이 Provider를 사용하는 것입니다. 다른 방법들은 아래와 같습니다. 그렇지만 아래의 방법들은 Provider를 사용하는 것보다 문법적으로 좀 더 편하게 사용할 수 있는 방법일 뿐입니다.

  • Value
  • Factory
  • Service
  • Constant

그럼 각기 다른 방법으로 service들을 생성하고 사용하는 방법을 살펴보도록 하겠습니다. Value를 사용하는 가장 간단한 방법부터 시작해보도록 하겠습니다.

Note: A Word on Modules

주입자(injector)가 객체를 생성하고 연결시켜 주기 위해선, 해당 객체들을 생성하는 방법(recipe)이 등록이 되어야 합니다. 각각의 생성 방법은 객체의 식별자와 해당 객체를 어떻게 생성해야 하는지를 포함하고 있습니다.

각각의 생성방법(recipe)들은 Angular module에 포함됩니다. Angular module은 하나 호혹은 그 이상의 생성방법을 포함하고 있습니다. 일일이 수동으로 모듈의 의존관계들을 쫒아다니는 것을 재미없는 일이기때문에, 모듈은 의존관계에 대한 정보까지도 포함을 하고 있습니다.

Angular application이 주어진 application module을 가지고 시작할때, Angular는 새로운 주입자(injector)인스턴스를 생성합니다. 그리고 이 주입자(injector)는 핵심 모듈인 ng module에 정의된 모든 생성방법들의 조합체로서 생성방법들의 레지스트리를 생성하게 됩니다. 그렇게 생성이 된 주입자(injector)는 application실행중에 특정 객체를 생성해야 할 경우, 생성방법 레지스트리를 참조하게 됩니다.

Value Recipe

자 그럼, “clientId”라는 이름을 가지고 remote API에 대한 인증에 사용될 문자열을 제공하는 간단한 서비스를 만들어 보도록 하겠습니다.

var myApp = angular.module('myApp', []);
myApp.value('clientId', 'a12345654321x');

위의 예제를 통해 myApp이라는 Angular module을 어떻게 생성하는지와 단순 문자열인 clientId*서비스를 생성하는 생성방법(recipe)를 어떻게 포함시켰는지를 보세요.

그리고 Angular의 데이터 바인딩을 통해 해당 문자열을 어떻게해서 표시하는지는 아래의 예제를 통해 알 수 있을 겁니다.

myApp.controller('DemoController', ['clientId', function DemoController(clientId){
this.clientId = clientId;
}]);
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta http-equiv="Content-type" content="text/html" charset="utf-8">
<title>Angular Provider Test</title>
<script type="text/javascript" src="lib/angular/angular.js"></script>
<script type="text/javascript" src="app/main.js"></script>
</head>
<body ng-controller="DemoController as demo">
Client ID: {{demo.clientId}}
</body>
</html>

위의 예제를 통해, DemoControllerclientId라는 id를 가진 서비스에 해당 문자열을 요청했을때, 해당 문자열을 반환해주기 위해서 Value recipe를 사용했습니다.

그럼 좀 더 복잡한 예제를 살펴보겠습니다.

Factory Recipe

Value recipe는 가장 간단한 반면, 서비스를 생성할때 자주 필요한 몇가지 중요한 기능들을 가지고 있지 않습니다. 그럼 이번에는 Value recipe의 형제격인 Fatory에 대해 살펴보겠습니다. Factory recipe는 다음과 같은 능력을 가지고 있습니다.

  • 다른 서비스(의존관계를 가질 수 있죠.)를 사용할 수 있는 능력
  • 서비스 초기화
  • 지연 혹은 늦은 초기화

Facotry recipe는 인자가 없거나 혹은 하나 이상의 인자(다른 서비스들에 대한 의존 관계를 말합니다.)를 가지는 함수를 사용하여, 새로운 서비스를 생성합니다. 해당 함수가 반환해주는 값은 서비스 인스턴스 입니다.

참고

Angular내의 모든 서비스들은 singleton 객체들입니다. 
즉, 주입자(injector)는 해당 객체를 생성하기 위해 각 recipe를 단 한번만 사용합니다.
그리고 다음에 해당 객체가 필요할 경우를 대비해서 내부 캐쉬에 해당 객체의 참조 값을 저장해놓습니다.

Factory recipe는 Value recipe보다 많은 능력을 가지고 있기때문에, Value recipe를 통해 만들었던 서비스를 물론 만들 수 있습니다. 위에서 Value recipe를 가지고 작성했던 예제를 다음과 같이 다시 작성할 수 있습니다.

myApp.factory('clientId', function clientIdFactory(){
return 'a12345654321x';
});

그런데 간단한 토근 문자열을 반환하기 위해 작성한 코드의 양이 Value recipe를 사용했을때보다 더 많습니다. 그리고 이해하기에도 Value recipe코드가 더 보기 편하죠.

그렇지만, remote API에 대한 인증에 사용될 토근을 계산하는 서비스를 생성한다고 생각해보죠. 해당 토큰을apiToken이라고 하고, clientId를 기반으로 계산하여 생성한후 브라우져의 로컬 스토리지에 저장이 됩니다.

myApp.factory('apiToken', ['clientId', function apiTokenFactory(clientId){
var encrypt = function(data1, data2){
//NSA-proof encryption algorithm
return (data1 + ":"+data2).toUpperCase();
};

var secret = window.localStorage.getItem('myApp.secret');
if(!secret){
secret = window.crypto.getRandomValues(Uint16Array.from(clientId));
window.localStorage.setItem('myApp.secret', secret);
}
var apiToken = encrypt(clientId, secret);

return apiToken;
}]);

myApp.controller('DemoController', ['apiToken', function DemoController(apiToken){
this.apiToken = apiToken;
}]);

(Unit16Array, window.crypto.getRandomValues)

위 코드 예제에서, apiToken 서비스는 Factory recipe를 통해 정의되었고, clientId값을 가지고 또 다른 secret을 생성하였습니다.

(되도록이면 [serviceId]Factory 이렇게 이름을 짓는 것이 좋습니다. 물론 강제는 아니지만 에러 발생 시 에러 로그나 디버깅을 할때 원하는 코드를 보다 쉽게 찾는데 도움이 될 것입니다.)



핑백

덧글

댓글 입력 영역


side adsense

adSense 900*70