
Today I Learn📖
- Javascript의 코드 트릭 (강의)
- HTML, CSS (강의)
- DOM, Virtual DOM (강의)
- id와 class의 차이, CSS 선택자 종류 (추가 학습)
- 레이아웃 리플로우, 리페인팅 (추가 학습)
- document.createDocumentFragment(추가 학습)
: ES6의 구조 분해 할당 문법을 통해 두 변수를 swap 할 수 있음
let a = 5, b = 10;
[a, b] = [b, a];
console.log(a, b); // 10 5
: 두 객체를 별도 변수에 합쳐줄 수 있음
const person = {
name: 'Ha-Song-Hee',
familyName: 'Ha',
givenName: 'Song-Hee'
};
const favoriteCafe = {
name: 'TwoSomePlace',
cause: 'CakeVeryGooood'
};
const Hasonghee = { ...person, ...favoriteCafe };
console.log(Hasonghee);
// {
// name: 'TwoSomePlace'
// cause: 'CakeVeryGooood'
// givenName: “Song-Hee”
// name: "TwoSomePlace" // 같은 키는 우선 순위에 따라 정해진다.
// }
// 기본값을 넣어주고 싶을 때 || 사용
// name이 0 / undefined / 빈 문자열 / null일 경우 'Guest'로 할당
const name = name || 'Guest';
/// && => flag가 true일 경우에만 실행
flag && func();
// 객체 병합
const makeAvartar = (showGender) => {
return {
name: 'Songhee',
...showGender && { gender: 'woman' }
}
};
console.log(makeAvartar(false));
// { name: 'Songhee' }
console.log(makeAvartar(true));
// { name: 'Songhee', gender: 'woman' }
HTML (Hyper Text Markup Language)
프로그래밍 언어 X
=> 로직이 실행되지 않기 때문 ! 그냥 문서의 연결 링크, 서식 등을 지정해주는 것
문서 구조(Structure) & 의미(Semantic)의 역할 담당
CSS (Cascading Style Sheets)
HTML에서 표현, 내용, 스타일 등을 분리해서 별도 양식으로 지정한 것
-> 그러다보니 HTML의 스타일 태그들은 점점 사라짐
문서의 표현 역할 담당
사용법
<head> 태그 안에 <style> 태그를 넣고, 스타일 태그 내에서 CSS 문법 작성하기/* CSS 문법 */
selector { /* 어디에 적용할지 */
property: value;
/* 어떤 스타일을: 어떻게 적용할지 */
...
}
참고 사이트: 코드펜
HTML 사용 주의점
태그마다 가진 기본 스타일이 있음
-> 맘에 안 들면 CSS 적용 안 해도 패딩 등의 스타일 적용될 수 있음
=> reset CSS로 기본 스타일 싹 삭제하면 됨
각 브라우저마다 기본 스타일이 다름
-> Normalize CSS를 통해 브라우저간 차이점 통합 시키기 가능
- 추상화 / 모델링: 현실에 있는 것을 특정 관점에서 바라보아서 객체로 만드는 것
key-value 형태, 웹 UI의 상태, 기능, 속성 등을 객체로 뽑아낸 것트리 구조: 최상위에서 하위로 뻗어나가는 구조

DOM 트리의 순회는 Pre Order(전위순회)로 이루어짐
-> 루트 ➡️ 왼쪽 자식 ~ 오른쪽 자식
- 브라우저가 HTML을 읽고 파싱 후,
DOM TREE구성- 그 다음, 브라우저가 Style Sheet를 파싱한 후 DOM 요소에 스타일을 입힘 ->
CSS OM TREE
=> 여기까지가 Attachment- 위 두 트리를 결합해서
Render Tree생성 => 레이아웃(/ 리플로우)을 통해 DOM 노드의 위치 정함- 렌더 트리를 바탕으로 화면에 그림
↘️ DOM, CSSOM, RENDER TREE
1. 자바스크립트 메서드로 DOM 선택
.getElementById("id")id로 요소 노드 찾음, 같은 id 존재할 경우 제일 먼저 찾은 요소 하나를 반환 .getElementsByClassName("class명")class로 요소 노드 찾음, 여러 개 존재시 일치하는 모든 요소를 리스트로 반환 .getElementsByTagName("태그명"): DOM Tree에서 태그로 요소 노드 찾음, 여러 개 존재시 일치하는 모든 요소를 리스트로 반환 .querySelector("아이디 / .클래스명")CSS Selector 문법으로 요소 노드 찾음, 같은 id 존재할 경우 제일 먼저 찾은 요소 하나를 반환 .querySelectorAll("아이디 / .클래스명")CSS Selector 문법으로 요소 노드 찾음, 여러 개 존재시 일치하는 모든 요소를 리스트로 반환 window.id / window[id]2. 위 방법으로 선택한 DOM 탐색 -> 돔선택.메서드
.parentNode.firstElementNode.lastElementNode.children.nextElementSibling.previousElementSibling3. DOM 조작
.className, .classList.hasAttribute("속성명").getAttribute("속성명").setAttribute("속성명", "값").removeAttribute("속성명").textContent = "텍스트값".innerHTML = "<태그>변경할 값</태그>".creatElement("태그명").appendChild(생성한 요소 노드명).removeChild(요소 노드명)가상돔 탄생Virtual DOM (가상 돔)
실제 DOM TREE에서 필요한 정보만 담아 자바스크립트 객체로 만든 것
-> 돔을 직접 수정하지 않고, 가상 돔에서 바뀐 부분만 수정 후 렌더링
=> 브라우저 렌더링 프로세스가 줄어듦
리액트 & 뷰에서도 가상돔을 사용함
React(=> Virtual DOM)이 DOM보다 빠른 것은 아님
-> 페이지에 그려진 DOM이 많으면 느려지는 건 똑같음. 심지어 진짜 돔, 가상돔 2번 탐색해야하니까 탐색 & 메모리 사용이 2배여서 실제로는 더 느림 (가상돔은 브라우저 렌더링 횟수를 줄여주는 것, 속도는 X)
-> 빠른 개발에는 성능 최적화보다 개발 편의성이 더 우선시되는데, 가상돔은 편하고 유지보수를 쉽게 만들어줌. 그리고 대부분의 상황에서 충분히 빠르니까 문제가 되지 않아 사용하는 것 !
id: HTML 요소를 유일하게 식별하기 위해 사용
-> 원칙적으로 하나의 id는 한 번만 사용되어야 함
-> CSS에서의 선택자는 #
-> JavaScript에서는 getElementById()이 가장 많이 쓰임 (querySelector(), querySelectorAll() 등으로도 선택 가능)
// HTML
<div id=“아이디명”>content</div>
// CSS
#아이디명 {
background-color: blue;
}
// 자바스크립트
const element = document.getElementById(“아이디명);
console.log(element);
동일한 id가 여러 개 사용될 경우
-> CSS에서는 모든 요소에 해당 스타일이 적용될 수도 있음. 하지만 표준적이지 않은 방법
-> 자바스크립트에서는 예상치 못한 동작 발생 가능 (에러 위험 높임)
-> getElementById()에서는 여러 개여도 첫 번째로 등장하는 id만 반환
class: 여러 요소에 공통된 스타일 또는 기능을 적용하기 위해 사용
-> 하나의 요소에 여러 개의 class 사용 가능 (재사용성 높음)
-> CSS에서의 선택자는 .
-> JavaScript에서는 getElementsByClassName(), querySelector() 등 사용 가능
// HTML
<div class=“클래스명1 클래스명2”>content</div>
<div class=“클래스명1”>content</div>
// CSS
.클래스명1 {
border: 1px solid black;
}
.클래스명2 {
border-radius: 8px;
}
// 자바스크립트
const elements = document.getElementsByClassName(“클래스명1”);
console.log(elements);
| 구분 | id | class |
|---|---|---|
| 유일성 | 문서 내에서 유일해야 함 | 여러 요소에 사용 가능 |
| 용도 | 특정 요소를 정확하게 식별 | 공통 스타일 및 기능 적용 |
| 우선순위 | 높음 | 낮음 |
| CSS 선택자 | #아이디명 | .클래스명 |
| JavaScript | getElementById() | getElementsByClassName() |
CSS 선택자 종류
- 기본 선택자
⠀/* 전체 선택자: 문서 내 모든 요소 선택 */ * { color: blue; } ⠀ /* 태그 선택자: 특정 HTML 태그 선택 */ p { font-size: 16px; } ⠀ /* id 선택자: 특정 id 요소 선택 */ #아이디명 { color: blue; } ⠀ /* class 선택자: 특정 클래스 요소 선택 */ .클래스명 { color: blue; }- 복합 선택자
⠀/* 자식 선택자 (>): 바로 아래 자식 요소 선택 */ div > p { color: blue; } ⠀ /* 후손 선택자 (공백): 특정 요소의 모든 하위 요소 선택 */ div p { color: blue; } ⠀ /* 인접 형제 선택자 (+): 바로 다음 형제 요소를 선택 */ h1 + p { font-size: 14px; } ⠀ /* 일반 형제 선택자 (~): 특정 요소의 모든 형제 요소 선택 */ h1 ~ p { color: blue; }- 속성 선택자: HTML 요소의 속성 기준 선택
⠀/* 특정 속성을 가진 요소 */ input[type="text"] { font-size: 14px; } ⠀ /* 특정 속성 값을 포함하는 요소 */ a[href*=“99heesong] { color: blue; }- 의사 선택자, 의사 요소
⠀/* 의사 클래스(:): 특정 상태의 요소를 선택 */ a:hover { color: blue; } ⠀ /* 의사 요소(::): 요소의 특정 부분을 선택 */ p::first-line { font-size: 14px; }
브라우저 렌더링 중, Layout 단계에서 화면에 변화가 발생하여 이 단계가 재실행되는 과정들. 웹 성능 최적화에서 중요한 역할을 함
Layout 단계: Render Tree를 기반으로 요소들의 위치와 크기를 계산하는 단계
레이아웃 리플로우 (Layout Reflow): 요소의 위치와 크기를 다시 계산해야 할 때 발생하는 과정
-> 브라우저가 모든 요소의 위치와 크기를 재계산해야 하므로 성능 부담 큼
-> 모든 부모 & 자식 요소를 다시 계산해야 하므로 성능 저하의 주원인이 될 수 있음
리플로우 발생 원인
리페인팅 (Repainting): 스타일 변경으로 인해 요소가 다시 그려질 때 발생하는 과정
-> 위치와 크기는 유지됨
-> 리플로우보다는 아니지만, 브라우저 리소스를 사용하는 거니까 빈번하면 성능 저하 발생 가능
리페인팅 발생 원인:
visibility 속성 변경 (display는 리플로우도 같이 발생)| 구분 | 리플로우 (Reflow) | 리페인팅 (Repaint) |
|---|---|---|
| 발생 원인 | 레이아웃에 영향을 주는 속성 변경 | 스타일(색상, 배경 등) 변경 |
| 렌더링 과정 | Layout 단계 + Painting 단계 재실행 | Painting 단계만 재실행 |
| 성능 부담 | 매우 큼 | 성능 저하에 영향 줄 수 있음 |
정말 빠른 성능이 필요해서 가상돔을 쓰지 않고 최적화할 때 사용
-> DOM 접근 횟수를 줄여 성능 최적화
DocumentFragment: 브라우저가 제공하는 가상의 DOM 노드 컨테이너
-> 브라우저 성능 최적화를 위해 DOM 조작을 메모리에서 먼저 수행하고, 마지막에 한번에 실제 DOM에 추가함
-> 실제로 화면에 렌더링되거나 DOM 트리의 일부로 간주되지 않음
-> 하지만 실제 일반 노드처럼 동작함 (자식 요소 추가, 수정 가능)
=> 메모리 상에만 존재하는 임시 노드 개념
// DocumentFragment 생성
const fragment = document.createDocumentFragment();
// 여러 개의 리스트 아이템 생성
for (let i = 0; i < 5; i++) {
const li = document.createElement("li");
li.textContent = `아이템 ${i + 1}`;
fragment.appendChild(li); // Fragment에 추가
}
// DOM에 한 번에 추가
document.getElementById("myList").appendChild(fragment);
DOM을 조작하면 변경 사항이 화면에 즉시 반영됨 (리렌더링, 리플로우 & 리페인팅)
-> 반복되면 성능 저하 유발
=> DocumentFragment 사용시 해결 가능
DocumentFragment에 모두 적용하고, 한꺼번에 DOM에 추가해서 렌더링 비용 최소화됨| 항목 | 가상 DOM | DocumentFragment |
|---|---|---|
| 목적 | 라이브러리나 프레임워크 사용시 UI 업데이트 최적화 | 바닐라JS에서 DOM 조작 시 리렌더링 최소화 |
| 의존성 | 프레임워크에 의존적 (React, Vue.js 등) | 브라우저 네이티브 API |
| 동작 방식 | 가상 DOM 트리를 메모리에 유지하고 비교 | 메모리에서 DOM 요소를 먼저 조작 후 한꺼번에 이동 |
| 최적화 범위 | 전체 DOM 트리의 변경 사항을 비교하고 업데이트 | 특정 DOM 요소만 조작 |
| 비용 | 가상 DOM 생성 및 비교에 메모리 비용이 발생 | 메모링서만 작업하므로 리소스 비용 적음 |
코딩 테스트를 준비하며 마음가짐, 공부 방법, 좋은 코드 작성 방법 등에 대한 꿀팁을 많이 알려주셔서 도움이 많이 될 것 같다. 코딩테스트라고 하면 마음이 급급해지는데, 차분하게 메모하면서 풀기 기억..!
그리고 시간복잡도를 계산하고 유형을 추리해야한다는 것도 머리로는 알지만 실제로는 잘 안 됐는데, 좋은 점수를 위해 체화시켜야할 것 같다 ㅎㅎ
자바스크립트 코드 트릭을 여러 개 알려주셨는데 희미한 기억이거나 새로운 것들만 적어봤다. 얘네도 까먹지 않고 사용해야겠다 😃
HTML, CSS에 대해 복습할 수 있었다. 그리고 생소한 개념인 DOM과 가상돔에 대해 알게되고, 그 안의 메서드들을 보면서 자바스크립트의 사용법을 익혔다.
강사님 덕분에 코딩테스트 대비 갈피를 잡을 수 있었고, 프론트엔드 개발자로서의 기초 지식을 탄탄히 쌓은 느낌이다.
이선협 강사님 덕분에 많이 배웠습니다 !! 감사합니다 ㅎㅎ