XMLHttpRequest
XMLHttpRequest(XHR) 객체는 서버와 상호작용하기 위해 사용됩니다. 전체 페이지의 새로 고침 없이도 URL를 통해 데이터를 전송하거나 받아 올 수 있습니다. XMLHttpRequest는 이름에 XML이 붙어서 XML 데이터 통신으로 오해 할 수 있는데, 모든 종류의 데이터를 받아 올 수 있습니다.
객체 생성
XMLHttpRequest 객체는 브라우저에서 제공하는 Web API이기 때문에 브라우저 환경에서만 정상적으로 동작됩니다. node.js 환경에서는 제공되지 않습니다. XMLHttpRequest 생성자 함수를 호출해서 생성합니다.
const xhr = new XMLHttpRequest();
요청 전송
클라이언트(브라우저)에서 서버로 요청을 보내기 위해서는 HTTP Method와 요청 URL을 정의하는 것 부터 시작합니다. XMLHttpRequest의 내장 함수인 open()을 이용합니다.
xhr.open('GET', '/posts');
open() 함수에 첫번째 매개변수는 HTTP Method, 즉 HTTP 요청 방식입니다.
- GET — 리소스 요청
- POST — 리소스 생성
- PUT — 리소스 수정
- PATCH — 리소스 일부 수정
- DELETE — 리소스 삭제
open() 함수를 통해서 HTTP 요청 방식과 요청 URL를 정의했다고 해서 바로 실행이 되는 것은 아닙니다. 클라이언트에서 서버로 HTTP 요청을 하기 전에 요청에 맞는 헤더 값을 설정해야합니다. setRequestHeader() 함수를 통해서 요청 헤더 값을 설정할 수 있습니다. 일반적으로 요청할 때 서버로 전송하는 데이터의 타입을 선언하기 위한 용도로 많이 사용합니다. 헤더 값 중 content-type에 해당합니다. content-type은 서버로 전송할 데이터의 MIME 타입 정보를 설정합니다. 웹 개발시 자주 사용하는 MIME 타입은 크게 3가지 입니다.
- application/json
- text/plain
- multipart/form-data
다음과 같이 요청을 위한 content-type을 정의할 수있습니다.
xhr.setRequestHeader('content-type', 'application/json');
open() 함수와 setRequestHeader() 함수로 요청에 필요한 정의가 끝나면 최종적으로 send() 함수를 통해 요청을 보내게 됩니다. 이때 서버로 전송할 데이터가 있다면 send() 함수에 매개변수로 데이터를 전달하면 됩니다. 전달된 데이터는 request의 body에 담겨서 전송되게 됩니다.
단, HTTP 요청 방법이 GET인 경우는 send() 함수에 매개변수로 데이터를 전달해도 전달한 데이터는 실제로는 전송되지 않습니다.
다음은 HTTP 요청 방식 중 POST를 사용해서 데이터를 전송하는 예제입니다.
const xhr = new XMLHttpRequest(); //XMLHttpRequest 객체 생성xhr.open("POST", "/posts"); //HTTP Method, URL 정의xhr.setRequestHeader("content-type", "application/json"); //헤더 값 중 content-type 정의const data = {id: 2,title: "XHLHttpRequest",author: "Jeremy",};xhr.send(JSON.stringify(data)); //JSON.stringify를 통해 오브젝트 데이터를 문자열 형태로 변경해서 전송해야 함.
응답 처리
클라이언트로 서버로 요청(Request)을 전송하면, 서버는 요청한 결과를 응답(Response) 하게 됩니다. XMLHttpRequest 객체가 발생시키는 이벤트를 통해서 서버가 전송한 응답을 처리할 수있습니다.
const xhr = new XMLHttpRequest(); //XMLHttpRequest 객체 생성xhr.open("GET", "/posts"); //HTTP Method, URL 정의xhr.setRequestHeader("content-type", "application/json"); //헤더 값 중 content-type 정의xhr.send(); // 요청 전송xhr.onload = () => {if(xhr.status === 200) { // 정상적으로 응답이 되면 status가 200const res = JSON.parse(xhr.response); // 응답 데이터를 JSON.parse 함수로 JSON 객체로 변경console.log(res);} else { // 에러 발생console.error(xhr.status, xhr.statusText); //응답 상태와 응답 메시지를 출력}}
테스트
여기서는 JSONPlaceholder(https://jsonplaceholder.typicode.com) 라는 테스트를 위한 가짜 서버 서비스를 이용하도록 하겠습니다.
JSONPlaceholder 에서는 다음과 같이 테스트를 위한 리소스를 제공합니다.
- /posts
- /comments
- /albums
- /photos
- /todos
- /users
다음과 같이 open() 함수에 URL에 “https://jsonplaceholder.typicode.com/posts” 인수로 넘기면 100개의 데이터를 받아 오게 됩니다.
const xhr = new XMLHttpRequest(); //XMLHttpRequest 객체 생성xhr.open("GET", "https://jsonplaceholder.typicode.com/posts"); //HTTP Method, URL 정의xhr.setRequestHeader("content-type", "application/json"); //헤더 값 중 content-type 정의xhr.send(); // 요청 전송xhr.onload = () => {if (xhr.status === 200) {// 정상적으로 응답이 되면 status가 200const res = JSON.parse(xhr.response); // 응답 데이터를 JSON.parse 함수로 JSON 객체로 변경console.log(res); // 100개의 데이터를 받아 옴} else {// 에러 발생console.error(xhr.status, xhr.statusText); //응답 상태와 응답 메시지를 출력}};
전체 데이터 중 특정 id에 해당하는 데이터만 가져오고 싶다면 요청 URL을 다음과 같이 작성하면 됩니다.
https://jsonplaceholder.typicode.com/posts/:id
만약에 id가 1번인 데이터를 가져오고 싶다면, https://jsonplaceholder.typicode.com/posts/1 로 호출하면 됩니다.
이번에는 데이터를 생성해 보도록 하겠습니다.
const xhr = new XMLHttpRequest(); //XMLHttpRequest 객체 생성xhr.open("POST", "https://jsonplaceholder.typicode.com/posts"); //HTTP Method, URL 정의xhr.setRequestHeader("content-type", "application/json; charset=UTF-8"); //헤더 값 중 content-type 정의xhr.send(JSON.stringify({title:"foo", body:"bar", userId:1})); // 요청 전송xhr.onload = () => {if (xhr.status === 201) {// POST 요청이 정상적으로 성공이 되면 201const res = JSON.parse(xhr.response); // 응답 데이터를 JSON.parse 함수로 JSON 객체로 변경console.log(res); //} else {// 에러 발생console.error(xhr.status, xhr.statusText); //응답 상태와 응답 메시지를 출력}};
이번에는 id가 1인 데이터를 수정해 보도록 하겠습니다.
const xhr = new XMLHttpRequest(); //XMLHttpRequest 객체 생성xhr.open("PUT", "https://jsonplaceholder.typicode.com/posts/1"); //HTTP Method, URL 정의xhr.setRequestHeader("content-type", "application/json; charset=UTF-8"); //헤더 값 중 content-type 정의xhr.send(JSON.stringify({title:"foo", body:"bar", userId:1})); // 요청 전송xhr.onload = () => {if (xhr.status === 200) {// PUT 요청이 정상적으로 성공이 되면 200const res = JSON.parse(xhr.response); // 응답 데이터를 JSON.parse 함수로 JSON 객체로 변경console.log(res); //} else {// 에러 발생console.error(xhr.status, xhr.statusText); //응답 상태와 응답 메시지를 출력}};
이번에는 id가 1인 데이터를 삭제해 보도록 하겠습니다.
const xhr = new XMLHttpRequest(); //XMLHttpRequest 객체 생성xhr.open("DELETE", "https://jsonplaceholder.typicode.com/posts/1"); //HTTP Method, URL 정의xhr.setRequestHeader("content-type", "application/json; charset=UTF-8"); //헤더 값 중 content-type 정의xhr.send(); // 요청 전송xhr.onload = () => {if (xhr.status === 200) {// DELETE 요청이 정상적으로 성공이 되면 200const res = JSON.parse(xhr.response); // 응답 데이터를 JSON.parse 함수로 JSON 객체로 변경console.log(res); //} else {// 에러 발생console.error(xhr.status, xhr.statusText); //응답 상태와 응답 메시지를 출력}};