JavaScript DOM요소 선택하기

seul_velog·2021년 12월 21일
2

JavaScript

목록 보기
21/25
post-thumbnail

📍 DOM이란?

문서 객체 모델(DOM, Document Object Model)은 XML이나 HTML 문서에 접근하기 위한 일종의 인터페이스이다.
이 객체 모델은 문서 내의 모든 요소를 정의하고, 각각의 요소에 접근하는 방법을 제공한다.

  • 웹페이지를 자바스크립트로 제어하기 위한 객체 모델을 의미하며, window 객체의 document 프로퍼티를 통해서 사용할 수 있다.

  • Window 객체가 창을 의미한다면 Document 객체는 윈도우에 로드된 문서를 의미한다고 할 수 있다.

  • 브라우저가 읽거나 어떤 작업을 할 수 있는 언어가 JavaScript 라고 한다면, DOM은 바로 이 작업이 이루어지는 장소이다. (DOM은 브라우저에 의해 기록되는 모든 것이고, JavaScript는 이를 조작할 수 있는 문법언어일 뿐이다. )

DOM의 종류

  1. Core DOM : 모든 문서 타입을 위한 DOM 모델
  2. HTML DOM : HTML 문서를 위한 DOM 모델
  3. XML DOM : XML 문서를 위한 DOM 모델

DOM은 W3C의 표준 객체 모델이며, 다음과 같이 계층 구조로 표현된다 ▼

Document 객체

Document 객체는 웹 페이지 그 자체를 의미하며, 웹 페이지에 존재하는 HTML 요소에 접근하고자 할 때는 반드시 Document 객체부터 시작해야 한다.

  • Document 객체는 HTML 요소와 관련된 작업을 도와주는 다양한 메소드를 제공한다.

  • Document 메소드

    • HTML 요소의 선택
    • HTML 요소의 생성
    • HTML 이벤트 핸들러 추가
    • HTML 객체의 선택




📍 DOM 요소 접근 및 선택

- get 메서드

1. 태그로 접근

document.getElementsByTagName

문법 )
const elements = document.getElementsByTagName(name);

  • Document 인터페이스의 getElementsByTagName 메서드는 엘리먼트의 HTMLCollection 과 주어진 태그명을 반환한다.
  • 반환된 HTMLCollection 은 살아있으며, 이는 document.getElementsByTagName() 을 다시 호출하지 않아도 자동으로 업데이트하여 DOM 트리와 동기화된 상태를 유지함을 의미한다.



2. 클래스 이름으로 접근

document.getElementsByClassName

문법)
const elements = document.getElementsByClassName(names);

  • class의 이름을 이용해서 HTML 요소(element)들을 가져오는 메서드이다.

  • Document 인터페이스 의 getElementsByClassName메서드는 주어진 클래스 이름을 모두 가진 모든 자식 요소의 배열과 유사한 객체를 반환한다.

  • 복수형태로 가져 온다.

  • Element.getElementsByClassName()
    : 주어진 클래스를 가진 모든 자식 엘리먼트의 실시간 HTMLCollection 을 반환한다.
    document.getElementsByClassName()
    : 도큐먼트 루트로부터 도큐먼트 전체를 탐색한다는 점을 제외하고는 위와 동일하게 작동한다.



3. 아이디로 접근

document.getElementById

문법)
document.getElementById(id);

  • 주어진 문자열과 일치하는 id 속성을 가진 요소를 찾고, 이를 나타내는 Element 객체를 반환한다.
  • ID는 문서 내에서 유일하므로 특정 요소를 빠르게 찾을 때 유용하다.
  • 만약 document에 구체적인 ID의 엘리먼트가 없다면 null을 반환한다.
  • 복수형태로 찾지 않는다.



- DOM 요소 Query

1. querySelector

document.querySelector

문법)
document.querySelector(selectors);

CSS 선택자로 요소를 선택하게 해준다. 주의할 점은 선택자에 해당하는 첫번째 요소만 선택한다는 것이다.
ex) document.querySelector('.abc') : 클래스 값이 abc인 첫번째 요소에 접근

  • 노드의 하위 트리에서 첫 번째로 일치하는 Element 노드를 반환한다. 결과가 없으면 null을 반환한다.
  • 매개변수 selectors는 하나 이상의 선택자를 포함한 DOMString 으로, 유효한 CSS 선택자여야 하며 아닐 경우 문법 에러가 발생한다.



2. querySelectorAll

document.querySelectorAll

문법)
elementList = parentNode.querySelectorAll(selectors);

선택자를 만족하는 모든 요소의 목록이 필요하다면 querySelectorAll()을 사용한다.

  • 노드의 하위 트리 안에서 일치하는 모든 Element를 포함한 NodeList를 반환한다. 결과가 없으면 빈 NodeList를 반환한다.





📌 getElementById VS querySelector

<form id="userForm">
  <input id="username" type="text" value="Kim" />
</form>

위의 코드에서, username 요소를 username 변수에 할당한다고 가정해보자.

1) getElementById 를 사용할 경우 ▼

var username = document.getElementById("username");

2) querySelector 를 사용할 경우 ▼

var username = document.querySelector("#userForm #username");;
  • querySelector를 통해 원하는 요소를 선택하는 것이 더 구체적이다.

✍️ 구체적인 요소를 선택한다면 querySelector(All)을 사용하겠지만, getElementByID가 더 빠르며 지원이 잘 되어 잘 쓰인다는 것 같다. 🤔

추가) querySelector가 getElementById등 보다 더 유연하게 쓰일 수 있는 이유
: 어떤요소를 가져오는지에 따라 상관없이 항상 동일한 API를 쓸 수 있다는점, 구체적으로 요소를 선택할 수 있다는점(CSS문법처럼)




📌 getElementsByClassName VS querySelectorAll

<form id="productForm">
  <input id="productOne" class="product" type="text" value="Product 1" />
  <input id="productTwo" class="product" type="text" value="Product 2" />
  <input id="productThree" class="product" type="text" value="Product 3" />
</form>

위의 코드에서, 모든 product 요소를 products 변수에 할당한다고 가정해보자.

1) getElementsByClassName 을 사용할 경우 ▼

var products = document.getElementsByClassName("product");

2) querySelectorAll 을 사용할 경우 ▼

var products = document.querySelectorAll("#productForm .product");
  • getElementsByClassNameHTMLCollection에 리턴이 되고, querySelectorAllNodeList에 리턴이 된다.




5. HTMLCollection 과 NodeList

HTMLCollection과 Nodelist는 문서 내의 노드들을 가지고 있는 컬렉션이며, 유사배열이다.

  • 따라서 length 프로퍼티를 가지기 때문에 객체를 배열처럼 접근할 수 있고(인덱스 접근) 반복문을 돌 수 있다.
  • 유사 배열 객체이므로 자바스크립트에서 제공하는 배열 객체의 메소드 map, forEach, reduce 등은 사용할 수 없다. ( NodeList는 HTMCollection과 다르게 NodeList.prototype.forEach 메서드를 상속받아 사용할 수 있다. )

5-1. HTMLCollection

: getElementsByTagName , getElementsByClassName 메서드가 반환하는 HTMLCollection 객체는 노드 객체의 상태 변화를 실시간으로 반영하는 살아있는 live DOM 컬렉션 객체이다. 이것은 객체가 스스로 실시간 노드 객체의 상태 변경을 반영함을 의미한다.


5-2. NodeList

: querySelectorAll 등의 메서드가 반환하는 NodeList 객체는 노드 객체의 상태 변화를 반영하지 않는 non-live DOM 컬렉션 객체이다. NodeList는 앞의 HTMLCollection과 다르게 노드가 변경되도 그 상태를 반영하지 않는다.

📌 추가)
: 대개의 경우 NodeList는 라이브(Live) 콜렉션으로 DOM의 변경 사항을 실시간으로 반영한다. 그러나 document.querySelectorAll() 메소드에 의해 반환되는 NodeList는 정적(Static) 콜렉션으로 DOM의 변경 사항이 실시간으로 반영되지 않는다.

HTMLCollection과 NodeList의 차이

  • 이 둘은 프로퍼티와 메서드에서 차이를 보이고 있다.
  • HTMLCollection은 배열의 forEach를 쓰지 못한다. (for과 같은 반복문을 통해서 배열의 각 요소에 접근해야 한다.)
  • Nodelist는 forEach를 쓸 수는 있지만, map은 사용하지 못한다.
  • Array.map 을 사용하기 위해서는 배열의 메서드인 from 을 활용한다.



따라서 HTMLCollectionNodeList편리하게 사용하기 위해서는 배열로 만들어 주는 것이 좋다. 특히 HTMLCollection과 같은 live 객체는 반복문을 순회하면서 노드가 변경되는 경우, 개발자의 의도와는 다른 결과가 발생할 수 있으므로 배열로 바꾸어 사용하는 것이 바람직하다.

객체를 배열로 만드는 방법
✍️ JS로 그림판을 만들 때 사용했던 Array.from 을 예로 들어보자.

Array.from

유사배열객체(array-like object)나 반복가능객체(iterable object)를 얕게 복사(shallow copy)하여 새로운 배열(Array) 객체를 만들어 리턴해 준다.

  • 유사배열객체(array-like object) : length 속성과 index element를 가지는 객체
  • 반복가능객체(iterable object) : 배열을 일반화한 객체 ex)Map, Set
console.log(Array.from('seul'));
// Array ['s', 'e', 'u', 'l']

console.log(Array.from([ 1, 2, 3], x => x + x));
// Array [2, 4, 6]

✍️ 강의에서 HTMLCollection이 왜 나왔는지 궁금해 하셨던 부분이 getElementsByClassName 메서드가 반환하는 HTMLCollection 객체와 관련이 있다는 것을 알았다.

때문에 Array.from 그리고 forEach를 사용해서 컬러배열을 생성하고 원하는 함수를 배열 요소 각각에 실행시키는 것에 대해서 조금이나마 이해가 되었고, 뒤로 갈수록 코드 한줄에 많은 연결고리가 있다는 것을 느꼈다.

DOM내용 중에서도 DOM요소를 선택하는 것과 관련해서 정리를 해보았는데, (사실 그림판을 만들다가 제어대상을 찾는 API, 그리고 Array.from 가 궁금해서 여기까지 온 것이다 😅) DOM을 주제로도 따로 공부해야겠다.


✍️ 어느 자료에서는 getElementsByTagName(name) 이 HTMLCollection 이라고 하고, 또 다른 자료에서는 "인자로 전달된 태그명에 해당하는 객체들을 찾아서 그 리스트를 NodeList라는 유사 배열에 담아서 반환하는 메서드" 라고 하기에 알아봤더니, 최신 W3C 명세에서는 elements 가 HTMLCollection 라고 하지만, WebKit 브라우저에서는 NodeList 를 반환한다고 한다.🧐 MDN




reference
gogori-DOM
JS-document
MDN
chloeee-querySelector
young-HTMLCollection
hianna
basemenks-NodeList
TCPschool-dom

profile
기억보단 기록을 ✨

0개의 댓글