Node.js 16의 AbortController로 HTTP 요청 타임아웃 처리하기
문제 상황
외부 API 호출 시 응답이 지연되면서 서버 전체가 hanging 되는 이슈가 발생했다. 기존에는 axios의 timeout 옵션을 사용했지만, 일부 레거시 코드에서는 native http 모듈을 직접 사용하고 있어서 타임아웃 처리가 누락된 부분이 있었다.
AbortController 도입
Node.js 15부터 브라우저와 동일한 AbortController API가 전역으로 추가되었다. 이를 활용하면 요청 취소 로직을 표준화할 수 있다.
const https = require('https');
function fetchWithTimeout(url, timeout = 5000) {
return new Promise((resolve, reject) => {
const controller = new AbortController();
const timer = setTimeout(() => {
controller.abort();
reject(new Error('Request timeout'));
}, timeout);
https.get(url, { signal: controller.signal }, (res) => {
let data = '';
res.on('data', chunk => data += chunk);
res.on('end', () => {
clearTimeout(timer);
resolve(data);
});
}).on('error', (err) => {
clearTimeout(timer);
reject(err);
});
});
}
실제 적용
마이크로서비스 간 통신 레이어에 일괄 적용했다. signal 옵션만 추가하면 되어서 기존 코드 수정이 최소화되었다.
const request = https.request(options, callback);
request.on('error', (err) => {
if (err.name === 'AbortError') {
logger.warn('Request aborted due to timeout');
}
});
결과
- 타임아웃 처리가 누락된 구간 제거
- 브라우저와 동일한 패턴으로 코드 통일
- 향후 fetch API 전환 시에도 동일한 방식 사용 가능
Node.js 17에서는 fetch API도 실험적으로 추가될 예정이라고 하니, AbortController 기반 패턴이 더욱 중요해질 것 같다.