Fetch API 사용 시 오류 처리 구현

이 도움말에서는 Fetch API를 사용할 때의 몇 가지 오류 처리 접근 방식을 보여줍니다. Fetch API를 사용하면 원격 네트워크 리소스에 요청할 수 있습니다. 원격 네트워크를 호출하면 웹페이지에 다양한 잠재적 네트워크 오류가 발생할 수 있습니다.

다음 섹션에서는 발생 가능한 오류를 설명하고 오류 및 예기치 않은 네트워크 상태에 회복력이 있는 적절한 수준의 기능을 제공하는 코드를 작성하는 방법을 설명합니다. 탄력적인 코드를 사용하면 사용자를 만족시키고 웹사이트의 표준 서비스 수준을 유지할 수 있습니다.

이 섹션에서는 사용자가 "My Travels.mp4"라는 새 동영상을 만든 후 동영상 공유 웹사이트에 동영상을 업로드하려고 시도하는 시나리오를 설명합니다.

가져오기를 사용할 때는 사용자가 동영상을 성공적으로 업로드하는 해피 패스를 쉽게 고려할 수 있습니다. 하지만 그다지 원활하지는 않지만 웹 개발자가 계획해야 하는 다른 경로가 있습니다. 이러한 (불만족스러운) 경로는 사용자 오류, 예상치 못한 환경 조건 또는 동영상 공유 웹사이트의 버그로 인해 발생할 수 있습니다.

사용자 오류의 예

  • 사용자가 동영상 파일 대신 이미지 파일 (예: JPEG)을 업로드합니다.
  • 사용자가 잘못된 동영상 파일을 업로드하기 시작합니다. 그런 다음 업로드가 진행되는 중에 사용자가 업로드할 올바른 동영상 파일을 지정합니다.
  • 동영상이 업로드되는 동안 사용자가 실수로 '업로드 취소'를 클릭합니다.

환경 변화의 예

  • 동영상을 업로드하는 중에 인터넷 연결이 끊깁니다.
  • 동영상이 업로드되는 동안 브라우저가 다시 시작됩니다.
  • 동영상이 업로드되는 동안 동영상 공유 웹사이트의 서버가 다시 시작됩니다.

동영상 공유 웹사이트의 오류 예시

  • 동영상 공유 웹사이트에서 공백이 있는 파일 이름을 처리할 수 없습니다. "My Travels.mp4" 대신 "My_Travels.mp4" 또는 "MyTravels.mp4"와 같은 이름을 예상합니다.
  • 동영상 공유 웹사이트에서 허용되는 최대 파일 크기를 초과하는 동영상을 업로드할 수 없습니다.
  • 동영상 공유 웹사이트에서 업로드된 동영상의 동영상 코덱을 지원하지 않습니다.

이러한 예는 실제로 발생할 수 있으며 실제로 발생합니다. 이전에 이러한 예시를 접했을 수도 있습니다. 이전 카테고리에서 각각 하나씩 예를 들어 다음 사항을 논의해 보겠습니다.

  • 동영상 공유 서비스에서 주어진 예시를 처리할 수 없는 경우 기본 동작은 무엇인가요?
  • 이 예에서 사용자는 어떻게 될 것으로 예상하나요?
  • 이 절차를 개선하려면 어떻게 해야 하나요?
작업 사용자가 잘못된 동영상 파일을 업로드하기 시작합니다. 그런 다음 업로드가 진행되는 중에 사용자가 업로드할 올바른 동영상 파일을 지정합니다.
기본적으로 발생하는 상황 새 파일이 업로드되는 동안 원본 파일은 백그라운드에서 계속 업로드됩니다.
사용자가 기대하는 사항 사용자는 추가 인터넷 대역폭이 낭비되지 않도록 원래 업로드가 중지되기를 기대합니다.
개선할 수 있는 점 JavaScript는 새 파일 업로드가 시작되기 전에 원본 파일의 가져오기 요청을 취소합니다.
작업 사용자가 동영상 업로드 중간에 인터넷 연결이 끊깁니다.
기본적으로 발생하는 상황 업로드 진행률 표시줄이 50%에서 멈춘 것처럼 보입니다. 결국 Fetch API에 시간 초과가 발생하고 업로드된 데이터가 삭제됩니다. 인터넷 연결이 복원되면 사용자가 파일을 다시 업로드해야 합니다.
사용자가 기대하는 사항 사용자는 파일을 업로드할 수 없을 때 알림을 받기를 기대하며, 다시 온라인 상태가 되면 업로드가 50% 에서 자동으로 재개되기를 기대합니다.
개선할 수 있는 점 업로드 페이지는 사용자에게 인터넷 연결 문제를 알리고 인터넷 연결이 재개되면 업로드가 재개된다고 안내합니다.
작업 동영상 공유 웹사이트에서 공백이 있는 파일 이름을 처리할 수 없습니다. 'My Travels.mp4' 대신 'My_Travels.mp4' 또는 'MyTravels.mp4'와 같은 이름이 필요합니다.
기본적으로 발생하는 상황 업로드가 완전히 완료될 때까지 사용자는 기다려야 합니다. 파일이 업로드되고 진행률 표시줄에 '100%'가 표시되면 진행률 표시줄에 '다시 시도해 주세요'라는 메시지가 표시됩니다.
사용자가 기대하는 사항 사용자는 업로드가 시작되기 전에 또는 적어도 업로드 후 1초 이내에 파일 이름 제한에 대한 메시지를 받기를 기대합니다.
개선할 수 있는 점 동영상 공유 서비스에서 공백이 포함된 파일 이름을 지원하는 것이 좋습니다. 업로드가 시작되기 전에 사용자에게 파일 이름 제한사항을 알리는 것도 방법입니다. 또는 동영상 공유 서비스에서 자세한 오류 메시지와 함께 업로드를 거부해야 합니다.

Fetch API로 오류 처리

다음 코드 예에서는 최상위 await (브라우저 지원)을 사용합니다. 이 기능을 사용하면 코드를 단순화할 수 있기 때문입니다.

Fetch API에서 오류가 발생하는 경우

이 예에서는 try/catch 블록 문을 사용하여 try 블록 내에서 발생하는 모든 오류를 포착합니다. 예를 들어 Fetch API가 지정된 리소스를 가져올 수 없는 경우 오류가 발생합니다. 이와 같은 catch 블록 내에서 의미 있는 사용자 환경을 제공해야 합니다. 일종의 진행률을 나타내는 일반적인 사용자 인터페이스인 스피너가 사용자에게 표시되면 catch 블록 내에서 다음 작업을 실행할 수 있습니다.

  1. 페이지에서 스피너를 삭제합니다.
  2. 문제가 무엇인지, 사용자가 취할 수 있는 옵션을 설명하는 유용한 메시지를 제공합니다.
  3. 사용 가능한 옵션에 따라 사용자에게 '다시 시도' 버튼을 표시합니다.
  4. 오류 추적 서비스 또는 백엔드로 오류 세부정보를 비공개로 전송합니다. 이 작업은 나중에 진단할 수 있도록 오류를 로깅합니다.
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를 전달하는 방법을 보여줍니다. AbortSignalAbortController에 연결되며 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)
}

결론

오류 처리의 한 가지 중요한 측면은 오류가 발생할 수 있는 다양한 부분을 정의하는 것입니다. 각 시나리오에 대해 사용자에게 적절한 대체 옵션이 있는지 확인합니다. 가져오기 요청과 관련하여 다음과 같은 질문을 자문해 보세요.

  • 대상 서버가 다운되면 어떻게 되나요?
  • 가져오기가 예상치 못한 응답을 수신하면 어떻게 되나요?
  • 사용자의 인터넷 연결이 끊어지면 어떻게 되나요?

웹페이지의 복잡도에 따라 다양한 시나리오의 기능과 사용자 인터페이스를 설명하는 플로우 차트를 스케치할 수도 있습니다.