FE 웹 서비스에서 우아하게 비동기 처리하기

Ina·2021년 5월 1일
2

TIL

목록 보기
13/20

웹 서비스에서 다루기 어려운 영역중 하나, "비동기 프로그래밍"

비동기 프로그래밍이 어렵지만 중요한 이유?
서버 응답 기다릴 때 다른 인터랙션에 반응하지 않는다면 화면이 멈춰있을 것.

👉 비동기 프로그래밍을 통해 서버 응답 기다리는 동안 다른 액션도 취해줘야 한다.

Javasctipt에서는 Callback, Promise, Observable 등을 통해 비동기 상황을 핸들링할 수 있음.

이 코드의 문제점은 무엇일까?

function fetchAccounts(callback){
	fetchUserEntity((err,user) => {
    	callback(err, null);
        return;
       		}
      
      fetchUserAccounts(user.no, (err, accounts) => {
          if(err !=null) {
              callback(err, null);
              return;
          }

          callback(null, accounts);
          });
        });
}
  1. 복잡함.
  2. 성공&실패의 경우가 섞여서 처리되고, 매번 비동기 호출시마다 에러처리를 해줘야 함.

이 코드는 왜 좋은 코드일까?

async function fetchAccounts() {
	const user = await fetchUserEntity();
	const accounts = await fetchUserAccounts(user.no);
	return accounts;
}

성공하는 경우만 다루고, 실패하는 경우는 catch 절에서 분리해 처리한다. '실패'하는 경우에 대한 처리를 외부에 위임할 수 있다.

좋은 비동기 코드?
성공/실패의 경우를 분리해 처리한다
👉 비즈니스 로직을 파악하기 쉽다.

그 동안의 FE에서의 비동기 처리는?

const {data, error} = useAsyncValue(()=>{
	return fetchSomething();
})

react-query, SWR같은 라이브러리 활용하여
Promise를 반환하는 함수를 React Hook의 인자로 넘기고,
Promise의 상태 변화에 따라 Hook이 반환하는 data, error의 값을 적절히 채워줌.

실제 컴포넌트를 만든다면,

function Profile() {
	const foo = useAsyncValue(()=> {
    	return fetchFoo();
    });
    
    if(foo.error) return <div>로딩에 실패했습니다.</div>
    if(!foo.data) return <div>로딩중입니다....</div>
    return <div>{foo.data.name}님 안녕하세요!</div>
}

이런 식으로

➡️ 성공&실패하는 경우가 섞여서 처리된다.
➡️ 실패하는 경우에 대한 처리를 외부에 위임하기 어렵다.

↪️ 여러 개의 비동기 작업이 동시에 실행된다면 even worse 🙅‍♀️


만약, React 컴포넌트가 아닌 일반적인 비동기 함수였다면?

async function fetchFooBar() {
	const foo = await fetchFoo();
   	const bar = await fetchBar(foo);

}

위와 같이 간단하게 작성했을 것.

But, React에서 Hook or state를 사용하는 방식으로는 위와 같이 간단하게 비동기 처리가 어려움.
특히 2가지 이상 로직이 들어갈 때 더더욱 어려워짐.

React 팀이 제안하는 "React Suspense for Data Fetching"

<!아직은 실험 단계임!>

React Suspense for Data Fetching
컴포넌트는 성공한 상태만 다루고,
로딩&에러 상태는 외부에 위임함으로써 동기와 거의 같게 사용할 수 있는 기능

  • 로딩: 가장 가까운 Suspense의 fallback으로 그려진다
  • 에러 : 가장 가까운 ErrorBoundary가 componentDidCatch()로 처리

어떻게 사용할 수 있는가?

위와 같이 사용하는 라이브러리의 옵션으로 사용 가능.


토스팀에서는 일부 내부 프로덕트에서 적용중.
데이터가 준비되는대로 하나씩 자연스럽게 보여줄 수 있어서!! 좋은 사용자 경험!

이렇게 코드 조각을 감싸는 맥락으로 책임을 분리하는 방식 : 대수적 효과라고 함

+++ 사용자 경험 향상시킬 수 있는 기술 키워드

  • React Cuncurrent Mode, useTransition, useDeferredValue

출처

https://toss.im/slash-21/sessions/3-1

profile
프론트엔드 개발자. 기록하기, 요가, 등산

0개의 댓글