React, diffing 알고리즘

jjyung·2021년 12월 5일
1

React

목록 보기
2/7

👍 글을 쓰게 된 계기

리액트를 배우다 보면 '가상돔'이라는 개념을 마주하게된다. 가상돔이란 말 그대로 가상으로 만들어진 돔을 뜻한다. 실제로 돔 API를 계속 호출하면 리페인팅, 리플로우로 인해 렌더링이 계속 발생하고, 성능이 떨어지게 된다.

이런 문제를 해결하기 위해 리액트에서는 가상돔을 사용하여 바뀐 부분만 변화시킨다. 최근에 알고리즘 공부에 푹 빠져있기도 하고(존잼...) 페이스북뿐만 아니라 인스타그램등 성능이 중요한 빅테크 기업에서도 리액트를 사용해 성능을 개선하고 있어, diffing 알고리즘의 실체가 너무 궁금해져 글을 쓰게되었다.

✌️ Diffing Algorithm이란?

In React, displaying 1000 elements would require in the order of one billion comparisons. This is far too expensive. Instead, React implements a heuristic O(n) algorithm based on two assumptions:
1. Two elements of different types will produce different trees.
2. The developer can hint at which child elements may be stable across different renders with a key prop.

위의 설명은 리액트 공식홈페이지에 나와있는 설명이다.

즉, 요소 하나하나를 바꾸다보면 수십만번의 비교가 이루어져야하고, 이 작업은 상당히 비쌀 수 밖에 없다. 그래서 리액트에서는 두 개의 트리가 나온다는 점과 모든 개발자들이 key props를 통해 바뀌었다는 것을 명시할 수 있다는 점으로 해당 문제를 해결하고자 했다.

👻 동작 원리

우선, 두 가지 돔 트리를 비교한다는 점은 위에서 명시했다. 그러면 다양한 케이스가 나올 수 있다.

1. 루트 노드가 아예 다른 경우
이 경우는 아예 처음부터 다르기 때문에 아예 새로운 트리를 구축하게된다.그리고 이전에 있던 state들은 모두 사라진다. 사실 상식적으로 생각해보면 당연한 것 같다. 부모가 바뀌는데 자식들이 남아있으면 그것도 이상하니까..ㅎㅎ

2. 타입은 같지만 속성이 다른 경우
속성(스타일)만 달라지는 경우에는 두 속성을 비교하여 바뀐 부분만 변화 시킨다.

3. 자식 요소가 바뀌는 경우
DOM동시에 두 리스트를 순회하고 바뀐 점이 있다면 그 부분만 재귀가 돌면서 처리해준다. 단, 첫 번째 자식부터 비교하며 변경하기 때문에 첫 자식 요소에 요소를 삽입하는 경우 처음부터 비교를 해야하기 때문에 성능상 좋지 않다. 이 문제를 리액트에서는 key를 통해 해결했다.

위의 문제점처럼 처음부터 하나하나 비교하는 것이 아니라, key속성을 통해 해당 Key가 존재하는지만 확인하면 된다. 다만 배열의 경우, index를 key로 사용했을때 재배열한다면 미묘하게 결과가 맞지 않을것이다. 그 이유는 index는 유일한 값이 아니기 때문에 오류가 날 수 밖에 없다. 그래서 key로는 id처럼 유일한 값을 사용해야 한다.

🎃 어떤 알고리즘을 사용했나?

diffing 알고리즘에서는 heuristics알고리즘을 이용한 순회를 하게되고 변경된 결과를 업데이트 한다. 이 때 휴리스틱 알고리즘은 중요한 정보만 고려해서 최선의 값을 찾아내는 알고리즘이라 100% 정확하지 않다고 공홈에 적혀있다 (물론 결과는 똑같이 나온다)

diffing 알고리즘은 성능을 완벽하게 개선하지 못한다고 판단한 페이스북은 2017년 4월에 Reconciliation 에서 Fiber 을 도입했다.

🤟 결론

공홈에서 올려준 코드와 미디엄에서 분석해놓은 걸 보면 볼수록 신기하다. 역시 페이스북이란 생각도 들고, 이러한 동작 원리 덕분에 성능이 개선된다는것이 정말 신기하다. 나도 정말 알고리즘을 잘해서 성능을 개선할 수 있는 core 개발자가 되고 싶다.

🤞 출처

  1. 미디엄
  2. 공식홈페이지
  3. YodaCode 홈페이지
profile
🏃‍♀️movin' forward, developer

0개의 댓글