· JS 는 < single-thread language > 이므로, 서버 요청을 기다려야 한다면 사용자는 멈춰있는 브라우저를 보게됨
👉 동기가 아닌 "비동기 처리" 를 이용해 서버로 통신할 필요가 있음
· 비동기 요청 후, main thread 는 유저의 입력을 받거나, 페이지를 그리는 등의 작업을 처리
· 비동기 응답을 받으면 응답을 처리하는 callback 함수를 < task queue > 에 추가
· < event queue > 는 main thread 에 여유가 있을 때 < task queue > 에서 함수를 꺼내 실행
⚪ "직렬적"으로 작업을 수행 👉 어떤 작업이 수행 중인 경우, 다음 작업은 대기 상태
⚪ 동기식 처리모델
< 동기(Synchronous) > 코드는 해당 블록이 실행될 때 thread의 제어권을 넘기지 않고 "순서대로" 실행
<script>
function func1() {
console.log('func1');
func2();
}
function func2() {
console.log('func2');
func3();
}
function func3() {
console.log('func3');
}
func1();
<< result >>
func1
func2
func3
</script>
⚪ "병렬적"으로 작업을 수행 👉 작업이 종료되지 않은 상태라도 대기하지 않고 다음 작업을 실행
· 서버에 작업을 요청한 후 서버로부터 응답이 오기까지 대기하지 않고 다음 작업을 수행
· 서버로부터 응답이 오면 이벤트가 발생, 이벤트 핸들러가 응답 결과를 가지고 계속해서 작업 수행
⚪ 비동기식 처리모델
< 비동기(Astnchronous) > 코드는, 코드의 "순서와 다르게" 실행
· 비동기 처리 코드를 감싼 블록은 < task queue > 에 추가
· Main thread 가 <동기 코드>를 실행한 후, 제어권이 돌아왔을 때 < event loop > 가 < task queue > 에 넣어진 비동기 코드 실행
<script>
function func1() {
console.log('func1');
func2();
}
function func2() {
setTimeout(function() {
console.log('func2');
}, 0);
func3();
}
function func3() {
console.log('func3');
}
func1();
<< result >>
func1
func3
func2
</script>
비동기 처리모델에서 호출될 함수를 미리 전달, 처리 종료 후 콜백함수가 호출
<script>
db.getUsers((err, users) => {
console.log(users);
});
</script>
⚪ 비동기 동작
db.getUsers
· 데이터베이스에서 유저목록을 찾아오는 비동기 동작을 수행하는 함수
⚪ 이벤트 등록 / 실행
(err, users) => { console.log(users); }
· 인자로 전달되는 함수가 getUsers 가 실행될 때 등록되는 이벤트 함수
· 이벤트 함수를 인자로 전달하는 형태가 "callback"
· getUsers 함수 실행이 완료되면 (err, users)를 인자로 갖는 익명함수가 실행
⚪ callback 의 표준
· callback 함수의 첫번째 인자는 err 를 전달하는게 표준
· 특정 이벤트 발생 시 시스템에 의해 호출되는 함수
· parameter 를 통해 전달받은 함수의 내부에서 setTimeout()
으로 세팅된 특정 시점에서 실행
⚪ 콜백 지옥
· 비동기식 처리 모델은 요청을 "병렬" 로 처리하여 다른 요청이 중단되지 않는 장점이 존재
· 비동기 처리를 위해 콜백 패턴을 사용하면 "처리 순서" 를 보장하기 위해 여러 개의 콜백 함수가 중첩되어 복잡도가 높아짐
👉 Callback 지옥
· 콜백 지옥이 발생하면 가독성이 떨어져 실수를 유발하거나 디버깅이 어려움
<script>
step1(function(value1) {
step2(value1, function(value2) {
step3(value2, function(value3) {
step4(value3, function(value4) {
step5(value4, function(value5) {
});
});
});
});
});
</script>
⚪ 에러 처리의 한계
· 콜백 방식의 비동기 처리가 갖는 가장 큰 문제
· setTimeout()
은 비동기 함수이므로, 콜백 함수가 실행될 때까지 기다리지 않고 "즉시 종료" 되어 < 호출 스택에서 제거 >
· "error" 는 호출자 방향으로 전파
👉 setTimeout 함수를 실행하면, 콜백함수의 "주체"가 setTimeout 에서 < event loop > 를 들고있는 event handler, 즉 "system" 으로 변경됨
👉 따라서, < setTimeout 함수의 콜백 함수 > 를 호출한 것은 setTimeout 함수가 아닌 상위 스코프의 "system" 이므로, setTimeout 함수의 콜백 함수 내에 발생한 예외는 catch
로 잡지 못함
· 비동기 처리가 고도화되면서, < Callbakc hell > 등이 단점으로 부각
👉 Promise
를 활용하여 "비동기 처리의 순서 조작", "에러 핸들링", "여러 비동기 요청 처리" 등이 쉬워짐
· Promise API 는 비동기 API 중 하나
· < task queue > 가 아닌 < job queue (or microtast queue) > 사용
· 처리 우선 순위 = job queue > task queue
<script>
setTimeout(() => {
console.log("타임아웃1");
}, 0);
Promise.resolve()
.then(() => console.log("프로미스1"));
setTimeout(() => {
console.log("타임아웃2");
}. 0};
Promise.resolve()
.then(() => console.log("프로미스2"));
<< result>>
프로미스1
프로미스2
타임아웃1
타임아웃2
</script>
· 기존 XMLHTTPRequest 를 대체하는 HTTP 요청 API
· ES6에 추가된 Promise 를 리턴하도록 정의됨
⚪ 네트워크 요청 성공 시, Promise 는 Response 객체를 resolve 함
⚪ 네트워크 요청 실패 시, Promise 는 에러를 reject 함
· 브라우저 API 중 1개
· 네트워크 전송에 관한 비동기 통신 API
· 다양한 전문 전송, 사용자 정보 읽기, 서버에서 데이터 받아옴 ( 새로고침 없이 )
fetch(url [, option])
<script>
fetch(url, [option])
.then((response) => response.json())
.catch((err) => console.log("err:", err));
</script>
· 서버에서 응답 헤더를 받자마자 fetch 호출 시, promise 가 반환
· method
사용할 메소드 선택 ( 'GET', 'POST', 'PUT', 'DELETE' )
· headers
헤더에 전달할 값 ({'content-Type': 'application/json'})
· body
바디에 전달할 값 (JSON.springfy(data))
· mode
'cors' 등의 값 설정 (cors, no-cors, same-origin)
· credentials
자격 증명을 위한 옵션 설정 (include, same-origin, omit)(default = same = origin)
· cache
캐시 사용 여부 (no-cache, reload, force-cache, only-if=cached)
· 옵션 값이 없는 경우 기본으로 GET 세팅
· response.status
HTTP Status Code 를 담음
· response.ok
응답 상태가 200 ~ 299 사이에 있는 경우 True
, 나머지는 False
· response.headers
맵과 유사한 형태의 HTTP 헤더
Response 객체의 헤더 정보를 얻음
· response.json()
응답을 파싱해 JSON 객체로 변경
얻어온 body 정보를 json 으로 만드는 Promise 를 반환
response.text
, response.formdata
, response.blob
로 다른 형태의 바디를 읽을 수 있음
· response.text
응답을 텍스트 형태로 반환
· response.formdata
응답을 FormData 객체 형태로 반환
· response.blob
응답을 Blob(타입이 있는 바이너리 데이터) 형태로 반환
· method
HTTP 메서드
· headers
요청 헤드가 담긴 객체 (제약 사항 존재)
· body
보내려는 데이터(요청 본문)로 string 이나 FormData, JSON, Blob 등의 객체 형태
⚪ GET 을 이용하여 기본 데이터를 가져오는 구조
<script>
fetch('url~')
.then((response) => response.json())
.then((json) => console.log(json));
</script>
⚪ POST 를 이용하여 옵션을 사용한 구조
<script>
fetch('url~')
method: 'post',
headers: {
'Content-type': 'application/json; charset=UTF-8',
},
body: JSON.stringify({
title: 'foo',
body: 'bar',
userId: 1,
}),
})
.then((response) => response.json())
.then((json) => console.log(json));
</script>