JavaScript/DOM

DOM조작

yunajoe 2022. 11. 26. 20:05

DOM조작이란?

- 새로운 노드를 생성하여 DOM에 추가하거나 기존 노드를 삭제 또는 교체 하는 것을 말한다. 

- DOM 조작에 의해 DOM에 새로운 노드가 추가되거나 삭제되면 리플로우와 리페인트가 발생하는 원인이 되므로 성능에 영향을 준다. 

 

Element.prototype.innerHTML 

- setter와 getter 모두 존재하는 접근자 프로퍼티로써 요소 노드의 HTML 마크업을 취득하거나 변경한다 

- 요소노드의 innerHTML 프로퍼티를 참조하면 요소 노드의 콘텐츠영역(시작태그와 종료태그사이) 내에 포함된 모든 HTML 마크업을 문자열로 반환 

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
  <div id="foo">Hello <span>world!</span></div>
</body>
<script>
    // #foo 요소의 콘텐츠 영역 내의 HTML마크업을 문자열로 반환
    console.log(document.getElementById('foo').innerHTML); // Hello <span>world!</span>

	// HTML 마크업을 무시하고 텍스트만 반환
    console.log(document.getElementById('foo').textContent); // Hello world!

</script>
</html>

 

- innerHTML 프로퍼티에 문자열을 할당하면 요소 노드의 모든 자식 노드가 제거되고 할당한 문자열에 포함되어 있는 HTML 마크업이 파싱되어 요소 노드의 자식 노드로 DOM에 반영 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
  <div id="foo">Hello <span>world!</span></div>
</body>
<script>
    document.getElementById('foo').innerHTML = 'HI <span>there!</span>';
</script>
</html>

 

innerHTML 프로퍼티를 사용하면 HTML 마크업 문자열로 간단이 DOM 조작이 가능 

- 요소 노드의 innerHTML 프로퍼티에 할당한 HTML 마크업 문자열은 렌더링 엔진에 의해 파싱되어 요소 노드의 자식으로 DOM에 반영 

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <ul id="fruits">
        <li class="apple">Apple</li>
    </ul> 
</body>
<script>
    const fruits = document.getElementById('fruits'); 
    
    // 노드 추가 
    fruits.innerHTML += '<li class="banana">Banana</li>'; 
    
    // 노드 변경 
    fruits.innerHTML = '<li class="orange">Orange<li>';  

    // 노드 삭제 
    fruits.innerHTML = '';  
</script>
</html>

 

 

 

노드 추가
노드 변경

 

노드 삭제

 

 

 

단점: 

1. 사용자로부터 입력받은 데이터(untrusted input data)를 그대로 innerHTML 프로퍼티에 할당하는 것은 

크로스 사이트 스크립팅 공격(XSS: Cross-Site Scripting Attacks)에 취약하므로 위험하다 

HTML 마크업 내에 JS 악성 코드가 포함되어 있다면 파싱 과정에서 그대로 실행될 가능성이 있기 때문이다 

 

2. innerHTML 프로퍼티에 HTML 마크업 문자열을 할당할 경우 요소 노드의 모든 자식 노드를 제거하고 할당한 HTML 마크업 문자열을 파싱(parsing)하여 DOM을 변경 

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <ul id="fruits">
        <li class="apple">Apple</li>
    </ul> 
</body>
<script>
    const fruits = document.getElementById('fruits'); 
    // 노드 추가 
    // 아래 동작은 기존의 #fruits 요소의 모든 자식 노드(li.apple) 를 제거하고 새롭게 요소 노드 li.apple과 li.banana를 생성하여 #fruits 요소의 자식 요소로 추가 하는 것 
    // 즉, fruits.innerHTML = fruits.innerHTML + '<li class='banana'>Banana</li>'; 
    fruits.innerHTML += '<li class="banana">Banana</li>';  
</script>
</html>

3. 

 

 

 

리플로우(reflow)와 리페인트(repaint)

JS 코드에 DOM이나 CSSOM을 변경하는 DOM API가 사용된 경우 DOM이나 CSSOM이 변경된다 이 때 변경된 DOM과 CSSOM은 다시 렌더 트리로 결합되고 변경된 렌더 트리를 기반으로 레이아웃과 페인트 과정을 거

yunaaa0620.tistory.com