일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- ethers typescript
- redux toolkit 설명
- redux 기초
- 스마트컨트렉트 함수이름 중복 호출
- 러스트기초
- 티스토리챌린지
- cloud hsm 서명
- cloud hsm
- 러스트 기초
- ethers websocket
- 체인의정석
- SBT표준
- Vue
- 계정추상화
- erc4337
- cloud hsm 사용하기
- 오블완
- Vue.js
- 컨트렉트 동일한 함수이름 호출
- ethers type
- erc4337 contract
- rust 기초
- ambiguous function description
- 머신러닝기초
- vue기초
- ethers v6
- 러스트 기초 학습
- git rebase
- 스마트 컨트렉트 함수이름 중복
- 스마트컨트렉트 예약어 함수이름 중복
Archives
- Today
- Total
체인의정석
React) 재랜더링과 메모이제이션 Memo, useMemo & useEffect 본문
728x90
<재랜더링 패턴 3개>
React에서는 재랜더링이 발생하는 3가지 패턴
1. State 업데이트
2. Props가 변경된 컴포넌트
3. 재랜더링 된 컴포넌트 아래의 모든 컴포넌트
이러한 재랜더링을 계속하게 될 경우 부하가 많이 발생하게 된다.
<메모이제이션>
리액트에서 컴포넌트, 변수, 함수 등을 재렌더링할 때 제어가 필요한 경우에는 메모이제이션을 수행한다.
메모이제이션은 이전 처리 결과를 저장해 둠으로써 처리 속도를 높이는 기술로 필요할 때만 다시 계산하게 하여 불필요한 처리를 줄일 수 있다. 만약 부모가 재랜더링을 하더라도 메모이제이션이 되어 있다면 자녀 컴포넌트의 재랜더링을 막을 수 있다.
- 컴포넌트 메모이제이션
memo를 사용하면 컴포넌트 자체가 메모이제이션이 되면서 이러한 랜더링 과정에서 부모가 바뀌더라도 자식은 바뀌지 않게 된다.
- 함수 메모이제이션
그러나 함수를 Props로 받은 경우 자식 컴포넌트 입장에서는 Props가 변화했다고 판정해서 카운트업할 때마다 재랜더링을 하게 된다. 리액트에서는 함수 메모이제이션 기능인 UseCallBack을 제공하며 useCallBack의 경우 첫 번째 인수에 함수, 두번ㄷ째 인수에 useEffect와 같은 의존 배열을 받는다.
- 변수 메모이제이션
useMemo를 사용하면 변수 정의를 반복해서 하는 부하를 줄일 수 있다.
<사용 패턴>
패턴 1: 의존성이 없는 경우 (가장 일반적)
// ✅ 가장 일반적 - 의존성 배열이 비어있음
useEffect(() => {
fetchData();
}, []); // 빈 배열로 마운트 시에만 실행
const fetchData = async () => {
// API 호출
};
패턴 2: 의존성이 있는 경우
// ✅ 의존성이 있을 때는 useCallback 사용
const fetchData = useCallback(async () => {
// API 호출
}, [userId, page]); // 의존성 명시
useEffect(() => {
fetchData();
}, [fetchData]);
패턴 3: 직접 useEffect 내부에서 처리
// ✅ 간단한 경우 직접 처리
useEffect(() => {
const fetchData = async () => {
const res = await api.getData();
setData(res);
};
fetchData();
}, [userId]); // 의존성만 명시
2. 언제 메모이제이션을 사용해야 할까? 🤔
useCallback이 필요한 경우:
- 함수가 여러 곳에서 재사용됨
- 함수가 다른 useEffect의 의존성으로 사용됨
- 함수가 자식 컴포넌트에 props로 전달됨
- 함수 내부에서 많은 상태값을 참조함
useCallback이 불필요한 경우:
- 함수가 useEffect 내부에서만 사용됨
- 함수가 단순하고 의존성이 적음
- 컴포넌트가 자주 리렌더링되지 않음
3. 실제 예시 비교 📊
❌ 문제가 있는 코드:
const MyComponent = () => {
const [data, setData] = useState([]);
const [userId, setUserId] = useState(1);
// 매번 새로운 함수가 생성됨
const fetchData = async () => {
const res = await api.getData(userId);
setData(res);
};
// 무한 루프 발생!
useEffect(() => {
fetchData();
}, [fetchData]); // fetchData가 매번 변경됨
};
✅ 해결 방법 1: useCallback 사용
const MyComponent = () => {
const [data, setData] = useState([]);
const [userId, setUserId] = useState(1);
const fetchData = useCallback(async () => {
const res = await api.getData(userId);
setData(res);
}, [userId]); // userId가 변경될 때만 함수 재생성
useEffect(() => {
fetchData();
}, [fetchData]);
};
✅ 해결 방법 2: 직접 처리 (더 간단)
const MyComponent = () => {
const [data, setData] = useState([]);
const [userId, setUserId] = useState(1);
useEffect(() => {
const fetchData = async () => {
const res = await api.getData(userId);
setData(res);
};
fetchData();
}, [userId]); // userId가 변경될 때만 실행
};
4. 권장사항
간단한 경우 (권장):
useEffect(() => {
const fetchData = async () => {
// API 호출
};
fetchData();
}, [dependency]);
복잡한 경우:
const fetchData = useCallback(async () => {
// 복잡한 로직
}, [dependencies]);
useEffect(() => {
fetchData();
}, [fetchData]);
728x90
반응형
'개발 > frontend' 카테고리의 다른 글
Ts에서 export가 하나도 정의되어 있지 않은 경우 (모듈 vs 파일) (0) | 2025.08.20 |
---|---|
Indexed DB & 프론트엔드 (ts) (4) | 2025.07.17 |
Redux와 Thunk, CreateAsyncThunk (0) | 2025.07.10 |
Redux) redux-tool kit createEntityAdapter 설명 (1) | 2025.07.10 |
Redux 사용하기 (Redux tool kit) (3) | 2025.07.10 |
Comments