<< 박사란? | Home | 조직력의 발전방향은? >>

Angularjs 1.2에서 1.3 업그레이드

본 포스트는 Angularjs 1.2에서 1.3으로 업그레이드를 하실분들에게 도움을 주고자 Migrating from 1.2 to 1.3" 문서를 정리한 것입니다. 아직 1.3에 추가적인 버그가 나와서 패치가 되고 있지만 성능부분이 더 좋아졌다고 하니 1.3이 안정화되면 업그레이드 하시길 권고해 드립니다. ^^

1.3 특징

1. 성능
- DOM 조작이나 digest 등 많은 처리에서 3 ~ 4배 빨라졌다.

2. 주목할 기능
- One-time bindings - 표현식 앞에 "::"를 붙여서 interpolate(값할당)가 한번 일어나며, 그 이후에는 감시(watch)되지 않는다.
- ngAria - 기본적으로 (접근성 관련) 액세스 가능한 사용자 지정 구성 요소를 구현하기 위한 새로운 모듈.
- ngMessages - 폼 검증에 대한 피드백(결과)을 쉽게 표시하기 위한 메세지 지시자.
- ngModelOptions - 바인딩된 모델(model binding)의 동작을 사용자 정의가 가능한 지시자. 예로는 아래와 같다.
  • debounce는 모델 업데이트 타이밍 제어가 가능.
  • getter-setter 형식의 모델 바인딩 가능.
  • update-on-blur는 blur시 모델 업데이트.
- Strict DI - 단순화한 DI 구문을 사용해 minify할 수 없는 코드를 찾을 수 있는 옵션(Implicit injection 문법 사용시 오류를 발생시킴).
- Material Design 지원.

마이그레이션 가이드

1. $parse
- prevent invocation of Function's bind, call and apply
angular 표현식에서는 function의 .bind .call .apply를 호출할 수 없게 된다. 기존 function의 행동을 예측할 수 없는 형태로 변경되지 않게 하기 위해서이다.

- forbid __proto__ properties in angular expressions
angular 표현식에서는 proto 속성이 동작하지 않는다.

- forbid __{define,lookup}{Getter,Setter}__ properties
angular 표현식에서는 {define, lookup} {Getter, Setter}를 사용할 수 없다. 만약에 몇몇 사유에 의해 필요한 경우, 위험 요소를 즐이기 위해 wrap/bind를 scope 객체를 통해 사용해라.

- forbid referencing Object in angular expressions
angular 표현식에서는 Object를 사용할 수 없다. Object.keys가 필요한 경우는 scope를 통해 접근할 수 있게 해라.

2. Angular.copy
- preserve prototype chain when copying objects
원본 Object의 prototype을 카피 Object에 적용하기 위해 angular.copy가 변경되었다. 이전에는 원본 Object의 프로토타입 체인 속성을 직접 복사했다.
카피된 객체의 hasOwnProperty 속성만 iterate하면 prototype의 속성은 포함되지 않는다. 이것은 좀 더 합리적인 행동이라고 생각하고 실제 어플리케이션이 행동에 의존하는 경우는 드물다.
만약, 애플리케이션이 행동에 의존하는 경우는 객체(상속 속성 포함)의 모든 속성을 hasOwnProperty로 필터링하지 않도록 iterate하라.
이 변경 사항은 IE8에서 동작하지 않는 기능을 사용할 수도 있다는 것에 주의하라. 만약 IE8에서 동작시키고 싶은 경우는 Object.create와 Object.getPrototypeOf의 polyfill을 사용해라.

3. core
- drop the toBoolean function 'f', '0', 'false', 'no', 'n', '[]'는 더이상 falsy로 간주되지 않고, JavaScript의 falsy값인 false, null, undefined, NaN, 0, ""만 parser에 의해 falsy로 처리된다.

4. $compile
- always error if two directives add isolate-scope and n…
하나의 요소에 isolate scope와 다른 scope를 요청하면 오류가 발생된다. 변경 전에는 isolate가 아닌 scope의 directive 다음에 isolate scope의 directive 순으로 컴파일러가 적용할 경우에는 두개의 directive가 child scope와 isolate scope를 요청하는 것이 가능했다. 지금은 순서에 관계없이 컴파일러 오류를 발생시킨다.
만약 당신의 코드가 지금 $compile:multidir 오류를 던진다면 같은 Element에 여러 directive가 isolate와 isolate 아닌 scope를 요청하지 않았는지 체크하고 코드를 고쳐라.

5. NgModel
- ensure pattern and ngPattern use the same validator
ng-pattern(ng-pattern="exp") 또는 pattern 속성(pattern="{{exp}}")을 angular 표현식으로 사용하고 있다면, 그리고 표현식이 문자열로 평가되는 경우, validator는 정규 표현식 객체 리터럴(/abc/i)로 문자열을 분석하지 않고 전체 문자열을 정규 표현식으로 되어 버린다. 즉, 이 의미는 플래그가 RegExp 객체로 처리되지 않는다. 이 문제를 해결하기 위해 정규식 객체를 angular 표현식의 값으로 사용해라.
//before
$scope.exp = '/abc/i';

//after
$scope.exp = /abc/i;

6. Scope
-
change Scope#id to be a simple number
Scope#$id는 문자열이 아니라 숫자로 되어 있다. 이 id는 주로 디버깅 목적으로 이용되고 있어서, 다른 곳에는 영향을 주지 않을 거라고 생각하고 있다.

7. forEach
- cache array length
forEach는 배열의 초기의 아이템 수만 iterate할 수 있고, iteration 도중에 배열에 추가된 항목은 forEach의 대상이 되지 않는다.
이 변경으로 인해 forEach가 Array#forEach와 동작이 비슷하게 되었다.

8. jqLit​​e
- data should store data only on Element and Document nodes
text/comment 노드에 jqLit​​e의 데이터를 넣을 수 있었는데, jQuery처럼 Element와 Document 노드에만 가능하게 되었다.

9. $resource
- allow props beginning with $ to be used on resources
$resource가 속성을 삭제하는 행동을 기대하는 경우 수동으로 직접 수행해야 한다.

10. angular.toJson
- only strip properties beginning with $$, not $
toJson이 속성을 삭제하는 행동을 기대하면 수동으로 직접 수행해야 한다.


11. $compile
- deprecate `replace` directives
Element를 replace하는 directive를 정의하기 위한 replace 플래그는 다음 Angular의 주요 버전에서는 삭제된다. 이 기능은 성가신 문제(속성을 어떻게 병합하는지 등)가 있으며,이 기능을 해결하는 것보다 더 많은 문제를 야기하고 있다. 또한, Web Components는 DOM에 사용자 지정 요소가 존재하는 것이 일반화되었다.

12. $parse
- remove deprecated promise unwrapping
promise unwrapping 기능은 제거되었다. 이것은 1.2.0-rc.3에서 이미 depreciated되어 있다. 아래 두 함수는 제거 되었다.
  • $parseProvider.unwrapPromises
  • $parseProvider.logPromiseWarnings

13. Scope
- $broadcast and $emit should set event.currentScope to null
$broadcast와 $emit 이벤트의 전파(propagation)를 종료한 시점에서 이벤트 currentScope 속성을 null로 재설정하게 된다. currentScope 속성에 비동기적으로 액세스하는 코드는 targetScope를 사용하도록 마이그레이션 하라.

14. jqLit​​e
- stop patching individual jQuery methods
jQuery의 detach() 메서드는 $destroy 이벤트를 트리거하지 않는다. Element에 붙인 Angular 데이터를 삭제하려면 remove()를 사용하라.

15. $http
- remove deprecated responseInterceptors functionality
지금까지는 response interceptor를 다음과 같이 등록할 수 있었다.
// register the interceptor as a service
$provide.factory('myHttpInterceptor', function($q, dependency1, 
  dependency2) {
  return function(promise) {
    return promise.then(function(response) {
      // do something on success
      return response;
    }, function(response) {
      // do something on error
      if (canRecover(response)) {
        return responseOrNewPromise
      }
      return $q.reject(response);
    });
  }
});

$httpProvider.responseInterceptors.push('myHttpInterceptor');

v1.1.4(4ae46814)에서 도입된 API는 다음과 같다.
$provide.factory('myHttpInterceptor', function($q) {
return {
  response: function(response) {
    // do something on success
    return response;
  },
  responseError: function(response) {
    // do something on error
    if (canRecover(response)) {
      return responseOrNewPromise
    }
    return $q.reject(response);
  }
};
});

$httpProvider.interceptors.push('myHttpInterceptor');

이 API의 자세한 내용은 interceptors에서 확인할 수 있다.

16. injector
- invoke config blocks for module after all providers
이전에는 config 블록이 provider 등록 전에 불려졌기 때문에 동작을 제어하기가 가능했지만, 지금은 항상 config 앞에 provider를 등록되게 되어져 있어서 동작을 제어 할 수 없게 되었다.

예:
이전에는 다음과 같은 코드가 작동하고 있었다.
angular.module('foo', [])
.provider('$rootProvider', function() {
  this.$get = function() { ... }
})
.config(function($rootProvider) {
  $rootProvider.dependentMode = "B";
})
.provider('$dependentProvider', function($rootProvider) {
   if ($rootProvider.dependentMode === "A") {
     this.$get = function() {
      // Special mode!
     }
   } else {
     this.$get = function() {
       // something else
     }
  }
});

$rootProvider와 $dependentProvider 등록 사이에 config 블록이 있어서 응용 프로그램의 동작을 변경할 수 있었지만, 이제는 이러한 방법이 싱글모듈 내에 있어서 더이상 실현될 수 없다.

17. ngModelOptions
- move debounce and updateOn logic into NgMod…
이 커밋은 NgModelController의 API를 변경하고 있다.

$setViewValue(value) - 이 메소드는 $viewValue를 변경하지만, 이전처럼 $modelValue가 변경되면 즉시 커밋하지 않는다. 지금은 관련된 ngModelOptions directive에서 지정된 트리거의 발생에 의해 커밋되도록 되었다. ngModelOptions에 debounce 지연이라는 트리거가 지정되어 있는 경우에는 변경의 커밋은 더 연기(debounce)된다. 대부분의 경우 NgModelController 사용 방법에 큰 영량을 미치지는 않는다. updateOn이 디폴트로 포함되어 있어 $setViewValue는 트리거에 의해 즉시 커밋될(잠재적 연기 가능) 것이다. $cancelUpdate() - $rollbackViewValue()로 이름이 ​​변경되었다. 그리고 현재의 $viewValue 값이 복귀하기 위해서는 $lastCommittedViewValue값으로 뒤로 가야한다. 그럴려면 보류중인 debounce 업데이트와 input을 다시 render하는 작업을 취소한다.

$cancelUpdate()를 사용하는 코드는 다음 예제처럼 마이그레이션 하라.

전 :
$scope.resetWithCancel = function (e) {
	if (e.keyCode == 27) {
	  $scope.myForm.myInput1.$cancelUpdate();
	  $scope.myValue = '';
	}
};

후 :
$scope.resetWithCancel = function (e) {
	if (e.keyCode == 27) {
	  $scope.myForm.myInput1.$rollbackViewValue();
	  $scope.myValue = '';
	}
}

18. $interpolate
- split .parts into .expressions and .separators
$interpolate에 의해 반환되는 function은 .parts 배열을 가질수 없다. 대신, 두개의 배열을 갖게 된다.
  • .expressions - interpolate된 텍스트의 expression 배열. expressions은 $parse로 분석되며, 계산되어질 때 문자열로 변환된다.
  • .separators - 텍스트에서 interpolation 사이를 구분하는 문자열의 배열로,이 배열은 병합하기 쉽게하기 위해 항상 .expressions 배열보다 1 아이템 길다.

19. $animate
- insert elements at the start of the parent container instead of at the end
$animate 부모 컨테이너의 마지막 요소로하는 after 매개 변수를 더이상 디폴트가 아니다. 대신 after가 지정되어 있지 않은 경우에는 새로운 요소를 부모 컨테이너의 첫 번째 자식으로 삽입 할 수 있다.
기존 코드를 업데이트하기 위해서는 $animate.enter() 또는 $animate.move()의 모든 인스턴스를
$animate.enter(element, parent);

에서
$animate.enter(element, parent, angular.element(parent[0].lastChild));

로 변경하여야 한다.

- make CSS blocking optional for class-based animations
전이(transitions)를 사용하거나, 설치 CSS class(class-add와 class-remove 등) 기반의 애니메이션 코드는 스타일이 즉시 적용되는 것을 보장하려면 빈 transition 값을 주어야 한다. 다른말로는, 애니메이션의 코드가 설치 class에서 정의된 스타일을 적용하고, CSS class에서 "transition:0s none" 값이 존재하지 않는 한 즉시 적용되지 않는다. 이 상황은 전이(transitions)는 애니메이션이 한번 시작된 후 베이스 CSS 클래스에 존재하는 경우에만 해당된다.

전 :
.animated.my-class-add {
	opacity:0;
	transition:0.5s linear all;
}
.animated.my-class-add.my-class-add-active {
	opacity:1;
}

후 :
.animated.my-class-add {
	transition:0s linear all;
	opacity:0;
}
.animated.my-class-add.my-class-add-active {
	transition:0.5s linear all;
	opacity:1;
}

자세한 내용은 ngAnimate 문서를 봐주세요.

20. $compile
- add support for $observer deregistration
attr$observe 호출할 경우 더이상 observer function을 리턴해주지 않고, 대신 등록 해제(deregistration) function을 리턴해 준다. 다음의 예에 따라 코드를 마이그레이션하세요.

전 :
directive('directiveName', function() {
return {
  link: function(scope, elm, attr) {
    var observer = attr.$observe('someAttr', function(value) {
      console.log(value);
    });
  }
};
});

후 :
directive('directiveName', function() {
return {
  link: function(scope, elm, attr) {
    var observer = function(value) {
      console.log(value);
    };

    attr.$observe('someAttr', observer);
  }
};
});

21. $httpBackend
- don't error when JSONP callback called with no parameter
에러와 empty 응답에 대한 JSONP의 동작이 변경되었다. 이전에는, JSONP 응답이 비어 있는 경우에는 에러로 간주되었지만 지금은 에러를 발견하기 위한 이벤트를 올바르게 수신할 수 있게 되었다. 이젠 empty 응답도 성공적으로 수신할 수 있다.

22. build
- remove IE8 target from all test configs
IE8은 더이상 지원되지 않는다.

23. input
- support types date, time, datetime-local, month, week
date, time, datetime-local, month, week의 Type은 항상 Date 객체가 필수이다.

용어

  • interpolation : {{}} 값을 채움.
  • debounce : 지정한 값만큼 지난 후 바인딩된 모델값의 변경.



Add a comment Send a TrackBack