DOM(Document Object Model)이란?
DOM은 문서 객체 모델(Document Object Model)의 약자로, HTML 등의 요소를 JavaScript와 같은 언어에서 사용할 수 있도록 해주는 구조를 의미한다.
이렇게만 설명하면 잘 이해가 되지 않을 수 있다.
DOM에 대해 더 깊이 이해하기 위해 먼저 브라우저의 작동 원리를 살펴보자.
브라우저의 작동 원리
브라우저가 어떤 페이지를 표시하는 과정을 예로 들어보자.
브라우저는 서버에 요청을 보내 HTML을 다운로드한다.
HTML을 받은 후 브라우저는 위에서부터 차례대로 내용을 해석한다.
이 과정에서 브라우저는 HTML 정보를 내부 메모리 상에서 DOM이라는 구조로 변환한다.
그 다음 DOM을 사용하여 실제 페이지를 화면에 그린다.
이제 브라우저의 전체적인 흐름을 이해했으니, DOM에 대해 좀 더 자세히 알아보자.
노드란?
DOM의 구조는 트리 구조로, 마치 나무를 거꾸로 뒤집은 형태와 같다.
나무에 많은 가지와 잎이 있는 것처럼, DOM도 많은 객체로 구성되어 있으며, 각각의 객체는 노드(Node)라고 불린다.
DOM 조작이란?
DOM은 화면의 요소와 연동되어 있기 때문에, DOM의 노드를 변경하면 즉시 그 변경 사항이 페이지에 반영된다.
JavaScript와 같은 프로그래밍 언어를 사용하면 버튼의 글자를 바꾸거나 새로운 요소를 추가하는 것이 가능하다.
이렇게 페이지의 모습을 동적으로 변경하기 위해 DOM의 노드를 조작하는 것을 DOM 조작이라고 한다.
// 예시 코드
document.addEventListener("DOMContentLoaded", function() {
// 버튼의 텍스트를 변경하는 DOM 조작 예시
const button = document.getElementById("myButton");
button.textContent = "클릭하세요";
// 새로운 요소를 추가하는 DOM 조작 예시
const newElement = document.createElement("div");
newElement.textContent = "새로운 요소";
document.body.appendChild(newElement);
});
DOM을 이해하고 나면, 이제 가상 DOM에 대해 알아볼 차례이다.
가상 DOM(Virtual DOM)
가상 DOM은 메모리 상에 DOM의 가상 표현을 유지하고 실제 DOM과 동기화하는 프로그래밍 개념이다.
가상 DOM에 대해 이해하기 위해 DOM 조작과 렌더링에 대해 먼저 알아보자.
DOM 조작과 렌더링
DOM 조작과 렌더링은 밀접하게 관련되어 있다.
JavaScript 코드로 DOM을 조작하면 브라우저는 많은 단계를 거쳐 렌더링을 수행해야 한다.
복잡한 DOM 조작을 하거나 DOM 노드를 자주 업데이트하면 렌더링 시간이 오래 걸릴 수 있다.
이 문제를 해결하기 위해 가상 DOM이 도입되었다.
가상 DOM의 원리
가상 DOM은 실제 DOM의 복사본이라고 생각하면 이해하기 쉽다.
React에서는 먼저 실제 DOM의 복사본인 가상 DOM을 만든다. UI에 변경이 있을 때마다 새로운 가상 DOM을 생성하고, 두 개의 가상 DOM을 비교하여 차이를 감지한다.
차이가 있는 부분만 실제 DOM에 반영하여 실제 UI를 업데이트한다.
이를 통해 최소한의 DOM 조작으로 페이지를 변경할 수 있다.
가상 DOM에 대해 이해했으니, 이제 모듈 번들러에 대해 알아보자.
모듈 번들러란?
모듈 번들러는 여러 파일을 하나로 묶어주는 도구이다.
예를 들어 쇼핑 사이트를 개발할 때 로그인 기능, 장바구니 추가 기능, 상품 구매 기능 등이 각각 다른 파일에 작성되어 있을 수 있다.
모듈 번들러를 사용하면 여러 파일을 하나의 JavaScript 파일로 묶을 수 있다.
모듈 번들러의 필요성
여러 파일을 하나로 묶는 이유는 웹사이트의 성능을 향상시키기 위해서이다.
모듈 번들러를 사용하지 않으면 클라이언트는 필요한 파일을 개별적으로 다운로드해야 하므로 페이지 로딩 속도가 느려질 수 있다.
모듈 번들러를 사용하면 모든 기능이 하나의 파일로 묶이기 때문에, 사이트를 열 때 다운로드해야 할 파일이 하나로 줄어들어 로딩 속도가 빨라진다.
트랜스파일러
트랜스파일러는 "트랜스레이션"과 "컴파일러"의 결합어로, 한 프로그래밍 언어로 작성된 코드를 다른 프로그래밍 언어로 변환하는 소프트웨어를 의미한다.
컴파일러와 트랜스파일러의 차이
컴파일러는 프로그래밍 언어로 작성된 코드를 기계어로 변환하는 소프트웨어이다.
예를 들어, GO 언어로 작성된 프로그램은 컴파일러를 통해 기계어로 변환되어야 컴퓨터가 이해할 수 있다.
트랜스파일러는 한 프로그래밍 언어로 작성된 코드를 다른 언어로 변환한다.
예를 들어, TypeScript로 작성된 코드는 트랜스파일러를 통해 JavaScript 코드로 변환된다.
이를 통해 브라우저에서도 TypeScript 코드를 실행할 수 있게 된다.
유명한 트랜스파일러 도구로는 Babel이 있다.
바벨(Babel)의 정의
바벨은 자바스크립트 코드를 최신 문법에서 오래된 문법으로 변환해주는 트랜스파일러이다.
이는 자바스크립트의 새로운 기능을 지원하지 않는 브라우저에서도 코드를 실행할 수 있게 해준다.
바벨의 필요성
다양한 브라우저가 존재하고, 각 브라우저는 지원하는 자바스크립트 기능이 다르다.
바벨을 사용하면 새로운 자바스크립트 문법을 오래된 문법으로 변환하여 모든 브라우저에서 코드가 동일하게 동작할 수 있도록 한다.
모듈의 정의
모듈은 특정 기능을 구현하기 위한 프로그램의 덩어리이다.
예를 들어 쇼핑 사이트 개발 시 로그인 기능, 장바구니 추가 기능, 상품 구매 기능 등을 각각의 파일로 나누어 정리할 수 있다.
이러한 각각의 파일을 모듈이라고 한다.
모듈 분할의 장점
모듈 분할의 장점은 코드의 가독성을 높이고, 재사용성을 높이며, 팀 개발을 용이하게 한다는 점이다.
ESM(ECMAScript Module)의 정의
ESM은 ECMAScript Module의 약자로, 자바스크립트 파일을 모듈화하는 언어 표준 기능이다.
ESM의 필요성
ESM은 CommonJS의 문제점을 해결하기 위해 등장했다.
CommonJS 모듈은 브라우저에서 직접 사용할 수 없기 때문에 번들링을 거쳐야 했다.
ESM은 브라우저에서 직접 모듈을 불러올 수 있도록 하여 이 문제를 해결하였다.
ESM의 사용 방법
ESM에서는 import
와 export
라는 키워드를 사용해 모듈을 불러오거나 내보낼 수 있다.
ESM을 사용할 때는 <script>
태그의 type
속성에 module
이라고 반드시 지정해야 한다.
이렇게 해야 브라우저가 파일을 모듈로 인식할 수 있다.
비동기 처리
비동기 처리는 동기적이지 않은 처리를 의미한다.
동기 처리는 작업이 순서대로 실행되는 방식이며, 비동기 처리는 이전 작업이 완료될 때까지 기다리지 않고 다음 작업을 수행하는 방식이다.
비동기 처리의 필요성
동기 처리 방식에서는 시간이 많이 걸리는 작업이 있을 경우 다른 작업이 지연될 수 있다.
비동기 처리를 사용하면 이런 문제를 해결할 수 있다.
자바스크립트에서는 비동기 작업을 통해 웹페이지가 멈추지 않고 사용자 입력에 반응할 수 있도록 한다.
// 예시 코드
function fetchData() {
console.log("Fetching data...");
// 비동기 처리 예시: setTimeout을 사용하여 지연된 작업을 수행
setTimeout(() => {
console.log("Data fetched!");
}, 2000); // 2초 후에 실행
}
function main() {
console.log("Start");
fetchData();
console.log("End");
}
main();
Promise란?
프로미스(Promise)는 ES2015에 도입된 비동기 처리의 상태와 결과를 표현하는 객체이다.
Promise 사용 방법
프로미스를 생성하려면 new Promise
구문을 사용한다.
프로미스는 'pending', 'fulfilled', 'rejected'의 세 가지 상태를 가지며, 작업이 성공하면 resolve
를, 실패하면 reject
를 호출하여 상태를 변경할 수 있다.
let promise = new Promise((resolve, reject) => {
// 작업 성공 시 resolve 호출
resolve('Fulfilled!');
// 작업 실패 시 reject 호출
// reject('Rejected!');
});
promise.then(result => {
console.log(result); // Fulfilled!
}).catch(error => {
console.log(error); // Rejected!
});
then
과 catch
의 사용 방법
then
메서드는 작업이 성공했을 때, catch
메서드는 작업이 실패했을 때 실행할 동작을 정의한다.
비동기 작업의 결과를 처리하기 위해 다음과 같이 사용할 수 있다.
let orderPizza = new Promise((resolve, reject) => {
let isDelivered = true; // 피자가 배달되었는지 여부
if (isDelivered) {
resolve('배달 완료: 맛있었어요');
} else {
reject('취소됨: 환불해 주세요');
}
});
orderPizza.then(result => {
console.log(result); // 배달 완료: 맛있었어요
}).catch(error => {
console.log(error); // 취소됨: 환불해 주세요
});
이와 같이 프로미스를 사용하면 비동기 작업의 결과를 효과적으로 처리할 수 있다.
이제까지 DOM, 가상 DOM, 모듈 번들러, 트랜스파일러, 바벨, 모듈, ESM, 비동기 처리, 그리고 프로미스에 대해 알아보았다.
각 개념들은 현대 웹 개발에서 필수적으로 이해해야 하는 중요한 요소들이다.
이 개념들을 잘 이해하고 활용하면 더욱 효율적이고 강력한 웹 애플리케이션을 개발할 수 있을 것이다.
이 글이 여러분의 웹 개발 여정에 도움이 되기를...
'Javascript' 카테고리의 다른 글
TypeScript에서 Array<T>와 T[]의 차이점 이해하기 (0) | 2024.07.17 |
---|---|
JavaScript의 async, await에 대해 깊이 이해하기 (0) | 2024.07.01 |
TypeScript 타입 추론의 새로운 지평: infer의 매력 (0) | 2024.06.16 |
예제로 알아보는 TypeScript 유틸리티 타입 (1) | 2024.06.16 |
Deno v2를 향하여 - Deno v2, deno_std v1, Fresh v2에 대하여 (0) | 2024.06.10 |