cadenzah's hideOut

~ 정처없이 떠돌 수 없어 속이 베베 꼬인 영혼을 위로하며 ~



가상 DOM이란 무엇인가?

이 글은 What is Virtual DOM? 의 내용을 번역한 것입니다. 일부 의역이 있을 수 있습니다.

요약하면, 가상 DOM이란 정교한 웹 UI를 빠르게 제작하고자 하는 최근에 떠오르는 트렌드에서 핵심적인 부분을 일컫는다

그렇지만 좀 깊게 들어가보자. 올해 들어 나는 이 신비로우면서 새로운 형태의 DOM에 대하여 듣기 시작했다. 마침내 나의 호기심은 점점 더 커졌고, "가상 DOM이 무엇인가"를 검색해봤다. 잠깐의 검색만 가지고는 나의 호기심을 단숨에 해결할 수 없었지만, 일련의 트렌드가 존재한다는 사실을 확인할 수는 있었다.

그리고 몇주 전, 나는 StackOverFlow의 이제는 닫힌 한 질문 - 가상 DOM이 무엇인가?을 읽게 되었다. 이 질문에 대하여 딱히 종합적인 답변은 없어보였고, 나는 이 트렌드가 상당히 중대한 일이라고 느꼈다. 그래서 수년 만에 첫 블로그 글을 작성하고 있다.

혼란을 방지하기 위하여, 아래의 명확한 구분을 고려해보자:

  1. 표준 DOM : W3C 표준. 오늘날 웹 브라우저들의 표준적인 DOM을 일컫는다. 나는 이를 "평범한 구식 DOM"이라고 부르는데, 이는 마치 과거에 Vanila JavaScript vs. jQuery와 같은 대목에서 언급되는 평범한 구식 JavaScript와 비슷한 것이다. 또한 이는 브라우저 DOM, 물리 DOM 을 일컫기도 한다.

  2. Shadow DOM : 현재 W3C 표준화 작업 중. Shadow DOM은 현 시점에서 가상 DOM과 직접적인 연관은 없다. Shadow DOM은 스타일 캡슐화를 가능하게 해주는 웹 컴포넌트의 한 측면이다. 자세한 내용은 다른 곳에서 더 알아볼 수 있다.

  3. 가상 DOM : 표준이 없다. 가상 DOM에 대한 해법은 표준 DOM을 기반으로 만들어진다. 결국 가상 DOM은 DOM을 활용한다는 것이다. 다만, 가상 DOM은 최대한 효율적으로, 최소한도로만 DOM을 활용한다.

표준 DOM에 대한 배경

어떤 것의 가상 버전에 대한 이해를 하고자 한다면, 우선 그 어떤 것의 원본을 이해하는 것이 먼저다. 본래 DOM에 대해 정리하 수 있는 내용을 이 글에 포함했었는데, 너무 길어져서 별도의 글 DOM이란 무엇인가?로 분리했다. 기본적인 사항을 그려보고 싶은 사람은 이 글을 먼저 읽어보자.

DOM이란 무엇인가?에서 DOM이란 문서의 추상화이라고 설명했다. 왜 가상 DOM까지 필요한 건지 명확하게 짚고 넘어가기 위하여, 표준 DOM이 가진 장단점을 살펴보자.

표준 DOM의 장점

  • 크로스 플랫폼, 크로프 브라우저 스크립트 작성에 용이하다
    • quirksomde.org가 제공하는 DOM 호환성 표를 확인해보면 알 수 있듯 대부분 초록불이 있음을 확인할 수 있다. 요즘같은 시대에 이건 참으로 환상적인 일이다.
  • 점진적인 성능 향상을 위한 단단한 기반을 제공한다.
  • 간단한 컨텐츠 화면 제공.

표준 DOM의 단점

DOM은 웹의 동적 UI를 만들기 위한 최적화가 전혀 이루어지지 않았다

jQuery의 DOM 조작 메서드는 신이 내린 선물이었고, 요상하기 그지 없는 DOM을 다루는 고통을 완화하는 데에 도움을 주었지만, 그 밑에 깔린 퍼포먼스 문제를 전혀 해결하지 않았다. 모바일이 대세인 웹 브라우징 환경에 우리가 대응하게 되면서, 느린 UI 상호작용은 빈번해졌고 훨씬 두드러지게 되었다.

우리는 대부분의 경우 단일 페이지 웹 앱(SPA)과 제3자 외부 컨텐츠가 넘쳐나는 페이지들을 만든다. 이 경우, 첫 렌더링 이후에 아주 느린 성능을 보인다. 페이지마다 천개가 넘는 DOM 요소를 조작하고, 페이지에 온갖 HTML 요소를 비동기적으로 불러온 뒤 그것들에 스타일을 적용해야만 한다. 이제 더 이상은 간단한 HTML 문서가 아니게 되어버렸고, 아주 느린 UX가 발생하게 되는 것이다. 모든 자원이 다운로드되고 나면, 단지 DOM 요소를 재배치하거나, 컨텐츠를 업데이트하는 정도의 작업만 수행할 뿐인데, 왜 이렇게 느려지는 것일까? 이 문제의 가장 큰 원인은 바로 유명 라이브러리들의 DOM 조작 메서드가 아주 느리다는 점이다.

특정 시점에 어떤 페이지 내에 존재하는 DOM 요소의 개수는 엄.청. 많을 수 있다

  • Twitter는 몇분만 스크롤을 내리고 나면 3만개 이상의 노드가 존재하게 된다.
  • Facebook은 몇분만 스크롤을 내리고 나면 17만개 이상의 노드가 존재하게 된다.

2014년의 웹 앱들은 사람들이 원하는 것만큼 빠르다고 느껴지지 않는다

2008년으로 되돌아가보면, 웹 개발자 커뮤니티에서는 비효율적인 DOM 조작을 극복하기 위하여, 느슨한 Best Practice 들을 만들어내기 시작했다. 보다 최근에는 일부 기업들은 각자의 방식으로 이 방법론을 코드화해왔다.

하지만 지금도 웹 개발자들이 어플리케이션 프레임워크를 사용하여 새로운 UI를 만들 때, 이러한 Best Practice를 지킨다 하더라도 여전히 수많은 복잡성과 고통이 존재한다. AngularJS를 예로 들자면, 비록 웹 어플리케이션을 개발하기 위한 환상적인 프레임워크이긴 하지만, 여전히 느린 DOM 작업으로 고통받게 되며 이를 극복하기 위한 Angular에 특화된 처치가 필요하다.

새로운 접근 방법

복잡한 UI를 만들고자 하는 수많은 팀들의 Best Practice는 멈추지 않았다. DOM을 다루는 최고의 방법, 그리고 재사용가능한 컴포넌트를 설계하는 방법에 대한 논의는 여전히 존재한다. 그 중 떠오르는 하나의 트렌드는 DOM 조작을 과거보다 훨씬 추상화하는 것에 집중되어있다. 이런 관점의 라이브러리와 프레임워크를 가상 DOM 프로젝트라고 부르겠다.

이러한 라이브러리와 이것의 창조자들이 깨달은 것은, 바로 훨씬 빠르고 유지보수가 용이한 웹 UI를 만들기 위해서는 개발자들이 DOM과 상호작용 하는 방식에 제약을 두어야 한다는 것이다. 무수하게 얽히고 설킨 중첩 객체들을 갱신하고 통제하기 위한 복잡한 Best Practice 대신, 가상 DOM 라이브러리들은 거대한 UI 전체를 항상 다시 렌더링하는 것을 원칙으로 둔다. 훨씬 빠르고 유지보수가 용이한 웹 UI를 만든다는 목표를 충족시키기 위하여, 가장 빠른 DOM 조작들만 허용하고, 이러한 DOM 조작마저도 반드시 라이브러리 자체에 의한 명령을 통하여서만 이루어지도록 하는 것이다.

보다 더 추상화

가상 DOM에 대한 이러한 떠오르는 접근 방식은 단순히 DOM 조작을 일괄 처리하는 것을 능가한다. 또한 이는 HTML Templating에 견주어 보아도 대부분의 경우 이를 능가한다. 이 라이브러리들은 대개 선언적인 객체 추상화(Declarative Object Abstractions)를 통하여 UI 코드 덩어리들을 다룬다. 이러한 추상물은 보통 컴포넌트라고 불린다.

프레임워크에 의하여 별도로 정의된 컴포넌트 객체 덩어리의 전/후 변화를 비교(diff), 그리고 반드시 필요할 때에만 변화 내용을 DOM에 기록하기. 이런 접근법을 통하여 가상 DOM 접근법은 성능뿐만 아니라 유지보수성까지 향상시킨다고 증명되었다.

코드의 핵심부에 가상 DOM의 아이디어를 적용한 다양한 라이브러리와 프레임워크들이 새로이 등장했다. 많은 라이브러리 개발자들, 그리고 가상 DOM 관련 라이브러리를 사용하는 웹 개발자들은 가상 DOM에 대하여, 그리고 현재 진행중인 프로젝트 또는 사용중인 프레임워크에 가상 DOM의 접근법을 어떻게 활용할 수 있을지 궁금해한다.(역자주: 링크글에 대한 해석을 아래에 첨부합니다) Famo.us는 DOM의 문제점을 회피하고 있는 프레임워크로 널리 과장되어 알려져있다. React는 UI를 만드는 데에 가상 DOM과 함수적 접근을 한 것으로 알려진 유명한 라이브러리 중 하나다. 대부분의 이러한 라이브러리들은 가상 DOM이라는 적절한 이름이 지어진 중요 프로젝트를 활용한다.



DOM 업데이트에 대한 Enyo 관련 질문

질문

React.js와 관련된 발표를 들었는데, React는 Enyo와 상당히 유사하다고 생각했다. 주된 이점은 가상 DOM에 대한 발상으로 보이는데, 여기서는 DOM을 변경하는 것이 제한되고 실제 DOM과 가상 DOM의 상태가 서로 다를 때에만 그 변경점이 적용되는 식으로 작동한다.

Enyo 또한 이러한 테크닉을 이용하는가? 이와 관련하여 지인과 이야기할 일이 있었는데, 그가 말하길 Enyo 객체는 DOM과 일대일로 묶여 m있으며, Enyo 객체에 생겨난 변화는 바로 DOM으로 전파된다고 한다. 하지만 이것은 틀린 것으로, 대부분의 변화는 해당 컴포넌트에 대한 render 또는 update 호출이 필요하기 때문이다.

또한 만약 부모 컴포넌트에 redner가 호출된다면, 자식 컴포넌트들은 자신들에 변경점이 없더라도 DOM에 리렌더링이 발생하는가?

답변

나는 아직 React를 경험하지 않았지만, 내가 읽어본 바에 의하면 유사한 점이 몇 가지 있다. 예를 들어, Enyo는 DOM과 별도로 메모리 상에 컴포넌트 위계 구조를 유지한다. 여기에는 여러 장점이 있지만 당신의 질문에 한정한다면, 프레임워크가 DOM에 직접 접근하지 않고도 컴포넌트를 조작하거나 삭제할 수 있도록 해준다.

하지만, 만약 당신이 DOM에 표시되고 있는 무언가를 갱신한다면, 이것은 명시적으로 render()를 호출할 필요 없이 DOM에 즉시 반영될 것이다. 예를 들어, enyo.Control을 생성한 뒤 control.set("content", "New Content")를 호출한다면, 새로운 innerHTML이 즉시 갱신될 것이다.

내가 알기로는, 그리고 당신이 아마 예측하고 있듯이 이것은 React도 다르지 않다. set()과 render()를 매번 호출하는 것은 너무 번거로울 것이다.

당신의 마지막 질문에 대한 답을 하자면, Control을 render()한다면, 해당 Control뿐만 아니라 자식들까지 render할 것이다. 만약 자식들이 이미 render되었다면, 그 자식들은 없어지고 다시 re-render될 것이다. 보통, 이것은 당신이 해야할 일이 아니라 특정 경우에서만 해당되는 일이다. 대신에 만약, 부모 Control의 어떤 특성만을 갱신했다면(예를 들어 style), 이 경우에는 해당 DOM 특성만 갱신되고 해당 Control과 자식들은 re-render되지 않을 것이다.


덧글

댓글 입력 영역