일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 선형대수
- 구멍가게코딩단
- 자료구조와 함께 배우는 알고리즘 입문
- GIT
- 목록처리
- 처음 만나는 AI수학 with Python
- 데비안
- 처음 만나는 AI 수학 with Python
- 리눅스
- 페이징
- baeldung
- 서버설정
- 자료구조와함께배우는알고리즘입문
- 코드로배우는스프링웹프로젝트
- iterator
- 스프링부트핵심가이드
- 스프링 시큐리티
- 네트워크 설정
- resttemplate
- 친절한SQL튜닝
- Kernighan의 C언어 프로그래밍
- 이터레이터
- 알파회계
- ㅒ
- 티스토리 쿠키 삭제
- d
- network configuration
- 자바편
- /etc/network/interfaces
- 코드로배우는스프링부트웹프로젝트
- Today
- Total
bright jazz music
[Do it! w. TS] 03. 가상 DOM 이해하기 본문
npx create-react-app ch02_1 --template typescript
문서객체모델(DOM, Document Object Model)이란?
웹브라우저는 HTML 형식의 문자열을 화면에 추력할 때 문자열을 분석(parsing)하여 특별한 형식의 자바스크립트 객체 조합으로 바꾼다. 이 특별한 형식의 자바스크립트 객체는 모두 자신의 특징에 맞는 인터페이스를 구현하는데 이들 인터페이스를 '총칭'하여 문서객체모델이라고 한다. (여러 가지 인터페이스가 있고 이들을
window 객체
: 웹브라우저의 자바스크립트 엔진은 window라는 이름의 전역변수를 기본으로 제공한다.
여기서 window는 웹브라우저의 특정 웹페이지를 의미하는 객체이다. window 객체는 Window 타입 객체로서 Window 타입을 브라우저 객체모델(BOM, Browner Object Model)이라고 한다.
document 객체
: 웹페이지가 HTML 문서를 화면에 출력할 때 window 객체는 document라는 이름의 속성 객체로 HTML 문서 기능을 사용할 수 있게 해준다. HTML 문서의 html 요소는 오직 1개만 있어야 하므로 window.document(줄여서 document)는 html 요소를 의미한다.
docment.head와 document.body 객체
: HTML 문서의 html 요소는 head와 body 태그를 1개씩만 가질 수 있다. document 객체(window.document)는 이런 조건에 맞추어 head 요소를 의미하는 head 속성 객체와 body 요소를 의미하는 head 속성 객체와 body 요소를 의미하는 body 속성 객체를 제공한다.
document.createElement 메서드
: 인터페이스는 객체가 제공해야 할 여러 기능을 구체적으로 정의한 규약이다. 웹브라우저는 DOM의 다양한 인터페이스를 각각의 목적에 맞게 구현한 객체로 생성할 수 있도록 document.createElement 메서드를 제공한다.
용법
let element = document.createElement(tagName[, options]);
용례
//div 요소를 자바스크립트로 생성하는 예
let newDiv = document.createElement("div")
HTMLElement 인터페이스
:HTMLElement는 모든 종류의 HTML 요소가 구현하는 인터페이스이다. 일부요소는 이 인터페이스를 직접 구현하기도 하지만 대부분은 HTMLELement를 상속하여 자신들의 인터페이스를 구현한다. 위에서 선언한 변수인 newDiv의 타입은 HTMLDivElement이다.
HTMLElement의 부모 요소 상속 구조
HTMLElement 자체는 부모 인터페이스 3개를 상속한다. 이 가운데 부모 인터페이스인 Node는 appendChild 메서드를 제공한다. HTMLElement는 HTML 태그의 부모 인터페이스이므로 모든 HTML 태그는 appendChild 메서드를 가진다.
용법
let aChild = element.appendChild(aChild);
용례
let p = document.createElement("p") //<p> 요소 생성(즉, DOM 요소 생성)
// <p> 요소를 <body>의 마지막 자식 요소로 추가
//여기서는 p 하나만 생성했지만 실제로는 한꺼번에 많은 DOM 객체를 생성한다.
document.body.appendChild(p) //렌더링 (객체를 window.document.body에 추가하여 보이게 함)
//각각의 DOM rorcpsms appendChild 호출을 거쳐 부모/자식 관계로 얽힌 거대한 트리구조가 생성된다.
//웹브라우저에서는 이 DOM 객체들의 트리구조를 DOM 트리라고 한다.
자바스크립트만 사용하는 프런트엔드 개발 (물리 DOM)
리액트를 사용하는 프런트엔드 개발 (가상DOM)
웹브라우저의 document.createElement와 유사하게 react 패키지는 createElement라는 함수를 제공한다.
그것은 React.createElement이다.
createElement의 첫 번째 매개변수 type의 타입은 아래의 세 가지 중에 하나일 수 있다.
- FunctionComponent<P>
- ComponentClass<P>
- string
두 번째 매개변수는 props?는 변수 이름 뒤에 ?가 붙었으므로 생략할 수 있는 선택 매개변수(optional argument)이다.
따라서 <p> 요소를 생성하고 싶다면 다음처럼 'p' 문자열을 사용한다.
const p = React.createElement('p')
root.render 메서드
pPhysicalDOM이라는 객체가 존재한다면, 물리DOM은 document.body.appendChild(pPhysicalDOM)과 같은 코드를 사용하여 이 객체를 DOM트리에 추가해 준다. 그 결과로 pPhysical 객체가 화면에 나타나는 것이다.
아래와 같은 코드에서는 pVirtualDOM은 생성만 되었을 뿐 가상 DOM트리에는 추가되지 않았다.
import React from 'react';
import ReactDOM from 'react-dom/client';
const pVirtualDOM = React.createElement('p', null, 'Hello virtual DOM World!');
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
여기서 기억해야 할 것은 document.body.appendChild(pVirtualDOM)과 같은 코드를 만들 수 없다는 것이다.
pVirtualDOM은 document.body.appendChild가 이해할 수 있는 DOM 객체가 아니기 때문이다.
따라서 pVirtualDOM이 화면에 나타나려면 document.body.appendChild가 아닌 다른 방법을 사용해야 한다.
root.render 함수가 이 역할을 해준다. 즉, 가상 DOM을 물리 DOM으로 전환해 주는 역할을 한다.
root.render(pVirtualDOM)
위 코드가 가상DOM 객체를 화면에 렌더링하려고 시도하는 부분이다. 그런데 root.render 메서드는 변환한 가상DOM 객체를 append할 물리 DOM 객체가 필요하다.
HTMLElement의 부모 인터페이스인 Element는 문자열 타입의 id라는 이름의 속성을 제공한다.
document.getElementById 메서드
document 객체는 id 속성과 관련하여 getElementById 메서드를 제공한다. 이 메서드는 이미 생성된 특정 물리 DOM 객체를 찾아주는 역할을 한다. 다음 코드는 id 속성값이 'root'인 DOM 객체를 찾아낸다.
let rootDiv = document.getElementId('root')
index.tsx 코드 분석
import React from 'react';
import ReactDOM from 'react-dom/client';
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
// 가상DOM 객체 생성
const pVirtualDOM = React.createElement('p', null, 'Hello virtual DOM World!');
root.render(pVirtualDOM);
이 방식은 복잡하지만 최초 렌더링 이후 가상 DOM 트리 구조에 변화가 생겨 이 변화를 사용자에게 알리려고 재렌더링 되는 상황을 생각해보자. 만약 'Hello virtual DOM World!'이 아니라 'Welcome to out site!'를 화면에 나타내려고 하면, 이 때는 가상 DOM 트리를 물리 DOM트리로 변환하는 문제가 아니다. 이미 존재하는 물리 DOM 트리에 특정 HTML 요소의 속성값을 바꾸는 문제이다.
즉 더이상 createElement와 appendChild의 문제가 아니라 특정 HTML 요소의 DOM 객체를 찾아 해당 요소의 속성값(여기서는 innerText)을 변경하는 문제이다.
임의의 물리 DOM트리에서 일부 HTML 요소의 속성값이 변경될 때 이를 탐지하여 DOM 트리에 반영할 수 있을까?
사실 이는 속성값을 바꿔야 하는 HTML 요소를 document.getElementById('아이디')로 찾아 DOM 객체를 얻은 뒤 DOM 객체가 제공하는 속성이나 메서드로 원하는 작업을 하면 된다.
그러나 문제는 '아이디' 부분에 있다.
즉 HTML 요소를 <p>처럼 간결하게 사용하지 못하고 항상 <p id='아이디'> 형태로 id 속성을 명시해 줘야 한다. 또한 중복되지 않는 id 속성값을 부여하는 일도 쉽지 않다. 따라서 리액트는 가상 DOM이라는 개념을 도입하여 이 아이디 문제를 해결한다.
'Framework > ReactJs' 카테고리의 다른 글
체크박스 로직(발송예약/수정: 체크 상태가 유지돼야 하는 경우) (0) | 2024.04.15 |
---|---|
useContext 훅 (0) | 2023.06.16 |
todo-react-app(front) : 완료(인증포함) (0) | 2023.05.26 |
todo-java (0) | 2023.05.24 |
todo-react-app(front) : fetch 이후 CORS 오류, useEffect, fetch, Promise (0) | 2023.05.24 |