브라우저 종료 시 안정적으로 API 요청하기: keepalive 옵션 활용기 🚀

sumi-0011·2024년 10월 26일
3
post-thumbnail

목차

  • 문제 상황
  • 해결 과정
  • 최종 해결책
  • 참고 자료

문제 상황 😵

다른 서비스간 로그인 연동 기능에서 특별한 요구사항이 있었습니다. 사용자가 로그인 과정에서 서비스를 이탈하면, 실패 상태를 다른 서비스에 API로 알려줘야 했죠.
(다른 서비스는 polling으로 상태를 체크하고 있었습니다)

단순히 생각했을 때는 unload 이벤트에 API를 호출하면 될 것 같았지만... 실제로는 그렇게 간단하지 않았습니다. 🤔

해결 과정 🔍

1. 첫 시도: unload 이벤트 활용

처음에는 아래와 같이 단순하게 구현했습니다.

const callback = () => {
  // API 호출 -> expired status로 변경
}

useEffect(() => {
  window.addEventListener('unload', callback);
  return () => {
    window.removeEventListener('unload', callback);
  };
}, [callback]);

하지만 이 방식에는 문제가 있었습니다. 브라우저가 종료되면서 API 요청이 간헐적으로 취소되는 현상이 발생했거든요. 🤯

2. 문제 분석

API 요청이 실패하는 이유를 파악해보니, 아래와 같이 확인할 수 있었습니다.
1. 브라우저는 열린 HTTP 요청의 완료를 보장하지 않습니다.
2. XHR 요청(fetch 또는 XMLHttpRequest)은 비동기적이고 non-blocking입니다.
3. 브라우저는 페이지가 종료될 때 진행 중인 백그라운드 프로세스를 계속 유지할 필요가 없다고 판단합니다.

3. 대안 탐색

하지만 어떻게든 API 요청이 끊기지 않게 해야했죠 😭 대안을 찾아 보았을 때,
브라우저 종료 시에도 HTTP 요청을 안정적으로 보내기 위한 두 가지 방법을 발견했습니다

  1. Navigator.sendBeacon() 사용
  2. fetchkeepalive 플래그 사용

sendBeacon()은 분석 정보 전송을 위해 설계된 좋은 방법이지만, 커스텀 헤더를 지원하지 않는다는 치명적인 단점이 있었습니다.

axios keepAlive 옵션 검토 ❌

axios에서도 keepAlive 옵션을 제공하지만, Node.js 환경에서만 사용 가능했습니다.

참고 링크 : https://gist.github.com/ccnokes/94576dc38225936a3ca892b989c9d0c6

// Node.js 환경에서만 가능한 코드
const axios = require('axios');
const http = require('http');
const https = require('https');

module.exports = axios.create({
  httpAgent: new http.Agent({ keepAlive: true }),
  httpsAgent: new https.Agent({ keepAlive: true }),
  // ...
});

최종 해결책 ✨

결국 fetchkeepalive 옵션을 조합한 방식을 채택했습니다.

const updateExpired = (uuid: string) => {
  const data = {
    status: 'expired',
  };

  const fetchConfig = {
    method: 'POST',
    body: JSON.stringify(data),
    headers: customHeader,  // 커스텀 헤더 설정
    keepalive: true, // 핵심! keepalive 옵션 추가
  };

  return fetch('API URL', fetchConfig);
};

이 방식의 장점:

  • 브라우저 종료 시에도 API 요청이 안정적으로 전송됨
  • 커스텀 헤더 사용 가능
  • 구현이 간단함

실제 다른 서비스에서 응답을 잘 받아오는지 반복적인 테스트를 통해, 정상적으로 받아오는 것을 확인하였습니다 🎉

마무리 🎯

브라우저 종료 시의 API 호출은 생각보다 까다로운 문제였지만, keepalive 옵션을 활용하여 깔끔하게 해결할 수 있었습니다.
특히 페이지 생명주기와 브라우저의 동작 방식을 공부할 수 있는 계기가 되었던것 같아요.

참고 자료 📚

profile
안녕하세요 😚

0개의 댓글