React는 어떻게 값을 비교할까?

dahyeon·2023년 1월 29일
2
post-thumbnail

useEffect의 의존성 배열에 값을 넣어주게 되면, 렌더링된 이후와 넣어준 값이 바뀔 때 해당 useEffect에 넘겨준 함수가 실행된다.

그렇다면 리액트는 넣어준 값이 언제 바뀌었다고 판단할까? 즉, 이전 상태와 이후 상태를 어떤 알고리즘을 통해 비교하는지 알아보자.


리액트는 Object.is() 알고리즘을 통해 새로운 값을 그 이전 값과 같은지 비교한다.

(공식 문서에서 찾을 수는 없었으나, 해당 링크에 설명되어있다.)

Object.is()

다음과 같이 사용하여, value1value2가 서로 같은 값인지 여부를 나타내는 Boolean 값을 반환한다.

Object.is(value1, value2);

다음 중 하나를 만족하면 두 값은 같다.

  • 둘 다 undefined
  • 둘 다 null
  • 둘 다 true 또는 둘 다 false
  • 둘 다 같은 문자에 같은 길이인 문자열
  • 둘 다 같은 객체
  • 둘 다 숫자이며,
    • 둘 다 +0
    • 둘 다 -0
    • 둘 다 NaN
    • 둘 다 0이나 NaN이 아니고 같은 값을 지님

예시

// 특별한 경우
Object.is(0, -0);            // false
Object.is(-0, -0);           // true
Object.is(NaN, 0/0);         // true

객체 간의 비교

Object.is() 알고리즘에서 같은 객체이려면 객체에 대한 ‘참조 값’(객체가 저장되어 있는 메모리 주소)이 같아야 한다.

따라서 다음의 값은 false가 된다.

Object.is([], []);           // false

그렇다면 여기서 의존성 배열에 넣어준 값이 객체이고,

객체 내부 속성의 이름과 값이 전부 같지만 참조 값이 다르다면

리액트는 다른 값으로 판단해야 한다.

한 번 테스트 해보자.

const [stateTest, setStateTest] = useState({
    name: "dahyeon",
    say: "hello",
  });

useEffect(() => {
  setStateTest({
    name: "dahyeon",
    say: "hello",
  });
}, [viewportSize]);

useEffect(() => {
  console.log(stateTest);
}, [stateTest]);

위 코드는 화면 사이즈(viewportSize)를 변경할 때마다 stateTest라는 값을 바꾸도록 구현된 코드이다. 만약 stateTest 값이 바뀌었다면 (리액트에서 다르다고 판단하였다면) 그 값이 출력된다.

그 결과는 예상한 것처럼 다음과 같다.

즉, 값의 타입이 객체이고, 객체 내부 속성의 이름과 값이 전부 같더라도 참조 값이 다르다면 리액트는 다르다고 판단한다.

다르게 말하면,

참조 값이 같으면 같다고 판단한다.

위 테스트 코드를 살짝 바꿔서,

const [stateTest, setStateTest] = useState({
    name: "dahyeon",
    say: "hello",
  });

useEffect(() => {
		console.log("setStateTest 실행됨");
    setStateTest(stateTest);
  }, [viewportSize]);

useEffect(() => {
		console.log(stateTest);
}, [stateTest]);

화면 사이즈(viewportSize)를 변경할 때마다 stateTest라는 값을 현재의 stateTest로 설정하도록 만들어보았다.

실행 결과 위와 같이 setStateTest가 실행되더라도 참조값은 같기 때문에, 리액트는 같다고 인식하는 것을 알 수 있다.


요약

  • 리액트는 두 값이 같은지 여부를 Object.is() 알고리즘을 통해 비교한다.
  • 따라서 객체의 참조 값이 같아야 같다고 판단한다.

참고자료
Understanding Referential Equality in React
Object.is() - JavaScript | MDN

profile
https://github.com/dahyeon405

0개의 댓글