DOM은 브라우저에서 HTML, XML 문서를 구조적으로 나타내주는 인터페이스입니다. DOM은 document 객체에 구현되어 있으며, 자바스크립트 코드로 어디에서나 document 객체를 조회할 수 있습니다.
웹 페이지가 로드되면 브라우저는 페이지의 문서 객체 모델(DOM)을 만든다. HTML DOM은 노드 트리로 구성된다. 자바스크립트는 객체 모델을 사용하여 다음과 같은 작업을 통해 동적 HTML을 만들 수 있습니다.
노드와 요소의 차이는 무엇일까요? 노드와 요소가 같은 것으로 생각하기 쉬우나 노드는 요소, 텍스트, 주석 등을 모드 포함한 개념이며 요소는 HTML 태그(div, p, title 등)를 사용해서 작성된 노드의 타입 중에 하나일 뿐입니다.
우리는 어떻게 DOM을 조작하는 것이 가장 효율적인 방법일까요? DOM을 조작하는 방법에는 노드를 탐색하는 방법과 요소를 탐색하는 방법으로 나누어집니다. 요소를 탐색하는 방법을 사용하면 주석이나 텍스트 등을 제외한 요소만을 탐색할 수 있기 때문에 DOM을 조작할 때는 주로 element를 탐색하는 방법을 많이 사용합니다.
자바스크립트는 Object Collecton으로 form[], anchor[], layers[], images[] 등을 가지게 됩니다. 이들은 문서 내에서 여러개 존재하면 배열(유사배열)처럼 각 객체에 접근한다. 아래의 코드는 document의 image 컬렉션 사용하여 이미지를 변경하는 예시입니다.
<script>
function changeImage() {
document.images[0].src = "c.jpg"
}
</script>
<body>
<img src="a.jpg"> // <img src="c.jpg">로 변경
<img src="b.jpg">
</body>
DOM과 관련된 메소드는 너무 많지만 그 중에 제일 중요한 것이 CRUD와 관련된 메소드입니다. 우선적으로 많이 사용하는 메소드를 정리하였습니다.
HTML 요소를 생성합니다. 생성한 HTML 요소는 메모리에 저장된다. 아래의 코드처럼 button 요소를 생성하여 텍스트를 추가하거나 속성값을 변경하는 것이 가능합니다.
const button = document.createElement("button") // 버튼 생성
button.textContent =click me;
console.log(button) // <button>click me</button>
하나의 노드는 트리구조에서 한 번만 추가가 가능합니다. 예를 들어 prpend로 부모의 첫번째 자식 노드로 추가한 후 append를 사용하면 첫번째 자식이었던 노드가 마지막 자식으로 변경됩니다.
노드 객체나 문자열을 부모 노드 마지막 자식 노드로 추가합니다. 또한 한번에 여러 개의 자식 요소를 추가하는 것이 가능하며, 리턴 값을 반환하지 않습니다.
const div = document.createElement('div');
const span = document.createElement('span');
document.body.append(div, 'hello', span); // undefined
/* 변경된 DOM 구조
<body>
<div></div>
hello
<span></span>
</body>
*/
노드 객체나 문자열을 부모 노드의 첫 번째 자식 노드로 추가합니다. 또한 한번에 여러 개의 자식 요소를 추가하는 것이 가능하며, 리턴 값을 반환하지 않습니다.
const div = document.createElement('div');
const span = document.createElement('span');
document.body.append(div, 'hello', span); // undefined
/* 변경된 DOM 구조
<body>
<div></div>
hello
<span></span>
</body>
*/
노드 객체를 선택한 부모 노드의 마지막 하위 노드로 추가하며, 노드 객체를 리턴 값으로 반환합니다.
const div = document.createElement('div');
const span = document.createElement('span');
document.body.appendChild(div) // <div></div>
/* 변경된 DOM 구조
<body>
<div></div>
<span></span>
<div></div>
</body>
*/
노드 객체를 조회는데 여러가지 메소드가 있지만 querySelector, querySelectorAll 두 가지 메소드만 알면 대부분의 요소를 조회할 수 있습니다.
특정 조건의 HTML 요소를 선택합니다.
<body>
<div class='container'></div>
</body>
const container = document.qurryselector('.container')
// container 클래스를 가지는 요소를 변수 container에 할당
특정 조건의 노드 객체요소를 포함한 배열을 반환합니다. 정확히는 유사 배열(Array like Object)의 형태로 for문을 사용할 수 있습니다.
<body>
<div class='intro'>hello</div>
<div class='intro'>world</div>
<div class='section'>foo</div>
</body>
const intro = document.qurryselectorAll('.intro') // intro 클래스를 가지는 요소를 변수 intro에 할당
intro.textContent = 'intro' // 선택된 요소의 텍스트를 intro로 변경
const div = document.createElement('div');
div.classList.add("abc") // 'abc' 라는 클래스 추가
console.log(div); //<div class='abc'></div>
div.classList.add("efg") // 'egf' 라는 클래스 추가
console.log(div); //<div class='abc efg'></div>
div.classList.remove("abc") // 'abc' 클래스 제거
console.log(div); //<div class='efg'></div>
노드 객체의 id값을 생성하거나 변경할 수 있있습니다.
<body>
<div class='container'></div>
</body>
const container = document.querrySelector('container')
container.id = 'a';
console.log(container); // <div class='container' id='a'></div>
container.id = 'b';
console.log(container); // <div class='container' id='b'></div>
노드 객체의 속성값을 변경할 수 있습니다. 첫 번째 인자로 속성의 이름을 받고 두번째 인자로 변경할 값을 넣어줍니다.
<body>
<div class='container'></div>
</body>
const container = document.querrySelector('container')
container.style("color : black);
console.log(container); // <div class='container' style='color : black'></div>
container.setAttribute('style', 'color : blue')
console.log(container); // <div class='container' style='color : blue'></div>
노드 객체의 속성값을 제거할 수 있습니다.
<body>
<div class='container'></div>
</body>
const container = document.querrySelector('container')
container.style("color : black);
console.log(container); // <div class='container' style='color : black'></div>
container.removeAttribute('style')
console.log(container); // <div class='container'></div>
메소드를 호출한 노드 객체를 제거합니다.
<body>
<div class='intro'>hello</div>
<div class='section'>world</div>
<div class='footer'>foo</div>
</body>
const world = document.querrySelector('section')
world.remove() // <div class='section'>world</div> 삭제
/* 변경된 DOM 구조
<body>
<div class='intro'>hello</div>
<div class='intro'>world</div>
</body>
*/
선택한 부모의 자식 노드 객체를 제거합니다.
<body>
<div class='intro'>hello</div>
<div class='section'>world</div>
<div class='footer'>foo</div>
</body>
const world = document.querrySelector('section')
body.removeChild(world) // <div class='section'>world</div> 삭제
/* 변경된 DOM 구조
<body>
<div class='intro'>hello</div>
<div class='intro'>world</div>
</body>
*/