DOM 을 사용해서 조작해보자!!

참고서적: DOM - 잡았다, 요 돔!, DOM 을 깨우치다

DOM 을 보니 좀더 깊이 공부해야할것으로 느껴졌다. 아마 앞의 진도에서는 자바스크립트를 배우며 DOM 역시 같이 사용할 것이다. 더 깊숙히 공부하기 위해 해당 내용을 정리하며, 공부하도록 하자.
본 내용은 공부할 목적으로 적은 내용이므로, 틀린 내용이 포함될 수 있다.

DOM 은 다양한 많은 것들을 제공한다. 예를 들어 HTML 상의 내용을 동적으로 변경하던가, 아니면, 새로운 Element 를 만들던가!!

Node의 추가 및 생성 메서드을 사용해보자!!

Node 객체는 여러가지 생성 및 추가 메서드를 제공한다.
이러한 메서드를 잘 사용한다면, 자바스크립트를 사용해 HTML 을 다루는데 유용할 것이다.

처음으로 Element 를 생성해 보도록하자.
Element 를 만드는 객체는 Document 객체에서 제공한다.

createElement 와 createTextNode


document.createElementElement 를 만드는 Method 이다.
이때 Parameter 로는 만들 Element의 이름 을 넣어준다.

document.createTextNode 는 말 그대로 TEXT__NODE 를 만들어 주는 메서드 이다.
이때 Paramter 로는 만들 TEXT__NODE 의 이름이다.

div생성! 이라는 문자를 만들어보자.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>DOM</title>
</head>
<body>
   <div id="root"></div> 
   <script src="index.js"></script>
</body>
</html>
const div = document.createElement(`div`); // div element
const text = document.createTextNode(`생성!`) // Text__NODE

console.log(div.nodeType); // 1 <-- Node.ELEMENT_NODE
console.log(text.nodeType); // 3 <-- Node.TEXT_NODE

console.log(`div: ${div}`);  // div: [object HTMLDivElement]
console.log(`text: ${text}`);  // text: [object Text]

콘솔로 나오는 것을 보면 각 divtext 가 생성된 object 가 보일 것이다.
이는 해당 Elementtext 가 생성되었다고 봐도 무방하다.
이제 이 생성된 Node 를 사용해야 한다.
아직은 HTML 문서 상에 따로 추가하지 않은 상황이라 문서상에 표시는 되지 않을것이다.
이때, 필요한 메서드가 Element.appendChild 이다.

appendChild


Element.appendChild 는 해당 Element자식 요소 를 추가해주는 메서드 이다.
이때, appendChildParameter 로는 추가할 Node 를 넣어준다.

우리가 만든 divtextappendChild 해보자.
만든 div 의 내용은 비어 있으니, textdiv 안에 넣는다.
그런후 HTML 문서상의 #root 에 만든 div 를 추가해본다.

const div = document.createElement(`div`); // div element
const text = document.createTextNode(`생성!`); // Text__NODE
const $root = document.querySelector(`#root`);

// 생성된 div 안에 text 를 넣는다.
div.appendChild(text);
// text 가 들어간 div 를 #root 에 자식으로써 추가한다.
$root.appendChild(div);

이제 Browser 상 HTML 을 보면 #root<div>생성!</div> 가 자식으로써 포함하고 있는것을 볼 수 있다.

하지만 위의 내용이 마음에 들지 않는다.
생성! 이 아닌 Hello world 로 변경하고 싶다.
이때, 여러가지 방법이 존재하는데 이러한 방법에 대해서 이야기 해보자.

Element 및 Text 노드를 생성, 추가 하는 속성들


Elementtext 노드를 생성, 추가 하는 유용한 속성 총 4가지 존재한다.
다음의 테이블을 보도록 하자.

값을 가져오는 Element 속성

namedescription
innerHTML지정한 요소태그의 자식 태그의 값을 가져온다.
값 삽입시 지정한 요소의 내부에 HTML Node 를 생성한다.
outerHTML지정한 요소태그 및 자식태그 전부 가져온다.
값 삽입시 지정한 요소에 HTML Node 를 생성하여 갱신한다.
textContent지정한 요소의 텍스트를 가져온다.
공백 텍스트 역시 전부 포함해서 가져온다.
값 삽입시 Text 노드를 생성하여 갱신한다.
innerText
비표준
지정한 요소의 텍스트를 가져온다.
불필요한 공백을 제외하고 값을 가져온다.
값 사입시 Text 노드를 생성하여 갱신한다.
outerText
비표준
지정한 요소의 텍스트를 가져온다.
값 삽입시 지정한 엘리먼트 자체를 지정한 텍스트로 변경된다.

위 테이블의 속성을 살펴보자.

innerHTML


지정한 요소태그의 자식 태그의 값을 가져온다.
값 삽입시 지정한 요소의 내부에 HTML Node 를 생성한다.

일단 #root 를 가져와 innerHTML 로 값을 살펴본후, 값을 교체해보자.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>DOM</title>
</head>
<body>
  <div id="root">
    <div>hello world</div>
  </div> 
   <script src="index.js"></script>
</body>
</html>
const $root = document.querySelector("#root");
console.log($root.innerHTML); // <div>hello world</div>
$root.innerHTML = `<span>change world!!</span>`;
console.log($root.innerHTML); // <span>change world!!</span>

$root 내부의 값이 <div>hello world</div> 에서 <span>change world!!</span> 으로 변경된 것을 볼 수 있다.

명심해야 할 것은 문자열 로 넣었다고 해서 문자열 이 들어갈 것으로 생각하면 안된다.
innerHTML문자열 을 노드로 생성하고 DOM 에 추가한다.

outerHTML


지정한 요소태그 및 자식태그 전부 가져온다.
값 삽입시 지정한 요소에 HTML Node 를 생성하여 갱신한다.

#root 에서 outerHTML 을 가져와본 이후, 값을 변경해 본다.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>DOM</title>
</head>
<body>
  <div id="root">
    <div>hello world</div>
  </div> 
   <script src="index.js"></script>
</body>
</html>
console.log(document.querySelector(`#root`).outerHTML);
/*
<div id="root">
        <div>hello world</div>
</div>
*/
document.querySelector("#root").outerHTML = `<span id="root">change world!!</span>`;
console.log(document.querySelector("#root").outerHTML); // <span id="root">change world!!</span>

#root<span id="root">change world!!</span> 으로 변경된것을 볼 수 있다.
값을 가져올때는 자식 태그뿐 아니라 자기 자신의 태그까지 포함해서 가져오며, 값 변경역시 자기 자신의 태그 자체를 변경한다.

사용시 주의가 필요하다.

textContent


지정한 요소의 텍스트를 가져오며, 공백 텍스트 역시 전부 포함해서 가져온다.
값 삽입시 Text 노드를 생성하여 갱신한다.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>DOM</title>
</head>
<body>
  <div id="root">
    <div>hello world</div>
  </div> 
   <script src="index.js"></script>
</body>
</html>
console.log(document.querySelector(`#root div`).textContent); // "hello world"
document.querySelector("#root div").textContent = `<span>change world!!</span>`;
console.log(document.querySelector("#root div").textContent); // "<span id="root">change world!!</span>"

#root divtextContent"<span>change world!!</span>" 을 넣었다.
이전 innerHTML 과는 다르게 textContentText Node 만을 취급한다.
즉 위 문자열을 Text Node 로 만들기에, 출력해보면 Element Node 가 아닌 문자열로 삽입된다.

즉, 단순한 문자열 변경이라면 innerHTML 보다는 textContent 를 사용하는 것이 성능상 이점이 있을 것이다.

innerHTML 속성은 문자열내 에서 발견된 HTML 요소를 실제 DOM 노드로 변환하는 반면, textContent 는 텍스트 노드를 생성하는데만 사용 가능하다.
...중략....
innerHTML 이 무겁고 비싼 대가를 치르는 HTML 파서를 호출하는 데 비해, 텍스트 노드 생성은 간단하게 처리되므로, innerHTML 계열의 사용을 삼가야 한다.

출처: DOM 을 깨우치다.

innerText 와 outerText


innerTextinnerContent 와 비슷한 면이 많다. 하지만 비표준 이라고 한다. 많이 쓰기는 하는것 같은데 일단 비표준 이라하니 대신 innerContent 를 쓰는게 왠지 나을 것 같다.

innerTextouterText 둘다 비표준 이다.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>DOM</title>
</head>
<body>
  <div id="root">
    <div>    hello world    </div> <!-- 공백을 많이 넣어본다. -->
  </div> 
   <script src="index.js"></script>
</body>
</html>
console.log(document.querySelector(`#root div`).innerText); // "hello world"

 // 공백을 많이 넣어본다.
document.querySelector("#root div").innerText = `
  <span>    change world!!    </span> 
`;

console.log(document.querySelector("#root div").innerText); 
// "<span > change world!! </span>"

중복된 공백이 없는 것을 알 수 있다. 이것을 제외하고 실상 innerText 와 별다른 차이점이 없어 보이지만 명확한 내용은 mdn web docs Node.textContent 에서 보도록 하자.

내용중 한가지 걸리는것은 innerText 에서 CSS 값 변경시 최신 계산값을 반영하기 위해 reFlow 가 있을 수 있다는 점이다.
이러한 점은 성능상에 문제가 있을 수 있다고 생각이 든다.

다음은 outerText 이다.
outerText 는 선택된 NodeText Node 를 가져오거나, 지정한 Text Node 로 변경한다.

주의점은 outer 라는 문구가 있듯, 변경시 자식요소 가 아닌 선택된 요소 자체를 바꿔버린다.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>DOM</title>
</head>
<body>
  <div id="root">
    <div>    hello world    </div> <!-- 공백을 많이 넣어본다. -->
  </div> 
   <script src="index.js"></script>
</body>
</html>
console.log(document.querySelector(`#root div`).outerText); // "hello world"

 // 공백을 많이 넣어본다.
document.querySelector("#root div").outerText = `
  <span> change world!! </span> 
`;

console.log(document.querySelector("#root").innerText); 
// "<span > change world!! </span>"

보면 알겠지만 #root div"<span > change world!! </span>" 으로 변경되었다.
이제 #root 는 자식 div 가 아닌 "<span > change world!! </span>" 을 가진다.
outer* 로 되는 속성은 사용시 주의가 필요하다.

추가 ) Element.inertAdjacentHTML(position, text)

실상 속성에서 끝내려 했지만, 이 메서드는 알아두는 것이 좋을 것 같다.
굉장히 재미있는 메스드라는 생각이 든다.

Element.insertAdjacentHTML() 은 첫번째 인자로 position 을, 두 번째 인자로 추가할 Node 문자열을 text 로 받는다.

여기서 position 은 추가한 Node 를 어디에 추가할지 결정한다.

이 메서드는 position 이 중요한데 총 4가지가 존재한다.
text 인자는 마치 innerHTML 같이 문자열을 받고 Node를 생성해서 DOM 에 반영한다.

Position 종류

namedescription
beforebegin시작태그의 앞에 생성된 Node 를 추가
afterbegin시작태그의 뒤에 생성된 Node 를 추가
beforeend끝나는 태그의 앞에 생성된 Node 를 추가한다.
afterend끝나는 태그의 뒤에 생성된 Node 를 추가한다.
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>DOM</title>
</head>
<body>
  <div id="body">
  </div> 
   <script src="index.js"></script>
</body>
</html>
const $root = document.querySelector(`#body`);

$root.insertAdjucentHTML("beforebegin", `
	<div id="header">
        <div>Header</div>
    </div>
`);
$root.insertAdjucentHTML("afterbegin", `
	<span>Hello</span>
`);
$root.insertAdjucentHTML("beforeend", `
	<span>world</span>
`);
$root.insertAdjucentHTML("aftereend", `
	<div id="footer">
        <div>Footer</div>
    </div>
`);

console.log(document.querySelector(`body`).outerHTML);
/*
<body>
   
    <div id="header">
        <div>Header</div>
    </div>
    <div id="body">
	    <span>Hello</span>
	    <span>world</span>
    </div>
    <div id="footer">
        <div>Footer</div>
    </div>
 
   <script src="index.js"></script>
   
</body>
 */

HTML 문서가 갱신된것이 확인된다.
이렇게 javascript DOM 을 사용하면 정적으로 HTML을 작성하지 않고 동적으로 작동하게 만들 수 있다.

다음은 Node 객체 자체에서 제공하는 유용한 메서드들을 더 살펴보도록 하자!!

profile
익숙해지면 다 할수 있어!!

0개의 댓글