김동현(정글12기-73) 정범진(정글12기-64) 최수지(정글12기-80) 황정연(정글12기-71)
학습 보조 수준
개념 학습, 문제 및 코드 이해, 힌트 요청, 코드 리뷰, 오류 분석
코드 구현을 제외하고는 자유롭게 사용 가능합니다.
💡 학습에 AI를 사용할 때에는 ChatGPT의 ‘Study Mode’나 Gemini의 ‘Guided Learning’ 옵션을 활성화하여 사용합니다.
💡 코드 구현시에는 최대한 AI를 사용하지 않고, 동료와의 협업과 도움을 최대한 활용합니다.
브라우저는 HTML의 각 테그들을 객체로 들고 있음 -> DOM은 html을 구조(객체)로 변환한 것
DOM은 HTML을 객체 트리로 표현한 것. 그리고 그 안에 모든 노드들도 각각 DOM이라고 부름
html에서 테그 내부 데이터를 바꾸면 화면에 바로 적용 -> dom을 바꾸면 화면도 바뀜
브라우저는 트리에서 노드의 데이터가 바뀌었을 때 어디가 어떻게 바뀌었는지 최적의 변경 방법을 계산하지 않음. -> 대신 개발자가 내린 DOM 조작 명령을 그대로 수행
일반적인 브라우저인 경우
<ul>
<li>A</li>
<li>B</li>
</ul>
에서 다음으로 바꿀 때
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
</ul>
아래 처럼 코드 작성하면 기존 a,b 제거 후 새로 a, b, c생성 -> 비효율
container.innerHTML = `
<li>A</li>
<li>B</li>
<li>C</li>
`
이렇게 작성할 경우 C부분만 새로 추가 -> 효율
const li = document.createElement("li")
li.textContent = "C"
ul.appendChild(li)
하지만 사람이 항상 아래처럼 효율적으로 작성하기 힘들기 때문에
Virtual DOM이 차이를 계산해서 브라우저한테 명령 전달
그리고 그 차이를 계산하는 알고리즘이 Diff알고리즘
Diff 알고리즘 핵심 규칙 3가지
<div>
->
<span>
<div class="a">
->
<div class="b">
실제 DOM 구조
ul (DOM 노드)
├── li (A)
└── li (B)
자식 노드는 배열처럼 접근 가능함
ul.children 하면
HTMLCollection [li, li] 반환
key가 필요한 이유
key가 없으면 둘 다 li이기 때문에 구분이 안됨
ㄴ 정확히는 key가 없으면 index 기준으로 비교 -> 타입같고 key 없ㅇ르 때 같은 위치의 요소를 같은 것으로 간주 -> 리스트 내부 순서 바뀌면 어지러워짐
테그가 같을 때 내용을 비교하기 때문에 만약 a, b위치를 바꿨을 때 key를 사용하지 않으면 a와 b모두 수정하게 됨
하지만 key를 사용하면 a와 b의 위치 이동을 발견하고 순서를 바꿀 수 있음
ㄴ 그리고 만약 자식노드가 추가로 있다면 a의 자식노드와 b의 자식노드 위치가 안바뀌고 그대로 있는 문제가 생길 수 있음
key는 우리가 지정해야됨. 보통 안바뀌는 값으로 지정 예를 들어 id
리엑트가 사용하는 Diff 알고리즘은 빠른추정(휴리스틱) Diff 사용
완벽한 Diff 알고리즘은 시간복잡도가 O(N^3)로 매우 느림
ㄴ 왜 n^3 지?
ㄴ 빠른 추정은 왜 n이지?
브라우저가 DOM을 탐색할 때 dfs(pre-order traversal)와 유사한 document order 순회를 사용
ㄴ 조건에 맞는 첫 번째 노드 발견 시 종료
idMap(브라우저마다 이름 다름): 브라우저가 내부에서 관리하는 id 매핑 구조
우리가 getElementById 했을 때 idMap["{id}"]에서 element 접근해서 반환
diff 알고리즘이 필요 없을 경우. 예를 들어 트리 전체를 수정해야 할 경우 오버헤드가 생겨서 안좋음
이전 Virtual DOM과 새로운 Virtual DOM을 비교할 때 같은 위치(index)를 기준으로 노드를 동일한 것으로 간주하고 매칭한다
DOM 자체는 diff하기에 구조적으로 비효율적이라 필요한 정보만 담은 Virtual DOM에서 diff 알고리즘을 사용
안녕하세요!
좋은 글 잘 보고 갑니다^^%