useEffect의 어두운 면

버미·2025년 3월 25일

FrontEnd

목록 보기
5/7
post-thumbnail

1. useEffect에 대해서

useEffect는 외부 시스템과 컴포넌트를 동기화하는 React Hook입니다.

usage: useEffect(setup, dependencies?)

react-api 참고서 - useEffect reference

docs에서는 이렇게 간단히 정의를 내려서 조금 의아했었다. 내가 이해한 대로 설명을 조금 덧 붙이자면 React에서는 상태 변수를 이용하여 상태 관리를 할 수 있는데 useEffect는 dependencies 배열안에 들어간 요소의 상태가 변경되면 특정 작업을 수행하도록 하는 함수인것이다.

또한 컴포넌트가 마운트 된 이후에 어떤 특정 작업을 할지 설정을 해주는 역할을 하기도 한다. 그렇기에 의존성 배열에 빈 배열만 넣게 되면 초기 렌더링 이후 한번만 실행된다. 완전히 생략할 경우에는 컴포넌트가 리렌더링 될 때마다 실행되니 주의하도록 하자.

2. useEffect가 어때서?

의존성 배열내부의 요소 중 하나가 바뀔 때마다 특정 작업을 진행해주는 것은 함수의 구현, 로직을 묶는데 도움이 될 수 있다. 하지만 엄청난 단점이 숨어 있다.

프로젝트 당시 의존성 배열 내부의 요소들을 잘못 설정하게 되면 무한 호출이 발생하게 된다는 것이다. 또한 내가 예상한 범위 외에서 의존성 배열 내부요소들이 변경될 때를 고려하지 못하게 되면 예상치 못한 시점에 로직이 실행되서 혼란에 빠지게 되는 경우가 많았다.

그렇기에 나는 useEffect를 그렇게 즐겨 사용하지 않았지만 팀과의 프로젝트 협업 시 다른 사람의 코드 스타일에는 useEffect가 많이 포함되었었으나 서로 담당하던 파트들이 정해져 있기에 크게 별 지장은 없었다. 하지만 그 코드에서 에러가 터지게 되었고 그 코드를 수정하는 과정에서 중복 호출과 관련된 문제로 많은 고민을 해야 했다.

이 과정 후 전체 피드백에서 useEffect를 많이 사용하지 말자는 의견이 나왔고 앞으로 프로젝트 리팩토링 과정에서도 최대한 자제하자는 부탁을 받았다.

3. 세상에 나쁜 메서드는 없다

그럼 사용하지 말아야 되는 거 아니냐? 이렇게 생각할 수 도 있다. 하지만 나는 세상에 나쁜 메서드는 없다고 생각한다. useEffect 라는 훅이 주는 특정 컴포넌트나 요소가 변경될 경우의 작업을 쉽게 구현할 수 있게 해준다던지 함수 컴포넌트를 사용하면서 수동으로 React 컴포넌트의 DOM을 수정하는 side 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]);
  // ...
}

참고서에서 사용한 예제

여기서 의존성 배열에 포함된 serverUrl, roomId라는 변수는 지금 사용되는 ChatRoom 컴포넌트 내부에서만 사용되는 것들이 아니다. roomId의 경우 props로 부모 컴포넌트에게서 받고 있으며, serverUrl의 경우 도메인과 연관이 있는 변수로서 매우 ChatRoom 컴포넌트에서만 한정적으로 사용되지는 않을 것이다.

이러한 외부적인 요소와 컴포넌트가 동기화를 해야 할 경우에 useEffect를 사용하라고 한다. 물론 참고서를 참고해서 보면 다양한 응용들도 많지만 최소한 외부적인 요소로 인해 컴포넌트가 변경되야 할 때 사용하자고 생각을 하게 되었다.

4. 커스텀 훅에서의 useEffect

function useChatRoom({ serverUrl, roomId }) {
  useEffect(() => {
    const options = {
      serverUrl: serverUrl,
      roomId: roomId
    };
    const connection = createConnection(options);
    connection.connect();
    return () => connection.disconnect();
  }, [roomId, serverUrl]);
}

use Effect를 이용한 커스텀 훅 예제

참고서에서 예로 든 예제에서는 useChatRoom이라는 커스텀 훅을 만들었다. 커스텀 훅은 상태 관리에 대한 로직이 길어질 때 사용을 하거나 컴포넌트가 의존하고 있는 공통적인 동작들이 있을 때 따로 만들어서 관리를 하도록 할 수 있다.

따로 관리하게 될 경우 side Effect (특정 작업) 후 반환되는 요소들을 불러와서 사용할 수 있고 하나의 컴포넌트뿐 아니라 여러 컴포넌트에서 사용이 가능하다는 장점이 있다. 그렇기에 useEffect를 비슷한 구조로 자주 사용할 경우에는 커스텀 훅을 사용하면 좋다고 한다.

덕분에 커스텀 훅을 언제 사용해야 될지에 대한 정리도 할 수 있게 되어 매우 도움이 되었던 정리였다고 생각한다. 또한, docs를 포함한 웹 문서들을 꼼꼼히 읽어보고 자세히 봐야겠다.

아직 배우고 있는 중인 개발자 꿈나무이며 틀린 부분 수정, 의견 교환 등 적극적인 의사소통 매우 환영합니다.
댓글 많이 남겨주세요 긴글 읽어주셔서 감사합니다

profile
함 가봐야 않겠나?

0개의 댓글