D3에서 가장 중요한 개념인 Data Join과 Selection에 대하여 다시 한 번 정리하면서 짚어본 것.

오명운님이 작성하신 셀렉션 작동원리(http://hanmomhanda.github.io/Docs/d3/How-Selections-Work.html)를 정리한 것이다.

Data join과 Selection 이해하기

배열의 서브클래스

D3에서 selection은 배열의 서브클래스이다. array.forEach, array.map과 같은 네이티브 메서드도 상속받아 지원하지만, D3가 selection.each와 같은 편한 대체 메서드를 제공한다.

문서요소 그룹핑

selection은 group의 배열인데 각 group은 문서요소의 배열이다.

ex)

  1. 단일 요소 선택 시(d3.select)
    var selection = d3.select("body");
    

  2. 다중 요소 선택 시(d3.selectAll)
    var selection = d3.selectAll("div");
    

  3. 여러 개의 그룹 선택 시
    var selection = d3.selectAll("div").selectAll("p");
    

    var selection = d3.selectAll("div").selectAll("p").selectAll("span");
    

각 group 배열은 group 배열 내 모든 원소의 공통적인 부모 노드를 저장하는 parentNode 속성을 가지고 있다. 부모 노드는 group 배열이 생성될 때 설정된다. 그래서, d3.selectAll("div").selectAll("p")를 호출하면, 부모가 div인 p 문서요소들을 원소로 하는 group 배열의 배열이 셀렉션으로 반환된다.

그룹핑을 변경하지 않는 메서드들

select는 원래의 selection에 있는 그룹핑을 변경하지 않고 그대로 보존한다. select 메서드는 원래 selection의 데이터를 새로운 selection에 물려주지만, selectAll은 물려주지 않는다. 그렇기때문에 data-join이 필요하다.

append 메서드와 insert 메서드는 select 메서드를 래핑한 메서드로, select와 마찬가지로 그룹핑을 그대로 보존하고 원래의 selection에 있던 데이터를 새로운 selection에 물려준다.

Null 문서요소

group 배열은 문서요소가 없는 상태를 나타내기 위해 null을 포함할 수 있다. null은 대부분의 처리에서 무시된다.

null이 발생되는 경우는 select 메서드가 해당 selector에 매칭되는 문서요소를 찾을 수 없을 때 발생할 수 있다. select 메서드는 그룹핑 구조를 그대로 보존해야하기 때문에 매칭되는 짝이 없는 곳은 null로 채운다.

ex) 4개의 section 노드 중 두 개만 aside를 가지고 있다면

d3.selectAll("section").select("aside");

위 코드의 실행 결과는..

데이터 바인딩

데이터는 셀렉션의 속성이 아닌, 셀렉션의 최말단 문서요소들의 속성이다. 각 문서요소의 __data__라는 속성에 할당된다. DOM에서 문서요소를 다시 select할 수 있으며, 선택된 해당 문서요소는 이전에 바인딩 된 데이터를 유지한다. => 따라서, 데이터는 지속성이 있지만(persistent) 셀렉션은 지속성이 없다(transient).


데이터가 바인딩될 수 있는 방법

  • selection.data를 통해 최말단 문서요소를 원소로 하는 group 배열에 조인
  • selection.datum를 통해 개별 최말단 문서요소에 직접 할당
  • append, insert, select 메서드를 통해 원래의 셀렉션으로부터 상속