-
시작한건 끝내야하는 useEffect, 그리고 returnREACT 2025. 12. 11. 14:32
오늘 useEffect 수업을 듣던중 비동기함수에 대한 설명이 나왔다.
useEffect(async () => { const data = await fetchUser(userId); setUser(data); }, [userId]);useEffect에서 async를 쓰면 Promise를 반환하니까 안된다는것이다.
속으로 난 왜 Promise는 안되냐...? 또 혼란스러웠다. 그냥 그러라고 있는거니까 외워야하나 싶기도하고
그러니까 여기선 useEffect는 무엇을 return 하느냐가 중요한 포인트였다.
useEffect는 사이드 이펙트를 위해 존재한다.
먼저 useEffect가 왜 존재하는지부터 아는게 좋을거같다.
react에서 컴포넌트의 주 목적은 UI를 렌더링한다는것은 다 알것이다.
그러나 실제 개발을 하다보면
- API 호출해서 데이터 가져오기
- DOM 직접 조작하기
- 타이머 설정하기
- 이벤트 리스너 등록하기
같은 렌더링 외의 작업들이 필요한 순간들이 있다. 이것을 사이드 이펙트, 부수효과 라고 말한다.
그래서 useEffect가 탄생하게 되었고 이름도 그런 이유로 Effect가 들어간다는 사실!
useEffect는 cleanup함수를 기다리고 있다!
정확히 이야기하면 cleanup 함수를 return 하길 기대하고 있다는것이다.
내가 헷갈렸던 부분이 이 return을 놓쳐서였는데
return에 비동기함수만 넣는거만 주의하면 어떤 함수든 자유롭게 쓸수있다.‼️ return에는 무조건 cleanup이나 undefined로 처리시켜야한다는것 ‼️ 꼬옥 기억하자
useEffect(() => { // 사이드 이펙트 실행 return () => { // React: "cleanup 함수가 오겠구나!" 하고 기다림 }; }, []);그럼 async 쓰고싶으면 어떻게 해야하는데..?
말한대로 return에만 넣지않으면 된다. 그말은 즉슨 사이드 이펙트 내에서 호출시키면 되는것이다
useEffect(() => { async function fetchAndSetUser() { const data = await fetchUser(userId); setUser(data); } fetchAndSetUser(); // 호출만 하고 return 안 함! // useEffect의 반환값은 undefined → 문제없음! }, [userId]); //왜 이건 되냐면? useEffect(() => { const promise = fetchAndSetUser(); // Promise 객체 생성됨 // 하지만 return 안 함! // useEffect의 반환값 = undefined }, []);useEffect return이 뭔데 이렇게 중요한건데?
그놈의 cleanup이 뭐라고 이렇게 사람을 헷갈리게 만들어놓는걸까 찾아보니 그것도 다 이유가 있엇슴,,
일단 cleanup은 다들 알다시피 실행시킨 함수를 종료, 정리하는 함수를 말한다.
근데 만약 cleanup 없이 함수를 실행시키는것만 있다면 당연히
- 1. 메모리 누수가 되고
- 2. 어디선가 버그가 터질테고
- 3. Race Condition 이 일어날것이다.
Race Condition이란
비동기작업에서 두번이상의 요청이 발생했을때,
같은 결과값을 공유하는 과정에서 순서나, 타이밍때문에 결과값이 덮혀버리는 문제를 말한다.
아래 예제코드처럼 return에서 cleanup을 해줘야 Race Condition을 방지할수 있는것이다!
useEffect(() => { let cancelled = false; // 시나리오 1. userId가 1 → API 요청 시작 (느림, 3초) async function fetchData() { // 시나리오 2. userId가 2로 변경 → 새 API 요청 (빠름, 1초) const data = await fetchUser(userId); if (!cancelled) { setUser(data); } } fetchData(); //시나리오 3. userId=2 응답 먼저 도착 → setUser(user2) return () => { // 시나리오 4. userId=1 응답 나중 도착 → setUser(user1) cancelled = true; // 잘못된 데이터니 이전 요청 취소해야됨 }; }, [userId]);useEffect도 스냅샷처럼 동작한다는것!
그리고 여기서 하나 더 추가로 알게된 사실은 렌더링할때마다 새로운 useEffect가 실행되는것이다.
앞서 State에 설명했던 대로 렌더링시점에서의 값을 가지고 실행하기 때문에
값이 변할때마다 새로운 effect가 생성되고그 때문에 useEffect에선 cleanup이 필수인것이다...!
만약 무한히 생성된다면 ...? 상상도 하기실타요
이전 글이 궁금하다면 아래링크 참고
2025.12.09 - [REACT] - state, 제대로 알고 쓰시나요?
state, 제대로 알고 쓰시나요?
state의 진짜목적state는 변수가 아니다. 당연한 사실이고 잘알고있었는데 막상 쓰다보면 또 변수처럼 생각하고 있는 나자신을 발견한다;;명심하자 state가 존재하는 이유는 값을 저장,수정,전달하
lyla-bae.tistory.com

뭐든 마무리가 중요함 마무리
결론적으로 중요한것은 useEffect는 시작한건 끝내야 한다는 원칙을 가지고 있다.
그래서 return이 cleanup 함수 전용인 이유인것이다!!
useEffect에 대해 아는거라곤 라이프사이클, 의존성배열 밖에 몰랐는데 덕분에 이해도가 조금 더 깊어졌다! 굿
참고자료
https://velog.io/@mamonde456/useEffect-Race-Condition#race-condition%EC%9D%B4%EB%9E%80
useEffect - Race Condition
Tanstack Query의 useQuery를 미니멀하게 클론 코딩하며 생긴 궁금증을 정리한 글이다.useEffect의 동작 과정, 클린업 함수, 그리고 Race Condition까지 학습한 내용을 흐름에 따라 풀어보았다.
velog.io
[react] useEffect 훅에서 async await 함수 사용하기
평소에 useEffect 안에서 async await 함수를 쓰고 싶었던 적이 많았는데 매번 에러가 나길래 안되는건줄 알았다. 근데 요즘 공부하고 있는 저자 이재승 님의 실전 리액트 프로그래밍 개정판 (리액트
velog.io
https://despiteallthat.tistory.com/182
[React] useEffect란?
오늘은 useEffect()에 대해 알아보겠습니다. [ useEffect ] useEffect() 함수는 React component가 렌더링 될 때마다 특정 작업(Sied effect)을 실행할 수 있도록 하는 리액트 Hook입니다.여기서 Side effect는 component가
despiteallthat.tistory.com
'REACT' 카테고리의 다른 글
React 정리해보기 (0) 2025.12.30 Virtual DOM부터 Memoization까지 (0) 2025.12.29 Props 요리조리 구워삶기 - Context API & Props Drilling (1) 2025.12.10 useState, 제대로 알고 쓰시나요? (0) 2025.12.09 굳이 createPortal로 모달을 만드는 이유는? (0) 2025.12.08