본문 바로가기

Frontend Study

[FE Bootcamp] 16일차_DOM

오늘은 DOM에 대해 학습하였다. 학교에서 웹 프로그래밍을 배울 때 잠깐 배우긴 했었지만 시간 관계상,.,.,.그렇게 자세히 배우진 않았었다. 그래서 조금 어려울 것 같다는 생각이 들었으나, 다행히 몇몇 용어가 다른 것을 제외하면 크게 달라진 부분은 없어 다행이었다.

 

1. Dom이란?

DOM은 Document Object Model의 약자로, HTML의 여러 요소들을 자바스크립트의 객체(Object)처럼 조작할 수 있는 모델을 말한다. 

일단 Document 부터가 '웹 페이지'를 나타내는 객체이고, 우리가 웹 페이지에서 사용하는 모든 요소 및 기능들은 Document 객체의 프로퍼티라고 볼 수 있다. 이를 알고 있으면 뒤 내용들을 이해하기 한결 수월해 질 것 같다.

 

DOM을 이용하면, HTML 요소들에 자바스크립트 문법을 적용할 수 있게 된다. 때문에 보다 동적인 웹 페이지 운용이 가능하며, 반복문, 조건문 등을 통해 훨씬 간편하게 페이지 관리를 할 수도 있다.

 

 

 

DOM은 트리 구조를 가지고 있다. 각 태그들은 '노드'라고 불리는 선으로 연결되어 있고, 자식 태그는 부모 태그의 속성을 물려받는다는 특징이 있다.

 

2. HTML에 JS 적용하기

우리는 CSS를 HTML에 적용하기 위해 <style>이라는 태그를 사용했었다. 마찬가지로, 자바스크립트 역시 <script>라는 별도의 태그가 필요하다.

하지만 무조건 <head> 태그 안에 위치해야 하는 <style> 태그와는 다르게, <script> 태그는 어디에든 위치할 수 있다

 

See the Pen Untitled by KingGyeongHoo (@KingGyeongHoo) on CodePen.

 

 

See the Pen Untitled by KingGyeongHoo (@KingGyeongHoo) on CodePen.

 

 

다음 두 코드를 비교해 보자. 위 코드는 <script>가 <head> 태그 안에, 아래 코드는 <body> 태그 맨 아래에 들어가 있다.

 

두 코드의 결과. 다르게 나오는 것을 확인할 수 있다.

 

단지 <script>의 위치만 바뀌었을 뿐인데 왜 결과가 다르게 나올까?

이는 웹 브라우저에서 코드를 해석할 때, <script> 태그를 만나면 바로 <script> 태그에 들어있는 자바스크립트 파일을 실행 하기 때문이다. 

 

위 코드의 경우, <script>가 <body>보다 위에 있는 <head> 안에 포함되어 있기 때문에, 브라우저가 <div> 태그를 확인하기 전에 이미 <script>가 실행 된다. 그러므로, js에서 document.querySelector('.message')(클래스가 message인 태그 찾기) 라는 명령을 실행해도, <body>를 들른 적이 없으므로 태그를 찾을 수가 없는 것이다.

 

반면 아래 코드는 <script>가 <body> 아래에 있다. 반대로 <div> 태그를 먼저 확인 하고 js가 실행되기 때문에 document.querySelector('.message')를 정상적으로 실행할 수 있는 것이다.

 

3. DOM 다루기

DOM에는 CRUD(Create, Read, Update, Delete)라는 메서드가 존재한다. 이름에서 알 수 있듯 각각 DOM 생성, 가져오기, 업데이트, 삭제이며, 추가로 한 DOM에 다른 DOM을 추가하는 Append까지를 기본 메서드라고 한다.

 

위에서 document를 하나의 객체라고 하였고, DOM을 다루기 위한 여러 메서드들은 document 객체의 프로퍼티이기 때문에, Dot Notation을 사용한다. 따라서 앞에 반드시 document.메서드 를 붙여주어야 한다.

 

See the Pen Untitled by KingGyeongHoo (@KingGyeongHoo) on CodePen.

 

 

 

이 화면으로 함께 알아 보도록 하겠다.

A. Create

Create는 새로운 DOM 객체를 생성하는 기능이다. 

 

document.createElement('태그명')

create를 통해 <body> 태그에 'div'라는 태그를 새롭게 만들었다. 하지만 아직 눈에 띄는 변화는 없다.

위에 설명했듯 DOM은 트리 구조를 가지고 있는데, 현재 새롭게 만든 <div> 태그는 아직 다른 태그와 연결되지 않았기 때문이다. 

 

기존 DOM 구조와 새로 추가된 div 태그

 

B. Append

Append는 위에서 create로 만든 태그를 다른 태그와 연결해준다.

 

document.붙이고 싶은 태그.append(붙일 태그)

 

append 태그를 사용하기 위해서는, 변수에 생성한 태그를 할당해 주는 것이 편하다.

괄호 안에 아예 document.createElement()를 통째로 넣는 방법도 있지만, 이는 불편할 뿐더러 변수에 할당하는 방법이 나중에 등장할 Update나 Delete 과정에서도 편리하기 때문이다.

 

let newDiv = document.createElement('div')
document.body.append(newDIV)

 

body 태그 안에 새로운 div 태그가 생긴 것을 볼 수 있다.

 

C. Read

Read는 querySelector를 이용해 HTML 태그들을 가져 오는 것을 말한다. 

원시 자료형의 경우 변수명, 배열은 index, 객체는 key를 통해 값을 조회할 수 있듯, DOM은 querySelector를 이용하여 HTML 태그들을 조회할 수 있다. 

 

document.querySelector('찾고자 하는 태그')
// ( ) 내부에 들어갈 수 있는 것
// 태그 -> 태그명
// id -> #id
// class -> .class

 

querySelector는 태그명, id, class를 조회할 수 있으며, 각 요소에 접근하는 법은 CSS에서 스타일을 넣는 것과 동일하다.

 

querySelector로 clss='box'를 조회한 결과

 

querySelector를 통해 box라는 클래스를 가진 태그들을 조회하였다. 하지만 class='box'인 태그는 4개인데, 출력된 것은 맨 위의 태그 뿐이었다. 

이처럼 querySelector는 여러개의 태그들 중 가장 위에 있는 태그 하나만을 나타낸다. 

여러개의 태그를 모두 나타내고 싶다면 querySelectorAll을 사용하면 된다.

 

querySelector로 조회한 결과

 

이때, 태그들은 배열의 형태로 나타나지만, isArray를 사용해 보면 배열이 아니라고 나온다.

이들을 '유사배열'이라고 하며, 반복문을 사용할 수는 있지만 배열에 사용 가능한 일부 메서드들은 사용할 수 없다는 차이가 있다. 

다만 배열의 형태를 가지고 있기 때문에 인덱스를 통해 각 요소에 접근하는 것은 가능하다.

querySelector 역시 변수에 할당 가능하며, querySelector를 할당한 변수는 document.을 사용하지 않아도 된다는 편리함이 있다.

 

let newDiv = document.createElement('div')
let container = document.querySelector('#container')
container.append(newDiv)

 

container 안에 새로운 div가 생겼다.

 

getElementById라던가, getElementsByClassName 등의 방법으로 조회하는 방법도 있지만, 좀 옛날 방식이라고 한다.

 

D. Update

이쯤에서 웹 페이지를 한번 보자. 달라진 것이 있을까?

 

놀랍게도 없음!

 

분명 container 안에 <div>를 추가하기까지 했는데 왜 달라진 것이 없는 것일까??

이는 아직 <div> 태그의 내용물이 없어서 그렇다.

어떤 텍스트도 없고, 클래스, 스타일 등의 요소도 없기 때문에 그냥 빈 태그 상태로 남아있는 것이다. 

이런 빈 태그의 내용을 채워 주는 과정이 바로 Update이다.

 

먼저 텍스트를 채워넣어보자

 

document.채우고 싶은 태그.texContent = '채워넣을 콘텐츠'

 

우리는 새롭게 만든 태그 안에 'Fuel'이라는 글자를 채우고 싶다. 

 

let newDiv = document.createElement('div')
let container = document.querySelector('#container')
container.append(newDiv)
newDiv.textContent = 'Fuel'

 

맨 끝에 Fuel이라는 글자가 생겼다.

 

헌데 아직은 글자만 생긴 상태이고, 다른 box들처럼 가운데 정렬이나 테두리가 적용되어 있지 않다. 

잘 생각해보면, CSS를 통해 클래스명이 'box'인 태그들에만 정렬이나 테두리를 적용해 주었었다.

그렇다면, 우리가 새로 만든 <div>에도 box라는 클래스명을 부여해주면 되는 것이다.

 

클래스를 부여할 태그.classList.add('클래스명')
클래스를 부여할 태그.className = '클래스명'
id를 부여할 태그.id = 'id'명

 

두 방법 모두 사용 가능하다. 다만 idList라는 메서드는 없는 것 같다.

그럼 이제 새로운 <div>에 클래스명을 부여해보자

 

let newDiv = document.createElement('div')
let container = document.querySelector('#container')
container.append(newDiv)
newDiv.textContent = 'Fuel'
newDiv.classList.add('box')

 

완벽히 같은 새 태그가 추가되었다.

 

E. Delete

새 태그를 추가했으면 지우는 방법도 알아야 한다.

 

//태그를 하나만 지우고 싶을 때
지우고 싶은 태그.remove()

//태그를 여러개 지우고 싶을 때
document.querySelector('상위 태그').innerHTML = '' //보안 문제 O

 

이외에도 반복문과 removeChild를 이용한 삭제, for-of를 이용한 삭제, 클래스명을 직접 찾아 삭제하는 방법 등 여러가지 방법들이 존재한다.

 

fuel이 삭제되었다

 

innerHTML을 이용해 삭제하는 방법

 

for문을 이용해 삭제하는 방법

 

 

과거 학교에서 수업을 들을 때, 새로운 태그를 추가하는 방법을 몰라 얼레벌레 '이건 저희가 배운 수준에선 안됩니다'라고 퉁쳐서 낸 적이 있는데, 알고보니 그때 배운 내용으로도 가능한 것이었다 카더라.,.,.,조교님 죄송해요,.,.

그리고 나는 getElementsBy로 Read하는 방법을 배웠었는데, 이게 꽤나 옛날 버전이라는 것에 놀랐다. 강의 업데이트좀 해라 동X대!! 일해라 X국대!!

여튼,.,,.,.오늘도 정말 알차게 배우고 간다. 내일까지 쭉 과제가 있는데, 대충 보아하니 벌써부터 어질어질 하지만,,.,. 열심히 해봐야지

과제를 미리 하지 말라고 해서 심화 과정으로 알아보라고 하는 내용을 알아보러 가려 한다. 

아무튼 파이팅~~!!