Virtual DOM ?
Virtual DOM은 실제 DOM 노드 트리를 복제한 JS 객체
실제 DOM 보다 가벼움! (DOM 관련 API 메서드를 가지고 있지 않기 때문)
Virtual DOM 없이 그냥 DOM 을 조작하게 되면 DOM의 변경이 있을 때 마다 브라우저 렌더링 과정 Parsing ~ Paint 까지 모두 새로 해야하기 때문에 비용이 크게 든다!... 💰
리액트, 뷰 같은 SPA 방식의 웹 개발은 많은 DOM 조작을 필요로 하게 되는데
이때의 렌더링 비용을 낮추기 위해 만들어졌다.
- 실제 DOM 노드에 변화가 생기면 새로운 Virtual DOM 트리를 생성
- 현재 Virtual DOM과 이전 Virtual DOM을 비교
- 변경된 부분을 실제 DOM에 반영
변화가 일어날 때 마다 새로운 Virtual DOM을 생성하는 것이 비효율적이라고 생각할 수 있는데 DOM의 조작에 있어서 비용이 비싼 이유는 렌더링 때문이지 새로운 DOM을 생성하는 것은 메모리 영역에서 해결하기 때문에 빠르게 진행됨 :)
즉, Virtual DOM의 목표는 렌더링을 최소화 하는 것
리액트에서는 재조정이라는 과정을 통해 렌더링을 최소화함.
재조정 : Virtual DOM과 실제 DOM을 비교하고 일치시키는 과정
재조정을 할 때 변경 전, 후의 Virtual DOM을 비교하는 과정에서
Diffing 알고리즘을 사용하는데
Diffing 알고리즘은 변경 전, 후의 Virtual DOM 요소의 태그가 같다면 속성만 변경하고 다르다면 이전 트리를 삭제하고 완전히 새로운 트리를 만든다.
(ex 요소의 태그가 같은 경우 h1 === h1, 다른 경우 h1 !== a)
리액트에서 자식 컴포넌트에 key prop을 주지 않아서 에러가 나는 경우가 있는데
재조정 과정을 알기 전 나는 굳이 왜 key prop을 줘야하는지 이해가 안 됐었다.
### 정상 예시 코드 ###
// before
<ul>
<li>first</li>
<li>second</li>
</ul>
// after
<ul>
<li>first</li>
<li>second</li>
<li>third</li>
</ul>
위와 1번 예시 코드 같은 요소의 전, 후 차이에서 추가만 되는 코드라면 재조정에서 새로 추가된 third만 렌더링 하게 되는데
### 렌더링 성능 이슈 예시 코드 ###
// before
<ul>
<li>first</li>
<li>second</li>
</ul>
// after
<ul>
<li>second</li>
<li>third</li>
<li>first</li>
</ul>
위 2번 예시 코드처럼 전, 후 차이에서 자리바뀜 + 추가 형태라면 리액트는 자리가 바뀌었으므로 새로운 컴포넌트로 판단하여 3가지 요소 모두 렌더링하게 되어 성능 이슈가 발생할 수 있다.
그래서 리액트는 key prop을 식별자로 제공하여 key 값을 기준으로 렌더링 유무를 판단할 수 있는 것이다.
당연히 key 값이 변하는 값이 아니라 고유 값이어야 하는 이유도 알겠죠 😉?