본문 바로가기

JavaScript

HTTP

클라이언트와 서버 간의 통신은 HTTP 요청과 응답을 통해서 발생하는데 클라이언트에서 서버로 요청을 보내기 위해서는 도메인과 경로로 구성된 URL이 필요합니다.

 

각 HTTP 요청에는 HTTP 메서드(GET, POST, PATCH, PUT, DELETE)가 할당되어 있습니다. 서버가 특정 작업을 수행하기 위해 어떤 메서드와 URL 조합을 사용할지는 전적으로 서버에 달려있습니다. 따라서 서버에 필요한 작업을 지시하지 않는 메서드를 사용하면 서버는 서로 다른 엔드 포인트를 노출하게 됩니다.

 

예를 들어 /post에 대한 POST 요청은 지원하지만 /posts에 PATCH 요청은 지원하지 않는 것입니다. 즉 서버 측이 지원하지 않는 조합을 사용할 경우 응답으로 HTTP 오류가 발생할 것입니다.

 

HTTP 요청의 또 다른 부분으로는 잠재적 헤더가 있습니다. HTTP 요청에 연결할 수 있는 추가 메타데이터인데, 일부 요청 중에서 예를 들면 POST 요청은 요청 본문을 포함하거나 요청에 첨부된 추가 데이터등을 포함하고 있습니다. 예를 들어 게시물을 생성할 경우 게시물 생성에 필요한 데이터를 요청에 연결해서 전송할 것입니다.

 

이때 메타데이터는 다른 형식으로 전송이 될 수 있는데 어떤 형식을 기대하고 전송해야 할지는 서버가 결정하게 됩니다. 가장 일반적인 형식은 JSON 데이터가 있으며 JavaScript에서 지원하는 Form 데이터 등이 있습니다.

 

 

 

 

 


[ XMLHttpRequset를 사용한 HTTP 요청 ]

 

요청 보내기

 

 

JSONPlaceholder - Free Fake REST API

{JSON} Placeholder Free fake API for testing and prototyping. Powered by JSON Server + LowDB. Tested with XV. As of Oct 2022, serving ~1.7 billion requests each month.

jsonplaceholder.typicode.com

*본 게시글은 JSONPlaceholder의 더미 데이터를 사용한 게시글입니다.

 

 

앞서 언급한 대로 서버에서 지원하지 않는 path와 HTTP 메서드 조합으로 요청을 보낼 경우 응답으로 HTTP 오류가 발생할 것입니다.

각 path 별 지원하는 HTTP 메서드

저의 경우 GET HTTP 메서드와 /posts path 조합으로 서버에 요청을 하도록 하겠습니다.

 

// HTTP 요청
const xhr = new XMLHttpRequest(); // 해당 객체를 통해 HTTP 요청을 보낼 수 있게됨

우선 XMLHttpRequest 객체를 생성해 줍니다.

 

xhr.open("GET", "https://jsonplaceholder.typicode.com/posts");

open 함수를 통해 생성한 XMLHttpRequest를 초기화해 줍니다. 

 

 

*open 함수 설정 옵션

XMLHttpRequest.open('HTTP 메서드', "요청을 보낼 URL", 비동기 여부, user, password)
  • 비동기 여부 : 기본값은 true입니다.
  • user : 인증이 필요한 경우 설정하는 username으로 기본값은 null입니다.
  • password : 인증이 필요한 경우 설정하는 password로 기본값은 null입니다.

 

xhr.send();

send 함수를 사용해 요청을 서버로 전송합니다.

 

 

요청의 결과로 개발자 도구 -> 네트워크 -> posts를 확인하면 응답으로 데이터가 들어온 것을 확인할 수 있습니다.

 

이때 응답으로 들어온 데이터의 형식을 파악하는 것이 중요합니다. 클라이언트와 서버는 특정한 형식으로 데이터를 교환하는데 일반적인 텍스 HTML 마크업을 보낼 수도 있고, XML 마크업을 보낼 수도 있고 CSV 파일을 보낼 수도 있지만 일반적으로는 JSON 형식을 많이 사용합니다. 위의 경우도 JSON 형식의 데이터가 응답으로 들어온 것입니다.

 

여기서 JSON이란 JavaScript Object Notation(자바스크립트 객체 표시법)을 의미합니다. JavaScript에서 사용하는 배열과 객체와 유사한 형태를 확인할 수 있습니다. 이는 JSON은 JavaScript 배열과 객체에서 유래했기 때문입니다. 

 

JSON 형식과 JavaScript의 객체 데이터는 거의 유사하지만 아래와 같은 차이점이 있습니다.

  • JSON 형식은 데이터의 저장만 가능하며, 메서드는 없습니다.
  • 속성의 이름은 큰 따옴표 내에 들어가야 합니다.(속성을 문자로 해야 하며 반드시 큰 따옴표 사용을 해야 합니다.)

 

 

요청을 보냈을 때 응답을 받을 수 있는 방법은 아래와 같습니다.

 

load event를 기다려야 합니다. 데이터가 로딩되면, 즉 요청이 완료되면 자동으로 발생하는 이벤트로 이벤트 리스너를 설정하면 가능한 작업입니다.

 

const xhr = new XMLHttpRequest();

xhr.open("GET", "https://jsonplaceholder.typicode.com/posts");

xhr.onload = function () {
  console.log(xhr.response);
};

xhr.send();

addEventListener의 경우 IE에서 지원하지 않기 때문에 onload 속성에 함수를 할당하는 방법을 사용해 주었습니다. 연결한 함수는 응답을 처리하며 응답을 인자로 받는 것이 아니라 XMLHttpRequest 객체에서 response를 추출합니다.

 

 

코드를 실행하면 위의 콘솔을 확인할 수 있으며, 이것이 서버에서 페칭 된 JSON 데이터입니다. 

 

 

*페칭 된 JSON 데이터는 앞서 언급한 대로 데이터 저장을 위한 것이기 때문에 JavaScript에서 사용할 경우 별도의 변환과정을 거친 후 메서드 사용이 가능합니다.

xhr.onload = function () {

// JSON => js 
  const listOfPosts = JSON.parse(xhr.response);
};

JavaScript에서 사용 가능한 배열과 객체로 변환하기 위해서는 parse 메서드가 있으며, 반대로 JavaScript 데이터를 JSON 데이터로 변환할 경우 stringify 메서드를 사용합니다.

 

위의 방법 외에도 XMLHttpRequest 객체에 내장된 편리한 기능을 사용할 수도 있습니다.

xhr.responseType = "json"; //응답유형설정

xhr.onload = function () {
  //   const listOfPosts = JSON.parse(xhr.response);
  const listOfPosts = xhr.response;
  console.log(listOfPosts);
};

XMLHttpRequest 객체의 responseType으로 응답 유형을 설정해주게 되면 별도의 변환 없이 JavaScript에서 사용 가능한 배열과 객체 데이터로 자동 변환이 됩니다.

 

 

이제 응답으로 받은 데이터를 화면에 렌더링해주록 하겠습니다.

const listEl = document.querySelector("ul.posts");
const postTemplate = document.getElementById("single-post");

const xhr = new XMLHttpRequest();

xhr.open("GET", "https://jsonplaceholder.typicode.com/posts");

xhr.responseType = "json"; //응답유형설정

xhr.onload = function () {
  const listOfPosts = xhr.response;
  console.log(listOfPosts);

  for (const post of listOfPosts) {
  	// postTemplate의 내용을 자식까지 포함하여 복사
    const postEl = document.importNode(postTemplate.content, true);
    // 복제한 postTemplate의 h2 요소에 응답으로 받은 데이터의 title 렌더링
    postEl.querySelector("h2").textContent = post.title.toUpperCase();
    // 복제한 postTemplate의 h2 요소에 응답으로 받은 데이터의 body 렌더링
    postEl.querySelector("p").textContent = post.body;
    // 복제한 postTemplate append
    listEl.append(postEl);
  }
};

xhr.send();

이때 응답은 비동기이기 때문에 onload 메서드의 함수 내부에 렌더링 코드를 작성해주어야 합니다. 

 

 

 

 

HTTP POST 요청

데이터를 응답으로 받을 수도 있지만 데이터를 서버로 보내야 할 경우도 있습니다.

예를 들어 해당 양식을 작성하고 ADD 버튼을 클릭하면 서버로 해당 데이터가 전송되어 저장되는 것입니다. 때문에 JSONPlaceholder에 요청을 보내 해당 데이터가 저장되도록 하겠습니다.

 

function sendHttpRequest(method, url) {
  const promise = new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();

    xhr.open(method, url);

    xhr.responseType = "json"; //응답유형설정

    xhr.onload = function () {
      resolve(xhr.response);
      const listOfPosts = xhr.response;
      console.log(listOfPosts);

      for (const post of listOfPosts) {
        const postEl = document.importNode(postTemplate.content, true);
        postEl.querySelector("h2").textContent = post.title.toUpperCase();
        postEl.querySelector("p").textContent = post.body;
        listEl.append(postEl);
      }
    };
    xhr.send();
  });

  return promise;
}

우선 기존의 HTTP 요청을 함수화 하여 재사용이 가능하도록 해주었고, 내부에서 Promise화를 해주었습니다. 요청이 resolve일 경우 응답으로 들어온 데이터 사용이 가능하도록 해주었습니다. onload의 하드코딩된 렌더링 로직은 재사용 가능하도록 아래에서 추가적으로 수정을 진행하도록 하겠습니다. 

 

async function fetchPosts() { // asysn / await 사용
  const responseData = await sendHttpRequest(
    "GET",
    "https://jsonplaceholder.typicode.com/posts"
  ); 

// 위의 비동기 코드 실행이 완료되면 아래 코드 실행
  const listOfPosts = responseData; // 응답으로 들어온 데이터

// 데이터 렌더링 로직
  for (const post of listOfPosts) {
    const postEl = document.importNode(postTemplate.content, true);
    postEl.querySelector("h2").textContent = post.title.toUpperCase();
    postEl.querySelector("p").textContent = post.body;
    listEl.append(postEl);
  }
}

앞서 HTTP 요청이 resolve일 경우 응답으로 들어온 데이터 사용이 가능하도록 해주었기 때문에 해당 데이터를 렌더링 하는 로직을 분리하여 함수 fetchPosts 내부로 옮겨주었습니다. 

 

 

현재까지 코드
const listEl = document.querySelector("ul.posts");
const postTemplate = document.getElementById("single-post");

function sendHttpRequest(method, url) {
  const promise = new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();

    xhr.open(method, url);

    xhr.responseType = "json"; //응답유형설정

    xhr.onload = function () {
      resolve(xhr.response);
    };
    xhr.send();
  });

  return promise;
}

async function fetchPosts() {
  const responseData = await sendHttpRequest(
    "GET",
    "https://jsonplaceholder.typicode.com/posts"
  );

  console.log(responseData);

  const listOfPosts = responseData;

  for (const post of listOfPosts) {
    const postEl = document.importNode(postTemplate.content, true);
    postEl.querySelector("h2").textContent = post.title.toUpperCase();
    postEl.querySelector("p").textContent = post.body;
    listEl.append(postEl);
  }
}

fetchPosts();

여기까지 진행하면 함수 sendHTTPRequest는 재사용이 가능한 HTTP 요청 함수가 되었습니다.

 

 

이제 앞서 언급한 ADD버튼 클릭 시 데이터를 전송하기 함수를 생성해주도록 하겠습니다.

async function createPost(title, content) {
  const userId = Math.random();
  const post = {
    title,
    body: content,
    userId,
  };
}

함수 createPost는 인수로 전달받은 title과 content, 랜덤 한 userId를 서버로 전송하는 기능을 하는 함수입니다. 때문에 객체 post를 서버에 전송하여 저장되도록 해주어야 합니다.

 

async function createPost(title, content) {
  const userId = Math.random();
  const post = {
    title,
    body: content,
    userId,
  };

  sendHttpRequest("POST", "https://jsonplaceholder.typicode.com/posts");
}

fetchPosts();

함수 sendHTTPRequest를 재사용하여 POST 메서드와 URL을 전달합니다. 여전히 객체 post를 서버에 전송할 수 없기 때문에 함수 sendHTTPRequest에 약간의 수정이 필요합니다.

 

함수 sendHTTPRequest에 매개변수 data를 추가해 줍니다. 매개변수 data의 경우 인수를 전달받지 않으면 undefined이기 때문에 별도의 기본값 설정은 해주지 않았으며, 매개변수 data는 send 메서드의 인수로 전달하되 JSON 데이터로 변환 후 전달하도록 합니다.

 

함수 sendHTTPRequest에 매개변수 data에 인수로 객체 post를 전달해 주고, 함수 createPost를 호출하여 인수를 전달합니다.

 

요청을 보내고 다시 개발자 도구 => 네트워크를 확인하면 추가적인 HTTP 요청을 확인할 수 있습니다.

 

페이로드를 확인하게 되면 요청으로 보낸 데이터가 정상적으로 전송된 것을 확인할 수 있습니다.

 

 

 

HTTP DELETE 요청

페칭 된 데이터 목록에서 DELETE 버튼을 클릭했을 때 서버로 DELETE 메서드를 전송하고 데이터를 삭제하는 함수를 만들어보도록 하겠습니다.

 

JSONPlaceholder의 경우 DELETE 메서드와 path에 삭제할 데이터의 ID를 조합하여 전송해주어야 합니다.

 

예시코드의 HTML 마크업은 페칭데이터를 ul 요소 안에서 li 요소에 매핑시켜 렌더링 하고 있습니다.

DELETE 버튼을 눌렀을 서버에서 해당 데이터가 제거돼야 하고, 클라이언트 또한 해당 데이터를 렌더링 하는 li 요소를 제거해주어야 하기 때문에 li 요소의 id 속성의 값을 데이터의 id 속성의 값을 할당합니다.

 

// listEl은 ul 요소입니다.
listEl.addEventListener("click", (event) => {
	// 클릭 이벤트 발생시 이벤트의 타켓 태그가 "BUTTON"일 경우
  if (event.target.tagName === "BUTTON") { 
  	// 이벤트가 발생한 요소의 조상요소 중 li 요소를 찾아 id속성의 값을 가져옵니다. 
    const postId = event.target.closest("li").id; 
    sendHttpRequest(
      "DELETE",
      `https://jsonplaceholder.typicode.com/posts/${postId}`
    );
  }
});

페칭 된 데이터의 리스트인 ul 요소에서 버튼을 클릭할 경우 해당 버튼의 가장 가까운 조상 li 요소, 즉 해당 버튼이 있는 li 요소의 id 값을 전달받은 후 URL뒤에 id값을 붙여 함수 sendHTTPRequest에 HTTP 메서드와 함께 전달해 줍니다.

 

* HTTP 관련 게시글이기 때문에 li 요소의 삭제 코드는 넣지 않았습니다.

 

DELETE 요청 또한 정상적으로 작동하는 것을 확인할 수 있습니다.

 

 

코드
const listEl = document.querySelector("ul.posts");
const postTemplate = document.getElementById("single-post");
const form = document.querySelector("#new-post form");
const fetchButton = document.querySelector("#available-posts button");

// HTTP 요청 함수
function sendHttpRequest(method, url, data) {
  const promise = new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();

    xhr.open(method, url);

    xhr.responseType = "json"; //응답유형설정

    xhr.onload = function () {
      resolve(xhr.response);
    };
    xhr.send(JSON.stringify(data));
  });

  return promise;
}

// 데이터 페칭 함수
async function fetchPosts() {
  const responseData = await sendHttpRequest(
    "GET",
    "https://jsonplaceholder.typicode.com/posts"
  );

  console.log(responseData);

  const listOfPosts = responseData;

  for (const post of listOfPosts) {
    const postEl = document.importNode(postTemplate.content, true);
    postEl.querySelector("h2").textContent = post.title.toUpperCase();
    postEl.querySelector("p").textContent = post.body;
    postEl.querySelector("li").id = post.id;
    listEl.append(postEl);
  }
}

// HTTP POST 함수
async function createPost(title, content) {
  const userId = Math.random();
  const post = {
    title,
    body: content,
    userId,
  };

  sendHttpRequest("POST", "https://jsonplaceholder.typicode.com/posts", post);
}

fetchButton.addEventListener("click", fetchPosts);

form.addEventListener("submit", (event) => {
  event.preventDefault();
  // 이벤트가 발생한 현재 타겟
  const enteredTitle = event.currentTarget.querySelector("#title").value;
  const enteredContent = event.currentTarget.querySelector("#content").value;

  createPost(enteredTitle, enteredContent);
});

// HTTP DELETE 함수
listEl.addEventListener("click", (event) => {
  if (event.target.tagName === "BUTTON") {
    const postId = event.target.closest("li").id;
    sendHttpRequest(
      "DELETE",
      `https://jsonplaceholder.typicode.com/posts/${postId}`
    );
  }
});

 

 

 

 

현재까지는 HTTP 요청이 정상적으로 작동하는 경우의 코드만 작성하였지만 실제로 HTTP 요청이 실패하는 경우가 많이 발생합니다. HTTP 요청의 실패는 다양합니다. 인터넷 연결이 나쁘거나 서버가 다운되거나 데이터가 유효하지 않거나 등등의 많인 이유가 있습니다.

 

onerror 메서드를 통해 HTTP 요청 실패를 핸들링할 수 있습니다. 

 

데이터 페칭 함수의 path를 오류가 나게 수정을 해줄 경우 위와 같은 에러를 확인할 수 있지만 onerror 메서드를 통해 HTTP 요청 실패를 핸들링한 것은 확인할 수가 없습니다. 이는 error 핸들러는 실질적으로 제대로 작동한 HTTP 요청을 제외하고 서버 쪽 오류만 있기 때문에 트리거 되지 않고 200이 아닌 코드만 표시되었기 때문입니다.

 

즉, onerror 메서드는 요청을 전송하지 못했거나 요청 시간을 초과했을 경우에만 제대로 작동하게 됩니다. 따라서 요청은 정상적으로 전송됐고 해당 요청에 대한 응답이 넘어왔기 때문에 onerror 메서드 작동하지 않고 onload 메서드만 작동하게 됩니다.

// HTTP 요청 함수
function sendHttpRequest(method, url, data) {
  const promise = new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();

    xhr.open(method, url);

    xhr.responseType = "json"; //응답유형설정

    xhr.onload = function () {
      xhr.status >= 200 && xhr.status < 300
        ? resolve(xhr.response) // HTTP 요청이 200 ~ 300 즉, 정상적으로 이루어졌을 경우 resolve
        : reject(new Error("무언가 잘못되었습니다.")); //요청은 정상적으로 이루어졌지만 status의 범위안에 없을 경우 reject
    };

    xhr.onerror = function () {
      reject(new Error("HTTP 요청 실패")); // HTTP 요청을 실패한 경우 reject
    };

    xhr.send(JSON.stringify(data));
  });

  return promise;
}

때문에 HTTP 요청 관련 에러 핸들링을 위해 함수 sendHTTPRequest를 수정해 줍니다. 요청과 응답이 정상적으로 됐지만 status 404 등의 에러를 핸들링하기 위해 onload 메서드에  status가 200 ~ 300인 경우 resolve를, 아닌 경우 reject를 추가했으며, 요청이 정상적으로 이루어지지 않았을 때 에러 핸들링을 위해 onerror 메서드에 reject를 추가해 주었습니다.

 

페칭 함수의 경우도 try catch 구문으로 수정하여 문제가 발생한 프로미스에 대해서 작업이 중단되도록 해주었습니다.

 

 

 

 


[ fetch API를 사용한 HTTP 통신 ]

fetch('url') // 인수로 URL 전달

fetch 함수는 기본적으로 프로미스 기반으로 작동하는 함수입니다. 따라서 fetch 함수를 사용하여 HTTP 통신을 할 경우 따로 프로미스를 지정할 필요 없습니다. fetch 함수의 인수로 URL을 전달하면 GET 메서드를 사용한 HTTP 요청을 하게 됩니다.

 

 

HTTP 요청 함수 수정하기
// HTTP 요청 함수
function sendHttpRequest(method, url, data) {
  return fetch(url);
}

앞서 생성한 HTTP 요청 함수인 sendHTTPRequest에 fetch 함수를 사용할 경우 자체적으로 프로미스화가 되기 때문에 위와 같이 작성해줄 수 있습니다. 함수 sendHTTPRequest에서 반환되는 프로미스로 응답에 대해 활용할 수 있게 됩니다.

 

요청이 정상적으로 들어갔고 요청에 대한 응답 또한 정상적으로 들어온 것을 확인할 수 있습니다.

 

 

이때 fetch 함수는 XMLHTTPRequest와는 다르게 파싱 된 응답이 아닌 스트리밍 된 응답을 반환합니다. 즉 응답 객체에 바로 사용할 수 있는 응답 본문이 포함되는 대신에 아래와 같은 작업을 해주어야 합니다.

function sendHttpRequest(method, url, data) {
  return fetch(url).then((response) => { // 매개변수 reponse에 응답으로 넘어오는 객체를 받고
    return response.json(); // json 메서드를 사용하여 결과값이 반환되게 합니다.
  });
}

응답으로 들어오는 객체에 json 메서드를 사용하여 결괏값이 반환되도록 해주어 새로운 프로미스가 반환되도록 합니다. 응답 객체에 json 메서드를 사용하게 되면 fetch 함수가 응답 객체를 파싱하고 이를 JSON에서 JavaScript 데이터로 변환 작업을 하게 됩니다.

 

즉, json 메서드는 JSON.parse를 대체하는 메서드가 아니라 응답 객체를 작업 가능한 스냅샷으로 만들어 주는 것입니다.

 

이제 함수 sendHTTPRequest는 응답 데이터를 프로미스로 반환하는 함수가 되었습니다.

 

 

HTTP POST 요청

현재 수정된 함수 sendHTTPRequest는 GET 요청만 전송 가능한 상태입니다. 

 

function sendHttpRequest(method, url, data) {
  return fetch(url, { method, body: JSON.stringify(data) }).then((response) => {
    return response.json();
  });
}

fetch 함수는 요청 메서드를 인자로 직접 입력하는 것이 아닌 두 번째 인자에 해당 요청을 구성하는 객체로 작동하게 됩니다. 이를 위해 두 번째 인자의 객체에 method 속성에 요청 메서드를 문자열로 전달해 줍니다. 추가로 body 속성도 설정해 줍니다.

  • body : json 데이터에 대한 설정으로, 요청 시 전송하는 데이터를 JSON 데이터로 변환합니다.

 

POST 요청도 정상적으로 수행되는 것을 확인할 수 있습니다.

 

 

 

요청 헤더 추가하기

요청 헤더의 경우 때에 따라 중요하게 적용됩니다. 일부 API의 경우 전송하는 데이터의 유형을 설명해야 한다거나 추가적인 인증 데이터를 필요로 하는 경우가 있기 때문입니다. 이때 헤더가 전송되는 요청에 메타 데이터 역할을 하게 됩니다.

 

  • headers : 헤더로 추가하고자 하는 모든 객체가 들어갑니다. 

 

일반적으로 추가할 수 있는 헤더의 유형은 표준화되어 있습니다. 일반적으로 사용되는 헤더 유형으로 살펴보도록 하겠습니다.

function sendHttpRequest(method, url, data) {
  return fetch(url, {
    method,
    body: JSON.stringify(data),
    headers: { "Content-Type": "application/json" },
  }).then((response) => {
    return response.json();
  });
}
  • "Content-Type" : "application/json" : 해당 요청에 JSON 데이터가 있다고 서버에 전달 

헤더에 정상적으로 추가된 것을 확인할 수 있습니다.

 

*fetch API의 경우 요청으로 전송되는 데이터의 형식을 자동으로 헤더에 추가하기 때문에 Content-Type 설정이 필요 없습니다.

 

 

에러 핸들링
// HTTP 요청 함수
function sendHttpRequest(method, url, data) {
  return fetch(url, {
    method,
    body: JSON.stringify(data),
    headers: { "Content-Type": "application/json" },
  }).then((response) => {
    return response.json();
  }).catch(

    // 오류 핸들링 로직
  );
}

catch 구문에 오류 핸들링 로직을 작성할 예정입니다. 하지만 catch 구문에서 핸들링 가능한 오류는 앞서 언급한 요청 자체가 전송되지 않았을 때의 오류입니다.

 

// HTTP 요청 함수
function sendHttpRequest(method, url, data) {
  return fetch(url, {
    method,
    body: JSON.stringify(data),
    headers: { "Content-Type": "application/json" },
  })
    .then((response) => {
      if (response.status >= 200 && response.status < 300) {
        // 서버의 응답이 정상일 떄
        return response.json();
      } else {
        //  응답이 정상이 아닐 때
        return response.json().then((errData) => {
          console.log(errData);
          throw new Error("서버에서 오류 발생");
        });
      }
    })
    .catch((error) => {
      // 요청이 되지 않았을 경우 에러 핸들링 로직
      console.log(error);
      throw new Error("무엇인가 잘못되었습니다.");
    });
}

때문에 then 메서드 안에서 status로 오류에 대한 핸들링 로직을 작성해주어야 합니다.

 

정상적으로 오류가 핸들링되는 것을 확인할 수 있습니다.

 

 

 

 

[ XMLHTTPRequest와  fetch API 비교 ]

XMLHTTPRequest 와  fetch API 모두 HTTP 요청을 전송할 때 사용합니다. fetch의 경우 비교적 최신이며 오래된 브라우저(IE)에서는 지원되지 않지만 큰 장점으로는 사용하기가 쉽고 프로미스를 적극적으로 사용한다는 장점이 있는 반면 에러 핸들링이 다소 번거롭다는 단점이 있습니다. 앞서 작성한 헤러 핸들링 코드의 경우 심각한 수준은 아니지만 최선의 코드라고는 할 수 없습니다.

 

 

 

 

 

[웹 작동원리 링크]

 

How The Web Works

Learn how the web works, which technologies are involved and what you should learn if you're interested in starting a career in web development!

academind.com

 

[XMLHTTPRequest mdn]

 

Using XMLHttpRequest - Web APIs | MDN

In this guide, we'll take a look at how to use XMLHttpRequest to issue HTTP requests in order to exchange data between the web site and a server.

developer.mozilla.org

 

[fetch API mdn]

 

Fetch API - Web APIs | MDN

The Fetch API provides an interface for fetching resources (including across the network). It will seem familiar to anyone who has used XMLHttpRequest, but the new API provides a more powerful and flexible feature set.

developer.mozilla.org

 

'JavaScript' 카테고리의 다른 글

[Movie App Project ] JS로 Store 구현하기  (0) 2022.12.30
Testing  (0) 2022.12.28
함수  (2) 2022.12.25
Closure  (0) 2022.12.25
클래스  (0) 2022.12.24