Angular.js의 스코프 상속
Angular.js에서는 스코프가 상당히 중요한데 예를 들어 컨트롤러를 생성할 때마다 스코프가 생기고 이 스코프는 중첩 관계를 가져서 부모의 스코프와 자동으로 상속구조를 만들 수 있다.(컨트롤러에서만 스코프를 새로 생성하는 건 아니다.) 이 때 스코프는 기본적으로 HTML 중첩구조를 그대로 따라서 상속구조를 가지게 된다.
<body ng-app>
<div ng-controller="MainCtrl">
{{greet}}!! {{whoami}}
<div ng-controller="NavCtrl">
{{greet}}!! {{whoami}}
</div>
<div ng-controller="SideCtrl">
{{greet}}!! {{whoami}}
</div>
</div>
</body>
위와 같은 구조의 HTML 주고를 생각해 보자. 이때 JS 파일은 다음과 같다.
function MainCtrl($scope) {
$scope.whoami= "Main Controller";
$scope.greet = "Hello";
}
function NavCtrl($scope) {
$scope.whoami= "Nav Controller";
}
function SideCtrl($scope) {
$scope.whoami= "Side Controller";
}
이를 실행하면 다음과 같이 나온다.
이때 스코프는 다음과 같은 구조를 갖게 된다.
여기서 스코프 003이 MainCtrl
이고 004와 005가 각각 NavCtrl
와 SideCtrl
이다. 즉, NavCtrl
와 SideCtrl
가 MainCtrl
의 스코프를 상속받는 구조가 되기 때문에 NavCtrl
와 SideCtrl
에 없는 greet
라는 값을 그대로 쓸 수 있다. 즉, 이 상속구조를 잘 이용하면 공통되는 값이나 기능(함수)를 부모 스코프에 두고 밑에서는 상속받아서 그대로 사용할 수 있다.
HTML없이 상속하기
위에서 보았듯이 Angular.js는 HTML 구조에 기반해서 스코프 상속을 하게 된다. 하지만 때에 따라서는 HTML 구조가 필요없는 경우가 있다. ControllerA와 ControllerB가 있는데 공통적으로 가지는 구조가 많아서 이를 한 곳으로 모으고 싶을 때 상속으로 공통화하려는 목적외에는 필요없는 컨트롤러를 굳이 불필요하게 HTML에 넣을 필요는 없고 상황에 따라서는 둘의 위치가 달라서 HTML에 상위에 넣는 것이 애매한 경우도 있을 것이다. 스코프 처리에 대한 내부 로직을 자세히는 모르지만 이 경우에 굳이 불필요하게 스코프를 따로 생성할 필요도 없을 것이다.
이를 위해서 Angular.js는 angular.extend함수를 지원하고 있다.(문서는 무척 빈약하다.) 앞에서 본 예제에서 HTML은 변경하지 않고 greet
만 다른 컨트롤러(상속받을)로 추출하려면 다음과 같이 할 수 있다.
function ParentCtrl($scope) {
$scope.greet = "Hello";
}
function MainCtrl($scope) {
angular.extend(this, new ParentCtrl($scope));
$scope.whoami= "Main Controller";
}
function NavCtrl($scope) {
angular.extend(this, new ParentCtrl($scope));
$scope.whoami= "Nav Controller";
}
function SideCtrl($scope) {
angular.extend(this, new ParentCtrl($scope));
$scope.whoami= "Side Controller";
}
angular.extend()
를 사용해서 ParentCtrl
을 상속받아서 공통 기능을 가지는 컨트롤러를 HTML을 수정하지 않고 만들었다.
여기서 주의할 점은 ParentCtrl
가 다른 컨트롤러와는 약간 다르다는 것이다. 다른 컨트롤러는 Angular 앱이 컨트롤러로 인식하므로 파라미터에 의존성을 주입해 주시만 ParentCtrl
은 모양만 똑같을 뿐 그냥 함수일 뿐이다.(다른 컨트롤러도 그냥 함수이지만 Angualr 앱이 인식하지 못한다는 의미다.) 그래서 ParentCtrl
의 파라미터인 $scope
는 의존성 주입으로 받는 것이 아니라 다른 컨트롤러에서 new ParentCtrl($scope)
할 때 전달받은 파라미터이다. 그래서 $location
, $http
, $timeout
처럼 Angular 앱이 의존성 주입해주는 객체를 직접 받으면 안되고 $scope
처럼 상속받는 객체에서 파라미터로 전달해 주어야 한다.
function ParentCtrl($scope, $location) {
$scope.greet = "Hello";
}
function MainCtrl($scope, $location) {
angular.extend(this, new ParentCtrl($scope, $location));
$scope.whoami= "Main Controller";
}
즉 위와 같이 상속받는 곳에서 의존성 주입을 해서 상속받을때 전달해 주어야 한다.
Angular Js $resource 를 통해 data 를 프레임워크 컨트롤러 단에서 받는 방법 혹시 아십니까?
컨트롤러함수에 $resource를 주입해서 사용하면 될것 같은데요.
좋은 정보 감사합니다.
그 동안 상속문제로 고민이 많았는데 덕분에 해결했습니다.
감사합니다 ^__^ 덕분에 코드가 깔끔해지고 있어요
^^