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를 사용하여 진행 중인 요청을 취소합니다. 진행 중인 요청은 시작되었지만 완료되지 않은 네트워크 요청입니다.

처리 중인 요청을 취소해야 하는 시나리오는 다양할 수 있지만 최종적으로 사용 사례와 환경에 따라 달라집니다. 다음 코드는 AbortSignal를 Fetch API에 전달하는 방법을 보여줍니다. 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)
}

결론

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

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

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