React 최적화

soonniee·2021년 5월 30일
0

클린코딩

목록 보기
10/10
post-thumbnail

Caching Functions

함수는 JSX 컴포넌트 render 메소드 안에서 호출 될 수 있다.

function expensiveFunc(input) {
    ...
    return output
}
class ReactCompo extends Component {
    render() {
        return (
            <div>
                {expensiveFunc}
            </div>
        )
    }
}

함수 실행이 오래 걸릴 경우, 렌더링 하는 나머지 부분이 대기하게 되어 사용자들의 경험에 방해가 된다.

ReactCompo를 보면, expensiveFunc은 JSX 안에서 렌더링 되어 리렌더링 될때마다 실행되어 값을 리턴하여 DOM에 렌더링 시킨다. 함수는 CPU 집약적으로 리렌더링될때마다 실행되며 React는 해당 실행이 끝날때 까지 남은 리렌더링 알고리즘을 실행하기 위해 기다려야 한다.

위 상황에서 최고의 선택은 입력되는 값이 같다면 캐시 처리하여 같은 값을 리턴하도록 하는 것이다. 따라서 같은 입력이 다시 발생할 경우 함수의 연속 실행이 더 빨라지게 된다.

function expensiveFunc(input) {
    ...
    return output
}
const memoizedExpensiveFunc = memoize(expensiveFunc)
class ReactCompo extends Component {
    render() {
        return (
            <div>
                {memoizedExpensiveFunc}
            </div>
        )
    }
}

위의 코드에서 사용된 memoize 함수는 memoize-one 라이브러리에서 사용 가능.

memoize 함수에 대한 자세한 내용 : Memoization과 React

React.PureComponent

다시 렌더링이 시작되기 전에 실행되는 생명주기 함수 shouldComponentUpdate로 이 기능을 무시함으로써 속도를 높일 수 있습니다. 이 함수의 기본 implementation은 true를 반환하고 React는 업데이트를 진행합니다.

shouldComponentUpdate(nextProps, nextState) {
  return true;
}

몇몇 상황에서 컴포넌트를 업데이트할 필요가 없다는 것을 알고 있다면 shouldComponentUpdate에서 false를 반환해서 컴포넌트와 그 자식 컴포넌트에서 render()를 호출하는 것을 포함해서 전체 렌더링 프로세스를 건너뛰게 할 수 있습니다.

대부분의 경우 shouldComponentUpdate()를 직접 작성하는 대신 React.PureComponent에서 상속 받을 수 있습니다. 그것은 현재와 이전의 prop과 state의 얕은 비교로 shouldComponentUpdate()를 호출하는 것과 같습니다.

예시

class ReactComponent extends Component {
    constructor(props, context) {
        super(props, context)
        this.state = {
            data: null
        }
        this.inputValue = null
    }
    handleClick = () => {
        this.setState({data: this.inputValue})
    }
    onChange = (evt) => {
        this.inputValue = evt.target.value
    }
    shouldComponentUpdate( nextProps,nextState) {
        if(nextState.data === this.state.data)
            return false
        return true
    }
    render() {
        l("rendering App")
        return (
            <div>
                {this.state.data}
                <input onChange={this.onChange} />
                <button onClick={this.handleClick}>Click Me </button>
            </div>
        )
    }
}

React.PureComponent 사용

class ReactComponent extends React.PureComponent {
    constructor(props, context) {
        super(props, context)
        this.state = {
            data: null
        }
        this.inputValue = null
    }
    handleClick = () => {
        this.setState({data: this.inputValue})
    }
    onChange = (evt) => {
        this.inputValue = evt.target.value
    }
    render() {
        l("rendering App")
        return (
            <div>
                {this.state.data}
                <input onChange={this.onChange} />
                <button onClick={this.handleClick}>Click Me </button>
            </div>
        )
    }
}

위와 같이 shouldComponentUpdate를 지우고 React.PureComponent를 상속받도록 하였다.

text 창에 2를 입력하고 Click Me를 연속으로 누르면 ReactComponent는 한번 렌더링 된 후 다시는 렌더링 되지 않는 것을 볼 수 있다.

이것은 단순히 객체 참조만 비교하는 것이 아니라 이전 props와 state 객체들과 변경할 state와 props를 얇게 비교한다.

React.PureComponent는 component가 렌더링 되는 횟수를 줄임으로서 최적화를 하게 해준다.

참고

[번역] React의 성능을 최적화하는 10가지 방법
성능 최적화 - React 공식문서

0개의 댓글

관련 채용 정보