React.lazy 와 Suspense 를 통한 컴포넌트 비동기 렌더링

React.lazy 와 Suspense 는 리액트에 내장되어있는 코드스플리팅을 위한 유틸 함수 및 컴포넌트입니다. 사용방법은 우리가 이전 섹션에서 구현했던 withSplitting 과 매우 유사합니다. 이 기능은 리액트 16.6 부터 도입이 되었으며, 이전 버전에서는 withSplitting 처럼 코드 스플리팅을 하거나, 혹은 react-loadable (다음 섹션에서 다루룹니다) 을 사용해야 했습니다.

React.lazy 와 Suspense 를 사용하는것이 이제 최신 리액트버전에서는 정석적인 방법입니다. 하지만, 서버사이드 렌더링을 하게되는 경우 리액트 매뉴얼에서는 아직까지는 react-loadable 을 사용하는것을 추천하고 있습니다. 아직까진 React.lazy 와 Suspense 가 서버사이드 렌더링까지 지원하고 있지는 않지만, 추후엔 지원 될 것으로 예상됩니다.

React.lazy 의 역할은, 우리가 구현했던 withSplitting 과 유사합니다. 그리고 Suspense 는 리액트에 내장되어있는 컴포넌트인데, 이를 통하여 코드스플리팅된 파일이 로딩되는동안 임시적으로 보여줄 JSX 를 설정 할 수 있게 해줍니다.

한번 직접 사용해봅시다!

React.lazy 는 이렇게 사용합니다:

const SplitMe = React.lazy(() => import('./SplitMe'));

withSplitting 을 사용할때랑 거의 비슷하죠?

그리고, Suspense 는 이렇게 사용합니다:

import React, { Suspense, Component } from 'react';

react 에서 위와 같이 불러오고,

JSX 에서 사용할땐 React.lazy 를 통하여 불러온 컴포넌트를 Suspense 로 감싸서 사용합니다.

<Suspense fallback={<div>로딩중입니다...</div>}>
  <SplitMe />
</Suspense>

참 쉽죠? 전체 App.js 코드를 확인해볼까요?

src/App.js

import React, { Component, Suspense } from 'react';
import logo from './logo.svg';
import './App.css';

const SplitMe = React.lazy(() => import('./SplitMe'));

class App extends Component {
  state = {
    visible: false
  };
  handleClick = () => {
    this.setState({
      visible: true
    });
  };
  render() {
    const { visible } = this.state;
    return (
      <div className="App">
        <img
          src={logo}
          className="App-logo"
          alt="logo"
          onClick={this.handleClick}
        />
        <p>Hello React!</p>
        {visible && (
          <Suspense fallback={<div>로딩중입니다...</div>}>
            <SplitMe />
          </Suspense>
        )}
      </div>
    );
  }
}

export default App;

이제 SplitMe 가 렌더링 될 때 아직 코드를 다 불러온 상태가 아니라면 "로딩중입니다..." 라는 문구가 나타날것입니다. 물론, 로컬에서 테스트 할 때는 엄청나게 빨리 불러오게 되므로 눈깜짝할 사이에 뜨기 때문에 제대로 확인하지 못할수도 있습니다.

그럴땐, 크롬 개발자도구에서 네트워크 탭을 열어서 Offline 체크박스 우측의 Online 셀렉트박스를 눌러서 다음과 같이 느린 인터넷 환경을 시뮬레이트 하여 확인을 해보시면 됩니다:

Edit splitting-sample

results matching ""

    No results matching ""