동적인 웹 사이트를 만들기 위해 필요한 언어인 JavaScript
는 어떻게 웹을 동적으로 만들어줄 수 있는 걸까?
우선 웹을 동적으로 변환시키기 전에 HTML과 CSS의 요소를 받아와야 하는데, 이때 필요한 게 DOM
이다. DOM
을 통해 HTML/CSS의 요소에 접근한 JavaScript
는 다양한 프로퍼티와 메소드를 활용해 요소를 수정하며 웹 페이지를 동적으로 동작하게 만든다. DOM
에 대한 자세한 설명은 아래를 참고하자.
'Document Object Model' 의 약자인 DOM
은 직역하자면 문서 객체 모델
이다. 문서 객체란 <html>
이나 <body>
같은 HTML 요소들이 자바스크립트가 이용할 수 있는 객체로 만들어진 것을 말한다.
이 DOM은 자바스크립트 명령에 의해 속성이나 디자인, 배치 등이 제어될 수 있다.
웹 페이지를 만들 때 자바스크립트와 DOM이 한 몸처럼 사용되다보니, 자바스크립트 안에 DOM이 있다거나 DOM을 자바스크립트로만 다룰 수 있다는 오해를 빚기도 한다. (나다) 그 이유는 현재 웹 브라우저에서 DOM을 조작하는 언어는 자바스크립트 뿐이기 때문이다.
그러나 파이썬에서도 BeautifulSoup
라는 대표적인 DOM 트리 파싱 라이브러리가 있듯이 자바스크립트로만 DOM을 다룰 수 있는 것은 아니고, 자바스크립트와 DOM은 엄밀히 다른 개념이다. 왜냐하면, DOM API
는 JavaScript API가 아닌 Web API
이기 때문이다.
이로 인해 만약 브라우저가 자바스크립트 외에 다른 언어를 지원하게 된다면 그 언어를 통해 DOM을 사용하여 동일한 방식으로 HTML 문서를 조작하고 화면을 렌더링할 수 있을 것이다.
프로그래밍 언어가 문서 구조, 스타일, 내용 등을 변경할 수 있게 하는 인터페이스이다.
브라우저에서 제공하는 Web API* 중 하나로, 이 API를 통해 원하는 대로 DOM을 찾고 조작할 수 있다. 정적인 웹 페이지에 접근하여 동적으로 웹 페이지를 변경하기 위해서는 메모리 상에 존재하는 DOM을 변경해야 하고, 이때 필요한 것이 DOM 요소들을 변경하는 프로퍼티와 메서드 집합인 DOM API인 것이다. 대표적으로는 노드를 취득하는 API (ex. document.querySelector), 그리고 노드를 추가 또는 조작하는 API (ex. Node.appendChild) 등이 있다.
*API (Application Programming Interface)
: 어떤 어플리케이션이나 웹 페이지의 동작을 위해 입력하는 프로그래밍 명령이라고 생각하면 쉽다.
자주 쓰는 HTML DOM Methods에는 다음과 같은 것들이 있다.
1. 선택 메소드: HTML의 요소에 접근하고 싶을 때 사용
/* id 속성으로 선택 */ document.getElementById('this-is-id'); document.querySelector('#this-is-id'); document.querySelectorAll('#this-is-id'); /* class 속성으로 선택 */ document.getElementsByClassName('this-is-class'); document.querySelector('.this-is-class'); document.querySelectorAll('.this-is-class'); /* tag 속성으로 선택 */ document.getElementsByTagName('input'); document.querySelector('input'); document.querySelectorAll('input');
나는
querySelector(All)
로 요소를 많이 선택하는데, 그 이유는 편하기 때문이다. 물론 속도적인 측면에서는getElement(s)By
가 더 빠르지만, 아직은 연습 중이기도 하고querySelector(All)
도 초당 약 7백만건의 작업을 처리해 느린 속도가 전혀 아니기 때문이다.만약 이 둘 중 무얼 사용해야 할지 모르겠다면?
1. runtime 감소 목적 ⇒getElement(s)By
2. 개발의 편함 목적 ⇒querySelector(All)
2. 기타 메소드
<div id="this-is-id"></div>
const $id = document.querySelector('#this-is-id'); /* HTML 요소를 생성 */ const divDOM = document.createElement('div'); /* 생성된 요소에 class 추가 */ divDOM.className = 'this-is-class'; divDOM.classList.add('class2'); /* HTML 요소에 텍스트 추가 */ $id.innerHTML = 'this is id'; divDOM.innerHTML = 'this is class'; /* HTML 요소에 추가 */ $id.append(divDOM); /* 텍스트를 출력 */ document.write('document write');
방금 알아낸 사실이 하나 있는데, append() 이후 부모 노드($id
)의 innerHTML을 수정하니 append 된 애들이 사라진다...
/* HTML 요소에 추가 */ $id.append(divDOM); /* HTML 요소에 텍스트 추가 */ $id.innerHTML = 'this is id'; divDOM.innerHTML = 'this is class';
여기서 잠깐 append()
메소드와 innerHTML
을 혼용할 때 주의점을 설명해주겠다. (빠른 도움 주신 김영민 강사님 감사합니다!)
innerHTML 속성을 수정하면 브라우저는 해당 DOM 요소의 내부 HTML(모든 자식 요소)을 새로운 값으로 완전히 재구성한다. 이 과정에서 append()
메소드로 추가된 요소들은 새로운 HTML 구조에 포함되어 있지 않은 요소들이므로 사라지게 된다.
반면, 부모 요소가 아닌 자식 요소의 innerHTML을 변경할 시 부모 요소에 append된 요소들은 영향을 받지 않는다. 이는 innerHTML 속성이 특정 요소에만 영향을 미치고 그 요소의 자식들만 재구성하기 때문이다. (만약 자식 요소에 append를 하고 innerHTML을 변경하면 해당 요소의 자식들이 사라지는 것은 동일)
이로 인해 append와 innerHTML 수정을 혼합해서 사용할 때는 이 점을 주의해서 사용해야 한다.
3. 이벤트 메소드: 요소의 이벤트에 대한 반응을 연결할 때 사용
/* 요소의 onclick 속성에 함수를 준다. */ 요소.onclick = function( ){ } /* 요소에 click이벤트가 발생했을 경우, 실행할 함수를 준다. */ 요소.addEventListener( 'click', 실행할 함수 )
이벤트 메소드에 대한 자세한 설명은 글을 새로 작성하겠다! (링크는 글 작성 이후 연결할 예정)
이렇게 오늘은 DOM API에 대해 알아보았다. 이 글을 알면서 새롭게 알게 된 점이 3가지 있다.
1. DOM API
가 자바스크립트 소속이 아닌 WEB API
였다는 점
2. getElement(s)By
가 querySelector(All)
보다 속도가 빠르다는 점
3. append()
메소드와 innerHTML
을 혼용할 때의 주의점
블로그 쓸 시간을 낼 수 없어 미루고 미루다 쓰고 있는 요즘인데 글을 작성하면서 더 깊게 검색하니까 강의를 들을 때보다 더 많은 걸 알아가게 되는 것 같다.