DOM 조작 방법

hyuk(정윤혁)·2022년 8월 23일
0

Today I Learned

목록 보기
35/38

DOM이란 무엇인가?

  • Document Object Model의 약자로, HTML 요소를 Object(JavaScript Object)처럼 조작(Manipulation)할 수 있는 Model입니다.

  • 자바스크립트를 사용할 수 있으면, DOM으로 HTML을 조작할 수 있습니다.
    HTML을 조작할 수 있다는게 무슨 뜻일까? HTML을 철저히 분석하여 그 내용으로 HTML의 아주 작은 부분까지 접근할 수 있는 구조(Model; Structure)를 만들어 냈습니다. 이렇게 만들어진 구조를 이용하여 HTML로 구성된 웹 페이지를 동적으로 움직이게 만들 수 있습니다. 조건문과 반복문, 배열, 객체를 활용하면 SNS에서 새롭게 생성되는 게시물을 저장하고 분류하는 작업을 할 수 있습니다.

DOM으로 HTML 조작하기

  • document 객체에는 많은 속성과 메소드가 존재합니다.
  • CRUD를 먼저 이해하는 것이 새로운 언어를 가장 빠르게 학습하는 방법입니다. (CRUD를 이해한 다음에는 다양한 trivia를 알아야 합니다.)

CREATE - createElement

DOM으로 HTML을 조작하는 방법 중 가장 기초적인, 새로운 element를 만드는 방법입니다.

  • 크롬 개발자도구의 콘솔 탭에서 새로운 div 엘리먼트를 생성합니다.

document.createElement('div')

  • div element를 변수 tweetDiv 에 할당합니다.

const tweetDiv = document.createElement('div')

새롭게 생성한 div element를 변수에 할당합니다. 화면에 어떤 변화도 나타나지 않습니다. 아직 화면에 변화가 없는 게 당연합니다. tweetDiv 라는 요소는 현재 공중부양 중입니다. 다음 그림을 보며 설명합니다. DOM의 구조를 나타내는 트리 구조를 하나 그립니다. 아무것도 연결이 되어있지 않은 하나의 노드를 그립니다.

  • 공중에 떠있는 엘리먼트를 확인하기 위해서는 APPEND 해야합니다. APPEND 를 이용해 실제 웹 페이지 상에도 보이는 것을 확인할 수 있습니다.

APPEND - append, appendChild

append 라는 메소드를 사용해서, 변수 tweetDiv 를 body 에 넣어보겠습니다.

  • 변수 tweetDiv에 담긴 새로운 div 엘리먼트를 body 엘리먼트에 append 합니다.

document.body.append(tweetDiv)

  • 개발자도구 Elements 탭에서 변경사항을 확인할 수 있습니다.

READ - querySelector, querySelectorAll

자바스크립트에서 원시 자료형인 변수의 값을 조회하기 위해서는, 변수의 이름으로 직접 조회할 수 있습니다. 참조 자료형인 배열은 index를, 객체는 key를 이용해 값을 조회할 수 있습니다. 그러나 DOM은 조금 특별한 방법을 사용해야 합니다. DOM으로 HTML 엘리먼트의 정보를 조회하기 위해서는 querySelector의 첫 번째 인자로 셀렉터(Selector)를 전달하여 확인할 수 있습니다. 셀렉터로는 HTML 태그("div"), id("#tweetList"), class(.tweet) 세 가지가 가장 많이 사용됩니다.

querySelector

  • querySelector 에 '.tweet' 을 첫 번째 인자로 넣으면, 클래스 이름이 tweet 인 HTML 엘리먼트 중 첫 번째 엘리먼트를 조회할 수 있습니다.

const oneTweet = document.querySelector('.tweet')

  • HTML 문서에는 클래스 이름이 tweet 인 엘리먼트가 여러 개 있는 데, 변수 oneTweet 에 할당된 엘리먼트는 단 하나입니다. 여러 개의 엘리먼트를 한 번에 가져오기 위해서는, querySelectorAll 을 사용합니다. 이렇게 조회한 HTML 엘리먼트들은 배열처럼 for문을 사용하실 수 있습니다.

앞서 조회한 HTML 엘리먼트들은 배열이 아닙니다. 이런 '배열 아닌 배열'을 유사 배열, 배열형 객체 등 다양한 이름으로 부릅니다. 정식 명칭은 Array-like Object 입니다.

const tweets = document.querySelectorAll('.tweet')
// querySelectorAll로 클래스 이름이 tweet 인 모든 HTML 엘리먼트를 유사 배열로 받아옵니다.

  • querySelector와 querySelectorAll 만 알아도 대부분의 엘리먼트를 조회할 수 있습니다. 하지만 get으로 시작하는 DOM 조회 메소드를 볼 수도 있습니다. 이런 메소드는 querySelector 와 비슷한 역할을 하는 오래된 방식이라고만 이해하면 됩니다. 만약 이전 버전의 브라우저(인터넷 익스플로러) 호환성을 신경 써야 한다면, 이런 옛날 방식을 사용해야 할 수도 있습니다.

const getOneTweet = document.getElementById('container') const queryOneTweet = document.querySelector('#container') console.log(getOneTweet === queryOneTweet) // true
// getElementById와 querySelector로 각각 받아 온 container 요소는 하나의 요소입니다.

  • CREATE에서 생성한 div 엘리먼트를 container에 넣을 준비를 마쳤습니다. 다음 코드를 입력하면, container의 맨 마지막 자식 엘리먼트로 tweetDiv를 추가합니다.

const container = document.querySelector('#container') const tweetDiv = document.createElement('div') container.append(tweetDiv)

id가 container인 엘리먼트의 마지막 자식 요소로 tweetDiv를 추가합니다.

UPDATE - textContent, classList.add

UPDATE에서는 기존에 생성한 빈 div 태그를 업데이트하여, 보다 다양한 작업을 할 수 있습니다. textContent 를 사용해서, 비어있는 div 엘리먼트에 문자열을 입력합니다.

  • textContent를 이용해 문자열을 입력합니다.

console.log(oneDiv) // <div></div>
oneDiv.textContent = 'dev';
console.log(oneDiv) // <div>dev</div>

  • 앞서 생성한 div 엘리먼트를 container에 append 했을 때, CSS 스타일링이 적용되지 않았습니다. CSS 스타일링이 적용될 수 있도록, div 엘리먼트에 class를 추가합니다.

oneDiv.classList.add('tweet')
console.log(oneDiv) // <div class="tweet">dev</div>

  • 생성한 엘리먼트에 텍스트를 채웠고, 클래스를 추가하여 스타일링을 적용했습니다. 이번에는 append를 이용해 container의 자식 요소로 추가합니다.

const container = document.querySelector('#container') container.append(oneDiv)

  • 새롭게 추가한 엘리먼트는 클래스 tweet 의 스타일이 적용된 상태로 출력됩니다.

DELETE - remove, removeChild

  • 삭제하는 방법에도 여러 가지가 있습니다. 먼저 삭제하려는 엘리먼트의 위치를 알고 있는 경우에 사용하는 방법입니다. 앞서 생성하고 추가한 tweetDiv 를 삭제합니다. remove 메소드를 사용할 수 있습니다.
const tweetDiv = document.createElement('div')
container.append(tweetDiv)
tweetDiv.remove() // 이렇게 append 했던 엘리먼트를 삭제할 수 있다.


tweetDiv를 container의 자식으로 추가한 뒤, 삭제합니다.

  • 여러 개의 자식 엘리먼트를 지우고 싶을 땐, innerHTML 을 이용하면, 모든 자식 엘리먼트를 지울 수 있습니다.

document.querySelector('#container').innerHTML = '';

innerHTML 을 이용하는 방법은 분명 간편하고 편리한 방식이지만, innerHTML은 보안에서 몇 가지 문제를 가지고 있습니다. 이 방법을 대신할 다른 메소드를 사용합니다. removeChild 는 자식 엘리먼트를 지정해서 삭제하는 메소드입니다. 모든 자식 엘리먼트를 삭제하기 위해, 반복문(while, for, etc.)을 활용할 수 있습니다. 다음의 코드는 자식 엘리먼트가 남아있지 않을 때까지, 첫 번째 자식 엘리먼트를 삭제하는 코드입니다.

while (container.firstChild) {
  container.removeChild(container.firstChild);
}

removeChild 와 while 을 이용해 자식 요소를 삭제하면, 제목에 해당하는 H2 "Tweet List"까지 삭제됩니다. 이를 방지하기 위한 방법은 여러 가지가 있습니다. 자식 요소가 담고 있는 문자열을 비교해 "Tweet List"만 남기거나, 새로운 변수를 생성하고 Tweet List를 할당해뒀다가 반복문이 끝난 뒤에 새롭게 추가할 수도 있습니다. 또는 자식 엘리먼트를 하나만 남기게 할 수도 있습니다.

const container = document.querySelector('#container');
while (container.children.length > 1) {
  container.removeChild(container.lastChild);
}
const tweets = document.querySelectorAll('.tweet')
tweets.forEach(function(tweet){
    tweet.remove();
})
// or
for (let tweet of tweets){
    tweet.remove()
}
profile
노션 저장소는 🏠홈버튼 눌러주세요 !

0개의 댓글