bgyoonsContact

Fire and Forget 패턴일 때의 비동기 처리

문제해결 | | 5분 읽기

try {
  API.POST({
    url: API_STATISTICS_VIEW_LOG,
    data: { productId },
  });
} catch (error) {}

위와 같은 api 호출하는 코드를 회사에서 발견했다.

그러나 이 부분은 async/await 처리를 안해주었기 때문에 에러가 발생해도 catch문으로 에러가 가지 않는다고 한다.

다행히 해당 호출부는 fire and forget 방식으로 해도 되는, 뷰에 영향을 안 미치는 로깅하는 작업이다.

그래서 아래 것들이 궁금해졌다.

  • 그럼 async/await를 한 것과 안한 것이 어떻게 동작 차이
    • async/await는 프로미스를 기반으로 하지만, 마치 동기 코드처럼 작성할 수 있게 해준다.
    • 스코프 기반
    • 아래 두 코드에서 await test();만 차이가 있는데 이에 따라 콘솔의 순서가 달라진다.
async function test() {
  console.log('1');
  const res = await fetch('/api');
  console.log('2');
}
 
console.log('A');
test();
console.log('B');
async function test() {
  console.log('1');
  const res = await fetch('/api');
  console.log('2');
}
 
console.log('A');
await test();
console.log('B');
function test() {
  console.log('1');
  const res = fetch('/api');
  console.log('2');
}
 
console.log('A');
test();
console.log('B');

→ 비동기 작업을 시작만 하고 바로 Promise를 반환

  • 에러 처리의 범위는 어디까지 해야하며 언제 try/catch문을 써야 하는 것인가
  • 비동기 호출은 async/await을 반드시 붙여야하는건지
    • Fire and Forget 패턴

Fire and Forget 패턴은 Async Programming 에서 사용된다. 어떤 작업을 실행하고 그 결과에 대한 응답을 기다리지 않고 바로 다음 코드를 실행하는 것을 의미한다.
이 패턴은 주로 성능 향상이나 비동기 작업을 수행할 때 사용되며, 작업의 완료나 결과에 대한 처리가 필요하지 않을 때 유용하게 사용된다. 예를 들면 로깅, 이벤트 발행, 통계 데이터 수집과 같이 작업의 성공 또는 실패에 대한 관심이 없는 경우에 활용될 수 있다.
Fire and Forget 은 결과 확인이나 오류 처리를 고려하지 않고 작업을 진행하므로, 신뢰성이 필요한 경우에는 사용하지 않아야 한다. 일반적으로 간단한 알림(notification) 서비스에는 적합한 패턴이다.

  • 로그/분석 이벤트
  • 백그라운드 트래킹
  • 알림 / 통계 전송
try {
  API.POST({
    url: API_STATISTICS_VIEW_LOG,
    data: { productId },
  });
} catch (error) {}

→ 즉시 Promise를 반환하기 때문에 catch문으로 가지 않음

그러나 Uncaught (in promise) TypeError: Failed to fetch 에러가 뜰 수 있어 .catch() 처리는 필요할 수 있다.

내부에서 throw 에러 처리가 되어 있다면 뜸.

근데 저 메서드 내부에서는 throw Error 안하고 있는 것을 확인함

따라서 아예 필요없음

  • fetch fire-and-forget은 페이지 이동하면 요청 날아갈 수도 있지 않나?

브라우저에게 HTTP 요청을 보존시키는 옵션이 여러가지 있음

  • Fetch 에 keepalive 플래그를 사용하면 페이지가 중단되더라도 해당 요청은 유지
  • Navigator.sendBeacon() 같은 더 간단한 함수
  • 가능하면 fetch() + keepalive
    • 80%의 브라우저가 지원
    • 커스텀 헤더 전송 가능
    • GET 요청으로도 가능
    • 예전 브라우저들 지원
  • sendBeacon() 이 좋은 경우는
    • 96%의 브라우저가 지원
    • 많은 커스터마이징이 필요 없을 때
    • 깔끔하고 우아한 API를 선호할 때
    • 브라우저의 다른 우선순위 요청들과 다투고 싶지 않을 때