- [개발자의품격][부트캠프][1기][10차시] JavaScript 주요 포인트 #12 | 고급 문법 - XMLHttpRequest, Fetch API, Promise, Async/Await2022년 02월 09일 22시 12분 57초에 업로드 된 글입니다.작성자: DandyNow728x90반응형
JavaScript 주요 포인트 #12
자바스크립트는 AJAX(Asynchronous JavaScript and XML) 이전과 이후로 나뉜다. AJAX로 인해 비동기 통신 및 웹페이지의 특정 일부분만 랜더링 하는 것이 가능해졌다. 이로 인해 웹이 급속도록 발전하게 되었다. AJAX는 동적인 웹 페이지를 만들기 위해 사용한다.
여기에서 다루게 될 내용은 XMLHttpRequest, Fetch API, Promise, Async/Await로서 자바스크립트 전체 문법을 통틀어 매우 중요한 부분이다. 이번 실습은 테스트 서버가 필요하다. 따라서 JSON Server를 실행한다.
JSON Server 실행
json-server --watch db.json
XMLHttpRequest
XMLHttpRequest(XHR) 객체는 서버와 상호작용하기 위해 사용한다. 지금은 XMLHttpRequest 객체를 직접적으로 사용할 일이 잘 없다. jQuery, fetch, axios을 사용하기 때문이다. 이 중에서도 axios를 주로 사용한다. 내부적으로 XMLHttpRequest가 돌아간다.
HTTP method(HTTP 요청 방식)
- GET - 리소스 요청
- POST - 리소스 생성
- PUT - 리소스 수정
- PATCH - 리소스 일부 수정(거의 안 씀)
- DELETE - 리소스 삭제
JSON Server Resources
- http://localhost:3000/posts
- http://localhost:3000/comments
- http://localhost:3000/profile
아래 코드 블록은 XMLHttpRequest 객체를 이용하여 서버의 데이터를 조회, 생성, 수정, 삭제하는 코드이다. 여기에서는 HTTP method(HTTP 요청 방식)와 JSON Server Resources를 이용한다.
<body> <button onclick="getData()">조회</button> <button onclick="postData()">생성</button> <button onclick="putData()">수정</button> <button onclick="deleteData()">삭제</button> <script> // 조회 function getData() { const xhr = new XMLHttpRequest(); xhr.open("GET", "http://localhost:3000/posts"); // 요청방식과 서버URL을 넣어준다. 준비 상태이다. xhr.setRequestHeader("content-type", "application/json"); // 요청에 맞는 헤더 값을 설정해야 한다. 서버와는 일반적으로 json 통신하기 때문에 거의 이렇게 쓴다고 보면된다. xhr.send(); // 서버에 요청을 보낸다. // 서버로 요청하면 그 결과가 응답이 왔을때 onload에 있는 코드가 실행된다. xhr.onload = () => { console.log(xhr); // 상태 코드 200, 성공 if (xhr.status === 200) { const res = JSON.parse(xhr.response); // object로 받아 온다. console.log(res); return res; } else { console.log(xhr.status, xhr.statusText); } }; } // 생성 function postData() { const xhr = new XMLHttpRequest(); xhr.open("POST", "http://localhost:3000/posts"); xhr.setRequestHeader("content-type", "application/json;charset=UTF-8"); // charset=UTF-8 한글이 깨지는 것 방지한다. const data = { title: "xmlhttprequest", author: "John Doe" }; // json은 유일한 키값이 항상 존재해하기 때문에 id가 반드시 있어야 한다. id번호는 자동으로 생성된다. xhr.send(JSON.stringify(data)); // object를 문자열로 변환한다. xhr.onload = () => { if (xhr.status === 201) { // 상태 코드 201, 생성만 201, 조회, 수정, 삭제는 200번이다. const res = JSON.parse(xhr.response); console.log(res); } else { console.log(xhr.status, xhr.statusText); } }; } // 수정 function putData() { const xhr = new XMLHttpRequest(); xhr.open("PUT", "http://localhost:3000/posts/2"); // id 2번 수정 xhr.setRequestHeader("content-type", "application/json;charset=UTF-8"); const data = { title: "javascript", author: "jeremy" }; xhr.send(JSON.stringify(data)); xhr.onload = () => { if (xhr.status === 200) { const res = JSON.parse(xhr.response); console.log(res); } else { console.log(xhr.status, xhr.statusText); } }; } // 삭제 function deleteData() { const xhr = new XMLHttpRequest(); xhr.open("DELETE", "http://localhost:3000/posts/2"); // id 2번 삭제 xhr.setRequestHeader("content-type", "application/json;charset=UTF-8"); xhr.send(); xhr.onload = () => { if (xhr.status === 200) { const res = JSON.parse(xhr.response); console.log(res); } else { console.log(xhr.status, xhr.statusText); } }; } </script> </body>
Fetch API
Fetch API를 이용하면 XMLHttpRequest와 동일한 기능을 더 쉽게 구현할 수 있다. Fetch API는 그 자체가 Promise이다.
<body> <button onclick="getData()">조회</button> <button onclick="postData()">생성</button> <button onclick="putData()">수정</button> <button onclick="deleteData()">삭제</button> <script> // 조회 function getData() { fetch("http://localhost:3000/posts") // .then(function (response) { // return response.json(); // json 으로 변환 // }) // .then(function (json) { // console.log(json); // }); // 위 조회 코드를 화살표 함수로 구현 .then((response) => response.json()) // json 으로 변환 .then((json) => console.log(json)); } // 생성 function postData() { fetch("http://localhost:3000/posts", { method: "POST", body: JSON.stringify({ title: "xmllhttprequest", author: "John Doe", }), headers: { "content-type": "application/json;charset=UTF-8", }, }) .then((response) => response.json()) .then((json) => console.log(json)); } // 수정 function putData() { // id 3번 수정 fetch("http://localhost:3000/posts/3", { method: "PUT", body: JSON.stringify({ title: "xmlhttprequest", author: "John Doe", }), headers: { "content-type": "application/json;charset=UTF-8", }, }) .then((response) => response.json()) .then((json) => console.log(json)); } // 삭제 function deleteData() { // id 3번 삭제 fetch("http://localhost:3000/posts/3", { method: "DELETE", }) .then((response) => response.json()) .then((json) => console.log(json)); } </script> </body>
Promise
Promise는 비동기 처리에 사용되는 객체이다. 비동기란 언제 끝날지 모르는 작업을 기다리지 않고 다음 작업을 처리하는 것을 말한다.
Promise 미적용
<script> function getData() { const xhr = new XMLHttpRequest(); xhr.open("GET", "http://localhost:3000/posts"); // 요청방식과 서버URL을 넣어준다. 준비 상태이다. xhr.setRequestHeader("content-type", "application/json"); // 요청에 맞는 헤더 값을 설정해야 한다. 서버와는 일반적으로 json 통신하기 때문에 거의 이렇게 쓴다고 보면된다. xhr.send(); // 서버에 요청을 보낸다. // 서버로 요청하면 그 결과가 응답이 왔을때 onload에 있는 코드가 실행된다. xhr.onload = () => { console.log(xhr); // 상태 코드 200, 성공 if (xhr.status === 200) { const res = JSON.parse(xhr.response); // object로 받아 온다. return res; } else { console.log(xhr.status, xhr.statusText); } }; } const data = getData(); console.log(data); // undefined(시차 발생, 서버가 요청에 대한 응답을 보내주기 전에 실행되었다.) console.log("다음 코드 실행"); </script>
Promise 적용
<script> // Promise 문법은 다음과 같다. // const promise = new Promise((resolve, reject) => { // if ("처리성공") { // resolve("결과 데이터"); // } else { // reject("에러"); // } // }); function getData2(url) { return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.open("GET", url); xhr.setRequestHeader("content-type", "application/json"); xhr.send(); xhr.onload = () => { if (xhr.status === 200) { const res = JSON.parse(xhr.response); resolve(res); } else { console.log(xhr.status, xhr.statusText); reject(xhr.status); } }; }); } // Promise를 적용하면 호출하는 쪽에서 then을 정의하여 사용할 수 있다. // 서버로부터 응답받기 전에 실행되어 버리면 문제가 되는 코드를 then 함수 내에 작성한다. getData2("http://localhost:3000/posts").then((res) => console.log(res)); // 2순위 실행 getData2("http://localhost:3000/comments").then((res) => console.log(res)); // 3순위 실행 console.log("다음 코드 실행"); // 1순위 실행 // getData1().then(getData2().then(getData3())) // 참고로 Promise는 이렇게 연결하여 사용할 수 있지만 복잡해진다. // 아래는 위 코드와 같다. // const data1 = getData1(); // const data2 = getData2(data1); // const data3 = getData3(data2); </script>
Promise 없는 then은 error
<script> function getCommentData(url) { const xhr = new XMLHttpRequest(); xhr.open("GET", url); xhr.setRequestHeader("content-type", "application/json"); xhr.send(); xhr.onload = () => { if (xhr.status === 200) { const res = JSON.parse(xhr.response); return res; } else { console.log(xhr.status, xhr.statusText); } }; } // promise를 적용하지 않았는데 호출하는 쪽에서 then을 사용하면 에러가 발생한다. getCommentData("http://localhost:3000/posts").then((res) => console.log(res) ); // Uncaught TypeError: Cannot read properties of undefined (reading 'then') </script>
Async/Await
Async/Await는 Promise와 동일한 목적으로 사용한다. 비동기 통신이 완벽히 끝날 때까지 기다린다. 서버와 통신 중 순차적으로 코드를 실행할 때 주로 사용한다. 데이터가 너무 많아서 아래 코드가 마냥 기다리게 하는 상황이 발생할 수 있다. 따라서 서버로 부터 응답 받은 데이터를 다음 코드에서 반드시 필요로 할때 사용한다. 그런 상황이 아니라면 데이터를 덜 받았더라도 나머지 코드가 실행되도록 해야 한다. 상황에 따라 잘 사용하자!
<body> <button onclick="getData()">조회</button> <script> // function 앞에 async를 붙인다. async function getData() { const res1 = await fetch("http://localhost:3000/posts"); // 서버로 부터 값이 오기를 기다렸다가 res1에 넣겠다. // const res1Json = res1.json(); // 콘솔창에 "Promise {<pending>}" 표시되었다. res1Json에 배열 요소가 들어오지 않은 상태이다. const res1Json = await res1.json(); // await으로 인해 res1Json에 배열 요소가 모두 들어온다. console.log(res1Json); } </script> </body>
728x90반응형'영광의 시대! > 2022 개발자의 품격 부트캠프 1기' 카테고리의 다른 글
다음글이 없습니다.이전글이 없습니다.댓글