AngularJS 어느 위치에서나 Scope에 접근하기

AngularJS에서 컨트롤러 외부(콘솔, 외부 라이브러리 콜백 등)에서 $scope에 접근해야 할 때 사용하는 방법입니다.

언제 사용하나요?

  • 브라우저 콘솔에서 디버깅할 때
  • 외부 JavaScript 라이브러리 콜백에서 AngularJS 데이터를 변경할 때
  • setTimeout, setInterval 등 비동기 콜백에서 scope 접근할 때
  • jQuery 이벤트 핸들러에서 AngularJS 데이터를 업데이트할 때

기본 방법 - angular.element()

// 특정 요소의 scope 가져오기
var scope = angular.element(document.getElementById("myElement")).scope();

// 또는 jQuery 선택자 사용
var scope = angular.element($("#myElement")).scope();

// scope 값 읽기
console.log(scope.myVariable);

// scope 값 변경 후 적용
scope.myVariable = "새로운 값";
scope.$apply();  // 변경사항을 화면에 반영

$apply()가 필요한 이유

AngularJS 외부에서 scope를 변경하면 Angular의 digest cycle이 자동으로 실행되지 않습니다. $apply()를 호출해야 변경사항이 화면에 반영됩니다.

// 잘못된 예 - 화면에 반영 안 됨
scope.userName = "홍길동";

// 올바른 예 - 화면에 반영됨
scope.userName = "홍길동";
scope.$apply();

// 더 안전한 방법 - 이미 digest 중일 때 에러 방지
scope.$apply(function() {
    scope.userName = "홍길동";
});

// 또는 $timeout 사용 (권장)
$timeout(function() {
    scope.userName = "홍길동";
});

실제 사용 예시

1. 외부 라이브러리 콜백에서 사용

// Summernote 에디터 콜백
$("#editor").summernote({
    onChange: function(contents) {
        var scope = angular.element($("#myController")).scope();
        scope.$apply(function() {
            scope.editorContent = contents;
        });
    }
});

2. jQuery 이벤트에서 사용

$("#externalButton").click(function() {
    var scope = angular.element($("[ng-controller=MyController]")).scope();
    scope.$apply(function() {
        scope.counter++;
        scope.updateMessage();
    });
});

3. 브라우저 콘솔에서 디버깅

// 크롬 개발자 도구에서
var scope = angular.element($("body")).scope();
console.log(scope);  // 전체 scope 확인

// 특정 컨트롤러의 scope
var scope = angular.element($("[ng-controller=MainCtrl]")).scope();
scope.items.push({name: "테스트"});
scope.$apply();

4. $rootScope 접근

// 전역 scope($rootScope) 접근
var $rootScope = angular.element(document.body).injector().get("$rootScope");
$rootScope.globalMessage = "전역 메시지";
$rootScope.$apply();

서비스 접근하기

// injector를 통해 서비스 접근
var injector = angular.element(document.body).injector();
var myService = injector.get("MyService");
var $http = injector.get("$http");

// 서비스 메서드 호출
myService.getData().then(function(data) {
    console.log(data);
});

주의사항

  • 이 방법은 디버깅이나 외부 라이브러리 연동용으로만 사용하세요
  • 일반적인 코드에서는 컨트롤러나 서비스 내에서 scope를 관리하는 것이 좋습니다
  • $apply() 중복 호출 시 에러가 발생할 수 있으므로 $timeout 사용을 권장합니다
  • Angular 2+ 에서는 이 방식이 적용되지 않습니다

에러 처리

// "$apply already in progress" 에러 방지
if (!scope.$$phase) {
    scope.$apply();
}

// 또는 safeApply 함수 정의
scope.safeApply = function(fn) {
    var phase = this.$root.$$phase;
    if (phase === "$apply" || phase === "$digest") {
        if (fn) fn();
    } else {
        this.$apply(fn);
    }
};