[Angular2] 데이터 바인딩

참고: angular2에 대한 연재는 여기를 참조해 주세요. 틀린 부분이나 의견, 피드백은 언제든지 환영합니다.

 

들어가기

오늘은 지난 시간에 설명한 컴포넌트의 상태를 어떻게 다룰지와 연관된 주제인 “데이터 바인딩“을 소개합니다. Angular 1을 사용해 보신 분들은 양방향 데이터 바인딩(2-way data binding)을 통해서 이미 “데이터 바인딩”이란 개념을 들어 보셨을 겁니다. 이번 글을 통해서 Angular2에서는 Angular1과 달리 어떻게 “데이터 바인딩” 기능을 제공하는지 알 수 있습니다.

 

데이터 바인딩?

먼저, 데이터 바인딩은 Angular에만 있는 특별한 개념이 아닙니다. 데스크톱 기반 앱의 UI 개발시에도 있었던 개념입니다. Java Swing을 예로 들어 볼까요? 사용자의 입력이 필요한 곳에 일반적으로 JTextField를 윈도우 창(Panel)에 배치 합니다. 그리고 버튼과 같은 요소에 리스너 메서드를 등록하여 사용자가 입력한 정보를 조회하여 비즈니스로직을 구현하는데요. 이 때 Swing에서는 사용자가 정보를 입력할 때 이를 JTextField 객체 내 상태에 바인딩합니다. 그리고 getText() API를 통해서 입력한 정보를 얻을 수 있습니다. 이처럼 기존 데스크톱 기반의 UI 라이브러리들은 사용자의 입력을 받을 수 있는 컴포넌트 안에 상태를 가지고 있고, 입력이벤트에 따른 상태 변경이 암묵적으로 자연스럽게 이루어집니다.

UI 프로그램의 트렌드가 데스크톱에서 웹으로 바뀌면서 기존에 데스크톱 기반 어플리케이션에서는 편리했던 입력 컴포넌트의 상태 정보 조회가 웹 기반 어플리케이션에서는 간단하지 않게 되었습니다. 이는 웹의 태생 자체가 사용자와의 양방향 상호작용이 많은 것을 가정한 것이 아니기 때문에 발생하는 불일치 입니다.

웹 어플리케이션에 어떻게 상태 정보를 조회하고 갱신하는지 확인해 봅시다. 보통 웹 어플리케이션에서는 DOM의 요소 안에 value나 checked 프로퍼티 등에 필요한 상태정보를 담고 있는 경우가 많습니다. 사용자가 입력한 정보를 얻기 위해서 웹에서는 DOM의 API나 jQuery를 사용해서 필요한 요소를 찾아내는 코드가 필수적으로 따라 붙게 됩니다. 아래는 jQuery의 val() API 문서에 있는 예제 소스 중 일부입니다.

script 태그 안에 있는 소스를 보면 input 태그의 “keyup” 이벤트가 발생할 때마다, 해당 input 요소(8번 줄의 this)에서 val() 메서드를 통해서 사용자가 입력한 값을 읽어서 다시 이를 p 요소를 조회한 후에 text 프로퍼티에 값으로 넣고 있습니다.

이러한 환경에서 웹기반 환경에서 사용자의 입력을 자동으로 반영해주는 것을 프레임워크 레벨에서 지원하기 시작했고, Angular 역시 이를 지원하는 프레임워크 중에 하나일 뿐입니다.

 

Angular2의 데이터 바인딩

Angular2에서는 화면에 UI역할을 하는 DOM과 Component 사이에서 총 4가지 방식의 데이터 바인딩 방법을 제공하고 있습니다. 아래는 Angular.io 매뉴얼에서 가져온 4가지 데이터 바인딩을 설명하는 그림입니다. 그림의 그려진 4개의 화살표가 데이터가 반영되는 방향을 의미하고 화살표 위에 내용이 실제 문법적 표현을 나타냅니다.

Angular2 데이터 바인딩 타입

첫 번째: 보간(interpolation)

Component의 상태를 그대로 화면에 노출 시킬 때 사용하는 방법입니다. 예를 들어 아래와 같이 MyComponent라는 Component에 myData라는 멤버 변수를 상태로 갖고 있다고 해봅시다.

이러한 경우 MyComponent를 표현할 template 에서 “{{ myData }}” 와 같이 MyComponent의 멤버변수를 중괄호 2개를 중첩하여 감싸면 myData안의 값이 자연스럽게 화면에 반영됩니다. 위 예제에서는 div태그 안에 myData 변수를 보간하였으므로 실제 html 소스로는 “<div>날 화면에 그려줘!</div>”로 바뀌게 됩니다. 따라서 그림의 첫 번째 화살표와 같이 Component 안의 데이터가 DOM에 반영된다고 볼 수 있습니다.

 

두 번째: 프로퍼티 바인딩

프로퍼티 바인딩은 Component의 상태 값을 DOM에 프로퍼티에 직접 반영하는데 쓰입니다. 문법은 해당 DOM의 프로퍼티를 대괄호([])로 감싸고 우측에 바인딩할 대상을 넣어주면 됩니다. 예를 들어, HTML의 input 태그는 메모리 상에 HTMLInputElement로 DOM에 반영되는데요. input 태그의 프로퍼티 중 하나인 disabled에 다음과 같은 방식으로 직접 Component의 상태를 반영하거나, 간단한 expression을 사용할 수 있습니다.

 

세 번째: 이벤트 바인딩

DOM의 요소들은 모두 특정 이벤트에 대한 리스너를 등록할 수 있습니다. 버튼에 onClick으로 이벤트를 직접 지정하기도 하지만 보통은  jQuery를 사용해서 이벤트를 등록합니다. Angular2에서는 DOM의 요소에 이벤트 리스너를 Component에 정의한 함수로 정의할 수 있게 해주면 이를 이벤트 바인딩이라고 합니다. 이벤트 바인딩하는 방법은 바인딩할 이벤트명을 소괄호( () )로 감싸고 우측에 메서드명을 적으면 됩니다.

아래는 button 요소에 “click”이벤트를, div 요소에 “mousemove” 이벤트를 바인딩한 예제입니다.

예제의 소스를 보면 다음과 같습니다.

소스의 내용을 살펴봅시다. 24번 라인에 먼저 button 요소에 소괄호를 사용하여 click 이벤트에 AppComponent의 “clickedButton” 메서드를 바인딩했습니다. 25번 라인에서는 div 요소의 “mousemove” 이벤트를 “printMousePosition” 메서드에 바인딩했습니다. 이벤트 바인딩으로 선언한 메서드의 파라미터로 $event는 DOM의 이벤트 객체가 자동으로 들어갑니다.

따라서 화면 상의 버튼을 클릭하면 clickedButton 메서드가 실행되면서 alert창이 뜨게 되고, div요소 위에 마우스를 움직일 때마다 printMousePosition메서드가 실행되면서, 해당 이벤트 발생 시점의 마우스 포지션을 positions 배열에 넣고 화면에 자동으로 출력합니다.

 

네 번째: 양방향 바인딩

마지막으로 양방향(two way) 바인딩입니다. 양방향 바인딩은 프로퍼티 바인딩과 이벤트 바인딩을 동시에 적용하는 방법입니다. 문법은 [(ngModel)]= “바인딩할 대상” 으로 해당 요소의 속성으로 넣어주면 됩니다. input, select 박스 등에 사용하면 바인딩한 Component에 상태가 화면의 View에도 반영이 되고, 반대로 사용자가 View에서 입력할 때 Component의 상태에도 자동으로 데이터가 반영이 됩니다. 아래 예제 input에 한번 입력해 보시기 바랍니다.

아래 소스를 살펴볼까요. 8번 라인에 ngModel로 AppComponent의 value를 양방향 바인딩하고, 이를 바로 p 태그 안에 보간하여 사용자가 입력한 값을 바로 보여줄 수 있게 처리 했습니다. 양방향 바인딩을 이용할 경우 손 쉽게 서버에서 보내는 데이터를Component의 모델에 저장하면 뷰에 반영이 되고 동시에 사용자가 뷰에서 수정한 값을 다시 Component의 모델에 반영할 수도 있습니다.

양방향 바인딩의 동작원리는 내부적으로 Change Detector에 의해서 이루어지는데요. 브라우저에서 발생 가능한 비동기 이벤트(XHR, setTimeout, Event)에 Change Detector가 루트 컴포넌트부터 Depth First Search 방식으로 데이터의 변경사항을 감지하여 양방향 바인딩을 가능하게 한다는 점만 가볍게 설명하고 넘어가겠습니다. 자세한 내용은 나중에 다시 다루도록 하겠습니다.

 

정리하며

오늘은 데이터 바인딩과 Angular2가 지원하는 4가지 방식의 데이터 바인딩에 대해서 살펴 보았습니다. 실상 Angular1에서는 양방향 바인딩이 기본이고 다른 바인딩은 아예 지원하지 않았습니다. 양방향 바인딩을 구현하기 위해서 Angular가 (내부적으로 $digest라는 사이클을 돌 때마다) 모든 변경사항을 체크해야 해서 퍼포먼스의 결함이 있었습니다.

Angular2에서는 양방향 바인딩 자체에도 완전히 새로운 알고리즘으로 퍼포먼스의 향상이 있었을 뿐 아니라 다른 바인딩 옵션을 제공하여 조금더 최적화딘 어플리케이션 개발을 돕습니다. 데이터 바인딩의 활용으로 불필요하게 늘어나는 스크립트 코드들이 줄어드니 사용하지 않을 이유가 없겠지요? 오늘은 여기서 이만 글을 마무리 합니다.

Angular2 글 목록보기