[AngularJS 1.x] EventQueue에서 Controller의 $scope를 사용하면 발생하는 문제 정리

2019. 5. 16. 09:32Programming/AngularJS

반응형

UI 코드가 복잡해지면서 이벤트 리스너나 콜백에서 $scope에 할당한 데이터에 접근하는 식으로 구현을 했었다. 언뜻 보기에는 잘 동작하는 코드같았다. 하지만 다른 페이지로 이동했다가 돌아왔을 때 이상한 동작을 발견해서, 기록해놓기로 했다.

내가 작성하던 플랫폼은 Controller 로드 시 서버에서 받아온 데이터를, $scope에 할당하는 형식으로 구현되어있다. 이번에 구현한 기능은 이 기본적인 형식뿐만 아니라, 이미지를 계속해서 로드하면서 동시에 마우스 이벤트에 따라 이미지 위에 도형을 그려야했다. Canvas의 Background와 Flickering에 대한 삽질 기록에서 구현한 기능의 개선판이었다.

Canvas의 Background와 Flickering에 대한 삽질 기록에서도 기술한 바 있듯 캔버스에서 백그라운드의 Flickering현상으로 인해 Image.onload를 사용하고 있었고, 도형을 그리기 위해서 mousemove, mousedown, mouseup등을 사용하고 있었다. 모두 EventQueue에서 동작하는 기능들이다. (EventQueue, EventLoop에 대해서는 [JS] 자바스크립트 엔진, Event Loop, Event Queue, Call Stack, imacoolgirlyo에 잘 정리되어있다.) 문제는 EventQueue에서 데이터에 접근하기 위해 $scope를 사용한다는 점이었다.

처음에는 잘 동작하는 것처럼 보이지만, Controller가 다시 생성되는 경우(나의 경우에는 네비게이션을 이용해서 다른 페이지로 이동하는 경우였다)에 문제가 발생했다. $scope에 저장된 데이터를 참조하려고 하는데, 이전에 생성됐던 $scope를 계속해서 참조하고 있었다. 예를 들어서 mousemove 이벤트가 발생 할 때마다 도형의 변경된 좌표를 저장해놓고, 캔버스 위에 좌표를 기준으로 도형을 그린다고 하자. 페이지를 이동한 뒤 다시 돌아와서 Controller가 다시 생성되면, mousemove내에는 이전에 변경해놨던 도형의 좌표가 저장되어있어서 mousemove 이벤트가 발생할 때마다 캔버스 위에 도형이 그려진다! 처음 접하면 환장할 노릇이다.

정확한 원인파악을 위해서는 angularJS의 소스를 열어서 $scope가 어떻게 생성되는지 파악해야겠지만, 우선은 해당 증상을 정리만 해두기로 했다. 어찌됐건 eventQueue에 등록한 함수에서 직접 $scope에 접근하지 않고 $rootScope에 $broadcast를 한다거나, DOM에 직접 접근해서 데이터를 읽어오는 등의 방법으로 증상을 해결할 수 있었다. 아무래도 angularJS에서 eventQueue를 사용할때는 한번 더 생각해볼 필요가 있을 듯 했다.

반응형