본문 바로가기
source-code/React

Suspense를 통한 Render-as-you-fetch

by mattew4483 2023. 8. 16.
728x90
반응형

waterfall problem

현 애플리케이션에서 비동기 통신 관련 로직은 다음과 같이 작성되어 있다.

const Detail = ({id}) => {
	const {data, isLoading} = useQuery(fetchDetail)
    
    if(isLoading){
    	return <Loading/>
    }
    
    return <DetailTemplate data={data}/>
}

react-query를 통해 비동기 통신을 제어하며, 이 때 해당 요청의 상태에 맞는 UI를 render한다.

(로딩 중일 경우 로딩 컴포넌트를, 완료된 경우 해당 데이터를 전달)

 

여기서 문제점.

const Detail = ({id}) => {
	const {data, isLoading} = useQuery(fetchDetail)
    
    if(isLoading){
    	return <Loading/>
    }
    
    return (
    	<>	
        	<AnotherData id={id}/>
        	<DetailTemplate data={data}/>
    	</>

}

위와 같은 상황에서 비동기 작업들이 동시에 수행되지 않고, 순차적으로 수행 되면서 불필요한 비효율을 발생시킨다.

(fetchData 작업이 완료되어야만, DetailTemplate 컴포넌트에서 비동기 작업을 시작할 수 있다)

 

Suspense

https://react.dev/reference/react/Suspense

 

<Suspense> – React

The library for web and native user interfaces

react.dev

React에서는 이러한 상황을 개선하기 위해 Suspense를 제공한다.

props
1) children
렌더링하려는 실제 UI. children이 rendering을 유예할 경우, Suspense boundary는 fallback을
rendering 하는 것으로 전환.

2) fallback
loading이 끝나지 않았을 경우, 실제 화면을 대체하는 UI. Suspense는 children이 유예됬을 경우 fallback을, 
데이터가 준비되었을 경우 children을 자동으로 전환.

 

기본적인 사용 방법은 다음과 같다.

const Detail = ({id}) => {
    return (
        <Suspense fallback={<Loading />}>
            <AnotherData id={id}/>
            <Suspense fallback={<SmallLoading />}>
              <DetailTemplate id={id}/>
            </Suspense>
        </Suspense>
    )
}

비동기 작업에 따른 렌더링 작업은 Suspense를 통해 제어할 수 있다.

→ 각 컴포넌트들이 각자의 데이터 fetching을 시작하게 되면서, waterfall problem을 해결할 수 있다.

728x90
반응형