심화 가이드
시그널

Resource 를 활용한 비동기 반응성

주의: resource 는 아직 실험 단계 입니다. 지금 사용해 볼 수는 있지만 이후에 안정 버전이 나오면서 변경될 수 있습니다.

signal, computed, input 등의 시그널 API는 대부분 동기 방식으로 동작합니다. 그런데 애플리케이션은 데이터를 비동기로 다뤄야 하는 경우가 종종 있습니다. 이 때 Resource를 활용하면 애플리케이션이 시그널 기반으로 동작하면서 비동기 데이터를 처리할 수 있습니다.

Resource를 활용하면 모든 종류의 비동기 작업을 다룰 수 있지만, 가장 많이 사용하는 경우는 역시 서버에서 데이터를 받아오는 것입니다. 아래 코드는 사용자 데이터를 받아오는 예제 코드입니다.

Resourceresource 함수로 생성하는 것이 가장 간단합니다.

      
import {resource, Signal} from '@angular/core';const userId: Signal<string> = getUserId();const userResource = resource({  // 반응셩 연산 함수를 정의합니다.  // params 값은 시그널을 읽을 때마다 다시 계산됩니다.  params: () => ({id: userId()}),  // 데이터를 받아오는 비동기 로더 함수를 정의합니다.  // Resource는  `params` 값이 변경될 때마다 이 함수를 실행합니다.  loader: ({params}) => fetchUser(params),});// 리소스의 로더 함수의 실행 결과로 연산 시그널을 생성합니다.const firstName = computed(() => userResource.value().firstName);

resource 함수는 ResourceOptions 객체를 인자로 받는데, 이 객체에는 paramsloader 프로퍼티가 있습니다.

params 프로퍼티에는 인자값을 생성할 반응형 연산 함수를 지정합니다. 이 계산 함수에서 읽는 시그널이 변경될 때마다 Resource는 새로운 값을 생성합니다. 연산 시그널과 비슷합니다.

loader 프로퍼티에는 어떤 값을 받아오는 비동기 함수인 ResourceLoader를 지정합니다. 리소스는 params 연산 함수가 새 값을 계산할 때마다 로더 함수를 실행하면서 그 값을 인자로 전달합니다. 자세한 내용은 Resource 로더 문서를 참고하세요.

Resource 객체에는 로더의 결과를 담는 value 시그널도 있습니다.

리소스 로더

리소스를 생성할 때 ResourceLoader를 지정합니다. 이 로더는 ResourceLoaderParams 객체를 인자로 받는 비동기 함수이며, 값을 하나 반환합니다.

ResourceLoaderParams 객체에는 params, previous, abortSignal 프로퍼티가 있습니다.

프로퍼니 설명
params 리소스의 params 연산 함수
previous status 프로퍼티와 이전 ResourceStatus 값이 담겨 전달되는 객체입니다.
abortSignal AbortSignal에 대해 자세하게 알아보려면 요청 취소하기 섹션을 참고하세요.

params 연산 함수가 undefined를 반환하면, 로더 함수가 실행되지 않으며 리소스의 상태는 'idle'로 유지됩니다.

요청 취소하기

리소스가 로드되는 동안 params 연산 함수가 변경되면 리소스는 완료되지 않은 로딩을 취소합니다.

그리고 ResourceLoaderParamsabortSignal을 지정하면 중단된 요청에 응답할 수 있습니다. 네이티브 fetch 함수를 AbortSignal로 적용해 봅시다:

      
const userId: Signal<string> = getUserId();const userResource = resource({  params: () => ({id: userId()}),  loader: ({request, abortSignal}): Promise<User> => {    // fetch는 `AbortSignal`을 통해 중단 요청이 들어올 때 미처리된 모든 `HTTP 요청을 취소합니다.    return fetch(`users/${request.id}`, {signal: abortSignal});  },});

AbortSignal을 사용해서 요청을 취소하는 방법을 자세하게 알아보려면 MDN의 AbortSignal 문서를 참고하세요.

재시도

리소스 객체의 reload 메서드를 실행하면 loader 함수를 다시 실행할 수 있습니다.

      
const userId: Signal<string> = getUserId();const userResource = resource({  params: () => ({id: userId()}),  loader: ({params}) => fetchUser(params),});// ...userResource.reload();

리소스 상태

리소스 객체는 비동기 로더를 실행하면서 여러 상태로 변화합니다.

프로퍼티 설명
value 리소스 객체의 최종 값, 값을 받지 못했으면 undefined
hasValue 리소스가 값을 갖고 있는지 여부
error 리소스 로더를 실행하다가 발생한 가장 최근 에러, 에러가 발생하지 않았다면 undefined
isLoading 리소스 로더가 실행중인지 여부
status 리소스의 세부 ResourceStatus, 아래에서 설명

status 시그널에는 시그널의 상태를 문자열로 더 자세하게 표현하는 ResourceStatus 값이 존재합니다.

상태 value() 설명
'idle' undefined 리소스에 유효한 요청이 없으며, 로더가 실행되지 않았음
'error' undefined 로더 실행 중 에러가 발생했음
'loading' undefined request 값이 변경되어 로더가 실행중
'reloading' 이전 값 리소스의 reload 메서드가 실행되어 로더가 실행중
'resolved' 계산된 값 로더 실행 종료
'local' 직접 설정된 값 리소스의 .set(), .update() 메서드로 값이 설정되 상태

이 상태값들은 사용자에게 표시하는 용도로 활용하거나, 로딩 인디케이터, 에러 메시지를 활용하는 용도로 활용할 수 있습니다.