
📅 2025-10-17
➡️ React useContext, React.memo, useMemo, useCallback에 대해 새롭게 알게 된 것 또는 헷갈리는 부분 정리 + 🤔❓

createContext : context 생성useContext : context를 구독하고 해당 context의 현재 값을 읽음Provider : context를 하위 컴포넌트에게 전달❗ 주의 사항
- Context의 value가 바뀌면 그 값을 구독하는 모든 하위 컴포넌트가 리렌더링
- 따라서 항상 value 부분을 신경 써줘야 함
→ 불필요한 비용이 발생할 수 있음
import { useState } from "react";
import Box1 from "./components/Box1";
import Box2 from "./components/Box2";
import Box3 from "./components/Box3";
function App() {
console.log("App 렌더링!");
const [count, setCount] = useState(0);
return (
<div>
<h3>카운터 예제</h3>
<p>현재 카운트: {count}</p>
<button onClick={() => setCount(count + 1)}>+</button>
<button onClick={() => setCount(count - 1)}>-</button>
<div style={{ display: "flex", marginTop: 10 }}>
<Box1 />
<Box2 />
<Box3 />
</div>
</div>
);
}
export default App;function Box1() {
console.log("Box1 렌더링!");
return (
<div style={{
width: 100,
height: 100,
background: "#91c49f",
display: "flex",
alignItems: "center",
justifyContent: "center",
color: "#fff"
}}>
Box1
</div>
);
}
export default Box1; ❗ 지금 상태에서 + 버튼을 클릭하면 App의 state(count)만 바뀌었는데 box1~3 모두 리렌더링import React from "react";
function Box1() {
console.log("Box1 렌더링!");
return <div>Box1</div>;
}
export default React.memo(Box1);const result = useMemo(() => {
return someHeavyCalculation();
}, [dependency]);
의존성 배열의 값이 바뀌지 않는 한, someHeavyCalculation()은 다시 실행되지 않음
예제
import "./App.css";
import HeavyComponent from "./components/HeavyComponent";
function App() {
const navStyleObj = {
backgroundColor: "yellow",
marginBottom: "30px",
};
const footerStyleObj = {
backgroundColor: "green",
marginTop: "30px",
};
return (
<>
<nav style={navStyleObj}>네비게이션 바</nav>
<HeavyComponent />
<footer style={footerStyleObj}>푸터 영역이에요</footer>
</>
);
}
export default App;
import React, { useState, useMemo } from "react";
function HeavyButton() {
const [count, setCount] = useState(0);
const heavyWork = () => {
for (let i = 0; i < 1000000000; i++) {}
return 100;
};
// useMemo를 사용하지 않았을 때
const value = heavyWork();
return (
<>
<p>나는 {value}을 가져오는 무거운 작업을 하는 컴포넌트</p>
<button
onClick={() => {
setCount(count + 1);
}}
>
누르면 아래 count가 증가해요
</button>
<br />
{count}
</>
);
}
export default HeavyButton;
❗버튼을 클릭할 때마다 heavyWork 연산을 하기 때문에 +1이 오래 걸림
import React, { useState, useMemo } from "react";
function HeavyButton() {
const [count, setCount] = useState(0);
const heavyWork = () => {
for (let i = 0; i < 1000000000; i++) {}
return 100;
};
// useMemo를 사용하지 않았을 때
//const value = heavyWork();
// useMemo를 사용했을 때
const value = useMemo(() => heavyWork(), []);
return (
<>
<p>나는 {value}을 가져오는 무거운 작업을 하는 컴포넌트</p>
<button
onClick={() => {
setCount(count + 1);
}}
>
누르면 아래 count가 증가해요
</button>
<br />
{count}
</>
);
}
export default HeavyButton;❗ 주의 사항
- 모든 계산에
useMemo를 붙이는건 오히려 비효율적
- 캐싱을 할때도 메모리와 비교 비용이 들기 때문
- 정말 계산이 비용이 비싸거나 참조 비교로 인해 불필요하게 렌더링이 자주 발생하는 경우만 사용
React.memo가 컴포넌트 자체를 기억한다면, useCallback은 함수(콜백)를 기억하도록 도와줌
리렌더링이 발생할 때마다 함수가 새로 만들어지면 불필요한 렌더링이 전파될 수 있기 때문에 함수를 메모리에 저장해 재사용하는 것이 핵심
예제
function App() {
const [count, setCount] = useState(0);
// count를 초기화하는 함수
const reset = () => setCount(0);
return (
<>
<p>현재 카운트: {count}</p>
<button onClick={() => setCount((n) => n + 1)}>+</button>
<button onClick={() => setCount((n) => n - 1)}>-</button>
<Box1 reset={reset} />
</>
);
}
Box1 내부에서는 단순히 이 함수를 버튼 클릭 시 실행
function Box1({ reset }) {
console.log("Box1 렌더링");
return <button onClick={reset}>초기화</button>;
}
App의 count가 바뀔 때마다 reset 함수도 새로 만들어지기 때문에, Box1은 React.memo로 감싸더라도 계속 리렌더링됨
→ 자바스크립트에서 함수도 객체의 한 종류이기 때문. 그래서 내용이 같아도 새로 만들어지면 다른 객체로 인식하기 때문에 props 변경으로 간주됨
const reset = useCallback(() => {
setCount(0);
}, []);[])이 비어있다면, 컴포넌트가 다시 렌더링되어도 reset 함수는 처음 만든 것 그대로 유지됨React.memo를 썼을 때 실제로 리렌더링되지 않음현재 값을 기준으로 로직이 달라지는 경우
const reset = useCallback(() => {
console.log(`${count} → 0 으로 초기화`);
setCount(0);
}, [count]);`
| Hook / 함수 | 역할 | 언제 쓰는지 | 기억해야 할 핵심 포인트 |
|---|---|---|---|
| React.memo | 컴포넌트를 메모이제이션 | 부모가 리렌더링돼도 props가 동일하면 자식 컴포넌트를 다시 렌더링하지 않음 | 컴포넌트 단위의 렌더링 최적화 |
| useMemo | 값(결과)를 메모이제이션 | 계산 비용이 큰 연산 결과를 재사용하고 싶을 때 | 의존 배열이 변하지 않으면 이전 계산 결과를 반환 |
| useCallback | 함수를 메모이제이션 | 자식 컴포넌트에 props로 함수를 넘길 때, 매번 새로운 함수가 만들어지는 걸 방지 | useMemo의 함수 버전 |
React.memo로 감싼 자식이 불필요하게 리렌더링되는 것을 막고 싶을 때🔗 https://ko.react.dev/reference/react/memo
🔗 https://ko.react.dev/reference/react/useMemo
🔗 https://ko.react.dev/reference/react/useCallback