'DOM'에 해당되는 글 3건

  1. 2015.12.23 childNodes vs nextSibling (and vs children) 돔 탐색 성능 차이
  2. 2007.04.21 Dom 사용하기.
  3. 2007.02.07 Dom Scripting

며칠 전에 angular 코드를 보다가 design note을 찾으러 위키를 갔는데 우연히 [performance]을 봤다.(design note는 [다른 곳]에서 찾음.)

다른 내용들은 일반적인 내용인데 내가 의아하게 느낀 부분이 자식노드를 탐색할 때 `DOM.childNodes`이 `node.nextSibling`보다 느리다는 얘기다. 그 예로 [jsperf링크]가 있어서 확인해보니 실제로 nextSibling이 빨랐고 몇 개 브라우저에서 좀 더 확인해봤는데 모두 nextSibling이 항상 빨랐다.


"왜 그럴까?" 잠깐 고민해봤는데 딱히 아이디어가 안떠올라 blink의 구현로직을 찾아보기로 했다.


먼저 clideNodes부분을 보니 Container노드(parentNode)일 때 그 안에 childeNode을 찾아 nodelist로 만든 다음 반환하는데 뭔가 특별해보이진 않는다.

PassRefPtrWillBeRawPtr<NodeList> Node::childNodes()
{
    if (isContainerNode())
        return ensureRareData().ensureNodeLists().ensureChildNodeList(toContainerNode(*this));
    return ensureRareData().ensureNodeLists().ensureEmptyChildNodeList(*this);
}

그럼 nextSibling은 뭘까 찾아봤다.

Node* previousSibling() const { return m_previous; }
Node* nextSibling() const { return m_next; }

엇. 이거 뭐지 그냥 반환만 하네... 그래서 찾아보니 nextSibling, previousSibling을 호출할 때는 뭔가 찾는게 아니라 아래와 같이 Node가 변경되면 값을 업데이트하고 호출할 때는 위와 같이 그냥 반환한다.

void ContainerNode::insertBeforeCommon(Node& nextChild, Node& newChild)
{
    Node* prev = nextChild.previousSibling();
    nextChild.setPreviousSibling(&newChild);
    if (prev) {
        prev->setNextSibling(&newChild);
    } else {
        m_firstChild = &newChild;
    }
    newChild.setParentOrShadowHostNode(this);
    newChild.setPreviousSibling(prev);
    newChild.setNextSibling(&nextChild);
}

void ContainerNode::appendChildCommon(Node& child)
{
    child.setParentOrShadowHostNode(this);

    if (m_lastChild) {
        child.setPreviousSibling(m_lastChild);
        m_lastChild->setNextSibling(&child);
    } else {
        setFirstChild(&child);
    }

    setLastChild(&child);
}

즉, childNodes을 찾을 때는 하위 노드를 찾아서 nodelist로 만든 다음 반환하기 때문에 비용이 좀 드는 것 같고, nextSibling은 그냥 바로 노드를 반환하기 때문에 비용이 적게 드는 것 같다. 

갑자기 비슷한 children이 생각나서 이건 어떻게 구현되어 있을까 하고 찾아봤는데 아래와 같이 구현되어 있다. 

PassRefPtrWillBeRawPtr<HTMLCollection> ContainerNode::children()
{
    return ensureCachedCollection<HTMLCollection>(NodeChildren);
}

이건 우리가 알고 있는 [live nodelist]인 것 같아 아마도 성능이 좋지 않을까 하고 비교해봤는데 결과는 nextSibling보다는 느리지만, childNodes보다는 빨랐다. [링크]


처음 가지고 있던 의구심을 해결하고 nextSibling, previousSibling, lastChild, firstChild는 이미 계산되어 가지고 있다는 사실을 알게됐다.


ps. github에서 유명한 프로젝트에 childNodes을 사용하는 부분을 찾아서 pr줍기를 시도했지만... 테스트 코드를 제외하곤 거의 없어 아쉬었다. 하지만, 우연히 버그같은 코드를 발견해서 [pr 줍기 성공]. :)





Posted by 전용우
Chris Heilmann라는 사람의 Dom Scripting강의 약 10분정도로 dom에 대해
설명함. 일단 중요한건 쉬움.:)

Beginning JavaScript with DOM Scripting and Ajax이란 책을 쓴 저자.
해당블로그에 많은 내용이 있으니 한번 방문해보세요.

Posted by 전용우

Dom Scripting

프로그래밍 2007.02.07 02:41

Dom Scripting Book Image
Dom Scripting

이책은 일단 쉽고,빠르게 읽을수 있고,유용하며 재미있다.
조금이라도 javascript을 알고있다면 너무 쉽게 읽을수 있다.
(시간이 없다면 3~10장까지만 보면됨.)


이책에 내용을 요약하자면.

  • Graceful degradation
    (만약에 자바스크립트를 잘 사용하고 있다면 자바스크립트가 없어도 사용자는
    네비게이션을 할수 있다.)
  • Unobtrusive JavaScript
    (자바스크립트는 부과적인 기능을 하는것이다.)
  • Backwards compatibility
    (뒤떨어진 환경에서도 가능해야한다.)

물론 위의글은 모두 정답이다.당연하고 기초적이긴 하지만 지키기에는 많은 노력이 뒤받침이되야한다.지금껏 해왔던 습관들을 버려야하고 기타 개발여건도 받쳐줘야하고..

내생각은 처음부터 하면 좋지만 여건이 안되면 나중에라도 서버단만 리팩토링을 하는것이 아니라 프론트도 리팩토링을 하면서 바꾸면 될것 같다.
 



 

  1. var value = element.attribute=value;
    var value = element.getAttribute(attribute); 같음. [본문으로]
  2. element.attribute=value;
    element.setAttribute(attribute)=value; 같음. [본문으로]
  3. node.childNodes[0];
    node.firstChild; 같음. [본문으로]
  4. node.childNodes[node.childNodes.length-1];
    node.lastChild; 같음. [본문으로]
  5. previousSibling은 반대. [본문으로]
Posted by 전용우