Allra Fintech

화면이 그려진 다음에 할 일

useEffect를 이해하고, 화면 렌더링 이후에 실행되는 코드를 다루는 방법을 배웁니다.

렌더링만으로는 부족할 때

지금까지 배운 흐름은 이랬습니다.
상태가 바뀌면 React가 화면을 다시 그린다.

그런데 실무에서는 "화면을 그린 다음에 해야 하는 일"이 있습니다.

  • 화면이 뜨자마자 서버에서 데이터를 가져와야 한다
  • 타이머를 걸어야 한다
  • 외부 라이브러리를 초기화해야 한다

이런 일들은 화면을 그리는 것과는 별개입니다.
React에서는 이걸 부수 효과(side effect) 라고 부르고, useEffect로 다룹니다.

useEffect 기본 형태

useEffect(() => {
  // 화면이 그려진 다음에 실행되는 코드
}, []);

두 부분으로 나뉩니다.

  • 첫 번째 인자: 실행할 함수
  • 두 번째 인자: 의존성 배열 — 이 배열에 담긴 값이 바뀔 때마다 함수가 다시 실행됩니다

빈 배열 []을 넘기면 컴포넌트가 처음 화면에 나타날 때 딱 한 번 실행됩니다.

화면에 뜨자마자 데이터 가져오기

function UserList() {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    fetch('/api/users')
      .then(res => res.json())
      .then(data => setUsers(data));
  }, []);

  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

흐름을 따라가면 이렇습니다.

  1. 컴포넌트가 화면에 나타남 (빈 목록)
  2. useEffect 실행 → 서버에 데이터 요청
  3. 데이터 도착 → setUsers로 상태 변경
  4. 상태가 바뀌었으니 화면 다시 그림 (목록 표시)

의존성 배열이 하는 일

의존성 배열에 값을 넣으면, 그 값이 바뀔 때마다 함수가 다시 실행됩니다.

const [userId, setUserId] = useState(1);
const [user, setUser] = useState(null);

useEffect(() => {
  fetch(`/api/users/${userId}`)
    .then(res => res.json())
    .then(data => setUser(data));
}, [userId]);

userId1에서 2로 바뀌면 useEffect 안의 함수가 다시 실행됩니다.
userId가 그대로면 실행하지 않습니다.

의존성 배열실행 시점
[]처음 한 번만
[userId]userId가 바뀔 때마다
생략매 렌더링마다 (주의 필요)

의존성 배열을 아예 생략하면 렌더링할 때마다 실행되기 때문에,
의도하지 않은 반복 실행이 발생할 수 있습니다. 대부분의 경우 배열을 명시하는 게 안전합니다.

정리 작업이 필요할 때

타이머나 이벤트 리스너처럼 "시작했으면 끝내야 하는" 작업은 정리 함수를 반환합니다.

useEffect(() => {
  const timer = setInterval(() => {
    console.log('tick');
  }, 1000);

  return () => {
    clearInterval(timer);
  };
}, []);

return 으로 반환한 함수는 컴포넌트가 화면에서 사라질 때 실행됩니다.

정리를 안 하면 타이머가 계속 돌거나, 이벤트 리스너가 쌓이는 문제가 생깁니다.
시작한 건 반드시 끝내야 합니다.

흔한 실수

// 의존성 배열 없이 setState → 무한 루프
useEffect(() => {
  fetch('/api/users')
    .then(res => res.json())
    .then(data => setUsers(data));
});

의존성 배열을 생략하면 매 렌더링마다 실행됩니다.
setUsers → 렌더링 → useEffect 실행 → setUsers → 렌더링 → ...
끝없이 반복됩니다.

데이터 요청 같은 작업은 반드시 [] 또는 적절한 의존성 배열을 넣어주세요.

정리

  • useEffect는 화면이 그려진 다음에 실행되는 코드를 담는 곳이다.
  • 의존성 배열로 "언제 다시 실행할지"를 제어한다.
  • 시작한 작업은 반환 함수로 반드시 정리해야 한다.

직접 해보기

  • 화면에 뜨자마자 콘솔에 메시지를 출력하는 컴포넌트 만들어보기

다음 챕터 예고

여기까지 오면 React의 핵심 도구(state, 참조값, useEffect)를 한 바퀴 돌았습니다.
다음에는 이 도구들을 합쳐서 투두리스트를 직접 만들어 보겠습니다.