브라우저의 렌더링 과정
1. 요청과 응답
- 브라우저 주소창에 URL 입력 시 브라우저가 DNS를 통해 IP 주소 조회함
- 해당 서버로 HTTP 요청 전송함
- 서버는 HTML 문서를 응답으로 반환함
- 브라우저는 HTML 문서 수신 후 렌더링 엔진에 전달함
2. HTTP 1.0 과 HTTP 2.0
- HTTP 1.0: 요청마다 TCP 연결 새로 생성함, 다중 요청 불가능함, 리소스가 많은 페이지에서 성능 저하 발생함
- HTTP 2.0: 하나의 연결에서 다중 요청 동시 처리 가능함, 헤더 압축과 서버 푸시 지원으로 성능 향상됨
3. HTML 파싱과 DOM 생성
DOM 생성과정 요약
1. 렌더링 엔진이 HTML 문서를 읽고 토큰 단위로 분해함
2. 토큰을 객체로 변환하여 노드를 생성(문서 노드, 요소 노드, 어트리뷰트 노드, 텍스트 노드).
3. DOM(Document Object Model) 트리 생성함
4(결과). DOM은 HTML 문서의 계층적 구조를 메모리에 표현한 객체 모델임
<html>
<body>
<h1>Hello</h1>
</body>
</html>
위 HTML 문서는 <html>, <body>, <h1> 요소를 노드로 가지는 DOM 트리 생성함
4. CSS 파싱과 CSSOM 생성
- CSS 파서가 스타일시트를 파싱하여 CSSOM(CSS Object Model) 트리 생성함
- CSSOM은 각 노드별 스타일 규칙을 담고 있음
- DOM과 결합하여 렌더 트리 생성에 사용됨
5. 렌더 트리 생성
- DOM 트리와 CSSOM 트리 결합하여 렌더 트리 생성함
- 렌더 트리는 실제 화면에 표시될 노드와 스타일 정보를 포함함
- 보이지 않는 노드(<head>, display:none)는 렌더 트리에 포함되지 않음
6. 자바스크립트 파싱과 실행
- 브라우저의 JavaScript 엔진이 자바스크립트 코드 처리함
- 토크나이징(Tokenizing): 소스 코드를 토큰 단위로 분해함
- 파싱(Parsing): 토큰을 AST(Abstract Syntax Tree)로 변환함
- 실행(Execution): AST를 바이트코드로 컴파일하고 실행함
7. 리플로우와 리페인트
- 리플로우(Reflow): 레이아웃이 변경될 때 다시 렌더 트리 계산하는 과정임
- 리페인트(Repaint): 색상, 배경 등 시각적 스타일 변경 시 발생함
- 리플로우가 성능에 더 큰 영향을 미침
8. 자바스크립트 파싱에 의한 HTML 파싱중단
- 브라우저는 <script> 태그 만나면 HTML 파싱 중단하고 스크립트 실행함
- DOM 생성 지연으로 초기 렌더링 속도 저하 원인 될 수 있음
9. script 태그의 async/defer 어트리뷰트
- async: 스크립트 다운로드와 HTML 파싱 병렬 처리, 다운로드 완료 시 즉시 실행함
- defer: 스크립트 다운로드 병렬 처리, HTML 파싱 끝난 뒤 실행함
<script src="script.js" async></script>
<script src="script.js" defer></script>
- async는 다운로드 완료 순서대로 실행, defer는 HTML 파싱 완료 후 순서대로 실행함
요약
- 요청과 응답 → HTML/CSS 파싱 → DOM/CSSOM 생성 → 렌더 트리 생성 → 자바스크립트 실행 → 리플로우·리페인트 순으로 렌더링 진행됨
- async, defer 속성 사용 시 HTML 파싱과 자바스크립트 실행 효율적으로 조정 가능함
DOM(Document Object Model)
1. 노드
- DOM은 문서의 계층적 구조와 정보를 표현하는 트리 구조 모델임
- HTML 요소, 텍스트, 속성 등을 각각 노드(node)로 표현함
- 노드 타입 종류
- 문서 노드(Document): HTML 문서 전체 표현
- 요소 노드(Element): HTML 태그 표현
- 텍스트 노드(Text): 요소 안의 텍스트 콘텐츠 표현
- 어트리뷰트 노드(Attribute): 요소의 속성 표현
- 주석 노드(Comment): 주석 데이터 표현
<html>
<body>
<h1 id="title">Hello</h1>
</body>
</html>
위 예시에서 <h1>은 요소 노드, "Hello"는 텍스트 노드임
- 문서노드는 Document, HTMLDocument 인터페이스를 상속받음
- 어트리뷰트 노드는 Attr을 상속받음
- 텍스트 노드는 CharacterData 인터페이스를 상속받
2. 요소 노드 취득
- 자바스크립트에서 DOM 요소 접근 방법
- getElementById(id): ID로 요소 선택
- getElementsByTagName(tag): 태그 이름으로 요소 컬렉션 선택
- getElementsByClassName(class): 클래스 이름으로 요소 컬렉션 선택
- querySelector(selector): CSS 선택자로 첫 번째 요소 반환
- querySelectorAll(selector): CSS 선택자로 모든 요소 반환
const title = document.getElementById('title');
const items = document.querySelectorAll('.item');
3. 노드 탐색
공백문자는 텍스트 노드를 생성한다!!
만약 인위적으로 HTML 공백문자를 제거하면 공백 텍스트 노드를 생성하지 않지만, 이는 가독성이 좋지않으므로 권장되지 않음.
- 노드 간 관계를 통해 DOM 트리 탐색 가능함
- parentNode: 부모 노드 반환
- childNodes: 자식 노드 반환 (텍스트 노드 포함)
- children: 자식 요소 노드만 반환
- firstChild, lastChild: 첫/마지막 자식 노드 반환
- previousSibling, nextSibling: 형제 노드 탐색
- previousElementSibling, nextElementSibling: 형제 요소 노드 탐색
const parent = title.parentNode;
const first = parent.firstChild;
4. 노드 정보 취득
- nodeType: 노드 유형 숫자 반환
- nodeName: 노드 이름 반환
- nodeValue: 텍스트 노드 값 반환
console.log(title.nodeType); // 1 (요소 노드)
console.log(title.nodeName); // H1
5. 요소 노드의 텍스트 조작
- textContent: 요소 내 모든 텍스트 콘텐츠 접근
- innerText: 렌더링된 텍스트만 접근
title.textContent = 'Welcome';
6. DOM 조작
- 요소 생성: document.createElement(tagName)
- 텍스트 노드 생성: document.createTextNode(text)
- 노드 추가: appendChild(node), insertBefore(new, ref)
- 노드 제거: removeChild(node)
- 노드 교체: replaceChild(new, old)
const newDiv = document.createElement('div');
document.body.appendChild(newDiv);
7. innerHTML
- 요소 내부 HTML 마크업을 문자열로 접근 및 변경 가능함
- 기존 콘텐츠 모두 제거하고 새로운 HTML 파싱하여 DOM으로 변환함
- XSS(교차 스크립팅 공격) 주의 필요함
- 웹 사이트의 어드민(관리자)이 아닌 악의적인 목적을 가진 제 3자가 악성 스크립트를 삽입하여 의도하지 않은 명령을 실행시키거나 세션 등을 탈취할 수 있는 취약점
- 예시
- <script>alert("hi")</script> : 대놓고 script 태그를 넣어 alert를 실행시키는 구문. 이 구문이 실행된다면 해당 사이트는 XSS에 대한 대책이 전혀 없는 것이라 봐도 무방
- <scr<script>ipt>alert("hi");</scr</script>ipt> : <script> 태그를 일차적으로 필터링하는 것을 우회하기 위한 구문, 중첩된 script 태그가 필터링되면 갈라져있던 script 태그가 결합되면서 구문이 실행
- <a onmouseover="alert('hi')"> : a 태그를 이용한 공격입니다. onmouseover 이벤트를 통해 공격을 실행
document.body.innerHTML = '<h2>New Content</h2>';
8. 어트리뷰트
- 요소의 속성 접근 및 조작 가능함
- getAttribute(name), setAttribute(name, value), hasAttribute(name), removeAttribute(name) 제공함
const link = document.querySelector('a');
link.setAttribute('href', 'https://example.com');
- HTML 표준 속성은 프로퍼티처럼 직접 접근 가능함
link.href = 'https://example.com';
9. 스타일
- style 프로퍼티 통해 인라인 스타일 조작 가능함
title.style.color = 'red';
title.style.fontSize = '24px';
- CSS 클래스 조작 메서드
- classList.add(className)
- classList.remove(className)
- classList.toggle(className)
- classList.contains(className)
title.classList.add('highlight');
10. DOM 표준
- W3C와 WHATWG에서 DOM 표준 관리함
- 현재는 WHATWG 단일 사양으로 통합됨
- DOM Level 1: 기본 구조와 접근 API 정의함
- DOM Level 2: 이벤트 모델, CSS 지원 추가함
- DOM Level 3: XPath, Load & Save, Keyboard 이벤트 추가함
- 이후 HTML5와 함께 지속 확장됨
요약
- DOM은 문서 구조를 객체 모델로 표현하고 자바스크립트를 통해 동적 조작 가능하게 함
- 노드 탐색, 조작, 속성 변경, 스타일 제어 등 풍부한 API 제공함
이벤트(Event)
1. 이벤트 드리븐 프로그래밍
- 프로그램 흐름이 이벤트에 의해 결정되는 프로그래밍 방식임
- 브라우저 환경에서는 사용자 입력, 네트워크 응답, DOM 변화 등이 이벤트임
- 이벤트 발생 시 미리 등록한 이벤트 핸들러 실행됨
2. 이벤트 타입
- 마우스 이벤트: click, dblclick, mousedown, mouseup, mousemove, mouseover 등
- 키보드 이벤트: keydown, keyup, keypress
- 폼 이벤트: submit, change, input, focus, blur
- 윈도우 이벤트: load, resize, scroll, unload
- 드래그 & 드롭 이벤트: dragstart, dragover, drop 등
document.body.addEventListener('click', () => console.log('clicked'));
3. 이벤트 핸들러 등록
- HTML 속성 방식: 요소 태그에 on이벤트명 속성으로 등록
- DOM 프로퍼티 방식: 요소의 이벤트 프로퍼티에 함수 할당
- addEventListener 메서드: 한 요소에 여러 핸들러 등록 가능
<button onclick="alert('clicked')">Click Me</button>
const btn = document.querySelector('button');
btn.onclick = () => console.log('clicked');
btn.addEventListener('click', () => console.log('another click'));
4. 이벤트 핸들러 제거
- HTML 속성 방식과 DOM 프로퍼티 방식은 핸들러를 null 할당으로 제거함
- addEventListener 방식은 같은 함수 참조 필요함
function handleClick() { console.log('clicked'); }
btn.addEventListener('click', handleClick);
btn.removeEventListener('click', handleClick);
5. 이벤트 객체
- 이벤트 발생 시 이벤트에 대한 다양한 정보 담긴 객체 자동 생성됨
- 이벤트 핸들러 첫 번째 매개변수로 전달됨
- 주요 프로퍼티: type, target, currentTarget, timeStamp, key, clientX, clientY 등
btn.addEventListener('click', e => {
console.log(e.type); // click
console.log(e.target); // 이벤트 발생 요소
});
6. 이벤트 전파
- 캡처링 단계: 최상위 요소에서 이벤트 대상까지 내려감
- 타깃 단계: 이벤트 대상 도달
- 버블링 단계: 이벤트 대상에서 최상위 요소까지 전파
const parent = document.querySelector('#parent');
parent.addEventListener('click', () => console.log('parent'));
btn.addEventListener('click', () => console.log('button'));
7. 이벤트 위임
- 버블링 이용해 상위 요소에서 하위 요소 이벤트 일괄 처리 기법임
- 성능 향상과 코드 단순화에 유리함
document.querySelector('#list').addEventListener('click', e => {
if (e.target.tagName === 'LI') console.log(e.target.textContent);
});
8. DOM 요소의 기본 동작 조작
- 링크 클릭 시 페이지 이동, 폼 전송 같은 기본 동작 취소 가능함
- preventDefault() 메서드 사용함
document.querySelector('a').addEventListener('click', e => {
e.preventDefault();
console.log('링크 동작 취소됨');
});
9. 이벤트 핸들러 내부의 this
- HTML 속성 방식: 이벤트 핸들러 내부 this는 해당 요소 참조함
- DOM 프로퍼티 / addEventListener: this는 이벤트를 바인딩한 요소 참조함
btn.addEventListener('click', function() {
console.log(this === btn); // true
});
10. 이벤트 핸들러에 인수 전달
- 직접 호출 시 이벤트 객체 대신 undefined 전달되므로 주의 필요함
- 래퍼 함수 사용으로 인수 전달 가능함
btn.addEventListener('click', e => handleClickWithArgs(e, 123));
function handleClickWithArgs(e, id) { console.log(id); }
11. 커스텀 이벤트
- CustomEvent 생성자 사용해 사용자 정의 이벤트 생성 가능함
- dispatchEvent() 메서드로 이벤트 발생시킴
const custom = new CustomEvent('myEvent', { detail: { key: 'value' } });
btn.addEventListener('myEvent', e => console.log(e.detail));
btn.dispatchEvent(custom);
한줄요약
- 이벤트 드리븐 프로그래밍에서 이벤트 등록, 제거, 전파, 위임, 기본 동작 제어, 커스텀 이벤트까지 모두 이해 필요함
타이머
1. 호출 스케줄링
- 자바스크립트는 단일 스레드 기반 언어임
- 동시에 여러 작업 수행 불가, 이벤트 루프와 태스크 큐 사용해 비동기 작업 처리함
- 호출 스케줄링은 특정 함수 실행 시점 예약하는 기능임
- 브라우저 환경에서는 Web API 타이머 함수 활용함
- 지정한 시간 경과 후 콜백 함수 실행 예약 가능함
2. 타이머 함수
setTimeout
- 지정 시간 후 한 번만 콜백 함수 실행함
- 타이머 ID 반환, clearTimeout으로 취소 가능함
const timerId = setTimeout(() => console.log('3초 후 실행'), 3000);
clearTimeout(timerId);
setInterval
- 지정 시간 간격마다 반복 실행함
- 타이머 ID 반환, clearInterval로 취소 가능함
const intervalId = setInterval(() => console.log('1초마다 실행'), 1000);
clearInterval(intervalId);
requestAnimationFrame
- 화면 주사율에 맞춰 콜백 실행함
- 주로 애니메이션 구현에 사용함
- setInterval 대비 성능 최적화 장점 있음
function animate() {
console.log('프레임마다 실행');
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
3. 디바운스와 스로틀
- 짧은 시간 동안 이벤트가 많이 발생하면 성능 저하 발생함
- 디바운스와 스로틀 기법으로 호출 횟수 조절 가능함
디바운스(Debounce)
- 마지막 이벤트 발생 후 일정 시간 지나야 콜백 실행함
- 연속 입력 종료 시점에 한 번만 실행되게 함
- 주로 검색창 입력 처리에 사용함
function debounce(fn, delay) {
let timer;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
}
}
const processChange = debounce(() => console.log('입력 완료'), 500);
스로틀(Throttle)
- 일정 시간 간격으로 콜백 실행 보장함
- 스크롤 이벤트 같은 고빈도 이벤트 최적화에 사용함
function throttle(fn, limit) {
let inThrottle;
return function(...args) {
if (!inThrottle) {
fn.apply(this, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
}
}
const handleScroll = throttle(() => console.log('스크롤 중'), 1000);
- setTimeout, setInterval, requestAnimationFrame으로 호출 스케줄링 가능함
- 디바운스와 스로틀 기법으로 이벤트 처리 최적화 가능함
- 불필요한 연산 줄이고 성능 개선에 기여함
'개발' 카테고리의 다른 글
github 액션 yml 파일 만들기 (CI/CD 파이프라인 구축) (2) | 2025.08.28 |
---|---|
vercel 로 배포 및 CI/CD 파이프라인 구축하기(배포 자동화) (2) | 2025.08.28 |
[모던 자바스크립트 DeepDive] Js 심화 스터디 week 7 (3) | 2025.08.27 |
[모던 자바스크립트 DeepDive] Js 심화 스터디 week 6 (1) | 2025.08.10 |
[모던 자바스크립트 DeepDive] Js 심화 스터디 week 05 (2) | 2025.07.28 |