Web Development/Front

[Angular] Data Binding & Change Detection

alexrider94 2021. 3. 12. 14:47

데이터 바인딩

웹 애플리케이션을 구축하는데 있어서 뷰와 모델의 분리는 필수적이다. 분리된 뷰와 모델은 유기적으로 동작하여야하는데 데이터 바인딩이 이러한 모순을 해결해준다.

 

데이터 바인딩은? 뷰와 모델을 하나로 연결하는 것

 

Angular에서의 데이터 바인딩은 템플릿(View)와 컴포넌트 클래스의 데이터(Model)를 하나로 연결해서 유기적으로 동작하게 한다.

 

jQuery에 의한 DOM을 도작하는 경우 뷰와 모델 간의 관계를 느슨하게 결합하기 어려운 구조를 갖아서 뷰가 변경되면 로직도 변경될 가능성이 매우 높다. 하지만 Angular는 DOM에 직접 접근하지 않고 템플릿과 컴포넌트 클래스의 상호 관계를 선언하는 방식(선언형 프로그래밍)으로 뷰와 모델의 관계를 관리한다. 이때 사용하는 것이 데이터 바인딩이다.

 

데이터 바인딩은 템플릿 문법으로 기술된다. 템플릿에서 직접 컴포넌트 클래스의 프로퍼티를 참조하기 때문에 DOM에 접근하고 조직하는 코드를 작성할 필요가 없다. 그래서 html요소가 변경되어도 컴포넌트 클래스는 변경할 필요가 없다.

 

Angular의 데이터 바인딩은 뷰와 모델의 관계를 기존의 웹 애플리케이션 방식보다 느슨하게 결합하므로 뷰와 모델을 보다 깔끔하게 분리할 수 있을 뿐만아니라 간결한 코드로 개발이 가능하다.

 

변화 감지

뷰와 모델의 동기화를 유지하기 위해 상태의 변화를 감지하고 이를 반영하는 것을 변화 감지라고 한다. 상태 변화를 감지하여 뷰에 반영하는 것으로 데이터 바인딩은 변화 감지 매커니즘의 토대 위에서 수행된다.

 

Angular에서는 양방향 바인딩과 단방향 바인딩을 모두 지원하며 zone.js 라이브러리를 사용하여 네이티브 DOM 이벤트를 사용하여도 변화 감지가 수행되도록 개선되었다.

 

→ Angular에서는 사실 양방향 바인딩을 지원하지 않는다. 양방향 바인딩의 실제 동작은 이벤트 바인딩과 프로퍼티 바인딩의 조합으로 이루어진다.

 

변화 감지의 동작원리는 View의 상태 변화는 DOM 이벤트를 캐치하는것으로 감지할 수 있는데 모델은 HTML요소가 아니므로 이벤트가 발생하지 않는다. 그래서 모델의 변화 감지를 위해서 별도의 조치가 필요하다.

* 모델이 변경된다는 것은 컴포넌트 클래스의 프로퍼티값이 변경되는것을 의미

* 모델이 변화할 가능성이 있는 경우 

  1. DOM 이벤트(Click, Key Press, Mouse Move 등)

  2. Timer 함수(setTimeout, setInterval)의 Tick 이벤트

  3. Ajax통신/Promise

비동기 처리가 수행될 때 컴포넌트의 클래스의 데이터가 변경될 수 있는데 변화 감지는 모델이 변화할 수 있는 이러한 상황들을 감시한다. 이를 위해서 zone.js는 addEventListener, Timer 함수, XMLHttpRequest, Promise 등을 몽키패치 한다.

 

* 몽키패치 - 일반적으로 런타임 중인 프로그램 메모리의 소스 내용을 직접 바꾸는 것이다. / 런타임상에서 함수, 메서드, 속성을 바꾸는 것을 말한다.

 

function zoneAwarePromise() {...}
function patchTimer() {...}
...

window.prototype.promise = zoneAwarePromise;
widnow.prototype.setTimeout = pathTimeout;
...

 

zone.js는 일부 함수를 proxy로 재정의하여 대체한다. 즉 이벤트 또는 Promise가 proxy로 랩핑되고 이러한 개념을 몽키패치라고 한다.

 

모델의 변화 감지를 위해서 별도의 조치가 필요하다 했는데 이제 모델을 변화시킬 수 있는 비동기 처리가 호출되면 패치를 통해 호출을 후킹한다. 비동기 처리 호출을 후킹할 수 있다는 것은 변화를 감지할 수 있다는 것이고 이 후킹 로직 내 에서 변화 감지를 수행하고 변화가 감지될 때마다 Digest loop를 실행하여 모델의 변화를 뷰에 반영한다.