개요
useEffect
는 컴포넌트를 외부 시스템과 동기화할 수 있게 해주는 React Hook입니다.
useEffect(setup, dependencies?)
Reference
useEffect(setup, dependencies?)
컴포넌트의 최상위에서 useEffect
를 호출하여 Effect를 선언할 수 있습니다.
import { useState, useEffect } from 'react';
import { createConnection } from './chat.js';
function ChatRoom({ roomId }) {
const [serverUrl, setServerUrl] = useState('https://localhost:1234');
useEffect(() => {
const connection = createConnection(serverUrl, roomId);
connection.connect();
return () => {
connection.disconnect();
};
}, [serverUrl, roomId]);
// ...
}
파라미터
setup
: Effect의 로직이 담긴 함수. 이 함수는 선택적으로 cleanup 함수를 반환할 수 있습니다. 컴포넌트가 DOM에 추가될 때 setup 함수가 실행됩니다. 의존성이 바뀔 때마다 cleanup → setup 순서로 실행됩니다. 컴포넌트가 DOM에서 제거될 때 cleanup 함수가 실행됩니다.dependencies
(선택): setup 코드에서 참조하는 모든 반응형 값의 배열. 의존성 배열이 바뀌지 않으면 이전 Effect가 재사용됩니다. 생략하면 매 렌더마다 Effect가 실행됩니다.
반환값
- 반환값 없음 (undefined)
주의사항
useEffect
는 반드시 컴포넌트의 최상위(혹은 커스텀 Hook 내부)에서만 호출해야 하며, 반복문/조건문 내부에서는 사용할 수 없습니다.- 외부 시스템과 동기화하지 않는다면 Effect가 필요하지 않을 수 있습니다.
- Strict Mode에서는 개발 환경에서만 setup+cleanup이 한 번 더 실행됩니다(테스트 목적).
- 의존성 배열에 객체/함수 등이 들어가면 Effect가 불필요하게 자주 실행될 수 있습니다. 불필요한 의존성은 제거하거나, state 업데이트/비반응성 로직은 Effect 외부로 분리하세요.
- Effect는 클라이언트에서만 실행됩니다. 서버 렌더링 중에는 실행되지 않습니다.
사용법
외부 시스템과 연결하기
네트워크, 브라우저 API, 서드파티 라이브러리 등 외부 시스템과 연결할 때 Effect를 사용합니다.
import { useState, useEffect } from 'react';
import { createConnection } from './chat.js';
function ChatRoom({ roomId }) {
const [serverUrl, setServerUrl] = useState('https://localhost:1234');
useEffect(() => {
const connection = createConnection(serverUrl, roomId);
connection.connect();
return () => {
connection.disconnect();
};
}, [serverUrl, roomId]);
// ...
}
- setup 함수에서 외부 시스템과 연결하고, cleanup 함수에서 연결을 해제합니다.
- 의존성 배열에는 setup/cleanup에서 사용하는 모든 값을 포함해야 합니다.
커스텀 Hook에서 Effect 감싸기
Effect를 자주 반복해서 작성한다면, 커스텀 Hook으로 추출해 재사용할 수 있습니다.
function useChatRoom({ serverUrl, roomId }) {
useEffect(() => {
const connection = createConnection({ serverUrl, roomId });
connection.connect();
return () => connection.disconnect();
}, [roomId, serverUrl]);
}
비-React 위젯 제어하기
Effect를 사용해 React 외부에서 생성된 위젯(예: 지도, 차트 등)을 제어할 수 있습니다.
Effect에서 데이터 패칭하기
Effect에서 데이터를 패칭할 수 있습니다. 단, 프레임워크의 내장 데이터 패칭 기능이 있다면 그 방법이 더 효율적입니다.
import { useState, useEffect } from 'react';
import { fetchBio } from './api.js';
export default function Page() {
const [person, setPerson] = useState('Alice');
const [bio, setBio] = useState(null);
useEffect(() => {
let ignore = false;
setBio(null);
fetchBio(person).then(result => {
if (!ignore) {
setBio(result);
}
});
return () => {
ignore = true;
};
}, [person]);
// ...
}
의존성 배열 지정하기
Effect 내부에서 사용하는 모든 반응형 값(예: props, state 등)은 의존성 배열에 반드시 포함해야 합니다. 불필요한 의존성은 Effect 외부로 빼내세요.
이전 state 기반으로 state 업데이트하기
Effect에서 이전 state를 기반으로 state를 업데이트할 때는 updater 함수를 사용해 의존성 문제를 피할 수 있습니다.
불필요한 객체/함수 의존성 제거하기
Effect 의존성 배열에 객체/함수 등이 들어가면 매번 새로 생성되어 Effect가 자주 실행될 수 있습니다. 이럴 때는 객체/함수를 Effect 내부로 옮기거나, useMemo/useCallback으로 감싸세요.
서버와 클라이언트에서 다른 내용 렌더링하기
서버 렌더링과 클라이언트 렌더링에서 다른 내용을 보여주고 싶을 때, Effect를 사용해 클라이언트에서만 실행되는 코드를 작성할 수 있습니다.
function MyComponent() {
const [didMount, setDidMount] = useState(false);
useEffect(() => {
setDidMount(true);
}, []);
if (didMount) {
// 클라이언트 전용 JSX 반환
} else {
// 초기 JSX 반환
}
}
트러블슈팅
Effect가 마운트 시 두 번 실행됨
Strict Mode에서는 개발 환경에서 setup+cleanup이 한 번 더 실행됩니다. cleanup 함수가 setup의 동작을 완전히 되돌릴 수 있도록 작성하세요.
Effect가 매 렌더마다 실행됨
의존성 배열을 빼먹었거나, 배열에 매번 바뀌는 값(객체/함수 등)이 들어가 있을 수 있습니다. 의존성 배열을 올바르게 지정하세요.
Effect가 무한 루프에 빠짐
Effect에서 state를 업데이트하고, 그 state가 의존성 배열에 들어가 있으면 무한 루프가 발생할 수 있습니다. 정말 필요한 경우가 아니라면 Effect에서 state를 업데이트하지 마세요.
cleanup 함수가 언마운트가 아닌데도 실행됨
cleanup 함수는 언마운트뿐 아니라 의존성 배열 값이 바뀔 때마다 실행됩니다. setup/cleanup이 항상 쌍을 이루도록 작성하세요.
Effect가 시각적 작업을 하는데 깜빡임이 발생함
Effect가 브라우저 페인트 이후에 실행되어 깜빡임이 발생할 수 있습니다. 이럴 때는 useLayoutEffect를 사용하세요.