[React.js]리액트 만들기.part3.suspense

유선향·2025년 10월 9일

<React>

목록 보기
4/5

바닐라 자바스크립트로 직접 리액트의 주요 기능을 만들어보며, 동작원리를 좀더 심층적으로 이해하기 위해 아래 글을 따라가며 얻은 인사이트와 학습을 기록하는 글입니다. 또한 아래 글의 4가지 챕터로 리액트의 동작원리를 이해하는 단계를 그대로 따라가기에, 아래 Medium 글을 참고하시는게 직접 해보시는 것에는 도움이 되실 겁니다.

lets-build-a-react-from-scratch-part-3-react-suspense-and-concurrent-mode

git hub repo : part3 branch(파트에 따라서 브랜치를 분배 했습니다)


동시성 모드란?

위의 해당글의 문제 해결

위의 글에서는 문제점에 대해 이야기 하고, 해결은 작은 과제처럼 남겨두었길래, 이 글에 문제점에 대한 해결의 내용을 남겨보려고 한다.


export const resourceCache = {};

const createResource = (fallback,task, key, ) => {
  //리소스 캐시가 있으면 참조하고, 없으면 propmise,key,fallback 을 throw 한다. 
  if (resourceCache[key]) return resourceCache[key];
  const promise = asyncTask();
  throw { promise, key, fallback };
};

export const Suspense = (props, children) => {
  const { fallback, task, key  } = props;
  createResource(fallback,task,key);
  return children;
};


//app.tsx

export default function App () {
  ...
  const photo1 = resourceCache["photo1"];
  const photo2 = resourceCache["photo2"];

  ...
  //비동기 적으로 불러오는 리소스를 참조하는 컴포넌트를 Suspense 컴포넌트로 감싼다. 

	<Suspense
        fallback={<h2>사진1 로딩중...</h2>}
        task={() => getMyAwesomePic("photo1")}
        key={"photo1"}
      >
        <img src={photo1} alt="사진1" />
      </Suspense>
   	<Suspense
        fallback={<h2>사진2 로딩중...</h2>}
        task={() => getMyAwesomePic("photo2")}
        key={"photo2"}
      >
        <img src={photo2} alt="사진2" />
      </Suspense>

...


//React.createElement 수정
const React = {
  createElement: (tag, props, ...children) => {
    if (typeof tag === "function") { 
      try {
        return tag(props, ...children);
      } catch ({ promise, key, fallback }) {
        promise.then((value) => {
          resourceCache[key] = value;
          reRender();
        });
        return fallback;
      }
    }
    const el = {
      tag,
      props,
      children,
    };
    return el;
  },
};
export default React;

동작 플로우

  1. app.tsx 가 초기 렌더 되면서, suspense 부분을 만나고, throw {promise, key,fallback} 인 상태로 createElement로 넘어가게 된다.
  2. createElement 에서는, catch 문으로 들어가서 에러 객체에 promise, key, fallback 을 구조 분해 하여 promise를 실행한다.(이때, 실행 중에는 return fallback으로 fallbackUi를 보여준다)
  3. promise 완료이후 resourceCache에 저장한 뒤에 reRender()를 실행한다.

해결한 모습

위 글의 문제점 처럼 task 1을 해결한 후에 task2를 실행하는 것이 아니라, task1,task2가 해결되면 fallbackUI 가아닌 실제 렌더링 해야하는 요소를 각각 보여준다.

0개의 댓글