지난 주차 FE 트랙 교육 주제는 DOM이었다.
DOM을 큰 틀로 DOM Tree, DOM api를 공부하도록 시켰는데 이해를 확실히 못하고 과제를 작성한 점들이 많으셨던 듯 하다.
물론 나도 DOM을 처음 봤을땐 이게 뭐야? 그냥 HTML아니야? 브라우저 아니야? 하는 식의 생각이 들었지만, 이번 교육 강의를 위해 훨~씬 자세하게 조사하면서 정의를 확실하게 내릴 수 있게 된 것 같다. 이것도 동아리의 선순환구조가 아닐까...
잊기 전에 정리를 할 건데, 가장 먼저 읽어봐야 하는 것은 MDN과 모던 자바스크립트 튜토리얼 문서이다.
위 두 문서를 몇 번 정독하다보면 어느 정도 시점에서 이해가 잡힌다.
DOM은 웹개발의 기초 이론이니 개발 관련 문서를 읽을 때 모르면 문제가 생길 수 있으니 확실하게 짚고 넘어가야 한다고 생각한다.
문서 객체 모델(The Document Object Model, 이하 DOM) 은 HTML, XML 문서의 프로그래밍 interface 이다.
DOM의 정의에서 생소한 단어는 interface라는 단어였는데, 인터페이스는 상호작용할 수 있는 부분이라고 이해했다.
첫 정의부터 모호할 수 있지만 이후 개념들을 차차 정리하다보면 어떻게 상호작용 할 수 있는 것인지 알 수 있을 것이다.
먼저 짚고 갈 점은, DOM은 브라우저가 구현했다는 점을 알고 지나가면 더 쉬울것 같다.
DOM은 문서의 구조화된 표현(structured representation)을 제공하며 프로그래밍 언어가 DOM 구조에 접근할 수 있는 방법을 제공하여 그들이 문서 구조, 스타일, 내용 등을 변경할 수 있게 돕는다.
DOM을 통해서 우리가 할 수 있는 상호작용은 DOM구조에 접근해서 문서의 내용을 변경할 수 있다고 한다.
문서의 내용을 변경한다는 것을 쉽게(?) 말하면 동적인 문서를 만들 수 있다는 것이다.
정~말 기본적으로 웹은 HTML(구조), CSS(스타일링), JS(기능)으로 이루어진다고 말할 수 있다.
여기서 HTML을 바꾸는 것은 JS의 역할이라고 알고 있을텐데, 이것이 DOM과 연관되어진다고 생각하면 된다.
물론 JavaScript가 이 역할만을 할 수 있는것은 아니지만, 대부분의 경우 브라우저에서 동작하기 때문에 넘어가겠다.
DOM 구조에 접근한다고 했으니 먼저 DOM구조가 무엇인지부터 알아보자.
DOM은 트리 구조로 HTML 문서를 표현한다.
DOM Tree 검색 결과. 그림은 다양하지만, 주된 내용은 같다.
사실 이러한 이미지들로 이해하는 것보단 개발자 도구의 Element탭이 좀 더 와닿았다.
하지만 둘이 완전히 같지 않을 수 있다.
개발자 도구가 생략해주는 부분이 있고, DOM의 기본 틀에 맞추어 HTML을 맞춰 수정해 보여주기도 하지만, DOM Tree구조를 이해하는 데 이만큼 쉬운 모델이 없는 것 같다.
기본적으로 HTML의 구조를 따라가고, 이를 Tree 형태로 표현한다.
얼핏 보면 최상위 태그인 <html>
이 DOM Tree의 가장 상위 요소로 보일 수 있으나, <html>
태그와 더불어 최상단의 선언문인 까지 포함하는 document 객체가 그 위에 있다는 점을 인지하자. 검색했던 모든 이미지의 html 위에는 document가 있을 것이다. (그렇기에 document.childNodes[0]
은 <Doctype HTML>
을, document.childNodes[1]
은 <html>
을 반환한다.)
이름대로 document는 문서 전체를 의미한다.
아직 설명하진 않았지만, Document Object Model인 만큼, 태그 하나하나가 전부 객체이다. 이 또한 인지하고 있자.
DOM 구조에 대해서 알았으니, DOM구조에 접근하는 방법에 대해서 보자.
스크립트를 작성할 때(인라인
<script>
요소를 사용하거나 웹 페이지 안에 있는 스크립트 로딩 명령을 사용하여), 문서 자체를 조작하거나 문서의 children 을 얻기 위해 document 또는 window elements 를 위한 API 를 즉시 사용할 수 있다.
JS를 조금이라도 만져봤다면, document.getElementById('id')와 같은 함수들을 사용해보았을것이다.
DOM은 문서의 children, 하위 요소를 얻기 위한 API를 제공한다는데, 위 메소드가 딱 이를 보여준다.
앞에서 태그 하나하나가 전부 객체라고 말했다.
DOM이 구성한 객체에 DOM이 제공하는 메소드와 프로퍼티들을 통해 접근할 수 있다.
DOM에 인터페이스라는 표현을 썼다는 것을 다시 한 번 짚고 넘어가자.
객체에 접근했다면, DOM API를 활용해 DOM을 수정할 수 있다.
MDN에서 나열한 간략한 목록
대부분의 예제에서 document.createElement로 요소를 생성하고, appendChild로 하위 요소로 집어넣는 과정을 진행할 것이다. (혹은 setAttribute로 속성을 부여하던가)
한번 예제를 진행하고 나면(자신만의 테스트 파일이던, 콘솔창에서던) DOM을 수정한다는 것이 이해가 안 될 수가 없다.
간단하게 개발자 도구에서 이 문장을 클릭해 검사하고, esc키를 눌러 콘솔창을 연 다음, $0(개발자 도구에서 지원하는 값)으로 접근한 뒤 하위 요소로 아무거나 넣어보자. ex) $0.innerText = "새로운 값"
또 하나 주목할 점은 getElementby... 의 element, 요소. 요소라는 말이 자꾸 나온다. 왜 Tag나 Object가 아닌 Element라고 할까?
메소드 이름이 getElement인 데에는 다 이유가 있을 것이다.
객체지향의 개념이지만, DOM에서 모든 객체들은 클래스(프로토타입)를 상속받는다.
JS 튜토리얼에서 그린 계층 구조
얼핏 보면 DOM Tree와 헷갈릴 수 있지만, 구조만 Tree이지 HTML 태그들로 이루어지지 않았다는 것을 볼 수 있다.
앞서 보자고 했던 Element가 저기 보이고, 하위 요소로는 익숙한 이름들(Input, Body, a tag와 같은..)이 보인다.
Element는 HTML과 SVG(벡터 이미지)로 나눠지는데, 이는 다른 종류의 문서 요소들도 먼저 Element로 나눈다는 것이다.
이는 상속의 관계인데, 하위 요소들은 상위 요소들의 클래스를 전부 상속받는다.
당장 DOM탐색기를 열어 HTML의 Body태그를 눌러 프로퍼티를 살펴보자.
(작성 중에 그냥 캡쳐)
어떤 클래스를 상속받고있는지는 Properties 탭을 통해 확인할 수 있다. (혹은 객체로 접근해서 __proto__를 확인하거나)
마치 저 그림 그대로다. body -> HTMLBodyElement -> Element -> Node -> EventTarget까지. Object는 JS의 모든 객체가 갖는 프로토타입이기 때문에 넘어가자.
각 프로토타입이 제공하는 메소드와 프로퍼티에 대해서는 모던 JS 튜토리얼에 친절하게 설명되어있다.
getElementById는 id 값을 통해 Element에 접근하는 방식이란 것을 이해할 수 있다.
위 그림에는 Element가 아닌 Node도 있는데, 이는 어떻게 접근하나 궁금할 수도 있는데, 그것은 Node 프로토타입에서 제공된 노드 값에 접근하는 프로퍼티들을 사용하면 된다. (모든 태그들과 내부 요소는 Node 프로토타입을 갖고 있을 테니, nextSibling, parentNode, previousSibling 등의 메소드를 사용해서 Node에 접근할 수 있다.)
이제 다시 DOM의 정의를 보자.
문서 객체 모델(The Document Object Model, 이하 DOM) 은 HTML, XML 문서의 프로그래밍 interface 이다. DOM은 문서의 구조화된 표현(structured representation)을 제공하며 프로그래밍 언어가 DOM 구조에 접근할 수 있는 방법을 제공하여 그들이 문서 구조, 스타일, 내용 등을 변경할 수 있게 돕는다. DOM 은 구조화된 nodes와 property 와 method 를 갖고 있는 objects로 문서를 표현한다. 이들은 웹 페이지를 스크립트 또는 프로그래밍 언어들에서 사용될 수 있게 연결시켜주는 역할을 담당한다.
BOLD 처리한 부분에 대한 설명을 의식의 흐름대로 나열해서 글의 방향성이 완벽하진 못하지만,
그래도 위 내용이 이해된다면, 아직은 어려운 DOM에 한 발자국 다가간게 아닐까 싶다.
왜, 옛날에 img를 버튼처럼 쓰면서 왜 img태그에는 disable 속성이 안들어가지? 하면서 의문을 가졌던 적이 있는데 form Element에만 disabled property가 존재한다는 답변을 봤었는데 그때는 이해 못했었지,
(아무 img태그의 프로퍼티)
이제 당당히 말할수 있다. HTMLImageElement를 펼쳐보면, disabled가 없을 것이고, 아무 input, textarea와 같은 form 요소들을 선택해서 HTMLInputElement의 프로퍼티에는 disabled가 있을 것이다.
치고나서 확인해봤는데 진짜다. 상당히 기분이 좋다. 배움의 기쁨!
이처럼 개발 관련 문서를 읽을 때 도움이 될 수밖에 없기에 DOM공부를 해둬야한다!
근데 나중에 더 찾아보니 어떤 브라우저는 img에 disabled 들어간다더라
이는 브라우저마다 DOM을 구현하는 방식이 다를 수 있음을 의미한다. DOM을 구현하는건 브라우저니깐.
처음 DOM을 공부하는 사람들이 이 말까지 이해할 수 있을까?