본문 바로가기

AngularJS

19. 의존관계 주입과 서비스 - 1 (서비스란?)

[1]. 서비스의 개요

1. 스캇 앨런(K. Scott Allen)이 작성한 AngularJS 추상화 : 서비스란?

 1) 어플리케이션 공통 로직으로서의 서비스

 -컨트롤러, 지시자, 다른 서비스는 모두 특정 서비스의 하나 이상의 의존관계를 가질 수있거나 갖지 않을 수 있다.

즉, 서비스는 어플리케이션의 각 다른 부분에서 공통으로 사용하는 코드를 담기에 좋은 곳이라는 말이다.

가령 여러 컨트롤러에서 특정 계산 알고리즘을 필요로 한다면 해당 알고리즘을 구현한 코드가 있는 서비스를 만들어 해당 알고리즘을

필요로하는 컨트롤러가 이 서비스를 사용하면 되는 것이다.


 2) 싱글톤(Singleton)으로서의 서비스

 - AngularJS는 서비스를 싱글톤으로 관리한다. 즉, 어플리케이션에서 서비스의 인스턴스를 오직 하나만 가지고 있게 한다는 것이다.

이는 서비스가 어플리케이션이 살아있는 동안에 유지해야 할 데이터를 보관하는 장소로 적당하다는 의미다. 

가령 화면이 변경되어 여러 컨트롤러와 모델들이 호출되고 다시 사라지는 동안 유지해야할 데이터가 있으면 서비스를 이용해 유지할 수 있다는 의미다.


 3) 커뮤니케이션 허브(hub)로서의 서비스

 - AngularJS는 관심사의 분리(seperation of concerns)를 할 수 있고 다양한 컴포넌트 사이에 서로의 존재 여부를 모르게 하기 위한

프레임워크 기능을 제공한다.

서비스는 컨트롤러, 지시자, 필터, 그리고 다른 서비스에 주입되므로 다른 컴포넌트 간에 느슨하게 연결(loosely coupled)하며 서로 

커뮤니케이션을 하게 하는 역할을 하게 된다.


 4) 의존성 주입 대상(injectable Dependencies)으로서의 서비스

 - 서비스를 가장 많이 사용하는 이유 중 하나는 서비스가 컨트롤러, 지시자, 필터, 그리고 다른 서비스(다른 컴포넌트)에 주입되기 때문이다.

이는 각 컴포넌트 사이에 느슨하게 연결을 하게 해주며 단위 테스트시에 얼마든 주입되는 컴포넌트를 대체시킬 수 있게 한다.

AngularJS는 $http, $log, $window 등 다양한 서비스를 제공하고 이러한 서비스를 다른 컴포턴트에게 주입할 수 있는 대상이 된다.


- 이처럼 서비스는 각 컨트롤러 사이의 데이터를 공유하게 해주며 어플리케이션에서 다루는 객체의 싱글톤을 유지하게 해준다.

이러한 서비스는 컨트롤러, 다른 서비스, 또는 지시자에서 주입되는 대상이 되는 것이다. 


2. AngularJS에서의 의존관계 주입

 - 하나의 객체가 다른 객체를 사용하는 순간 의존관계가 성립된다. 

그러므로 어느 어플리케이션이든 여러 객체 사이에 의존관계가 필연적으로 성립될 수 밖에 없다. 

※ 자바스크립트 상에서 객체들 사이의 의존관계가 생성되는 세가지 경우

 1) new 키워드를 통한 의존관계 성립

 2) 전역 변수 참조를 통한 의존관계 성립

 3) 인자를 통하여 참조를 전달받아 의존관계 성립


function demoCtrl(){

var bookmark  = new BookmarkResource(new Ajax(), new JsonParser());

}

위 demoCtrl() 컨트롤러의 문제는 bookmark 객체를 어떻게 생성해야하는지 알고 있어야 한다는 문제점이 있다.

즉, BookmarkResource를 사용하기 위해 Ajax와 JsonParser 인자가 필요하다는 것이다.

가령 BookmarkResource가 Ajax 요청을 사용하지 않거나 JSON 형식의 데이터가 아니라 XML 형식으로 바뀐다면 BookmarkResource를 사용하는 모든 컨트롤러 소스를 모두 다 수정해야 할 것이다.


- 이 문제점을 해결하기 위해 팩토리 함수를 전역변수로 만들어 문제점을 없앤다면

var factory = {

getBookmarkResource : function() {

return new BookmarkResource(factory.getAjax(), factory.getJsonParser());

},

getAjax : function(){return new Ajax();},

getJsonParser : function(){return new JsonParser();}

}

function demoCtrl(){

var bookmark = factory.getBookmarkResource();

}

- BookmarkResource는 팩토리의 getAjax, getJsonParser 함수를 사용해 필요한 객체를 얻어오게 된다. 

이렇게 팩토리를 이용해 bookmark 객체를 얻게 되면 데모컨트롤러는 BookmarkResourcr가 어떻게 생성되는지 몰라도 된다.

나중에 Ajax를 사용하지 않거나 JSON 형식이 아닌 XML형식으로 데이터 형식이 바뀌게 되어도 모든 컨트롤러 함수를 수정할 필요없이 팩토리 객체만 수정하면 된다.


하지만 위 소스에는 테스트하기 어렵다는 문제점이 있다.

데모 컨트롤러의 단위 테스트를 하기위 해 전역 객체인 팩토리 객체를 테스트용으로 변경하여 사용할 수 있지만 단위 테스트마다 팩토리 객체에 대한 상태를 초기화해야 하고 아직 전역 객체와의 강한 결합이 존재한다.


- 마지막으로 인자를 참좋하여 만들어진 의존관계 소스를 본다면...

function demoCtrl(BookmarkResource){

var bookmark = BookmarkResource.get();

}

위 코드는 데모 컨트롤러가 BookmarkrResource를 인자로 전달받아 의존관계가 성립된 것을 볼 수 있다. 

이렇게 인자를 통하여 BookmarkResource를 데모 컨트롤러가 주입을 받아 의존관계 주입이 되는 것이다. 

의존관계 주입(DI)을 통하여 데모 컨트롤러와 BookarkResource는 약한 결합을 갖게 된다.

데모 컨트롤러는 BookmarkResource가 어떻게 생성되는지 알 필요도 없고 단위 테스트에서도얼마든지 필요한 테스트용 BookmarkResource를 주입받을 수 있는 것이다.

이는 단위 테스트를 매우 쉽게 해준다. 

이처럼 AngularJS에서는 주입되는 대상을 서비스라 하여 BookmarkResource를 서비스로서 개발하고 다른 서비스 혹은 지시자등에

주입되는 방식인 DI를 이용해 컴포넌트별 의존관계를 정의할 수 있다.