이 도움말에서는 Fetch API를 사용할 때의 몇 가지 오류 처리 접근 방식을 보여줍니다. Fetch API를 사용하면 원격 네트워크 리소스에 요청할 수 있습니다. 원격 네트워크를 호출하면 웹페이지에 다양한 잠재적 네트워크 오류가 발생할 수 있습니다.
다음 섹션에서는 발생 가능한 오류를 설명하고 오류 및 예기치 않은 네트워크 상태에 회복력이 있는 적절한 수준의 기능을 제공하는 코드를 작성하는 방법을 설명합니다. 탄력적인 코드를 사용하면 사용자를 만족시키고 웹사이트의 표준 서비스 수준을 유지할 수 있습니다.
발생할 수 있는 네트워크 오류 예상
이 섹션에서는 사용자가 "My Travels.mp4"
라는 새 동영상을 만든 후 동영상 공유 웹사이트에 동영상을 업로드하려고 시도하는 시나리오를 설명합니다.
가져오기를 사용할 때는 사용자가 동영상을 성공적으로 업로드하는 해피 패스를 쉽게 고려할 수 있습니다. 하지만 그다지 원활하지는 않지만 웹 개발자가 계획해야 하는 다른 경로가 있습니다. 이러한 (불만족스러운) 경로는 사용자 오류, 예상치 못한 환경 조건 또는 동영상 공유 웹사이트의 버그로 인해 발생할 수 있습니다.
사용자 오류의 예
- 사용자가 동영상 파일 대신 이미지 파일 (예: JPEG)을 업로드합니다.
- 사용자가 잘못된 동영상 파일을 업로드하기 시작합니다. 그런 다음 업로드가 진행되는 중에 사용자가 업로드할 올바른 동영상 파일을 지정합니다.
- 동영상이 업로드되는 동안 사용자가 실수로 '업로드 취소'를 클릭합니다.
환경 변화의 예
- 동영상을 업로드하는 중에 인터넷 연결이 끊깁니다.
- 동영상이 업로드되는 동안 브라우저가 다시 시작됩니다.
- 동영상이 업로드되는 동안 동영상 공유 웹사이트의 서버가 다시 시작됩니다.
동영상 공유 웹사이트의 오류 예시
- 동영상 공유 웹사이트에서 공백이 있는 파일 이름을 처리할 수 없습니다.
"My Travels.mp4"
대신"My_Travels.mp4"
또는"MyTravels.mp4"
와 같은 이름을 예상합니다. - 동영상 공유 웹사이트에서 허용되는 최대 파일 크기를 초과하는 동영상을 업로드할 수 없습니다.
- 동영상 공유 웹사이트에서 업로드된 동영상의 동영상 코덱을 지원하지 않습니다.
이러한 예는 실제로 발생할 수 있으며 실제로 발생합니다. 이전에 이러한 예시를 접했을 수도 있습니다. 이전 카테고리에서 각각 하나씩 예를 들어 다음 사항을 논의해 보겠습니다.
- 동영상 공유 서비스에서 주어진 예시를 처리할 수 없는 경우 기본 동작은 무엇인가요?
- 이 예에서 사용자는 어떻게 될 것으로 예상하나요?
- 이 절차를 개선하려면 어떻게 해야 하나요?
Fetch API로 오류 처리
다음 코드 예에서는 최상위 await
(브라우저 지원)을 사용합니다. 이 기능을 사용하면 코드를 단순화할 수 있기 때문입니다.
Fetch API에서 오류가 발생하는 경우
이 예에서는 try
/catch
블록 문을 사용하여 try
블록 내에서 발생하는 모든 오류를 포착합니다. 예를 들어 Fetch API가 지정된 리소스를 가져올 수 없는 경우 오류가 발생합니다. 이와 같은 catch
블록 내에서 의미 있는 사용자 환경을 제공해야 합니다. 일종의 진행률을 나타내는 일반적인 사용자 인터페이스인 스피너가 사용자에게 표시되면 catch
블록 내에서 다음 작업을 실행할 수 있습니다.
- 페이지에서 스피너를 삭제합니다.
- 문제가 무엇인지, 사용자가 취할 수 있는 옵션을 설명하는 유용한 메시지를 제공합니다.
- 사용 가능한 옵션에 따라 사용자에게 '다시 시도' 버튼을 표시합니다.
- 오류 추적 서비스 또는 백엔드로 오류 세부정보를 비공개로 전송합니다. 이 작업은 나중에 진단할 수 있도록 오류를 로깅합니다.
try {
const response = await fetch('https://website');
} catch (error) {
// TypeError: Failed to fetch
console.log('There was an error', error);
}
나중에 로깅된 오류를 진단하는 동안 테스트 사례를 작성하여 사용자가 문제가 있음을 인식하기 전에 이러한 오류를 포착할 수 있습니다. 오류에 따라 테스트는 단위 테스트, 통합 테스트 또는 승인 테스트일 수 있습니다.
네트워크 상태 코드가 오류를 나타내는 경우
이 코드 예에서는 항상 HTTP 상태 코드 429 Too Many Requests
로 응답하는 HTTP 테스트 서비스에 요청합니다. 흥미롭게도 응답이 catch
블록에 도달하지 않습니다. 다른 특정 상태 코드 중 404 상태는 네트워크 오류를 반환하지 않고 대신 정상적으로 해결됩니다.
HTTP 상태 코드가 성공했는지 확인하려면 다음 옵션 중 하나를 사용하면 됩니다.
Response.ok
속성을 사용하여 상태 코드가200
~299
범위인지 확인합니다.Response.status
속성을 사용하여 응답이 성공했는지 확인합니다.Response.headers
와 같은 다른 메타데이터를 사용하여 응답이 성공했는지 평가합니다.
let response;
try {
response = await fetch('https://httpbin.org/status/429');
} catch (error) {
console.log('There was an error', error);
}
// Uses the 'optional chaining' operator
if (response?.ok) {
console.log('Use the response here!');
} else {
console.log(`HTTP Response Code: ${response?.status}`)
}
조직 및 팀의 담당자와 협력하여 잠재적인 HTTP 응답 상태 코드를 파악하는 것이 좋습니다. 백엔드 개발자, 개발자 운영팀, 서비스 엔지니어는 예상치 못한 특이 사례에 대한 독특한 통계를 제공할 수 있습니다.
네트워크 응답을 파싱하는 중에 오류가 발생한 경우
이 코드 예에서는 응답 본문을 파싱할 때 발생할 수 있는 다른 유형의 오류를 보여줍니다. Response
인터페이스는 텍스트나 JSON과 같은 다양한 유형의 데이터를 파싱하는 편리한 메서드를 제공합니다. 다음 코드에서는 HTML 문자열을 응답 본문으로 반환하는 HTTP 테스트 서비스에 대한 네트워크 요청이 이루어집니다. 하지만 응답 본문을 JSON으로 파싱하려고 시도하여 오류가 발생합니다.
let json;
try {
const response = await fetch('https://httpbin.org/html');
json = await response.json();
} catch (error) {
if (error instanceof SyntaxError) {
// Unexpected token < in JSON
console.log('There was a SyntaxError', error);
} else {
console.log('There was an error', error);
}
}
if (json) {
console.log('Use the JSON here!', json);
}
다양한 응답 형식을 수용할 수 있도록 코드를 준비하고 예상치 못한 응답으로 인해 사용자의 웹페이지가 손상되지 않는지 확인해야 합니다.
다음 시나리오를 생각해 보세요. 유효한 JSON 응답을 반환하는 원격 리소스가 있고 Response.json()
메서드로 성공적으로 파싱됩니다. 서비스가 다운될 수 있습니다. 다운되면 500 Internal Server Error
가 반환됩니다. JSON 파싱 중에 적절한 오류 처리 기법을 사용하지 않으면 처리되지 않은 오류가 발생하여 사용자의 페이지가 손상될 수 있습니다.
네트워크 요청이 완료되기 전에 취소해야 하는 경우
이 코드 예에서는 AbortController
를 사용하여 진행 중인 요청을 취소합니다. 진행 중인 요청은 시작되었지만 완료되지 않은 네트워크 요청입니다.
진행 중인 요청을 취소해야 하는 시나리오는 다양하지만 궁극적으로는 사용 사례와 환경에 따라 다릅니다. 다음 코드는 Fetch API에 AbortSignal
를 전달하는 방법을 보여줍니다. AbortSignal
는 AbortController
에 연결되며 AbortController
에는 브라우저에 네트워크 요청을 취소해야 함을 나타내는 abort()
메서드가 포함됩니다.
const controller = new AbortController();
const signal = controller.signal;
// Cancel the fetch request in 500ms
setTimeout(() => controller.abort(), 500);
try {
const url = 'https://httpbin.org/delay/1';
const response = await fetch(url, { signal });
console.log(response);
} catch (error) {
// DOMException: The user aborted a request.
console.log('Error: ', error)
}
결론
오류 처리의 한 가지 중요한 측면은 오류가 발생할 수 있는 다양한 부분을 정의하는 것입니다. 각 시나리오에 대해 사용자에게 적절한 대체 옵션이 있는지 확인합니다. 가져오기 요청과 관련하여 다음과 같은 질문을 자문해 보세요.
- 대상 서버가 다운되면 어떻게 되나요?
- 가져오기가 예상치 못한 응답을 수신하면 어떻게 되나요?
- 사용자의 인터넷 연결이 끊어지면 어떻게 되나요?
웹페이지의 복잡도에 따라 다양한 시나리오의 기능과 사용자 인터페이스를 설명하는 플로우 차트를 스케치할 수도 있습니다.