본문 바로가기
My Wiki (CodesStates)/DOM

(1-2) DOM으로 HTML 조작하기

by Esoolgnah 2021. 8. 5.
728x90

 

CREATE - createElement

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

document.createElement('div')

[코드] 새로운 div element 를 만든다.

 

 

[그림] 크롬 개발자도구의 콘솔 탭에서 새로운 div 엘리먼트를 생성해보자.

 

 

자바스크립트에서 어떤 작업의 결과를 담으려면 어떻게 해야 할까? 변수를 선언하고 어떤 작업의 결과를 변수에 할당한다. 여기서는 div element를 변수 tweetDiv 에 할당한다.

 

const tweetDiv = document.createElement('div')

[코드] 새롭게 생성한 div element를 변수에 할당한다.

 

 

아직 화면에 변화가 없는 게 당연하다. tweetDiv 라는 요소는 현재 공중부양 중이기 때문이다. 다음 그림을 보며 설명해보겠다. DOM의 구조를 나타내는 트리 구조를 하나 그린다. 아무것도 연결이 되어있지 않은 하나의 노드를 그린다.

 

[그림] createElement 메소드로 생성된 엘리먼트는 공중에 떠있는 상태이다.

 

 

위 그림처럼 공중에 떠있는 엘리먼트를 확인하기 위해서는 APPEND 해야한다. APPEND 를 이용해 실제 웹 페이지 상에도 보이는 것을 확인할 수 있다. 이어지는 콘텐츠 APPEND에서, tweetDiv 를 트리 구조에 연결해보겠다.

 

 

APPEND - append, appendChild

CREATE에서 만든 tweetDiv 라는 변수는 아직 공중부양을 하고 있다. append 메소드를 사용해서 변수 tweetDiv 를 body에 넣어보자.

document.body.append(tweetDiv)

[코드] 변수 tweetDiv 에 담긴 새로운 div 엘리먼트를 body 엘리먼트에 append 한다.

 

 

아직 새롭게 생성한 div 엘리먼트에 아무런 내용을 입력하지 않아서 보이는 내용이 없을 것이다. 크롬의 개발자도구 Elements 탭에서 내용을 확인해보자.

 

[그림] 개발자도구 Elements 탭에서 변경사항을 확인할 수 있다.

 

 

READ - querySelector, querySelectorAll

DOM으로 HTML 엘리먼트의 정보를 조회하기 위해서는 querySelector의 첫 번째 인자로 셀렉터(Selector)를 전달하여 확인할 수 있다. 셀렉터로는 HTML 태그("div"), id("#tweetList"), class(.tweet) 세 가지가 가장 많이 사용된다.

참고로 querySelector는 셀렉터를 조회한다는 의미를 가지고 있다. query의 의미가 "질문하다"라는 것을 알고 있다면 역할을 쉽게 유추하실 수 있다. 이 query라는 단어는 개발자 간에 "ㅇㅇㅇ를 조회한다"라는 의미를 "쿼리를 날리다"라는 jargon(특정 영역에서만 사용되는 단어)로 굳어졌기 때문에 알고 있어야 한다.

 

 

querySelector

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

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

[코드] querySelector 로 클래스 이름이 tweet인 HTML 엘리먼트를 조회한다.

 

 

HTML 문서에는 클래스 이름이 tweet 인 엘리먼트가 여러 개 있는 데, 변수 oneTweet 에 할당된 엘리먼트는 단 하나이다. 여러 개의 엘리먼트를 한 번에 가져오기 위해서는, querySelectorAll 을 사용한다. 이렇게 조회한 HTML 엘리먼트들은 배열처럼 for문을 사용하실 수 있다. 주의하자! 앞서 조회한 HTML 엘리먼트들은 배열이 아니다. 이런 '배열 아닌 배열'을 유사 배열, 배열형 객체 등 다양한 이름으로 부른다. 정식 명칭은 Array-like Object 이다. 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)

[코드] tweetDiv를 container의 마지막 자식 요소로 추가한다.

 

 

[그림] tweetDiv를 container의 마지막 자식 요소로 추가한 모습

 

[그림] id 가 container인 엘리먼트의 마지막 자식 요소로 tweetDiv를 추가한다.

 

새롭게 추가된 tweetDiv 는 별도의 class 가 지정되어 있지 않아, CSS를 이용한 스타일링이 적용되지 않는다. 새롭게 생성한 tweetDiv 에 class 를 붙여 스타일링을 적용해보자.

 

 

UPDATE - textContent, classList.add

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

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

[코드] textContent를 이용해 문자열을 입력해보자.

 

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

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

[코드] classList.add 를 이용해 'tweet' 클래스를 추가한다.

 

 

 

 

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

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

[코드] append 를 이용해 container의 자식 요소에 oneDiv 를 추가한다.

 

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

 

[그림] container에 oneDiv를 추가한다.

 

 

 

DELETE - remove, removeChild

삭제하는 방법을 학습해보겠다. 삭제하는 방법에도 여러 가지가 있다. 먼저 삭제하려는 엘리먼트의 위치를 알고 있는 경우에 사용하는 방법이다. 앞서 생성하고 추가한 tweetDiv 를 삭제한다. remove 메소드를 사용해보자.

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 는 자식 엘리먼트를 지정해서 삭제하는 메소드입니다. 모든 자식 엘리먼트를 삭제하기 위해, 반복문(while, for, etc.)을 활용할 수 있다. 다음의 코드는 자식 엘리먼트가 남아있지 않을 때까지, 첫 번째 자식 엘리먼트를 삭제하는 코드이다.

const container = document.querySelector('#container');
while (container.firstChild) {
  container.removeChild(container.firstChild);
}

[코드] container의 첫 번째 자식 엘리먼트가 존재하면 첫 번째 자식 엘리먼트를 제거한다.

 

[그림] container의 첫 번째 자식 엘리먼트가 존재하면, 첫 번째 자식 엘리먼트를 제거한다.

 

 

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

const container = document.querySelector('#container');
while (container.children.length > 1) {
  container.removeChild(container.lastChild);
}

[코드] container의 자식 엘리먼트가 1개만 남을 때까지, 마지막 자식 엘리먼트를 제거한다.

 

 

또는 직접 클래스 이름이 tweet인 엘리먼트만 찾아서 지우는 방법도 있다.

const tweets = document.querySelectorAll('.tweet')
tweets.forEach(function(tweet){
    tweet.remove();
})
// or
for (let tweet of tweets){
    tweet.remove()
}

[코드] 클래스 이름이 tweet인 엘리먼트만 찾아서 제거한다.

 

 

[그림] 클래스 이름이 tweet인 모든 엘리먼트를 제거한다.

 

 

 

 

 

반응형

'My Wiki (CodesStates) > DOM' 카테고리의 다른 글

(1-1) DOM 이해하기  (0) 2021.07.13

댓글