Document

김콩은·2022년 3월 22일
0

브라우저

목록 보기
1/1
post-thumbnail

호스트(host)
자바스크립트가 돌아가는 플랫폼

호스트 환경(host environment)
각 플랫폼은 특정 기능(객체와 함수)을 제공한다.

브라우저는 웹페이지를 제어하기 위한 수단을, Node.js은 서버 사이드 기능을 제공하게 된다.



📚 브라우저 환경


호스트 환경이 웹 브라우저일 때 사용할 수 있는 기능을 개괄적으로 보여주고 있다.


💡 window


window 객체는 2가지 역할을 한다.

  1. 전역 객체
  2. 브라우저 창 ➡ 이를 제어하는 다양한 메서드와 프로퍼티가 있다.

💡 DOM


DOM은 웹 페이지 내의 모든 콘텐츠를 객체로 나타낸 것이다. DOM 객체를 통해 페이지로 접근하여 페이지 내 그 무엇이든 변경, 생성 가능하다.


📌 DOM 명세서
: 문서의 구조, 조작, 이벤트에 대한 설명이 담겨있다.


📌 CSSOM 명세서
: CSS 규칙과 stylesheet를 객체로 나타내고 이 객체를 조작하는 방법, 이 객체와 문서 사이의 어떻게 조작하는지에 대한 설명이 담겨있다.


💡 BOM


문서 이외의 모든 것을 제어하기 위해 브라우저(호스트 환경)가 제공하는 추가 객체이다.


alert(location.href); // 현재 URL을 보여줌
if (confirm("go wikigedia?") {
	location.href = "https://wikipedia.org"; 
}
  • navigator
    브라우저와 운영체제에 대한 정보를 제공한다.
    - navigator.userAgent: 현재 사용중인 브라우저 정보
    - navigator.platform: 브라우저가 실행 중인 운영체제

  • location
    현재 URL을 읽을 수 있게 해주고 새로운 URL로 redirect할 수 있게 해준다.

  • alert/ cofirm/ prompt
    문서와 직접 연결되어 있지는 않지만, 사용자와 브라우저 사이의 커뮤니케이션을 도와주는 순수 브라우저 메서드이다.


📌 HTML 명세서
: HTML 명세서는 HTML, BOM, 브라우저에서만 사용되는 DOM 확장에 대한 설명을 담고 있다.



📚 DOM 트리


HTML 파싱을 통해 모든 element와 element의 attribute, text는 각각의 객체로 생성되고 이들 객체는 트리 데이터 구조 내에 연결되어 관계를 정의하게 된다. 이를 DOM이라 하며, 트리로 구조화되어 있기 때문에 DOM tree라 부른다.

DOM tree의 모든 객체는 자바스크립트를 통해 접근할 수 있고, 페이지를 조작할 때 사용한다.

📢 DOM을 조작하는 방법을 알기 전에 먼저 DOM의 구조에 대해 알아야 한다.


💡 DOM 구조


노드 타입은 총 열두 가지인데, 실무에서 주로 다루는 노드를 볼 것이다.

  • document node
    문서 전체를 나타낸다. 트리의 최상위에 존재하며 element, attribute, text node에 접근하려면 document node를 통해야 한다. 즉, DOM의 "진입점"이다.

  • element node
    HTML element는 중첩에 의한 부자 관계로 정보를 구조화한다. attribute, text node에 접근하려면 element node를 찾아 접근해야한다.

  • attribute node
    attribute node는 해당 attribute가 지정된 element의 자식이 아니라 해당 element의 일부로 표현된다. 따라서 해당 element node를 찾아 접근하면 attribute 참조, 수정할 수 있다.

  • text node
    text node는 element node의 자식이며 자식 노드를 가질 수 없다. 즉, 텍스트 노드는 DOM tree의 leaf node이다.

  • comment node
    정보를 기록하고 자바스크립트를 사용해 이 정보를 DOM으로부터 읽을 수 있다.


📌 HTML 안의 모든 것은 DOM을 구성한다.
HTML 문서 최상단에 위치하는 <!DOCTYPE html> 지시자, 문서 전체를 나타내는 document 객체, 주석은 모두 DOM 노드가 된다. 주석이 DOM에 추가되는 이유는 HTML에 뭔가 있다면 반드시 DOM 트리에 추가되어야 한다는 규칙 때문이다.



📚 DOM 탐색하기


DOM 객체를 조작하려면 DOM 객체에 접근해야 한다. DOM에 수행하는 모든 연산은 document 객체에서 시작하며, document 객체를 통해 어떤 노드에도 접근할 수 있다.


💡 DOM API


DOM은 자바스크립트를 통해 동적으로 변경할 수 있으며 변경된 DOM은 렌더링에 반영된다. 그런데 복잡한 DOM Tree를 탐색하기 위해 JavaScript로 탐색 알고리즘을 구현하는 것은 어렵다.

따라서 웹 문서의 동적 변경을 위해 DOM은 자바스크립트가 자신에 접근하고 수정할 수 있는 방법인 DOM API를 제공하며, 이는 프로퍼티와 메소드를 갖는 자바스크립트 객체이다.


📌 DOM API는 웹페이지의 DOM을 동적으로 변화시키기 위한 유일한 방법이다.


💡 Node 탐색하기



➖ DOM tree 상단의 노드 탐색하기


document가 제공하는 프로퍼티를 사용해 DOM tree 상단의 노드들에 접근할 수 있다.

  • html = document.documentElement

  • head = document.head

  • body = document.body


➖ 자식 노드, 후손 노드 탐색하기


자식 노드(child node, children)
바로 아래의 자식 요소
- elem.hasChildNodes(): 자식 노드의 존재 여부 검사

후손 노드(descendants)
중첩 관계에 있는 모든 요소. 자식 노드, 자식 노드의 모든 자식 노드 등


childNodes

for (let i = 0; i < document.body.childNodes.length; i++) {
      alert( document.body.childNodes[i] ); 
 }

firstChild / lastChile
첫 번째, 마지막 자식 노드에 빠르게 접근할 수 있다.

elem.childNodes[0] === elem.firstChild
elem.childNodes[elem.childNodes.length - 1] === elem.lastChild

📢 childNodes는 배열이 아닌 유사 배열 객체인 컬렉션(collection)이다.


➖ 형제와 부모 노드 탐색하기


형제 노드(sibling node)
같은 부모를 가진 노드


nextSibling / previousSibling

console.log( document.head.nextSibling ); // HTMLBodyElement
console.log( document.body.previousSibling ); // HTMLHeadElement

parentNode

console.log( document.body.parentNode === document.documentElement ); // true

💡 Element Node 탐색하기


childNodes는 모든 종류의 노드를 참조하지만 실무에서는 element node를 조작하는 작업이 대다수이다.

따라서 위의 그림처럼 element가 추가된(childNodes➡children) 프로퍼티를 사용하며, 이는 "element node에만" 적용이 가능하다.



📚 element 검색하기


목표 element node가 가깝지 않다면 DOM 탐색 프로퍼티만으로 접근하기 어렵다.

상대 위치를 이용하지 않으면서 웹 페이지 내에서 원하는 element node에 접근하는 메서드에 대해 알아볼 것이다.


💡 getElementById


: document 객체를 대상으로 해당 id를 가진 element node를 찾아준다.


📌 document node가 아닌 다른 node엔 호출할 수 없다.


📌 id는 유일무이해야 한다.
id를 중복해 사용한다면 id를 이용해 요소를 검색하는 메서드를 사용할 때 임의의 요소를 반환하게 된다.


태그나 클래스 등으로 원하는 노드를 찾아주는 메서드 있다.
elem.getElementsByTagName(tag)
elem.getElementsByClassName(className)
document.getElementsByName(name)


💡 querySelectorAll


: elem의 자식 요소 중 주어진 CSS 선택자에 대응하는 요소 모두를 반환한다.


querySelector
주어진 CSS 선택자에 대응하는 요소 중 첫 번째 요소를 반환한다. elem.querySelectorAll(css)[0]과 동일하다.

elem.querySelector(css): 해당하는 요소를 찾으면 검색을 멈춘다.
elem.querySelectorAll(css)[0]: 모든 요소를 검색해 첫 번째 요소만을 반환한다.


💡 matches


: elem.matches(css)는 element가 주어진 css 선택자와 일치하는지의 여부를 판단해준다.

element가 담겨있는 컬렉션을 순회해 원하는 element만 걸러내고자 할 때 유용하다.


💡 closest


elem.closest(css)는 css 선택자와 일치하는(자기 자신을 포함) 가장 가까운 조상 요소를 반환한다.

원하는 요소를 찾으면 검색을 중단하다.


💡 살아있는 컬렉션


: getElementBy로 시작하는 모든 메서드는 살아있는 컬렉션을 반환한다. 문서에 변경이 있을 때마다 컬렉션이 자동 갱신되어 최신 상태를 유지하는 것이다.

querySelectorAll은 정적인 컬렉션을 반환한다. 즉, 컬렉션이 한 번 확정되면 갱신되지 않는다.



📚 노드 프로퍼티


DOM 노드란 무엇인지, DOM 노드의 주요 프로퍼티는 무엇이 있는지 알아볼 것이다.

📢 DOM 노드는 프로토타입을 기반으로 상속 관계를 갖는 일반 자바스크립트 객체이며, 특정 노드에서 사용할 수 있는 프로퍼티와 메서드는 상속을 기반으로 결정된다.


💡 DOM 노드 클래스


EventTarget
루트에 있는 추상 클래스. DOM Node의 베이스


Node
추상 클래스. DOM Node의 베이스. Node 클래스의 객체는 절대 생성되지 않는다.

  • 주요 트리 탐색 기능 제공
    : parentNode, nextSibling, childNodes 등

  • 상속 받는 클래스
    : Text class, Element class, Comment class 등


Element
DOM Element Node의 베이스 클래스.

  • 주요 요소 전용 탐색 기능 제공
    : nextElementSibling, children, querySelector 등

  • 상속 받는 클래스
    : HTMLElement, XMLElement, SVGElement

    브라우저는 HTML, XML, SVG를 지원한다.


HTMLElement
HTML Element Node의 베이스 클래스.

  • 상속 받는 클래스
    - HTMLInputElement: input element
    - HTMLBodyElement: body element
    - HTMLAnchorElement: a element

input element 객체가 만들어질 때 상속받은 클래스가 제공하는 프로퍼티와 메서드

  • Object: 일반 객체 메서드
  • EventTarget: 이벤트 관련 기능
  • Node: 공통 DOM 노드 프로퍼티
  • Element: element 노드 메서드
  • HTMLElement: HTML element 메서드, getter/setter 제공
  • HTMLInputElement: 입력 관련 프로퍼티 제공

➖ DOM 노드 클래스 확인


이름
객체가 가지는 constructor 프로퍼티를 사용

alert( document.body.constructor.name ); // HTMLElement

상속여부
instanceof 사용

alert( document.body instanceof HTMLBodyElement ); // true

➖ DOM 노드 태그 이름 확인


alert( document.body.nodeName ); // BODY
alert( document.body.tagName ); // BODY

tagName
Element 클래스로부터 유래되었기 때문에 element Node에만 존재

nodeName
모든 Node에 존재


💡 innerHTML


  • element 안의 HTML을 문자열 형태로 받아올 수 있다.

  • element 안의 HTML을 수정할 수 있다.


📢 'innerHTML +=' 주의점

chatDiv.innerHTML += "<div>hello</div>"

HTLM을 추가하는 것이 아니라 기존 내용을 삭제하고 기존 내용과 새로운 내용을 합친 새로운 내용으로 덮어쓰는 것이다. 따라서 이미지 등의 리소스 전부가 다시 로딩된다.

드래그가 해제되고, 입력한 값이 사라지는 등의 부작용이 발생한다.


💡 outerHTML


element 자체를 포함한 전체 HTML이 담겨 있다.

<div>Hello, world!</div>
<script>
  	let div = document.querySelector('div');
	div.outerHTML = '<p>new element</p>';
	alert(div.outerHTML) // <div>Hello, world!</div>
</script>

📢 outerHTML에 하는 할당 연산은 DOM element를 수정하지 않는다.

새로운 HTML 조각이 document에서 div를 삭제 후 생긴 공간에 삽입된다. 새로운 내용이 보이게 되지만, div엔 여전히 기존 값이 저장되어 있고 새로운 HTML 조각은 어디에도 저장되어있지 않다.


💡 nodeValue / data


element와 다른 타입의 노드에는 innerHTML과 유사한 역할을 해주는 프로퍼티인 nodeValuedata를 사용한다.

<body>
  안녕하세요.
  <!-- 주석 -->
  <script>
    let text = document.body.firstChild;
    alert(text.data); // 안녕하세요.
    let comment = text.nextSibling;
    alert(comment.data); // 주석
  </script>
</body>

💡 textContent


element 내의 태그는 제외하고 오로지 텍스트에만 접근할 수 있다.

<div id="elem1"></div> // 이보라
<div id="elem2"></div> // <b>이보라</b>

<script>
  let name = prompt("이름", "<b>이보라</b>");
  elem1.innerHTML = name; // 태그는 태그로 해석된다.
  elem2.textContent = name; // 텍스트 그대로 저장된다.
</script>

예상치 못한 HTML이 사이트에 침투하는 것을 막으려면 textContent를 사용하는 것이 좋다.


💡 hidden


element를 보여줄지 말지 지정할 때 사용한다.

<div hidden>hi</div>
<div id="elem">hello</div>

<script>
  elem.hidden = true;
</script>

기술적으로 style = "display:none"과 동일하다.


💡 기타 프로퍼티


클래스마다 특징적인 프로퍼티 몇 가지를 볼 것이다.


➖ value


input, select, textarea의 값이 저장된다.

클래스

  • HTMLInputElement
  • HTMLSelectElement

➖ href


href 속성 값이 저장된다.

클래스

  • HTMLAnchorElement

➖ id


id 속성 값이 저장된다. 모든 Element Node에서 사용할 수 있다.

클래스

  • HTMLElement



📚 속성과 프로퍼티


<body id="page"> ➡ body.id = "page"

element node에서 대부분의 attribute는 DOM 객체의 프로퍼티가 되지만 항상 일대일로 매핑되는 것은 아니다.

📌 속성과 프로퍼티를 다루는 법

📌 속성-프로퍼티가 언제 일대일로 매핑되는지 / 언제는 되지 않는지

이 두 가지에 주의하면서 두 개념을 알아볼 것이다.


💡 DOM 프로퍼티


document.body.myData = {
  name: 'Caesar',
  title: 'Imperator'
};

내장 DOM 프로퍼티만으로 충분하지 않은 경우 자신만의 프로퍼티를 만들 수 있다.


Element.prototype.sayHi = function() {
  alert(`Hello, I'm ${this.tagName}`);
};

document.documentElement.sayHi(); // Hello, I'm HTML
document.body.sayHi(); // Hello, I'm BODY

내장 프로토타입을 수정해 모든 element node에서 이 메서드를 사용하게 할 수도 있다.


DOM 프로퍼티와 메서드는 일반 자바스크립트 객체처럼 행동한다.

  • 어떤 값이든 가질 수 있다.
  • 대소문자를 가린다.

💡 HTML 속성


profile
콩딩중

0개의 댓글