
useEffect()는 React에서 부수 효과(side effects)를 다루기 위해 사용되는 Hook입니다. 컴포넌트가 렌더링될 때마다 특정작업을 수행할 수 있도록 설정해줍니다. useEffect 는 React 컴포넌트가 화면에 나타난 후 이제 무엇을 할까?라고 컴포넌트에게 물어보는 것과 같습니다.
부수효과(side effects)
부수 효과란, 컴포넌트의 렌더링 결과에 영향을 주지 않으면서 컴포넌트의 생명주기에 따라 수행해야 하는 작업들을 말합니다. 예를 들어, 데이터 가져오기, 구독 설정, 수동으로 DOM을 조작하는 것 등이 있습니다. useEffect는 함수 컴포넌트에서 이러한 부수 효과를 수행할 수 있게 해줍니다.
생명주기(Life Cycle)
React 컴포넌트는 생명주기를 가집니다. 생명주기란, 컴포넌트가 생성되고, 렌더링된 후 소멸될 때 까지 일련의 과정을 말합니다. Mounting, Updating, Unmountiong 총 3가지의 단계로 이루어집니다.
클래스 컴포넌트에서는 componentDidMount, componentDidUpdate, componentWillUnmount 같은 생명주기 메서드를 사용할 수 있고, 함수 컴포넌트에서는 useEffect Hook을 사용하여 비슷한 작업을 수행할 수 있습니다.
추가적으로 더 학습하고 싶은 분들은 해당 사이트를 참고해 주세요.
State and Lifecycle – React
import { useEffect } from 'react';
useEffect(() => {
// 부수 효과를 수행하는 코드
}, [의존성 배열]);
useEffect(() => {
// 렌더링될 때마다 실행됩니다.
});1useEffect(() => {
// 컴포넌트가 마운트될 때(처음 화면에 나타날 때) 한 번만 함수가 실행됩니다.
},[]);useEffect(() => {
// name 값이 변경될 때마다 실행됩니다.
},[name]);useEffect는 실제로 프로젝트를 진행하면서, 자주 사용되는 Hook입니다.
예를 들어, 처음 페이지가 렌더링 될 때 서버에서 데이터를 받아와야 하는 상황에서 fetch 메소드를 사용하는 경우를 생각해 봅시다.
만약 useEffect를 사용하지 않고 데이터를 받아온다면 어떤 일이 발생할까요?
const [list, setList] = useState([]);
fetch('data/list.json')
.then((res) => res.json())
.then((data) => {
console.log('리스트 받아옴');
setList(data);
});

잠깐의 순간이지만, 렌더링이 3000번 이상 발생하고 있습니다. 왜 이러한 결과가 나오는 것일까요 ?
결과의 원인은 데이터를 파일에서 받아온 후, setList 메소드로 상태를 업데이트하면, 컴포넌트는 useState의 state가 변화하면서 렌더링이 발생합니다. 그럼 자동으로 다시 fetch 함수가 재실행되면서 데이터를 받아오게 되고, 이러한 과정이 무한히 반복되면서 위와 같은 결과가 발생하게 됩니다.
결과의 원인은 데이터를 파일에서 받아온 후, setList 메소드로 상태를 업데이트하면, 컴포넌트는 useState의 state가 변화하면서 렌더링이 발생합니다. 그럼 자동으로 다시 fetch 함수가 재실행되면서 데이터를 받아오게 되고, 이러한 과정이 무한히 반복되면서 위와 같은 결과가 발생하게 됩니다.
const [list, setList] = useState([]);
useEffect(() => {
fetch('data/list.json')
.then((res) => res.json())
.then((data) => {
console.log('리스트 받아옴');
setList(data);
});
},[]); // 의존성 배열 : 빈배열 (컴포넌트가 처음 마운트 될 때에만 콜백함수가 실행됨)

useEffect를 사용하는 경우, 처음 마운트 될 때에만 데이터를 호출하는 것을 확인할 수 있습니다.
데이터를 두 번 받아온 것 아닌가요 ?
이 예제에서 데이터가 두 번 로드되는 것을 보셨을 겁니다. 이는 React의 StrictMode기능 때문입니다.
StrictMode는 개발 모드에서 컴포넌트의 렌더링을 두 번 실행하여, 부주의한 사이드 이펙트를 포착하고 앱의 견고성을 높이기 위한 도구입니다. 이러한 이중 렌더링은 오직 개발 환경에서만 발생하며, 프로덕션 빌드에서는 발생하지 않습니다. 따라서 실제 사용자 환경에서는 성능에 영향을 주지 않습니다.
StrictMode를 사용하는 주된 이유는 다음과 같습니다
이 기능은 태그를 사용하여 적용할 수 있으며, 개발 중 버그와 문제를 식별하는 데 매우 유용합니다. 만약 이중 렌더링으로 인해 혼란을 겪고 있다면, 프로덕션 환경에서는 이 기능이 비활성화됨을 기억하시기 바랍니다.
컴포넌트 최상위에서 useEffect를 호출하여 Effect를 선언할 수 있습니다.
useState 와 마찬가지로 반복문이나 조건문에서는 사용할 수 없습니다.
function App() {
if(num === 1) {
useEffect(() => {
// 수행하고자 하는 함수
},[]);
}
}
function App() {
while (num < 9) {
useEffect(() => {
// 수행하고자 하는 함수
},[]);
}
}
useEffect를 사용하는 경우 import문을 사용하여 호출되어야 합니다.
import { useEffect } from 'react'; // 중괄호로 감싸 호출해야합니다.