Anuglar JS 공부 <2> Module,Controller,Directive, Service

Posted by lib oimb
2019. 1. 21. 01:52 AngularJS

 

 

1. Module 

 

Angular에서 Module은 AngularJs를 부트스트랩 시킬 하나의 영역을 정하는 것과 같다. 자바로 치면 Main Thread 영역이라고 생각하면 쉽다.

이 모듈을 선언하는 방법은 2가지가 있다.

 

1. ng-app = "myApp" 

 

이 방법은 자동으로 모듈을 설정하는 방법으로 한페이지당 한번밖에 사용하지 못한다는 단점이 있다. 물론 이는 큰 단점이 아니다. 보통 한페이지당 하나의 모듈을 사용하기 때문이다.

 

2. angular.bootstrap($('html').eq(0), [ 'myApp' ]);

 

이 방법은 수동으로 모듈을 설정하는 방법으로 한페이지당 여러번 사용 할 수 있다. 나는 주로 이 방법을 사용한다. 이는 보통 Html 문서가 끝나는 </body> 아래에다 선언한다.

<html ng-cloak>

<body>

...

</body>

<script type="text/javascript">

 $(document).ready(function() {

<%-- angularJS 수동 bootstrap --%>

 angular.bootstrap($('html').eq(0), [ 'myApp' ]);

</script>

</html>

위와 같이 사용한다 나는 <html ng-cloak> 와 같이 html 선언부에는 ng-cloak를 사용하기 때문에 이러한 방법을 주로 사용한다.

 

2. Module 생성

 

1에서 사용할 모듈을 선언하였므로 이번에는 Module을 생성하는 방법을 알아보자. 모듈을 생성하는 방법은 간단하다

 

var  myAppModule = angular.module('myApp', ["사용할 모듈"] );  또는  angular.module('myApp', ["사용할 모듈"] );

 

위와 같이 작성하면 모듈은 생성된다.

모듈을 생성하는 방법은 위와같이 정말 간단하다.  다만 모듈을 어떠한 구조로 사용할지를 생각해야 한다.

 

 

3. Module 구조

 

앞서 AngularJS<1>에서 AngularJS의  구조를 설명한바 있다. 바로 MVVM & MVC 이다.  모듈을 이러한 구조로 나눠서 사용하게 된다. 

  1.  컨트롤 선언을 위한 모듈 
  2.  서비스 선언을 위한 모듈
  3.  필터 선언을 위한 모듈
  4.  위의 1,2,3을 포함하기위한 모듈
  5.  4번과 같은 모듈들과 각각 초기화하여 사용하려는 의존적 모듈들을 주입하는 모듈

 

위와 같이 모듈을 구조적으로 선언하여 사용하게 된다. 말로는 설명이 어려우니 예를 들어보자 

의존성 주입을 위해선 5번부터 역순으로 선언해줘야 한다. 다만 필터는 제외한다 (모듈구분 에 있어 크게 중요하지 않음)

<1> Initial Module

angular.module('InitModule',['ngRoute','ngSantize','InitModule.firstModule'])

<2> firstModule 

angular.module('InitModule.firstModule',['InitModule.firstModule.controller','InitModule.firstModule.service'])
angular.module('InitModule.firstModule.controller',[])
angular.module('InitModule.firstModule.service',[])

<3> Service

angular.module('InitModule.firstModule.service').Service('firstService',['$http','$q',function($http,$q)]) {  }

<4>Controller  , Directive

angular.module('InitModule.firstModule.controller').Controller('firstController',['$scope','$window',function($scope,$window)]) {  }
angular.module('InitModule.firstModule.controller').directive('firstDirective',['$scope','$window',function($scope,$window)]) {  }

위와 같은 순서대로 진행 된다. 다만 Controller 와 Directive를 같이 선언하여 사용하고 있는데 이는 추후 설명한다.

 


1. Controller

 

다음 파트 Controller에 대해서 알아보자

Controller는 이름과같이 MVC에서 M 과 V 즉 모델(뷰모델)과 뷰를 제어하는 역할을 한다고 볼수 있다. 여기서 '제어'를 의미한다는것은 '바인딩' 한다는것을 의미한다고 생각하면된다. '바인딩' , 즉  뷰와 모델을 이어준다라고 생각하면 조금은 쉽겠다.

 

뷰와 모델을 $scope라는 pipe(통로)를 만든후에 각각의 값들은 서로 이어주는 역할을 한다. 이를 단순하게 보면 '이어준다' 이지만 과정을 들여다 보면 굉장히 어렵다

 

The purpose of $setViewValue is to propagate the value of the input / control into the ngModel pipeline:

change in control / inoput -> setViewValue -> parsers -> validators -> set on scope (simplified). Basically, you cannot separate the scope value from the value inside the ngModelController. The goal is to always have the value in the input control reflected in the whole ngModel pipeline, up to the scope value. In our example, the input value would be disconnected from the value inside the ngModelController. So the right way is to set the scope value to the last valid value, and it will propagate down to the input value.

 

위 말은 후에 알게된 $setViewValue에 대한 매커니즘을 소개하는 것인데, 굵은 글씨가 model이 바인딩 되는 과정을 설명하는 부분이다.

 

 

2. Controller 구조 , 역할

 

AngularJS의 컨트롤 역할은 '바인딩' 즉 '이어준다' 이게 끝이다. 이게 끝이지만 정말 중요하다.  컨트롤러는 '이어준다' 라는 역할만 수행해야지 서비스 또는 dom객체 조작에 관여하는 로직이 있어선 안된다. 

 

이는 AnularJS에서도 권고하는 사항인데 (https://docs.angularjs.org/guide/controller) 참조하길 바란다. 간단히 설명하자면

 

  • Set up the initial state of the $scope object.
  • Add behavior to the $scope object.

스코프 상태를 초기화 하거나 Object( 객체,함수,변수 , 서비스 호출) 를 추가할 때 사용하라는 것  

반대로 하지말아야 부분은

  • Manipulate DOM.

즉 Dom 조작이다. Dom조작은 디렉티브로 분리하여 사용할것을 권고한다.

 

 

3. Directive

 

디렉티브의 가장 간단한 형태는 애플리케이션이 필요한 곳에 여러 번 사용할 수 있는 작은 HTML 조각 형태다.디렉티브를 사용하면 애플리케이션에 별다른 노력없이도 쉽게 DOM을 주입하거나 사용자 정의 DOM의 상호작용을 적용할 수 있다. 디렉티브는 간단하지 않을 뿐더러 러닝커브가 생각보다 꽤 높다

 

directive의 컴파일과 링킹 과정은 이전 <1>에서 설명했듯이 크게 2가지 과정( compile -> link )을 거친다. (https://history1994.tistory.com/55)  따라서 이 부분은 생략하겠다.

 

 

3. Directive 작명법

 

Javascript 문에서는 camelCase작명을 따라 작성 ( testDirective)

 하지만 HTML 문서에서는 '-'를 이용한 snake-case 작명법으로 사용(test-directive)

 

일단 이 정도로 알고 있고 추후 디렉티브를 실제 어떻게 쓰는지는 차후 따로 directive 파트에서 알아보자

 



1. Service

 

Service는 이름 그대로 '서비스' 역할을 한다. 즉 Controller이 Service를 호출하여 서비스로직을 수행하고 이 Service는 서버단 (spring , node) 으로 데이터를 송신후 결과를 수신 받아 다시 Controller에게 넘겨주는 역할을 한다. 여기서 사용하는 모듈로는 $http 와 $q 가 존재한다.

General usage

The $http service is a function which takes a single argument — a configuration object — that is used to generate an HTTP request and returns a promise.

// Simple GET request example:
$http({
  method: 'GET',
  url: '/someUrl'
}).then(function successCallback(response) {
    // this callback will be called asynchronously
    // when the response is available
  }, function errorCallback(response) {
    // called asynchronously if an error occurs
    // or server returns response with an error status.
  });

The response object has these properties:

  • data – {string|Object} – The response body transformed with the transform functions.
  • status – {number} – HTTP status code of the response.
  • headers – {function([headerName])} – Header getter function.
  • config – {Object} – The configuration object that was used to generate the request.
  • statusText – {string} – HTTP status text of the response.
  • xhrStatus – {string} – Status of the XMLHttpRequest (completeerrortimeout or abort).

A response status code between 200 and 299 is considered a success status and will result in the success callback being called. Any response status code outside of that range is considered an error status and will result in the error callback being called. Also, status codes less than -1 are normalized to zero. -1 usually means the request was aborted, e.g. using a config.timeout. Note that if the response is a redirect, XMLHttpRequest will transparently follow it, meaning that the outcome (success or error) will be determined by the final response status code.

AnuglarJS의 실제 내용이다. 얼추 AJax 형태를 생각하면 쉽다. (https://code.angularjs.org/1.6.9/docs/api/ng/service/$http)

사용법은 링크를 타고 한번 쭈욱 읽어 보기를 바란다 특히 $http의 인자로 들어가는 객체의 프로퍼티 값중 params와 data 한번 잘 짚고 넘어가길 바란다.

 

또 $http 와 함께쓰는 $q는 promise역할과 관련있는 모듈이다. (https://code.angularjs.org/1.6.9/docs/api/ng/service/$q

따라서 promise의 짝궁 격인 resolve 와 reject가 함께 한다. 이것 이해가지 않는다면 자바스크립트의 callbackfunc 과 promise를 찾아 공부하길 바란다.

 

$http 와 $q를 합쳐서 사용하게 되면 이런 형태가 나온다.

 

this.T = function(paramObj){
		
		var deferred = $q.defer();		
		
		$http({
			method : 'POST',
			url : CONTEXT.HOME + 'T',
			data : $.param(paramObj),
			headers:{
				'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
				'X-Requested-With' : 'XMLHttpRequest'
			}
		})
		.then(function successCallback(response){			
			var data = response.data;
			deferred.resolve(data);
		},function errorCallback(response){			
			var data = response.data;
			deferred.reject(data);
		});
		
		return deferred.promise;
	}

 

 

	this.T = function(paramObj){
		
		var deferred = $q.defer();		
		
		Upload.upload({
			method : 'POST',
			url : CONTEXT.HOME + 'T',
			headers : { // ajax 해더 명시 필수
				'Content-Type': 'multipart/form-data; boundary=----Webkit',
				'X-Requested-With' : 'XMLHttpRequest'
			},
			data : paramObj
		})
		.then(function successCallback(response){			
			var data = response.data;
			deferred.resolve(data);
		},function errorCallback(response){			
			var data = response.data;
			deferred.reject(data);
		});
		
		return deferred.promise;
	}

 


 

자 그럼 모두 섞어보자

 

<!doctype html>

<html ng-app="Exam">

<head>

    <meta charset="UTF-8"/>

    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>

    <script>

        angular.module('Exam', ['controllerExam','serviceExam']);

        angular.module('controllerExam', []);

        angular.module('serviceExam', []);

        function MainController($scope, mainService){

            $scope.hello = mainService.say("Pal");

        }

        angular.module('controllerExam').controller('mainCtrl',['$scope','mainService',MainController]);

        //angular.module('controllerExam').directive();

        angular.module('serviceExam').service('mainService', [function() {

            var helloText = "__hi";

            return {

                say: function(name) {

                    return name + helloText;

                }

            };

        }])        

    </script>

</head>

<body>

    <div ng-controller="mainCtrl">

        <p>{{hello}}</p>

    </div>

</body>

</html>

 

이 댓글을 비밀 댓글로