웹 문서(Document)의 모든 요소를 프로그래밍에서 다룰 수 있는 객체(Object)로 만들고,
이러한 객체들을 계층화된 트리 구조의 모델(Model)로 정의하기 때문이다.
무슨 말인지 모르겠는데요.
그래서 Document / Object / Model 하나하나 알아볼 거다.
Object (객체)
객체는 정보와 기능이 담긴 상자라고 생각하면 된다.
객체는 대충 이런 느낌으로 생겼다. (별로 어려운 내용도 아니니 그냥 넘어가지 말고 주의 깊게 한 줄 한줄 읽는 거 추천)
let 강아지 = {
// 강아지의 정보
이름: "초코",
나이: 3,
색깔: "갈색",
// 강아지가 할 수 있는 행동
짖기: function() {
console.log("멍멍!");
},
앉기: function() {
console.log("앉았습니다");
}
}
// 강아지 정보 보기
console.log(강아지.이름); // "초코" 출력
console.log(강아지.나이); // 3 출력
// 강아지 행동시키기
강아지.짖기(); // "멍멍!" 출력
강아지.앉기(); // "앉았습니다" 출력
보면 강아지의 정보와 이 강아지가 할 수 있는 행동들이 모여 있다.
다시 말하지만 객체는 정보와 기능이 담긴 상자다.
오잉 그러면 저 강아지가 객체라는 상자라는 건가요?
ㅇㅇ 맞음
강아지 = 객체
강아지 정보 = 속성
강아지가 할 수 있는 행동 = 메소드
속성과 메소드는 추후에 블로그에 적을 수도 있지만
내 귀찮음이 성실함을 툭 치면 죽어버려서 본인이 직접 찾아보는 것을 추천.
간단하게
강아지.이름(속성) 하면 강아지의 객체에 저장된 이름이 나오고
강아지.짖기() (메소드) 하면 강아지의 객체에 저장된 행동을 함. 메소드는 뒤에()가 붙음 그게 실행한다는 뜻임.
객체 끝
MODEL(모델)
Model은 웹 문서를 프로그래밍적으로 다룰 수 있도록 만든 인터페이스이자 문서의 구조화된 표현 방식을 의미함.
뭐라는 거야
조금 더 쉽게
여기서 MODEL은 포괄적인 개념인데
HTML을 JS로 조작할 수 있는 인터페이스이자. (리모컨 같은 거임)
HTML의 구조화된 표현 방식을 의미한다는 거임. (지도 같은 거임)
저 두 가지 의미를 둘 다 포함하고 있음 리지도모컨임 ㅇㅇ
일단 구조화된 표현 방식인 트리 구조부터
이게 트리구조임
O ← 이것이 하나의 '매듭점(node)'
/ \ ← 이것들은 '연결선(edge)'
O O ← 다른 '매듭점들(nodes)'
그리고 저 하나하나를 노드(node)라고 부름.
매듭점, 연결점, 교차점 대충 이런 뉘앙스를 가짐.
저 동글뱅이들이 노드임.
이렇게 생긴 걸 트리 모델이라고 함.
근데 왜 이 구조를 써야 하는데요
맞는 말임 분명 다른 구조도 가능했을 거임 이런 식으로
<!-- 실제 HTML -->
<div>
<h1>제목</h1>
<p>내용</p>
</div>
// 1. 트리 모델
div
├── h1 ("제목")
└── p ("내용")
// 2. 리스트 모델 (다른 방식)
1. div 시작
2. h1 시작
3. "제목"
4. h1 끝
5. p 시작
6. "내용"
7. p 끝
8. div 끝
근데 트리구조를 채택하면 다음과 같은 이점이 있음:
부모-자식 관계를 직관적으로 표현
요소 찾기/수정이 쉬움
HTML의 계층구조와 잘 맞음
ㅇㅇ 그래서 트리구조를 선택한 거임.
근데 도대체 누가 멀쩡한 HTML을 트리구조로 바꿔준다는 거임 자꾸
님이 보고 있는 이 브라우저가 그걸함.
이를파싱(Parsing)이라고 함.
정보를 대충 가공하는걸 파싱이라고 보면 됨.
그리고 그 파싱을 하는 놈들을 파서(Parser)라고 부름.
브라우저에는 엔진들이 있는데
그중 HTML 파서가 HTML을 파싱 해서트리구조를 만듦.
참고로 CSS 파서가 CSS를 파싱 하면 CSSOM임 ㅋㅋ
JavaScript 엔진 (예: V8)
렌더링 엔진
이런 애들도 있음.
그럼 이제 또 의문이 생김.
도대체 누구 좋으라고 HTML을 파싱 해서 트리구조로 만드니 마니
이 난리부르스 다이아몬드 스텝을 밟고 있는 걸까?
정답은
1. 렌더링 엔진을 위해 (처음에 말한 지도 기능)
2. JS 조작을 위해. (처음에 말한 리모컨 기능임)
1. 은 위에서 언급한 렌더링 엔진이 만약 HTML 텍스트 그대로 사용하게 되면
허벌나게 뛰댕겨야됨.
부모-자식 관계 파악이 안돼서 폐륜이 발생할 수도 있고
스타일 상속 계산이 어려워서 재벌가처럼 상속분쟁이 일어날수도 있음.
레이아웃 계산도 어려워짐
암튼 렌더링 엔진이 힘들어함.
그래서 좀 효율적으로 뛰어다니라고 지도를 쥐어주는 거임.
(사실상 더 돌아다니기 편하게 맵자체를 변경한다는 표현이 조금 더 정확하지만)
결론 : 렌더링 편하자고 트리 구조로 바꾼 거임.
이론상 트리구조 없이 렌더링을 할 수 있음. 렌더링 엔진이 힘들 뿐 (렌엔 지켜 엉엉)
2. JS는 추후 설명함
NODE
아까 위에서 트리구조는 노드들을 가진다고 말했음.
1. 요소 노드(Element Node): <div>, <p> 등의 HTML 태그
2. 텍스트 노드(Text Node): 텍스트 내용
3. 속성 노드(Attribute Node): class, id 같은 속성
4. 문서 노드(Document Node): 문서 전체를 나타내는 노드
5. 주석 노드(Comment Node): HTML 주석
그래서 파싱 된 HTML은 이런 식으로 노드를 가지고 있음. 트리구조니깐.
밑은 더 자세한 예시임. (자세히 보셈)
// HTML 구조
<html>
<head>
<title>DOM 예시</title>
</head>
<body>
<div id="container">
<h1>제목</h1>
<p>텍스트 내용</p>
</div>
</body>
</html>
// 위 HTML의 DOM 트리 구조:
document (문서 노드)
└── html (요소 노드)
├── head (요소 노드)
│ └── title (요소 노드)
│ └── "DOM 예시" (텍스트 노드)
└── body (요소 노드)
└── div (요소 노드)
├── h1 (요소 노드)
│ └── "제목" (텍스트 노드)
└── p (요소 노드)
└── "텍스트 내용" (텍스트 노드)
document = {
documentElement: HTMLHtmlElement, // <html> 태그
head: HTMLHeadElement, // <head> 태그
body: HTMLBodyElement, // <body> 태그
// 주요 메서드들
getElementById(): Element,
getElementsByClassName(): HTMLCollection,
getElementsByTagName(): HTMLCollection,
querySelector(): Element,
querySelectorAll(): NodeList,
// 문서 관련 속성들
title: String,
URL: String,
documentURI: String,
characterSet: String,
// 이벤트 관련
addEventListener(): void,
removeEventListener(): void
// DOM 조작 메서드들
createElement(): Element,
createTextNode(): Text,
// ... 기타 여러 속성과 메서드들
}
대략적으로 이렇게 생겼다.
Document는 객체이기 때문에
위에 설명한 강아지처럼
속성과 메소드가 있다.
위에 언급한 객체의 메소드 사용법을 떠올려보자.
강아지를 짓게 하려면강아지.짖기() 를 사용해야 했다.
강아지.짖기()
강아지 = 객체
짖기() = 메소드
지금 나는 html 태그를 하나 선택하고 싶다고 가정해 보자.
(그때 필요한 메소드는 querySelector() 다.)
document.querySelector('p')
document = 객체
querySelector() = 메소드
이러면 p 태그를 선택할 수가 있다.
이렇게 객체를 조작하는 방식으로 JS로 간편하게 우리는 HTML을 조작할 수 있다.
왜냐
우리가 document라는 객체를 만들고 그 안에 HTML을 파싱 해서 넣었을 뿐 아니라
그 안에 유용한 메소드들이 있기 때문이다.
(참고로 메서드들은 브라우저가 추가해 준다.)
이게 모델에서 언급한 리모컨 기능이다. (인터페이스)
JS를 통해 쉽게 HTML을 조작할 수 있다.
근데 이렇게 안 하면 얼마나 더럽고 귀찮게 조작해야 되는데요?
// 1. DOM 구조가 없다고 가정하면 (HTML이 그냥 문자열)
let html = "<div><h1>제목</h1><p>내용</p></div>";
// HTML을 수정하려면 문자열 처리를 해야 함
html = html.replace("<h1>제목</h1>", "<h1>새로운 제목</h1>");
html = html.replace("<p>내용</p>", "<p>새로운 내용</p>");
------------------------------------------------------------
// 2. DOM 구조일 때 (현재 브라우저처럼)
let 제목 = document.querySelector('h1');
let 내용 = document.querySelector('p');
제목.textContent = "새로운 제목";
내용.textContent = "새로운 내용";
1번처럼 코드가 혼파망이 되어버린다.
DOM이 있음에 감사하자.
다시 document 객체로 돌아와 보자.
document = {
documentElement: HTMLHtmlElement, // <html> 태그
head: HTMLHeadElement, // <head> 태그
body: HTMLBodyElement, // <body> 태그
// 주요 메서드들
getElementById(): Element,
getElementsByClassName(): HTMLCollection,
getElementsByTagName(): HTMLCollection,
querySelector(): Element,
querySelectorAll(): NodeList,
// 문서 관련 속성들
title: String,
URL: String,
documentURI: String,
characterSet: String,
// 이벤트 관련
addEventListener(): void,
removeEventListener(): void
// DOM 조작 메서드들
createElement(): Element,
createTextNode(): Text,
// ... 기타 여러 속성과 메서드들
}