May 04, 2021

토스 SLASH 21의 프론트엔드 웹 서비스에서 우아하게 비동기 처리하기라는 주제로 박서진님이 발표하신 내용을 정리한 내용입니다.
// 💩
function getBazFromX(x) {
if (x === undefined) {
return undefined;
}
if (x.foo === undefined) {
return undefined;
}
if (x.foo.bar === undefined) {
return undefined;
}
return x.foo.bar.baz;
}핵심 기능이 코드로 잘 드러나지 않는다// 👍
function getBazFromX(x) {
return x?.foo?.bar?.baz;
}Optional Chaining 문법을 활용한 동일한 함수// 💩
function fetchAccounts(callback) {
fetchUserEntity((err, user) => {
if (err != null) {
callback(err, null);
return;
}
fetchUserAccount(user.no, (err, accounts) => {
if (err != null) {
callback(err, null);
return;
}
callback(null, accounts);
});
});
}성공하는 경우와 실패하는 경우가 섞여서 처리된다// 👍
async function fetchAccounts() {
const user = await fetchUserEntity();
const accounts = await fetchUserAccounts(user.no);
return accounts;
}보통 API 호출 시에, SWR, react-query와 같은 라이브러리 사용
Promise를 반환하는 함수를 React Hook의 인자로 넘기고, Promist 상태에 따라 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>;
}// 💩
function Profile() {
const foo = useAsyncValue(() => {
return fetchFoo();
});
const bar = useAsyncValue(() => {
if (foo.error || !foo.data) {
return undefined;
}
return fetchBar(foo.data);
});
if (foo.error || bar.error) return <div>로딩에 실패했습니다.</div>;
if (!foo.data || !bar.data) return <div>로딩중입니다 ...</div>;
return (
<div>
{foo.data}, {bar.data}
</div>
);
}async function fetchFooBar() {
const foo = await fetchFoo();
const bar = await fetchBar(foo);
return bar;
}데이터를 가져오기 위한 Suspense
React의 실험 버전에서만 사용 가능
function FooBar() {
const foo = useAsyncValue(() => fetchFoo());
const bar = useAsyncValue(() => fetchBar(foo));
return (
<div>
{foo}
{bar}
</div>
);
}<ErrorBoundary fallback={<MyErrorPage />}>
<Suspense fallback={<Loader />}>
<FooBar />
</Suspense>
</ErrorBoundary>쓰는 쪽에서 로딩 처리와 에러 처리를 한다Suspense의 Fallback으로 그려진다ErrorBoundary가 componentDidCatch()로 처리한다Recoil : Async Selector SWR, React Query : {suspense: true}
runPureTask로 실행시키면, 비동기 함수도 동기적으로 작성할 수 있다
어떤 코드 조각을 감싸는 맥락으로 책임을 분리하는 방식을 대수적 효과(Algebraic Effects)라고 한다
객체지향의 의존성 주입(DI), 의존선 역전(IoC)과도 유사
컴포넌트의 렌더 트리를 부분적으로로 완성함으로써 사용자 경험을 향상시킬 수 있다
React Concurrent Mode, useTransition, useDeferredValue
useMemo, useCallback SWR? React-Query?
이해하기 어려운 부분이 많았지만 많은 부분을 알고, 깨닫게 된 느낌을 받았다.
직군이 앓고 있는 문제를 제시하고 어려운 코드, 좋은 코드를 보여줌과 동시에 해결 방안을 제시하고 회사에서는 어떻게 사용하여 해결하였는 지를 설명해주는 기승전결이 너무 좋다고 느껴졌으며, 무료로 들을 수 있는 것에 감사하다고 생각된다.
개발하는 시간 외에 공부하는 시간을 만들어야겠다.