728x90
728x90

 

문제점

 

프로젝트 개발하던 중에, 마이페이지 부분에서 무한 렌더링이 발생했다. 사용자가 페이지에 접속하면, 화면이 계속해서 새로고침되는 현상이 발생한 것이다.

무한 렌더링… 이노무시키를 해결하기 위해 React DevTools를 사용하여 컴포넌트 트리를 검사했다. 자꾸만 렌더링이 되는 컴포넌트를 확인했고, 해당 컴포넌트의 코드를 여러번 검토했다. 컴포넌트의 상태와 속성 또한 여러번 다시 봤는데도 잘 안 잡혔는데, 어휴 머리 아파 이러면서 물 뜨러 갔다가 찾아냈다!

해결책

1. 컴포넌트 상태 업데이트에 대한 조건 넣기

무한 렌더링이 발생한 컴포넌트 안에서 상태가 변경될때 조건문을 추가했다. 렌더링을 제어하기 위해서였다. 이렇게 두면 상태가 변경되지 않는 한 렌더링이 반복되지 않았다

class InfiniteRenderComponent extends React.Component {
  state = {
    count: 0,
  };

  componentDidMount() {
    this.interval = setInterval(() => {
      if (this.state.count < 5) { // 특정 조건을 만족할때만 렌더링하도록 쓴 코드 
        this.setState((prevState) => ({ count: prevState.count + 1 }));
      }
    }, 1000);
  }

  componentWillUnmount() {
    clearInterval(this.interval);
  }

  render() {
    return <div>{this.state.count}</div>;
  }
}

나는 프로젝트에 문제가 생기면 , 인터넷과 공식문서를 미친듯이 뒤져서 답을 찾는다. 하지만 답을 그냥 그대로 붙여넣는 행동은 자제하자고 항상 생각한다.

내 뇌에 잘 녹아들어야지 내 코드에도 녹일 수 있다고 생각하기 때문이다. 그래서 항상 어떻게 사용해야 할 지 예시 파일을 만드는 편이다.

저 위의 파일도 그렇게 예시로 만들어본것이다.

2. . 컴포넌트 수명주기 메서드 활용 : ‘componentDidUpdate’

‘componentDidUpdate’ 라는 메서드를 사용해 상태 업데이트 후 렌더링을 조절할 수 있게 두었다.

메서드 이름이 …

 

 👰🏻 컴포넌트는 업데이트 되었어요 !

 

너무 귀엽다 진짜… 메서드들 중 이름 귀여운거 진짜 많은데 와 나 진짜 왜 사람들이 이걸 몰라주지ㅠㅠ

3. 그래서 이게 무슨 원리인데?

주로 컴포넌트의 상태와 수명주기 메서드를 활용해 렌더링을 조절하고 무한 렌더링을 방지하는 것이다. 상태 업데이트 시에 특정 조건을 검사하거나 ‘componentDidUpdate’메서드를 활용하여 필요한 경우 렌더링을 제어한다. 이러한 방식으로 React 컴포넌트에서 발생하는 무한렌더링 문제를 해결할 수 있다.

렌더링이 문제다 문제.

대규모 데이터를 다루는 React 애플리케이션일수록 화면이 느리게 렌더링된다. 이는 정말 당연한 이야기이다. 당연하지. 처리해야 할 게 많으니 느려지는 거는.

그런데,,,

 👿 컴포넌트가 불필요하게 재랜더링되는거는 그냥 신경을 안 쓴 거잖아!

 

아니, 내가 왜 이렇게 코드를 짰을까 두번 세번 후회하면서 다시 또 DevTools를 꺼내들었다.

어. 정말 답이 없었다.

  • DevTools 사용: React Developer Tools의 Profiler 탭을 사용하여 리렌더링을 초래하는 원인을 추적했다.
  • 코드 리뷰: 해당 컴포넌트의 props와 state의 변화를 주의 깊게 살펴보았다.

아마 문제의 원인은 부모 컴포넌트에서 불필요하게 자식 컴포넌트에게 전달되는 props 때문이었다.

  • React.memo 사용 : 동일한 props와 state로 호출될 때 재렌더링을 방지하는 역할을 한다
  • 컴포넌트 분리 : 불필요한 리렌더링을 초래하는 props를 가진 부분을 독립된 컴포넌트로 분리하기

1. Memoization 라이브러리

  • Memoization 라이브러리란?

→ 함수 결과를 캐싱하고, 동일한 인자로 함수를 호출할 때 캐싱된 결과를 반환하는 방법을 고려했다

해결책

Memoization 라이브러리 중하나인 ‘memoize-one’을도입하여 컴포넌트의 최적화를 진행해보았다. 이 라이브러리를 사용하면 함수의 결과를 메모이제이션하여 동일한 인자로 함수를 호출할 때 불필요한 연산을 피할 수 있다. 그러니까… 컴포넌트의 렌더링 . 효율적으로 관리되겠죠?

이게 왜 되는거냐면 Memoiization은 함수 호출 결과를 캐싱하여 이전에 계산한 값을 재사용했다. 이로서 연산의 중복을 방지했지롱. 저 라이브러리 리엑트 컴포넌트에서 쓰기 짱 편한듯

import memoize from 'memoize-one';

// Memoization 함수 생성
const memoizedFunction = memoize((arg1, arg2) => {
  // 복잡한 계산 로직
  return arg1 + arg2;
});

// 컴포넌트 내에서 Memoization 함수 사용
const result = memoizedFunction(5, 10); // 이후 동일한 인자로 호출 시 캐시된 결과 반환

 

왜 얘는 막쓴 코드 없냐고 물어볼 것 같아서 들고왔다.

함수의 결과가 캐싱되어 동일한 인자로 호출될때까지 계산되지 않고 캐싱된 결과가 반환된다. 이로 컴포넌트의 렌더링을 최적화할수 있다.

2. React.memo

리엑트의 성능 최적화 기능 중 하나다. PureComponent 이랑 유사한 기능을 함수형 컴포넌트에서도 사용할 수 있단다…오

동일한 props와 state로 컴포넌트가 호출될때 재렌더링을 방지하여 성능을 향상시킨다

import React, { useState } from 'react';

// 불필요한 리렌더링을 초래하는 컴포넌트
const SubComponent = ({ data, onClick }) => {
  console.log('SubComponent re-rendered!');
  return (
    <div>
      <p>{data}</p>
      <button onClick={onClick}>Click me</button>
    </div>
  );
}

// React.memo를 사용하여 리렌더링 최적화
const OptimizedSubComponent = React.memo(SubComponent);

const ParentComponent = () => {
  const [count, setCount] = useState(0);

  const handleClick = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <OptimizedSubComponent data="Hello, React!" onClick={handleClick} />
      <p>Clicked: {count} times</p>
    </div>
  );
}

export default ParentComponent;

 

일케 한번씩 써보았다. 오… 놀랍구만 놀라워

 

위 코드에서 OptimizedSubComponent는 동일한 props로 호출될 때 불필요한 리렌더링을 방지하며, 전체 앱의 성능을 향상시키게 된다.

react에서 성능 이슈는 다양한 원인으로 발생할 수 있어서 너무 화난다. 어디가 문제인지 모를때는 더더욱. 불필요한 리렌더링은 앱의 성능을 정말 크게 저하시킨다. 한국인들 빨리빨리 병 있는데 갑자기 어플 하나 키는데 10초~20초 걸리면 누가 그 어플 쓰겠어…

문제의 원인을 정확하게 파악하고, 적잘하게 대처하는것이 중요한 것 같다.

728x90
300x250

+ Recent posts