웹 기초 지식, Web API, 자바스크립트의 비동기 실행
fetch('https://www.google.com')
.then((response) => response.text())
.then((result) => { console.log(result); });
fetch()
서버에 리퀘스트를 보내고 리스폰스를 받는 보편적인 방법Callback
어떤 조건이 만족되었을 때 실행되는 함수then()
콜백을 등록해주는 메소드text()
리스폰스의 실제 내용을 갖고 있는 프로미스 객체를 리턴하는 리스폰스 객체의 메소드URI = scheme ":" ["//" authority] path [ "?" query ] [ "#" fragment ]
scheme
리소스에 접근할 방법을 정의해 둔 프로토콜 이름http
, https
, mailto
, tel
등authority
서버의 사용자 이름, 비밀번호, 호스트, 포트번호 등path
리소스 경로query
key=value 형태로 서버에 문자열로 전달하는 파라미터fragment
html 내부 북마크 등에 사용되며 서버에 전송되지 않는 정보JSON이란?
Number
, String
, Boolean
, Array
, Object
, null
자바스크립트 객체 표기법과 JSON 문법의 차이
undefined
, NaN
, Infinity
등JSON 데이터를 객체로 변환하기
JSON.parse()
메소드로 string 타입의 JSON 데이터를 자바스크립트 배열로 변환할 수 있다JSON
JSON 데이터를 다루기 위해 사용되는 자바스크립트의 기본 객체Request의 종류를 결정하는 메소드
GET
Read(데이터 조회)POST
Create(데이터 생성)PUT
Update(데이터 수정)DELETE
Delete(데이터 삭제)Request의 Head와 Body
Head
리퀘스트에 관한 여러 가지 부가 정보들이 들어있는 부분Body
실제 데이터를 담는 부분POST
, PUT
request는 보통 body에 data를 담아서 보내줘야 한다GET
, DELETE
request는 보통 body가 필요하지 않다Request Header
request head 안에 존재하는 하나하나의 key-value 쌍Header
Head의 내용:authority
URL의 authority:method
Request method:path
URL의 path:scheme
URL의 schemeaccept
클라이언트가 이해 가능한 컨텐츠 MIME 타입의 종류 (*/*: 모든 MIME 타입)accept-encoding
클라이언트가 이해 가능한 인코딩 종류(주로 압축 알고리즘)accept-language
클라이언트가 선호하는 언어(한국어, 영어 등)origin
fetch가 시작된 서버 이름referer
request를 보낸 페이지의 주소sec-ch-ua
브라우저의 버전sec-ch-ua-mobile
모바일 디바이스의 브라우저인지 아닌지sec-ch-ua-platform
유저가 실행하고 있는 플랫폼/운영체제sec-fetch-dest
리퀘스트의 목적지sec-fetch-mode
리퀘스트 모드 (CORS, navigate, no-cors, same-origin, websocket)sec-fetch-site
fetch가 시작된 서버와 요청된 리소스의 서버의 관계user-agent
리퀘스트를 보낸 브라우저와 그것이 설치된 운영 체제의 정보GET /men/shirts HTTP/1.1
과 같은 start-line을 사용하지 않는 대신에, method와 path를 일종의 pseudo-header로 표현한다POST request 보내기
GET request 보내기
// 3번 직원의 정보 조회
fetch('https://learn.codeit.kr/api/members/3')
.then((response) => response.text())
.then((result) => { console.log(result); });
POST request 보내기
// 새로운 직원 정보 추가
const newMember = {
name: 'jeris',
email: 'jeris@email.kr',
department: 'engineering',
};
fetch('https://learn.codeit.kr/api/members', {
method: 'POST',
body: JSON.stringify(newMember),
})
.then((response) => response.text())
.then((result) => { console.log(result)});
Option object
request options들을 요소로 하는 객체로 fetch() 함수의 두 번째 argument로 전달한다
JSON.stringify()
객체를 JSON string으로 변환하는 메소드
PUT request, DELETE request 보내기
PUT requst 보내기
// id=6인 직원 정보 수정
const member = {
name: 'jeris',
email: 'jeris@email.kr',
department: 'marketing',
};
fetch('https://learn.codeit.kr/api/members/6', {
method: 'PUT',
body: JSON.stringify(member),
})
.then((response) => response.text())
.then((result) => { console.log(result)});
DELETE request 보내기
// id=6인 직원 정보 삭제
fetch('https://learn.codeit.kr/api/members/6', {
method: 'DELETE',
})
.then((response) => response.text())
.then((result) => { console.log(result)});
모범적인 Web API, REST API
Client-Server
Client-Server 구조를 통해 양측의 관심사를 분리해야 한다Stateless
Client가 보낸 각 리퀘스트에 관해서 Server는 그 어떤 context도 저장하지 않는다. 즉, 매 리퀘스트는 각각 독립적인 것으로 취급된다는 뜻이다Cache
Cache를 활용해서 네트워크 비용을 절감해야 한다. Server는 response에, Client가 response를 재활용해도 되는지 여부(Cacheable)를 담아서 보내야 한다Uniform Interface
Client가 Server와 통신하는 인터페이스는 다음과 같은 하위 4가지를 준수해야 한다identification of resources
resource를 URI로 식별할 수 있어야 한다manipulation of resources through representations
Client와 Server는 둘 다 resource를 직접적으로 다루는 게 아니라 resource의 representations를 다뤄야 한다self-descriptive messages
request와 response 모두 그 자체에 있는 정보만으로 모든 것을 해석할 수 있어야 한다hypermedia as the engine of application state
response에는 현재 상태에서 다른 상태로 이전할 수 있는 링크를 포함하고 있어야 한다Layered System
Cline와 Server 사이에는 proxy, gateway와 같은 중간 매개 요소를 두고, 보안, 로드 밸런싱 등을 수행할 수 있어야 한다. 이를 통해 Client와 Server 사이에는 hierarchical layers가 형성된다Code on Demand
Client는 받아서 바로 실행할 수 있는 applet이나 script 파일을 Server로부터 받을 수 있어야 한다. 이 조건은 Optional이므로 REST architecture가 되기 위해 반드시 만족될 필요는 없다RESTful service
이런 REST API를 사용하는 웹 서비스identification of resources
에 관해서 특히 중요한 규칙 2가지document
하나의 객체로 표현할 수 있는 resource (file)collection
Documents를 담을 수 있는 resource (directory)JSON 데이터 다루기 종합
Serialization
자바스크립트 객체를 JSON string으로 변환하는 작업 (stringify)Deserialization
JSON string을 자바스크립트 객체로 변환하는 작업 (parse)response.json()
JSON string을 parsing한 결과를 담은 promise 객체를 리턴하는 메소드Status Code
Status Code
Request를 받은 server가 그 작업 결과를 나타내기 위해서 Response head에 넣는 숫자100 Continue
Client가 server에게 계속 request를 보내도 괜찮은지 물어봤을 때, 계속 request를 보내도 괜찮다고 알려주는 상태 코드101 Switching Protocols
Client가 protocol을 바꾸자는 request를 허락한다고 알려주는 코드200 OK
request가 성공적으로 처리되었음을 포괄적으로 의미하는 상태 코드201 Created
request의 내용대로 resource가 잘 생성되었음을 의미하는 상태 코드202 Accepted
request의 내용이 일단은 잘 접수되었음을 의미하는 상태 코드301 Moved Permanently
resource의 위치가 바뀌었음을 나타내는 상태 코드302 Found
resource의 위치가 일시적으로 바뀌었음을 나타내는 상태 코드301
, 302
같은 상태 코드가 있는 response의 head에는 Location이라는 헤더도 일반적으로 포함되어 있다304 Not Modified
response로 받았던 resource가 변경되지 않았으므로 client에게 caching된 resource를 사용하도록 권하는 상태 코드400 Bad Request
request에 문제가 있을 때 나타내는 상태 코드401 Unauthorized
아직 신원이 확인되지 않은(unauthenticated) user로부터 온 request를 처리할 수 없다는 뜻을 의미하는 상태 코드403 Forbidden
user의 신원은 확인되었지만 해당 resource에 접근 권한이 없어서 처리할 수 없다는 뜻을 의미하는 상태 코드404 Not Found
해당 URL이 나타내는 resource를 찾을 수 없다는 뜻을 의미하는 상태 코드405 Method Not Allowed
해당 resource에 대해서 요구한 처리는 허용되지 않는다는 뜻을 의미하는 상태 코드413 Payload Too Large
현재 request의 body에 들어있는 data의 size가 지나치게 커서 server가 거부한다는 뜻을 의미하는 상태 코드429 Too Many Requests
일정 시간동안 client가 지나치게 많은 request를 보냈다는 뜻을 의미하는 상태 코드500 Internal Server Error
현재 알 수 없는 server 내의 error로 인해 request를 처리할 수 없다는 뜻을 의미하는 상태 코드503 Service Unavailable
현재 server 점검 중이거나, traffic 폭주 등으로 인해 service를 제공할 수 없다는 뜻을 의미하는 상태 코드Content-type이란?
Content-Type header
body에 들어 있는 data가 어떤 타입인지를 나타낸다binary file
텍스트 파일 이외의 파일들을 보통 binary file이라고 한다알아두면 좋은 Content-type들
<?xml version="1.0" encoding="UTF-8 ?>
<person>
<name>Michael Kim</name>
<height>180</height>
<weight>70</weight>
<hobbies>
<value>Basketball</value>
<value>Listening to music</value>
</hobbies>
</person>
Schema
태그 정보에 대한 문서application/xml
이다+xml
을 붙여서 사용한다application/x-www-form-urlencoded
URL encoding
작업을 수행해 특정 특수 문자들 그리고 영어와 숫자를 제외한 다른 나라의 문자들을 percent encoding한다multipart/form-data
여러 종류의 data를 하나로 합친 Content-Typeboundary
기준으로 여러 종류의 데이터들을 각각 나눈다그 밖에 알아야 할 내용들
GET
, POST
, PUT
, DELETE
이외의 메소드들PATCH
새로운 data로 기존 data의 일부를 수정PUT
request는 기존 데이터를 아예 덮어쓰기 때문에 PATCH
request가 유용할 때가 있다HEAD
GET 메소드와 동일하지만 reponse body 부분은 제외하고, reponse head 부분만 받는다TCP(Transmission Control Protocol)
두 개의 호스트를 연결하고 데이터 스트림을 교환하게 해주는 중요한 네트워크 프로토콜IP(Internet Protocol)
송신 호스트와 수신 호스트의 Packet Switchng Netwrok에서 정보를 주고받는데 사용하는 정보 위주의 프로토콜Ethernet
로컬 환경의 컴퓨터 및 기타 장치를 네트워크에 연결하기 위해 개발된 프로토콜UDP(User Datagram Protocol)
전송 속도와 효율성이 보안과 신뢰성보다 중요할 때 데이터를 전송하기 위해 IP와 함께 사용되는 오래된 프로토콜FTP(File Transfer Protocol)
인터넷을 통해 한 호스트에서 다른 호스트로 파일을 전송하기 위해 사용했던 과거의 표준 프로토콜SSH(Secure Shell)
보안되지 않은 네트워크를 통해 네트워크 서비스를 안전하게 운영하기 위한 암호화 네트워크 프로토콜입HTTP
는 TCP를 기반으로, TCP는 IP를 기반으로, IP는 Ethernet을 기반으로 동작한다TCP
라는 프로토콜만으로 통신하는 코드를 짜기도 한다fetch 함수와 비동기 실행
- then()
메소드는 콜백을 등록만 하고 바로 그 다음 줄의 코드가 실행된다
- 콜백은 나중에 response가 도착했을 때 실행된다
- 비동기 프로그래밍(Asynchronous programming): 프로그램이 잠재적으로 장시간 실행되는 작업을 시작하고 해당 작업이 실행되는 동안 해당 작업이 완료될 때까지 기다리지 않고 다른 이벤트에 응답할 수 있도록 하는 기술
- 비동기 실행 함수의 실행 순서
참조
비동기 실행 함수
setTimeout()
첫 번째 파라미터의 콜백을 두 번째 파라미터 값의 밀리초(ms) 만큼 시간이 경과했을 때까지 실행을 미룬다console.log('a');
setTimeout(() => { console.log('b'); }, 2000);
console.log('c');
/*
a
c
b
*/
setInterval()
특정 콜백을 일정한 시간 간격으로 실행하도록 등록한다console.log('a');
setInterval(() => { console.log('b'); }, 2000);
console.log('c');
/*
a
c
b
b
...
*/
el.addEventListener()
Promise object(ES2015)
promise
작업에 관한 상태 정보를 갖고 있는 객체pending
작업이 진행 중인 상태fulfilled
작업이 성공적으로 완료된 상태rejected
작업이 실패한 상태then()
promise object's method, which resisters callback to execute when promise object's status changes from pending to fulfilledWhat is Promise Chaining
then()
method can be added after evrey then()
method.then()
method returns new promise object.Promise Chaining
addingthen()
method back to back.then()
method is executedthen()
method returned equal to that which the callback returnsthen()
method returned fulfilled, and the operation result equal to which the callback returnstext()
, json()
methods returnrejected state가 되면 실행할 callback
then()
method의 second parameter로, 전달받은 promise state가 rejected일 때 실행할 callback을 넣어줄 수 있다then 메소드 완벽하게 이해하기
catch 메소드
catch()
메소드를 사용해 then 메소드에 두 번째 콜백을 넣는 방법을 대신할 수 있다fetch('https://jsonplaceholder.typicode.com/users')
.then((response) => response.text())
.catch((error) => { console.log(error); })
// .then(undefined, (error) => { console.log(error); })
.then((result) => { console.log(result); });
finally 메소드
Promise 객체의 등장 배경
fetch('https://first.com', (response) => {
// Do Something
fetch('https://second.com', (response) => {
// Do Something
fetch('https;//third.com', (response) => {
// Do Something
fetch('https;//fourth.com', (response) => {
// Do Something
});
});
});
});
직접 만들어 보는 Promise 객체
const p = new Promise((resolve, reject) => {
setTimeout(() => { resolve('success'); }, 2000);
});
p.then((result) => { console.log(result); });
/*
Promise {<pending>}
// 2초 후
success
*/
new Promise(function(resolve, reject){})
프로미스 객체 생성 메소드resolve
작업 성공시 호출 되어 결과 값을 아규먼트로 받아서 fulfilled 프로미스를 리턴하는 함수reject
작업 실패시 호출 되어 결과 값을 아규먼트로 받아서 rejected 프로미스를 리턴하는 함수Promisify
Promisify
전통적인 형식의 비동기 실행 함수를 Promise 객체로 감싸서 그 Promise 객체를 리턴하는 형식으로 만드는 작업function wait(text, milliseconds) {
setTimeout(() => text, milliseconds);
}
fetch('https://jsonplaceholder.typicode.com/users')
...
.then((result) => { return wait(`${result}`, 2000); })
...
// function wait(text, milliseconds) {
// setTimeout(() => text, milliseconds);
// }
function wait(text, milliseconds) {
const p = new Promise((resolve, reject) => {
setTimeout(() => { resolve(text); }, 2000);
});
return p;
}
이미 상태가 결정된 Promise 객체
const p = Promise.resolve('success');
// 작업 성공 결과로 문자열 'success'를 갖는다
const p = Promise.reject(new Error('fail'));
// 작업 실패 정보로 문자열 'fail'을 갖는다
여러 Promise 객체를 다루는 방법(심화)
promise.all(array)
promise.race(array)
promise.allSettled(array)
[
{status: "fulfilled", value: 1},
{status: "fulfilled", value: 2},
{status: "fulfilled", value: 3},
{status: "rejected", reason: Error: an error}
]
settled state
fulfilled or rejected statepromise.any(array)
axios
axios
프로미스 API를 활용하는 HTTP 비동기 통신 라이브러리async/await이란?(ES2017)
// fetch('URL')
// .then((response) => response.text())
// .then((result) => { console.log(result); });
async function fetchAndPrint() {
const response = await fetch('URL');
const result = await response.text();
console.log(result);
}
fetchAndPrint();
async
AsyncFunction 객체를 반환하는 하나의 비동기 함수를 정의하는 키워드await
비동기적으로 실행될 부분을 지정하는 키워드catch문과 finally문
async function name() {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/users');
const result = await response.text();
console.log(result);
} catch (error) {
console.log(error);
} finally {
console.log('exit');
}
}
async 함수가 리턴하는 Promise 객체
async 함수 안의 async 함수
async를 붙이는 위치
// 1) Function Declaration
async function example1(a, b) {
return a + b;
}
// 2-1) Function Expression(Named)
const example2_1= async function add(a, b) {
return a + b;
};
// 2-2) Function Expression(Anonymous)
const example2_2 = async function(a, b) {
return a + b;
};
// 3-1) Arrow Function
const example3_1 = async (a, b) => {
return a + b;
};
// 3-2) Arrow Function(shortened)
const example3_2 = async (a, b) => a + b;
// 4) IIFE
(async function print(sentence) {
console.log(sentence);
return sentence;
}('I love JavaScript!'));
(async function (a, b) {
return a + b;
}(1, 2));
(async (a, b) => {
return a + b;
})(1, 2);
(async (a, b) => a + b)(1, 2);
async 함수를 작성할 때 주의해야할 성능 문제
async function getResponses(urls) {
for(const url of urls){
const response = await fetch(url);
console.log(await response.text());
}
}
getResponse
urls를 파라미터로, 여러 개의 URL들이 있는 배열을 받아서, 순서대로 각 URL에 리퀘스트를 보내고, 그 리스폰스의 내용을 출력하는 함수async function fetchUrls(urls){
for(const url of urls){
(async () => { // 추가된 부분!
const response = await fetch(url);
console.log(await response.text());
})(); // 추가된 부분!
}
}
Reference
- World Wide Web - Wikipedia
- Uniform Resource Identifier - Wikipedia
- URL - Wikipedia
- HTTP - Wikipedia
- POST - HTTP | MDN
- Content-Type - HTTP | MDN
- Sending form data - Learn web development | MDN
- Introducing asynchronous JavaScript - Learn web development | MDN
- Using promises - JavaScript | MDN
- Promise.resolve() - JavaScript | MDN
- Promise.reject() - JavaScript | MDN
- 자바스크립트 웹 개발 기본기 - 자바스크립트 강의 | 코드잇