리액트, 커튼 뒤에서 과연 무슨일이??

YEONGHUN KO·2022년 3월 28일
0

REACT JS - BASIC

목록 보기
20/31
post-thumbnail

color palette - navbar를 만들던 도중, 컴포넌트에 있는 state가 유지 되지 않는 걸 발견했다.

도대체 뭐가 문제여...???

구글링 하던 도중 리액트가 dom을 어떤식으로 출력하는지 까지 딥하게 알아보았다.

리액트 동작원리를 제대로 알아두면 좋겠다 싶어서 이렇게 아티클로 남긴다.


state가 유지 되지 않는 이유! 리액트가 실행되는 원리와 연관이 깊다. 리액트는 리랜더링이 일어날때 마다(setState, componentDidMount etc) diffing이라는 걸 한다.

Diffing: The process of checking the difference between the new VDOM tree and the old VDOM tree

그렇다 예전 DOM TREE(이하 ODT)와 새로운 DOM TREE(이하 NDT)를 비교하는 것이다. 이때 DOM TREE안에 새로운 element가 있으면 tree를 다시 구성하는 것이다.

그런데 ODT와 NDT사이에 겹치는 element가 있으면 재사용한다. 그럼, 겹치는 건 빼놓고 ODT에 없는것만 적절한 위치에 삽입하거나 갈아끼우면 된다. 이때 필요한것이 바로 KEY PROP이다!

이때 map을통해서 반복적인 자식들이 랜더링될때를 의미한다. map이 아닌 그냥 랜더링되는 태그는 key를 안써도 된다.

element type이 같다하더라도 key prop이 없으면 재사용하지 않고 다시 element를 생성하고 위치까지 바뀔 수 있다. 근데 key prop이 있으면 재사용할 수 있는 element가 명확해진다.

KEY PROP 공식문서

위의 문서를 참고해보면 될것이다. 이때 중요한것은 KEY는 unique, predictable, stable 해야한다. 그렇지 않다면 쓸데없는 인스턴스가 생겨나고, 쓸데없이 element가새로 만들어지며 이전 local state는 다 날라갈 것이다.

참고로, color project할때 navbar안에 있는 open, format state가 리랜더링 할때마다 다 새로고침되었는데 그 이유는 key prop에 uuid를 매번 새로 생성해서 pass하고 있었기 때문😭

아래는 공식문서에서 그대로 가져온 말이다.

Keys should be stable, predictable, and unique. Unstable keys (like those produced by Math.random()) will cause many component instances and DOM nodes to be unnecessarily recreated, which can cause performance degradation and lost state in child components.

Keys tell React about the identity of each component which allows React to maintain state between re-renders. If a component’s key changes, the component will be destroyed and re-created with a new state.
-- https://reactjs.org/tutorial/tutorial.html#picking-a-key

(참고로 vDOM안에 type이 변할때도 리랜더링되면서 이전 vDOM은 폐기하고 다시 새로운 가상돔을 만든다.)

단, 배열을 map을 통해서 랜더링할때 index를 key값으로 쓰는 경우가 있는데 삼가하자. 왜냐면 index를 key로 둘경우 위치가 바뀌었을경우 각각 고유의 element를 보는게 아니라 그냥 arr안에 위치를 보고 리랜더링한다.

역시 코드로 이해를 하자. 문지님 블로그에 코드로 잘 설명이 되어있다.

이렇게 비교해서 새로 DOM TREE를 만드는 과정을 reconciliation이라고 한다. 영영사전의 뜻은 아래와 같다.

the act of causing two people or groups to become friendly again after an argument or disagreement
the process of finding a way to make two different ideas, facts, etc., exist or be true at the same time

한 마디로 차이점, 모난 부분을 다듬어서 조화를 이루는 것이다.

근데 diffing algorithms은 tree의 뿌리까지 파고 들어가는 작업이다. 즉, 재귀가 일어난다. 근데 자바스크립트는 single thread 언어라서 재귀가 일어나면 재귀가 끝날 때 까지 다음 작업을 하지 못한다. 모든 작업이 완료되면 모든 변경사항이 응집되어있는 vDOM을 브라우저에 업데이트한다.

즉, 애니메이션, 레이아웃 변경 같은 효과가 일어날 시에 상당히 느려질 수 있다는 단점이 있다. 이를 방지하기 위해 리액트는 fiber라는 새로운 알고리즘을 도입하였다.


새로운 공식문서에 나와있는 말을 참고하자면,

DOM TREE에서 같은 위치에 있으면 STATE가 유지됨.

그러나 각 컴포넌트에 다른 KEY를 부여하면 같은 위치더라도 리랜더링시, STATE가 RESET됨

  • React keeps state for as long as the same component is rendered at the same position.
  • State is not kept in JSX tags. It’s associated with the tree position in which you put that JSX.
  • You can force a subtree to reset its state by giving it a different key.
  • Don’t nest component definitions, or you’ll reset state by accident.

출처
1. https://www.moonkorea.dev/React-%EB%A0%8C%EB%8D%94%EB%A7%81-%EC%9E%AC%EC%A1%B0%EC%A0%95%EA%B3%BC-key#%EC%9E%AC%EC%A1%B0%EC%A0%95%EA%B3%BC-key

  1. https://react.dev/learn/preserving-and-resetting-state
profile
'과연 이게 최선일까?' 끊임없이 생각하기

0개의 댓글