오늘은 DOM에 대해서 알아보자!
- 트리 구조인 DOM
트리 구조의 가장 큰 특징은 부모가 자식을 여러 개 가지고, 부모가 하나인 구조가 반복되는 점이다. 즉, 부모가 가진 하나 또는 여러 개의 자식 엘리먼트를 조회하는 코드를 작성한다면, 여러 번 반복해서 실행하는 코드가 필요하다.
DOM
- Document Object Model
- HTML 요소를 Object(JavaScript Object)처럼 조작(Manipulation)할 수 있는 Model
- JavaScript를 사용할 수 있으면, DOM으로 HTML을 조작할 수 있음
- HTML을 분석하여 HTML의 아주 작은 부분까지 접근할 수 있는 구조
- DOM을 이용하면 HTML로 구성된 웹 페이지를 동적으로 움직이게 만들 수 있다
- 조건문과 반복문, 배열, 객체를 활용하면 소셜 미디어에서 새롭게 생성되는 게시물을 저장하고 분류하는 작업을 구현할 수 있다
HTML에 Javascript를 적용하기 위해서는<script> 태그를 이용한다.
아래의 경우 HTML 파일과 같은 디렉토리에 존재하는 myScriptFile.js을 불러온다!
<script src="myScriptFile.js"></script>
웹 브라우저가 작성된 코드를 해석하는 과정에서 <script>요소를 만나면, 웹 브라우저는 HTML 해석을 잠시 멈춘다
HTML 해석을 잠시 멈춘 웹 브라우저는 <script>요소를 먼저 실행한다
<script> 요소는 등장과 함께 실행된다는 사실을 꼭 기억하자!

<script>요소를 추가하는 두 가지 대표적인 사례,<head> 요소에 추가하기</body>가 끝나기 전에 추가하기console.log('welcome JavaScript');
let msgElement = document.querySelector('#msg');
console.log(msgElement);
head의 경우
document.onload와 같은 로드 이벤트가 추가되어야 에러없이 작동된다.body의 경우
DOM 구조를 조회할 때에는 console.dir이 유용하다
console.dir은 console.log와 달리 DOM을 객체의 모습으로 출력
console.dir은 너무 많은 속성이 나타나기 때문에, 그래서 자식 요소를 검색하고 싶을 때 document.body.children 사용한다

id가 news-contents 인 div 요소는 <body> 요소의 자식 요소이다. 반대로 <body> 요소는 id가 news-contents div 요소의 부모 요소이다.
id가 news-contents 인 엘리먼트를 조회하려면, document.body.children 의 첫 번째 요소를 조회한다.
document.body 의 children을 조회할 때마다, 매번 document.body 로부터 찾아가는 일은 정말 번거롭기 때문에 따로 변수 선언을 해서 이 정보를 저장해두면, 주소를 참조하기 때문에 언제든지 접근할 수 있다.
그럼 이제 DOM을 이용하여 HTML Element를 추가해보자!
<div>요소를 만들어보자document.createElement('div')
자바스크립트에서 어떤 작업의 결과를 담으려면 어떻게 해야 할까? 변수를 선언하고 어떤 작업의 결과를 변수에 할당해야 한다. 여기서는 div element를 변수 tweetDiv 에 할당한다.
const tweetDiv = document.createElement('div')
하지만 지금은 만들어도 화면에 아무 변화가 일어나지 않는다.
그렇기 때문에 엘리먼트를 확인하려면 APPEND가 필요하다.
그럼 이제 HTML Element를 부모 노드에 포함해보자
append 라는 메서드를 사용해서, 변수 tweetDiv 를 <body> 에 넣어보자document.body.append(tweetDiv)
다음으로 HTML Element를 조회 해보자!
querySelector의 첫 번째 인자로 셀렉터(selector)를 전달하여 확인할 수 있다."div"), id("#tweetList"), class(.tweet) 세 가지가 가장 많이 사용된다.querySelector 에 '.tweet' 을 첫 번째 인자로 넣으면, 클래스 이름이 tweet 인 HTML 엘리먼트 중 첫 번째 엘리먼트를 조회할 수 있다.const oneTweet = document.querySelector('.tweet')
oneTweet 에 할당된 요소는 단 하나querySelectorAll 을 사용한다const tweets = document.querySelectorAll('.tweet')
[코드] querySelectorAll로 클래스 이름이 tweet 인 모든 HTML 요소를 유사 배열로 받아온다
querySelector와 querySelectorAll 만 알아도 대부분의 요소를 조회할 수 있다.const getOneTweet = document.getElementById('container')
const queryOneTweet = document.querySelector('#container')
console.log(getOneTweet === queryOneTweet) // true
[코드] getElementById와 querySelector로 각각 받아 온 container 요소는 하나의 요소
container의 맨 마지막 자식 요소로 tweetDiv를 추가해보자const container = document.querySelector('#container')
const tweetDiv = document.createElement('div')
container.append(tweetDiv)
이제 HTML Element를 변경하는 방법을 실습해보자
oneDiv라는 이름의 <div>요소를 만들어 보자const oneDiv = document.createElement('div');
console.log(oneDiv) // <div></div>
기존에 생성한 빈 div 태그를 업데이트하여, 보다 다양한 작업을 할 수 있다
먼저, textContent를 사용해서, 비어있는 div 엘리먼트에 문자열을 입력하자
oneDiv.textContent = 'dev';
console.log(oneDiv) // <div>dev</div>
class를 추가oneDiv.classList.add('tweet')
console.log(oneDiv) // <div class="tweet">dev</div>
const container = document.querySelector('#container')
container.append(oneDiv)
마지막으로 HTML Element를 삭제해보자
remove메서드를 사용해서 앞서 생성하고 추가한 tweetDiv를 삭제해보자const container = document.querySelector('#container')
const tweetDiv = document.createElement('div')
container.append(tweetDiv)
tweetDiv.remove() // 이렇게 append 했던 요소를 삭제할 수 있다.
[코드] id가 container인 요소 아래에 tweetDiv를 추가하고, remove로 삭제
그렇다면, 여러 개의 자식 요소를 지우려면, 어떻게 해야 할까?
innerHTML 을 이용하면, 아주 간단하게 모든 자식 요소를 지울 수 있다document.querySelector('#container').innerHTML = '';
[코드] id가 container인 요소 아래의 모든 요소를 지움
innerHTML 을 이용하는 방법은 분명 간편하고 편리한 방식이지만, innerHTML은 보안에서 몇 가지 문제를 가지고 있다.
removeChild 는 자식 요소를 지정해서 삭제하는 메서드const container = document.querySelector('#container');
while (container.firstChild) {
container.removeChild(container.firstChild);
}
removeChild 와 while 을 이용해 자식 요소를 삭제하면, 제목에 해당하는 H2 "Tweet List"까지 삭제된다const container = document.querySelector('#container');
while (container.children.length > 1) {
container.removeChild(container.lastChild);
}
또는 직접 클래스 이름이 tweet인 요소만 찾아서 지우는 방법도 있다
const tweets = document.querySelectorAll('.tweet')
tweets.forEach(function(tweet){
tweet.remove();
})
// or
for (let tweet of tweets){
tweet.remove()
}