시작하기 앞서...
제목, 내용, 이미지를 입력하는 페이지에서 내용을 입력할 때마다 사진이 계속 다시 렌더링 되어 깜박거리는 현상을 발견하였다.
그래서 이를 해결하기 위해 렌더링을 최소화하는 방법을 찾아보았다.
React Developer Tools
크롬 확장 프로그램 중에서 React Developer Tools 를 설치하고
개발자 도구 -> Profiler -> 설정에서 Highlight updates when components render 를 클릭하면 어디서 렌더링이 발생하는지 시각적으로 확인할 수 있게 된다.
그러면 아래 사진처럼 렌더링이 일어나는 부분에 노란색 테두리가 생기게 된다.
입력되는 부분은 내용인데 불필요하게 사진이 있는 곳까지 다시 렌더링 되어 사진을 화면에 보여주다 보니 깜박거리는 현상이 발생하게 되는 것이다.
이미지 깜박거림 해결하기
이미지를 입력하고 URL.createObjectURL 을 사용하여 이미지 미리 보기를 구현하고 있다.
(참고로 next.js 환경이라 Image 컴포넌트 사용함)
<Image
alt="등록한 이미지"
src={URL.createObjectURL(image)}
fill
/>
useMemo 란?
문제를 해결하기 위해 useMemo
훅을 사용하였다.
자세한 내용은 공식문서에서 확인할 수 있다. [React 한글 공식문서 - useMemo]
간단하게 설명하자면 useMemo 는 연산 결과를 메모이제이션(memoization) 하여 값이 변경될 때만 연산을 수행하고, 그렇지 않은 경우에는 메모이제이션된 값을 재사용하여 불필요한 연산을 방지하는 역할을 한다.
useMemo 사용하기
useMemo 훅을 사용하여 아래 코드처럼 작성하였다.
const imageUrl = useMemo(
() => (image ? URL.createObjectURL(image) : null),
[image]
);
...
<Image
alt="등록한 이미지"
src={imageUrl}
fill
/>
image 상태를 의존성으로 설정했기 때문에 image 가 변경될 때만 URL이 다시 생성되고, 그렇지 않으면 이전에 생성된 URL을 재사용하게 된다.
그러면 사진이 깜박거리는 현상은 사라지게 된다!
+) 추가내용
imageUrl 을 만들기 위해 사용했던 URL.createObjectURL()
은 클린업 함수로 해당 객체를 제거해야한다고 한다.
https://jjang-j.tistory.com/82
불필요한 렌더링 최소화 하기
사진이 깜박거리는 문제는 해결했지만
현재 내용 부분을 입력하는데 제목과 이미지 컴포넌트 부분이 렌더링 되는 것을 확인할 수 있다. 그래서 이를 최소화하려고 한다.
memo 란?
문제를 해결하기 위해 React 에 내장되어 있는 memo
컴포넌트를 사용하였다.
자세한 내용은 공식문서에서 확인할 수 있다. [React 한글 공식문서 - memo]
memo 를 사용하면, 컴포넌트가 동일한 props 로 렌더링 되는 경우 이전에 렌더링 된 결과를 재사용하여 불필요한 렌더링을 방지할 수 있다.
memo 사용하기
FormInput, FormTextarea, FormImage 컴포넌트에 모두 memo 컴포넌트를 감싸주었다.
export default memo(FormInput);
export default memo(FormTextarea);
export default memo(FormImage);
그러면 각 컴포넌트는 이제 props가 변경되지 않는 한 해당 컴포넌트는 다시 렌더링 되지 않게 된다.
그러나 실제 렌더링 되는 걸 보면 FormImage 는 다시 렌더링 되지 않지만 FormInput, FormTextarea 는 렌더링이 된다.
왜냐하면 setTitle과 setContent 에 대한 새로운 함수 참조가 생성되고 이로 인해 memo로 감싸진 FormInput과 FormTextarea 컴포넌트가 불필요하게 다시 렌더링이 된다.
onChange={(e) => setTitle(e.target.value)}
...
onChange={(e) => setContent(e.target.value)}
그래서 이를 해결하기 위해 setTitle 과 setContent 에 대한 함수 참조를 메모이제이션을 해야 된다.
useCallback 이란?
위에 문제를 해결하기 위해 useCallback
훅을 사용하였다.
자세한 내용은 공식문서에서 확인할 수 있다. [React 한글 공식문서 - useCallback]
useCallback 은 useMemo 와 유사하며, 다른 점은 메모이제이션된 콜백 함수를 생성하는 데 사용된다는 것이다.
useCallback 사용하기
setTitle과 setContent 에 useCallback 훅을 사용한다.
const handleChangeTitle = useCallback(
(e: ChangeEvent<HTMLInputElement>) => setTitle(e.target.value),
[]
);
const handleChangeContent = useCallback(
(e: ChangeEvent<HTMLTextAreaElement>) => setContent(e.target.value),
[]
);
...
<FormInput
...
onChange={handleChangeTitle}
/>
<FormTextarea
...
onChange={handleChangeContent}
/>
그러면 이제 입력하고 있지 않는 컴포넌트에서 렌더링이 발생하지 않게 된다!
마치며...
사실 지금까지 useMemo, useCallback, memo 에 대해 헷갈렸는데 이렇게 직접 사용해 보고 눈으로 렌더링 되는 부분을 확인하게 되니깐 각자 무슨 기능을 하고 어디에서 사용해야 되는지 잘 알게 되었다.
하지만 무조건 useMemo, useCallback, memo 을 사용한다고 좋은 것은 아니다. 성능을 최적화하기 위한 도구이지만 불필요하게 사용할 경우 코드 복잡성 및 메모리 사용량이 증가할 수 있어 성능 최적화가 필요한 지점을 식별해서 알맞게 사용해야 한다
'💜 리액트 > React' 카테고리의 다른 글
[React] useEffect 클린업(Clean Up) 함수로 메모리 누수 방지 (2) | 2024.06.14 |
---|---|
[React] 리액트 개발 도구로 디버깅하기 - React Developer Tools (0) | 2024.06.11 |
[React] 프로젝트 JavaScript 에서 TypeScript 마이그레이션 방법 (0) | 2024.05.26 |
[React] 리액트 Context API 전역 상태 관리 (0) | 2024.05.18 |
[VS Code] React 코드 스닛펫(snippet) 커스텀 만들기 방법 (0) | 2024.05.07 |
FE 개발자가 되고 싶은 짱잼이
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!