원문
https://dev.to/dionarodrigues/fetch-api-do-you-really-know-how-to-handle-errors-2gj0?ref=dailydev
밑에 코드는 콘솔에 어떤 메세지가 찍힐까? 성공? 실패?
try {
// this endpoint will return 404
const response = await fetch('https://restcountries.com/v4.1/all')
console.log('Success')
} catch {
console.error('Failed')
}
만약 실패 메세지라고 답했다면 이 글은 당신을 위한 글입니다. 왜냐하면 정답은 성공이거든요.
Fetch API 란?
간단하게 말하자면, Fetch API는 비동기 HTTP GET, POST 요청을 쉽게 만드는 인터페이스입니다.
이전에 작성한 "Fetch API is new old version of AJAX"란 글을 읽는 걸 추천드립니다.
이 글이 Fetch API에 대해 자세히 설명되어 있고, 그와 더불어 aysnc/await 문법과 어떻게 사용하는지에 대해서도 다뤘기 때문입니다.
어떻게 에러를 핸들링할까?
Fetch API를 사용할 때, 다양한 에러들이 발생합니다: 서버 에러(500), 낫파운드 에러(404), 네트워크 에러, CORS 에러, 등.
그리고 이 에러들을 핸들링하는 다양한 방법들이 있습니다.
1. try/catch 사용하기
promises는 익숙할거라고 생각합니다.(Fetch API가 유명한 하나의 이유가 promise를 반환한다는 점 때문입니다.)
우리는 fetch가 resolved, rejected, finished 됐을 때 then
, catch
, finally
를 사용할 수 있습니다.
fetch 요청을 try/catch로 감싸는 것은 에러를 핸들링하는 흔한 방법이지만(밑에 코드와 같이), 모든 에러를 잡을 수 있는 건 아닙니다.
try{
//this endpoint will return CORS error
const response = await fetch('https://google.com/api');
} catch {
console.error('Failed');
}
해당 코드는 프로미스가 rejected 됐을 때만 에러를 감지할 수 있습니다.
그리고 rejected는 두 가지 상황에서 일어날 수 있습니다 :
- 네트워크 에러: 서버 연결에 실패했을 경우
- CORS 에러:도메인이 다른 도메인에서 리소스를 얻을 수 있는 권한이 없는 경우
그리고 서버 상태 에러(404,500 등)에서는 resolved를 반환할 것입니다.
그렇기 때문에 처음 시작할 때 보여준 코드에서 catch가 에러를 잡을 수 없는 것 입니다.
2. 응답 상태 response state 확인하기
또 다른 흔한 방법은 프로미스가 resolve 됐을 때, 응답의 상태를 확인하는 것입니다.
그리고 이 방법이 바로 우리가 글의 첫 코드에서 404에러를 감지하는 방법입니다.
// this endpoint will return 404
const response = await fetch('https://restcoutries.com/v4.1/all');
if(response.ok){
// do sth with the response if response.ok is true
} else {
console.error('Failed')
}
여기서 우리는 response.ok
를 사용해서 해당 응답이 성공했는지 아닌지(true & false)를 확인합니다.
- 상태 코드는 200 과 299 사이일 때 response.ok는 true
입니다. (성공)
- 위의 상태 코드와 다른 상태라면 false
입니다. (예시는 404,500 입니다)
Fetch API를 사용할 때 에러 핸들링을 위한 좋은 방법
: try/catch 와 response.ok
를 혼합해서 사용하기
예시 1.
위에서 보았듯이, try/catch 와 response.ok
는 다른 타입의 에러를 잡을 때 사용됩니다.
그러므로, 우리는 이 두 방법을 합쳐서 더 좋은 방식으로 에러를 핸들링할 수 있습니다.
- try/catch 는 프로미스가 rejected 됐을 때(네트워크, CORS 문제 등)의 에러를 핸들링하기 위해 사용됩니다.
response.ok
는 서버 에러(404, 500 등)를 핸들링할 때 쓰이는데, 이때 프로미스는 resolved 됩니다.
try {
const response = await fetch('https://restcountries.com/v4.1/all');
if(response.ok){
console.log('Promise resolved & HTTP status is successful')
} else {
console.error('Promise resolved but HTTP status failed')
}
} catch {
console.error('Promise rejected')
}
예시 2.
try
블럭 안에서 에러를 핸들링하는 다른 흔한 방법은, response.ok
가 true
가 아닐 때 에러를 throw 하는 것 입니다.
에러를 throw하면, response.ok
가 true
가 아닐 때 catch
블럭이 실행되고, 우리는 모든 에러를 한 곳에서 관리할 수 있습니다.
그리고 에러의 타입에 따라 콘솔에 다른 메세지를 보여줄 수 있습니다.
response.ok
catch
블럭이 모든 타입의 에러들을 잡는다.catch
는 인수를 받는데, 이 인수는try
블럭에서 에러를 throw할 때 커스터마이징할 수 있다.response.status
는 에러 메세지를 커스텀할 때 HTTP status를 확인하는 용도로 사용될 수 있다. (400, 404, 500 등)
try {
const response = await fetch();
if(response.ok){
console.log('Promise resolved and HTTP request status is successful');
} else {
if(response.status === 404) throw new Error('404, Not Found');
if(response.status === 500) throw new Error('500, internal server error');
// for any other server error
throw new Error(response.status)
}
} catch(error) {
console.error('Fetch', error)
// output e.g.: "Fetch Error: 404, Not found"
}
끗!