728x90
반응형

이 글은 Udemy의 【한글자막】 React 완벽 가이드 2025 with React Router & Redux 를 수강하고 정리한 내용입니다.
🎈 memo 함수
- memo 함수는 불필요한컴포넌트를 다시 렌더링 하지 않도록 방지하는 함수입니다.
import React, { memo } from "react";
const MyComponent = memo(function MyComponent(props) {
// ...
});
- 부모 컴포넌트가 렌더링되면 자식 컴포넌트도 기본적으로 함께 렌더링됩니다. 하지만 자식 컴포넌트의 props가 변하지 않았다면 굳이 다시 렌더링할 필요가 없습니다.
- 이럴 때 memo로 감싸면, props가 이전과 동일할 경우 렌더링을 건너뜁니다. 즉, 컴호넌트 함수가 다시 호출 되지 않게 됩니다.
- ✅ 사용 전: 상태 변경 시 Counter 컴포넌트가 계속 실행됨

- ✅ 사용 후: memo 적용 시 Counter는 props가 동일하면 재실행되지 않음

✅ 작동 원리
- memo는 이전 props와 새로운 props를 얕게(shallow) 비교해서 동일하면 컴포넌트를 재실행하지 않도록 막습니다.
- 함수 컴포넌트 내의 상태가 바뀌는 건 막지 않아요. 부모 컴포넌트로부터 호출되는 경우에만 최적화됩니다.
⚠️ 모든 컴포넌트에 memo를 쓰는 건 오히려 성능 저하를 불러올 수 있습니다.
- props가 객체나 함수일 경우 비교가 까다로워 매번 새로 만들어졌다고 판단할 수 있기 때문입니다.
- 그래서 렌더링이 자주 발생하지만 props는 거의 바뀌지 않는 컴포넌트에만 사용하는 게 좋습니다.
🎈 useMemo() 훅
- useMemo()는 컴포넌트 내부의 복잡한 연산이 포함된 함수의 재실행을 방지하는 데 사용됩니다.
- memo가 전체 컴포넌트의 리렌더링을 막는 것과 달리, useMemo는 특정 값의 계산 결과를 메모이제이션합니다.
const initialCountIsPrime = useMemo(
() => isPrime(initialCount),
[initialCount]
);
- 첫 번째 인자는 실행할 함수를 전달하고, 두 번째 배열은 해당 함수를 다시 실행할 조건을 지정합니다.
- 의존성 배열 내 값이 바뀌지 않는 한, 이전에 계산한 값을 재사용합니다.
⚠️ useMemo 또한 모든 연산에 무조건 사용하는 것은 좋지 않습니다.
메모이제이션을 위한 연산도 비용이 들기 때문에, 연산이 무겁고 자주 바뀌지 않는 값에만 사용하는 것이 좋습니다
🎈 컴포넌트 함수의 실행 흐름
- 컴포넌트가 실행되면, React는 가상 DOM(Virtual DOM) 을 생성합니다.
- 이 가상 DOM과 이전 렌더의 가상 DOM을 비교하여 변경 사항을 찾아냅니다.
- 변경된 부분만 실제 DOM에 적용하여 성능을 최적화합니다.
가상 DOM을 사용하는 이유는 실제 DOM 조작보다 훨씬 빠르게 메모리에서 연산이 가능하기 때문입니다.
🎈 State 관리에서 key의 역할
- 컴포넌트는 각자 고유한 state를 가지며, 같은 컴포넌트를 여러 번 사용해도 상태는 서로 독립적입니다.
- 배열을 렌더링할 때 key 값을 index로 사용하는 것은 지양해야 합니다.
- 그 이유는 다음과 같습니다:
문제점:
- 배열 앞에 요소가 추가되면 기존 index가 바뀌어, 잘못된 상태가 다른 항목에 적용될 수 있습니다.
- React가 변경 여부를 정확하게 파악하지 못해 전체 항목을 다시 렌더링할 수 있습니다.
해결 방법:
- key는 고유 ID를 사용하는 것이 바람직합니다.
- 이렇게 하면 React가 각 항목을 정확히 추적할 수 있어 불필요한 렌더링을 줄이고 성능도 향상됩니다.
🎈 key의 또 다른 역할
<Counter initialCount={chosenCount} />
- 위 코드에서 chosenCount가 변경되어도, Counter 컴포넌트는 재사용되며 내부 상태는 유지됩니다.
- 이는 useState(initialCount)가 최초 렌더링 시 초기값만 사용하는 특성 때문입니다.
<Counter key={chosenCount} initialCount={chosenCount} />
- 반면, key를 설정하면 React는 chosenCount가 바뀔 때 이전 컴포넌트를 언마운트하고 새로 마운트합니다.
- 즉, 완전히 새로운 컴포넌트로 인식하게 됩니다.
참고: key는 props처럼 전달되지만, 자식 컴포넌트에서는 props.key로 접근할 수 없습니다.
이는 React 내부에서만 사용하는 식별자입니다.
🎈 상태 업데이트의 스케줄링 & 배칭
- setState는 즉시 실행되지 않고, React가 업데이트 일정을 조정합니다 (비동기 처리).
- 따라서 상태를 설정한 직후 console.log로 출력하면, 이전 값이 출력되는 경우가 많습니다.
안전한 상태 업데이트 방식:
setCount(prev => prev + 1);
- 위와 같이 이전 상태를 기반으로 한 함수형 업데이트를 사용하면,
- 상태 업데이트가 여러 번 연달아 일어나도 정확하게 처리됩니다.
배칭(Batching)
- 여러 개의 상태 업데이트가 동시에 발생하면 React는 이를 하나의 렌더링으로 묶어 처리합니다.
- 이렇게 하면 불필요한 렌더링을 줄이고 성능을 최적화할 수 있습니다.
🎈 Million.js로 React 성능 최적화
- Million은 React 앱의 렌더링 성능을 향상시켜주는 경량 라이브러리입니다.
npm install million
// vite.config.js
import MillionLint from "million/compiler";
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
export default defineConfig({
plugins: [MillionLint.vite({ auto: true }), react()],
});
- 설정만으로 자동 성능 최적화를 적용할 수 있습니다.

🧠 마무리 정리
기능 목적 사용 시기
| memo | 불필요한 자식 렌더링 방지 | props가 자주 바뀌지 않는 경우 |
| useMemo() | 복잡한 계산 결과 캐싱 | 무거운 연산이 있을 때 |
| key | 컴포넌트 구분 & 성능 최적화 | 리스트 렌더링, 상태 꼬임 방지 |
| 함수형 setState | 상태 안정적 업데이트 | 여러 상태 업데이트가 동시에 일어날 때 |
도움이 되셨다면 ❤️ 좋아요와 댓글로 피드백 주세요!
궁금한 점이 있다면 언제든지 질문 환영입니다 😄
지금까지 읽어주셔서 감사합니다!
반응형
'Programming > React' 카테고리의 다른 글
| [React] HTTP 통신 : fetch로 데이터 요청하고 로딩/에러 처리까지 (0) | 2025.04.22 |
|---|---|
| [React] 리액트 클래스 컴포넌트, 왜 아직도 알아야 할까? (1) | 2025.04.18 |
| [React] React로 퀴즈 앱 만들기 | 개발 회고 (1) | 2025.04.16 |
| [React] Side Effects / useEffect 훅 / useCallback 훅 (0) | 2025.04.11 |
| [React] Prop Drilling / Context API / Provider Pattern / userReducer (0) | 2025.04.09 |