앱에서 버튼을 클릭하면 일련의 동작들이 실행되게 됩니다.
버튼 클릭
-> 로컬 상태 변경
-> 서버에 요청1
-> 서버에 요청2
-> 로컬 상태 변경
-> UI 변화
여기서 출발점은 버튼 클릭
이고 최종 도착점은 UI변화
입니다.
만약 출발점에서 도착점에 도달하는 여정의 사이에 작은 가방을 가지고 다니면서 필요한 물건들을 담거나 뺄 수 있으면 어떨까요?
이런 멋진 아이디어를 생각한 사람은 이미 오래전부터 있었습니다.
이를 실행 컨텍스트 라고 합니다.
input이 들어와서 output이 나올때까지 유지되는 컨텍스트를 의미합니다.
설명하기 모호한데 가장 간단한 설명은 변수의 집합
이라고 할 수도 있을 것 같습니다. (근데 어디가서 이렇게 말하면 오답이긴 합니다.)
아래 코드는 context의 가장 간단한 구현이라고 볼수도 있습니다.
const context = { val: 1234 };
// 각각의 work는 context의 값을 읽거나 쓸 수 있습니다.
beginWork1(context);
beginWork2(context);
beginWork3(context);
일반적인 취소 가능한 mutation 함수
const onClickSendImage = async (images: File[]) => {
const abortController = new AbortController();
const urls = [];
for (const image of images) {
urls.push(await uploadImage(image, abortController));
}
await sendMessage(urls, abortController);
};
실행 컨텍스트를 사용한 취소 가능한 함수
const onClickSendImage = runInContext(async () => {
const urls = [];
for (const image of images) {
urls.push(await uploadImage(image));
}
await sendMessage(urls);
});
class HttpClient {
post(params) {
// 마치 나이더스 커널같은 통로가 생겼습니다!
const ac = getContext().abortController;
return fetch(params.path, {
body,
signal: ac,
});
}
}
이 방법은 루즈 커플링의 일종입니다.
읽어보면 아시겠지만 루즈 커플링은 장단점이 확실합니다!
이 글에서는 요청의 취소 처리를 실행 컨텍스트, 그리고 루즈 커플링을 통해서 어떻게 구현할 수 있는지만을 보여줍니다. 그리고 당연하게도 이건 요청 취소를 우아하게 처리하는 유일한 방법은 아닙니다.