지금까지는
컴포넌트 함수들이 어떻게 실행되고
특정 상황들에서 어떻게
실행을 방지하는지 배워봤습니다
그럼 이제부터는
컴포넌트 함수가 실행될 때 실제로 무슨 일이 일어나고
이 JSX 코드가 어떻게 화면에 나타나는지 배워보겠습니다
가장 먼저 볼 것은
컴포넌트 함수가 실행되고
이 JSX 코드가 반환되면
이 컴포넌트 트리가 생성되고
최종적으로는 이 네이티브 HTML 요소들로 끝나는 것이라는 겁니다
만약 이 전체 컴포넌트 트리가 마지막에 해결이 된다면 말입니다
그리고 이 HTML 코드가 DOM에 삽입됩니다
이게 무슨 말인지 이해가 안 되실 수도 있습니다
바로 HTML 요소가 컴포넌트들로부터 반환되고
DOM으로 삽입된다는 개념입니다
여러분이 페이지를 새로고침하거나
처음 방문했을 때 생기는 일입니다
왜냐하면 그렇게 해야
빈 페이지로 처음부터 시작하기 때문입니다
따지자면 이 인덱스 HTML 파일을
불러온다는 점을 기억하시기 바랍니다
이는 마지막에는 빈 페이지가 됩니다
디브(div) 하나와 이 script 하나만 불러왔습니다
사실 이 전체 리액트 앱이 이 디브에 담겨있는 겁니다
이 컴포넌트 트리와 그 트리로 생성된 HTML이
렌더링될 겁니다
그래서 페이지 소스 코드를 보면
아무것도 보이지 않습니다
대신 elements 창을 보면
완전한 DOM 트리가 있습니다
이건 전부 리액트가 삽입한 것입니다
하지만 이 버튼을 눌러보면
이것들이 재생성되거나 재삽입되지 않습니다
굉장히 비효율적이기 때문이죠
그러니까 컴포넌트 함수가 재실행됐다고 해서
예를 들어 counter 컴포넌트 함수에서 우리가
이 버튼 중 하나를 클릭해봐도
컴포넌트 함수가 생성한 모든 JSX 코드가
DOM으로 재삽입되지 않습니다
이전 코드가 버려지고
새로운 HTML 코드로 대체되는 게 아닙니다
개발자 도구를 보면 확인해 볼 수 있습니다
예를 들어, 여기 Counter 섹션을 보면
이 문단을 펼쳐보겠습니다
counter 값을 포함하고 있습니다
오른쪽에 있는 이 HTML 코드를 보면
이 버튼을 클릭할 때마다
이 span이 깜빡거리는 게 보입니다
그리고 크롬 개발자 도구의
이 요소들이 바뀔 때마다 깜빡입니다
그러니까, DOM이 바뀌었을 때입니다
다른 말로 하면, 여기서 깜빡이는 요소들에만
리액트의 개입이 있었다는 겁니다
그러니까 이 값을 증가시키면
리액트가 이 span만 업데이트하는 것처럼 보이고
이 span 요소로만 동작하는 것처럼 보입니다
다른 모든 DOM 요소들은 리액트의 간섭을 받지 않았습니다
따지고 보면 이 Counter 컴포넌트도 물론
이 문단과 버튼들을 반환합니다
그럼에도, 그 중 아무것도 깜빡이지 않습니다
아무것도 바뀌지 않았다는 뜻입니다
그 이유는 리액트가
가상 DOM이라고 불리는 것을 사용해서
실제 DOM의 어떤 부분들이 업데이트되어야 하는지 찾기 때문입니다
그리고 이 가상 DOM을 사용하는 이유는
가상 DOM을 사용하면
이는 메모리 안에서만 존재하고
실제 DOM을 사용하는 것보다 빠르기 때문입니다
그럼 이 가상 DOM은 어떤 식으로 동작될까요?
페이지를 새로고침하면 전체 리액트 앱이 시작되고
처음 렌더링이 됩니다
리액트는 컴포넌트 트리를 만들고
마지막에는 렌더링되어야 하는 실제 HTML 코드를
그 컴포넌트 트리로부터 전달합니다
그리고 가상 DOM 스냅샷(snapshot)을 생성합니다
그러니까, 아직 실제 DOM에는 다다르지 않았습니다
대신, 그저 실제 DOM이 어떻게 보여야 하는지
가상으로 나타내는 겁니다
다음 단계로 리액트는
생성됐었던 마지막 가상 DOM 스냅샷과 비교합니다
만약 앱이 금방 시작되었다면 이전의 스냅샷은 없을 것입니다
아무튼 리액트는 바뀐 것들을 전부 확인하고
실제 DOM에게 가서 변동 사항들을 적용합니다
이 경우에서는 그게 무슨 뜻이냐면, 전체 가상 DOM이
실제 DOM으로 삽입된다는 겁니다
이 경우에는
이 버튼을 클릭해보면
리액트는 결국 그 과정을 반복합니다
다시 컴포넌트 트리를 만들고
물론 트리에서 바뀐 부분들만
빠르게 찾아낼 것이고
그리고 실행된 컴포넌트 함수들만 찾아냅니다
이 Counter의 경우
memo를 사용하는지, 그리고 저 버튼들을 사용하는지에 따라
리액트는 업데이트된 HTML 코드를 전달합니다
그리고 그걸 이전 코드와 비교한다고
말할 수 있겠습니다
아직 실제 DOM과 비교한 건 없습니다
그냥 이 새로운 가상 DOM 스냅샷과
지난 가상 DOM을 비교했을 뿐입니다
그리고 물론 빠르게 바뀐 부분들을
찾아냅니다
이 경우에는 이 span이나
span 안에 있는 문자만 주의해서 보면 됩니다
그러면 다음 단계로 리액트는
그 변동사항들을 실제 DOM에 적용합니다
그리고 오로지 그 변동사항들만 적용합니다
이 경우에는 실제 DOM의 span에게만 찾아가서
기존 문자를 새로운 문자로 대체합니다
그것 외에는 아무 것도 하지 않습니다
이 부분을 이해하는 게 정말 중요합니다
컴포넌트 함수가 실행되고
JSX 코드가 나온다고 해서
이 코드가 실제 DOM에 삽입되거나
업데이트된다는 것은 아닙니다
실제 DOM 동작들은
성능적으로 무리가 많이 가기 때문입니다
그러므로 리액트는 실제 DOM을
매번 바꾸지 않습니다
대신, 이 스냅샷을 만들어서 비교하고
꼭 필요한 변동사항들 적용시켜
원하는 결과를 얻습니다