언어·프레임워크/React.js

[React.js] 컴포넌트 내부 vs. 외부 함수 정의: 성능 최적화 가이드

DandyNow 2025. 3. 12. 15:31
728x90
반응형

React 컴포넌트 내부 vs. 외부 함수 정의: 성능 최적화 가이드

React 컴포넌트를 개발할 때 함수를 어디에 정의하는 것이 좋을까? 컴포넌트 내부와 외부 각각의 장단점을 이해하고 상황에 맞는 최적의 선택을 하는 것은 성능 최적화와 코드 유지보수성에 큰 영향을 미친다. 이번 포스팅에서는 컴포넌트 내부와 외부 함수 정의의 차이점과 최적화 전략에 대해 자세히 알아보고자 한다.

1. 컴포넌트 내부 함수 정의

컴포넌트 내부 함수는 컴포넌트의 상태(state)나 props에 직접 접근할 수 있어 코드 가독성을 높이고 컴포넌트와 밀접하게 관련된 로직을 한 곳에 모을 수 있다는 장점이 있다.

function MyComponent({ data }) {
  const [count, setCount] = useState(0);

  const handleClick = () => {
    setCount(count + 1);
    console.log(data); // props에 직접 접근
  };

  return <button onClick={handleClick}>Click Me</button>;
}

하지만 컴포넌트가 리렌더링될 때마다 함수가 새로 생성되어 불필요한 메모리 사용이 발생할 수 있다. 특히, 컴포넌트 리렌더링이 자주 발생하거나 함수 내부 로직이 복잡한 경우 성능 저하를 초래할 수 있다.

2. 컴포넌트 외부 함수 정의

컴포넌트 외부 함수는 재사용성을 높이고 컴포넌트 리렌더링 시 함수가 다시 생성되지 않아 성능상 이점을 얻을 수 있다. 또한, 순수 함수(pure function)를 외부에 정의하면 테스트가 용이해진다.

const formatData = (data) => {
  // 데이터 변환 로직
  return transformedData;
};

function MyComponent({ data }) {
  const formattedData = formatData(data);

  return <div>{formattedData}</div>;
}

하지만 컴포넌트의 상태나 props에 직접 접근할 수 없어 추가적인 파라미터 전달이 필요할 수 있고, 컴포넌트와 함수 간의 관계가 명확하지 않아 코드 가독성이 떨어질 수 있다.

3. 성능 최적화 전략

1️⃣ useCallback 훅 활용

컴포넌트 내부 함수를 정의해야 하지만 불필요한 재생성을 막고 싶다면 useCallback 훅을 활용할 수 있다. useCallback 훅은 의존성 배열(dependency array)이 변경되지 않는 한 이전에 생성된 함수를 재사용하여 메모이제이션 효과를 얻을 수 있다.

function MyComponent({ data }) {
  const [count, setCount] = useState(0);

  const handleClick = useCallback(() => {
    setCount(count + 1);
    console.log(data);
  }, [count, data]); // count나 data가 변경될 때만 함수 재생성

  return <button onClick={handleClick}>Click Me</button>;
}

2️⃣ useMemo 훅 활용

함수의 반환값을 메모이제이션하고 싶다면 useMemo 훅을 사용할 수 있다. useMemo 훅은 의존성 배열이 변경되지 않는 한 이전에 계산된 값을 재사용하여 불필요한 연산을 방지할 수 있다.

function MyComponent({ data }) {
  const formattedData = useMemo(() => formatData(data), [data]); // data가 변경될 때만 formatData 호출

  return <div>{formattedData}</div>;
}

3️⃣ 컴포넌트 외부 함수 정의 (재사용 및 성능 최적화)

컴포넌트의 상태나 props에 의존하지 않고 재사용 가능한 독립적인 로직을 수행하는 함수는 컴포넌트 외부에 정의하는 것이 좋다.

const updateChartData = (format, data) => {
  const datasets = format.datasets[0];
  const newDatasets = {
    ...datasets,
    data: data.current_day_data,
  };

  return {
    ...format,
    labels: data.hour,
    datasets: [newDatasets],
  };
};

function Dashboard({ chartData }) {
  // ...
  const userChart1 = updateChartData(chartData, resData[1]);
  const userChart2 = updateChartData(chartData, resData[2]);
  const userChart3 = updateChartData(chartData, resData[3]);
  // ...
}

위 예시에서 updateChartData 함수는 컴포넌트의 상태나 props에 직접적으로 의존하지 않고, 독립적인 로직을 수행하므로, 컴포넌트 외부에 정의하는 것이 좋다. updateChartData 함수를 Dashboard 컴포넌트 내부에 useCallback 훅을 사용해 정의할 수도 있겠지만 각각 다른 resData 값을 인수로 전달 받고 있기 때문에 메모이제이션 효과를 보기 어려울 것이다.

4. 결론

컴포넌트 내부와 외부 함수 정의는 각각의 장단점을 가지고 있으며, 상황에 따라 적절한 방식을 선택해야 한다. 컴포넌트의 상태나 props에 의존적인 함수는 컴포넌트 내부에 정의하고, 재사용 가능한 독립적인 함수는 컴포넌트 외부에 정의하는 것이 좋다. 또한, useCallbackuseMemo 훅을 활용하여 불필요한 재생성이나 연산을 방지하고 성능을 최적화할 수 있다.

728x90
반응형