[React] 당신은 상태를 필요로 하지 않을 것입니다. #4 - 비동기(with. use) 편

고라니드로고라니드로
2 min read

이 포스트는 React 버전 18.3.1을 기준으로 합니다.

이번 편은 이전 편으로부터 이어집니다.

use의 구체적인 동작은 다음과 같습니다.

  1. use는 호출자로부터 Promise를 전달받습니다.

  2. Promise가 추적 중인지 확인합니다. 추적 중이 아니라면 추적을 시작합니다.

  3. 추적 중인 Promise의 상태를 확인합니다. 상태에 따라 다음을 진행합니다.

    1. 진행(pending) - 대기 Promise 객체를 throw 합니다. Suspense는 이를 catch 하여 await 합니다.

    2. 이행(fulfilled) - 결과를 반환합니다.

    3. 반려(rejected) - 오류를 throw 합니다. Suspense는 이를 catch 하지 않지만, ErrorBoundary가 이를 catch 하여 처리할 수 있습니다. 자세한 내용은 본 포스트에서 다루지 않습니다.

코드로 나타내면 아래와 같습니다.

function use<T>(promise: Promise<T>): T {
    if(!isTracking(promise)) { beginTracking(promise); }

    if(wasFulfilled(promise)) { return getValue(promise); }
    throw wasRejected(promise) ? getError(promise) : getWaiting(promise);
}

Promise 추적하기

Promise를 추적해야 하는 이유는 상태나 결과를 동기적으로 추출할 수 없기 때문입니다. 따라서 진행 상황에 따라 직접 정보를 갱신 및 유지해야 합니다. 그렇다면 Promise를 어떻게 추적할 수 있을까요?

enum PromiseState { PENDING, FULFILLED, REJECTED };

interface PromiseStatus<T> {
    state: PromiseState;
    waiting: Promise<void>;
    value?: T;
    error?: any;
}

const promiseStatusMap = new WeakMap<Promise<any>, PromiseStatus<any>>();

잠깐! WeakMap 사용이 처음이라면 [TypeScript] 메타데이터 관리하기(with. WeakMap)를 먼저 읽어보세요!

WeakMap을 활용하여 비교적 간단하게 구현할 수 있습니다. WeakMap에 포함 여부를 통해 간단히 추적 여부를 확인할 수 있습니다. 추적 중이라면 PromiseStatus에 접근하여 원하는 정보를 추출할 수도 있습니다.

beginTracking은 아래와 같이 구현할 수 있습니다.

function beginTracking(promise: Promise<any>): void {
    const status: PromiseStatus<any> = {
        waiting: promise.then(value => {
            status.state = PromiseState.FULFILLED;
            status.value = value;
        }).catch(error => {
            status.state = PromiseState.REJECTED;
            status.error = error;
        }),
        state: PromiseState.PENDING
    };
    map.set(promise, status);
}

최초에는 항상 대기 중인 것으로 취급하며, thencatch를 활용하여 결과에 따라 정보를 갱신합니다. 이 외의 함수는 모두 이렇게 관리되는 정보에 접근하여 읽어오는 것뿐이므로 쉽게 구현할 수 있을 것입니다.

시리즈는 다음 편에서 계속됩니다. 읽어주셔서 감사합니다!

주인장의 라이브러리

블로그 주인장이 구현한 라이브러리입니다! 기능을 직접 구현하는 대신 사용할 수 있습니다!

묻고 답하기

개인적인 판단에 의해 적절하다고 여겨지는 경우, 모두가 볼 수 있도록 이곳에 문답이 추가됩니다. 그렇지 않더라도 질문에 대한 답변은 별도로 이루어집니다.

0
Subscribe to my newsletter

Read articles from 고라니드로 directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

고라니드로
고라니드로