리액트 메모

렐루·2024년 8월 23일
0

리액트

목록 보기
20/20

1. 시작

최종 발표회에서 우리 프로젝트를 보러 오신 외부 참석자분께서 소스 코드를 살펴보시고 메모이제이션에 대해 질문하셨습니다. "메모이제이션을 넣을 만한 부분이 보이는데, 혹시 넣지 않은 이유가 있나요?"라는 질문이었습니다. 우리 팀원이 잘 대답해주긴 했지만, 저는 매우 당황스러웠습니다.

개발에 몰두하다 보니 전날까지 버그를 잡고 발표 준비를 하느라 메모이제이션에 대한 고민을 깊게 할 시간이 없었습니다. 그 질문이 정곡을 찔린 느낌이었습니다.

앞으로도 비슷한 질문을 받을 가능성이 높다고 생각했기에, 좋은 기회로 삼아 공식 문서를 보며 메모이제이션에 대해 공부한 내용을 정리해보려고 합니다.

2. memo, useMemo, useCallback

공식문서에 있는 내용을 간략하게 정리해보겠습니다.

2-1. memo

memo를 사용하면 컴포넌트의 props가 변경되지 않은 경우 리렌더링을 건너뛸 수 있습니다.

const MemoizedComponent = memo(SomeComponent, arePropsEqual?)

React는 일반적으로 부모가 리렌더링될 때마다 컴포넌트를 리렌더링합니다. memo를 사용하면, 새로운 props가 이전 props와 동일하다면 부모가 리렌더링될 때 새로운 props가 이전 props와 동일하면 리렌더링 되지 않는 컴포넌트를 만들 수 있습니다.

2-2. useMemo

useMemo 는 재렌더링 사이에 계산 결과를 캐싱할 수 있게 해주는 React Hook

const cachedValue = useMemo(calculateValue, dependencies)

2-3. useCallback

useCallback은 리렌더링 간에 함수 정의를 캐싱해 주는 React Hook

const cachedFn = useCallback(fn, dependencies)

https://ko.react.dev/reference/react/memo#minimizing-props-changes
https://ko.react.dev/reference/react/useMemo
https://ko.react.dev/reference/react/useCallback

3. 프로젝트에 적용

컴포넌트 프로퍼티 함수로 받을 때

<ChallengePageTitle
  title={"루틴 수정"}
  allStepCount={4}
  titleHidden={false}
  handleClickGoBack={() => {
    // 컨펌 열기 => 확인이면 뒤로 가기
    return open({
      type: "confirm",
      content: "저장되지 않은 변경사항은 삭제됩니다.",
      onConfirm: () => {
        router.back()
      },
    })
  }}
/>

위의 코드에서는 handleClickGoBack같은 함수는 컴포넌트가 리랜더링될 때마다 새로 생성된다. 리액트는 객체를 Object.is() 메서드로 얕은 비교를 하게 됩니다..

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Object/is

따라서 위의 콜백 함수를 useCallback을 사용하여 같은 주소값으로 비교할 수 있게 함으로써 Object.is()의 연산결과가 true로 같은 함수를 받게되어 컴포넌트가 리렌더링 되는 것을 방지해줍니다.

const handleClickGoBack = useCallback(() => {
  open({
    type: "confirm",
    content: "저장되지 않은 변경사항은 삭제됩니다.",
    onConfirm: () => {
      router.back()
    },
  })
}, [open, router])

<ChallengePageTitle
  title={"루틴 수정"}
  allStepCount={4}
  titleHidden={false}
  handleClickGoBack={handleClickGoBack}
/>

4. 느낀점

생각보다 적용할만한 곳이 없었습니다... (아마 제가 작성한 코드 말고 다른 코드를 보신 것이 아닐까 조심스럽게 예상합니다..)
effect를 사용하는 모든 곳에다가 콘솔을 찍었지만 첫번째 호출 이후에는 더 찍히는 부분은 없었습니다.
공식문서에서도 메모을 쓰기 전에 effect 종속성관리 또는 자식처럼 엘리먼트로 감싸기 같은 (아래 메모 참고..) 방법으로도 충분히 피할 수 있다는 말이 무슨 말인지 알 것 같습니다.

필요한 작업임에는 틀림없습니다. 그러나 처음부터 쓰기보다는 다른 방법을 먼저 찾아보고 이후에 다른 방법이 생각나지 않으면 써야할 것 같습니다!!

감사합니다.

profile
프론트 공부중입니다!

0개의 댓글