본문 바로가기

3주차

컴포넌트 순수하게 유지하기

컴포넌트를 엄격하게 순수함수로 작성하면 예상밖의 동작이나 당황케하는 버그를 피할 수 있다.

 

💡 순수성: 공식으로서의 컴포넌트

순수함수의 특징

  • 함수 밖 객체나 변수를 변경하지 않음
  • 같은 입력엔 항상 같은 결과를 반환함

React는 작성되는 모든 컴포넌트가 순수 함수일 거라 가정하고 설계되었다.
=>React 컴포넌트에 같은 입력이 주어지면 같은 JSX를 반환

 

💡 사이드 이펙트: 의도하지 않은 결과

React의 렌더링 과정은 항상 순수해야 한다. 컴포넌트는 렌더링하기 전에 존재했던 객체나 변수들을 변경하지 말아야 한다.


ex)

let guest = 0;

function Cup() {
  // 나쁜 지점: 이미 존재했던 변수를 변경하고 있다!
  guest = guest + 1;
  return <h2>Tea cup for guest #{guest}</h2>;
}

export default function TeaSet() {
  return (
    <>
      <Cup />
      <Cup />
      <Cup />
    </>
  );
}

 

위 컴포넌트가 여러번 불리면 다른 JSX를 생성하게됨..
다른 컴포넌트가 guest를 읽었다면 언제 렌더링 됐는지에 따라 그 컴포넌트 또한 다른 JSX를 생성..
예측할 수 없게 됨..

 

이는 guest 변수를 prop으로 넘겨 해결 가능

function Cup({ guest }) {
  return <h2>Tea cup for guest #{guest}</h2>;
}

export default function TeaSet() {
  return (
    <>
      <Cup guest={1} />
      <Cup guest={2} />
      <Cup guest={3} />
    </>
  );
}

 

이제 JSX가 반환되는 것은 오직 guest 프로퍼티에 의존하기 때문에 컴포넌트는 순수하다.

 

💡 Strict mode로 순수하지 않은 연산을 감지

  • React에는 렌더링하면서 읽을 수 있는 props, state, context라는 세 가지 종류의 입력 요소가 있는데, 이 요소들은 항상 읽기 전용으로 취급해야 한다.
    입력에 따라 무언가를 변경하려는 경우엔 변수를 직접 수정하는 대신 setState를 사용해야 한다.
  • React는 개발 중에 각 컴포넌트의 함수를 두 번 호출하는 “strict mode”를 제공
    컴포넌트 함수를 두 번 호출함으로써, 엄격 모드는 이러한 규칙을 위반하는 컴포넌트를 찾는 걸 도와준다.
  • strict mode는 프로덕션에 영향을 주지 않기 때문에 사용자의 앱 속도가 느려지지 않는다. 최상단 컴포넌트를 <React.StrictMode>로 감싸서 stric mode 사용

 

💡 지역 변형

    • 위에서 문제됐던 것은 렌더링하는 동안 컴포넌트가 "기존 변수"를 변경했다는 것.
      렌더링하는 도중에 컴포넌트 내부에서 그냥 만든 변수와 객체를 변경하는 것은 문제가 없다.=> 지역 변형

 

💡 부작용을 일으킬 수 있는 지점

  • 렌더링 중에 발생하는 것이 아니라 "사이드에서" 발생하는 현상을 사이드 이펙트라고 한다. (화면을 업데이트하고, 애니메이션을 시작하고, 데이터를 변경하는 등)
  • 리액트에서 사이드 이펙트는 보통 이벤트 핸들러에 포함.
    이벤트 핸들러는 리액트가 일부 작업을 수행할 때 반응하는 기능, 컴포넌트 내부에 정의되었다 해도 렌더링 중에는 실행되지 않음 -> 이벤트 핸들러는 순수할 필요가 없음!
  • 사이드 이펙트에 적합한 이벤트 핸들러를 찾을 수 없는 경우 : useEffect 호출을 사용하여 JSX에 해당 이벤트 핸들러를 연결할 수 있으나 이 방법은 최후의 수단으로 사용하자
  • 👉 가능하면 렌더링만으로 로직을 표현하기.

 

리액트는 why 순수해야될까?

  • 동일한 입력에 대해 동일한 결과를 반환하기 때문에 하나의 컴포넌트는 많은 사용자 요청을 처리할 수 있다.
  • 입력이 변경되지 않은 컴포넌트는 렌더링을 건너뛰어 성능을 향상시킬 수 있다.
  • 깊은 컴포넌트 트리를 렌더링하는 도중에 일부 데이터가 변경되는 경우 React는 오래된 렌더링을 완료하는 데 시간을 낭비하지 않고 렌더링을 다시 시작할 수 있다.