[programmers] TIL_DAY-16
✅ 동기(Synchronous)와 비동기(Asynchronous)
간단하게, 동기 처리와 비동기 처리에 대해 정리하면
동기 처리
- 실행 중인 작업이 종료될 때까지 기다렸다가 종료되면 다음 작업이 실행된다.
- 장점: 작업을 순서대로 하나씩 처리하므로 실행 순서가 보장된다.
- 단점: 앞선 작업이 실행되는 동안 이후 작업들이 블로킹된다.
비동기 처리
- 실행 중인 작업이 종료되지 않더라도 다음 작업을 곧바로 시작한다.
- 장점: 현재 작업이 종료되지 않은 상태라도 다음 작업을 실행하므로 블로킹이 발생하지 않는다.
- 단점: 작업의 실행 순서가 보장되지 않는다.
만약 API 요청에 대한 응답을 기다리기 위해서 UI가 멈춘다면?...
✅ 자바스크립트의 이벤트 루프와 태스크 큐
자바스크립트 엔진은 싱글 스레드 방식으로 동작한다. 동기 처리 방식처럼 한번에 하나의 작업만 처리할 수 있다. 하지만 브라우저의 동작을 보면 마치 멀티 스레드 방식으로 동작하는 것처럼 보인다.
멑티 스레드처럼 동작하게 도와주는 이벤트 루프와 태스크 큐
이벤트 루프
- 이벤트 루프는 콜 스택에 현재 실행 중인 컨텍스크가 있는지, 그리고 태스크 큐에 대기 중인 함수가 있다면 이벤트 루프는 순차적으로(FIFO) 태스크 큐에 대기 중인 함수를 콜 스택으로 이동 시킨다.
태스크 큐
- setTimeout과 같은 비동기 함수의 콜백 함수 또는 이벤트 핸들러가 일시적으로 보관되는 영역이다.
자바스크립트 엔진은 단순히 콜 스택에 있는 작업을 순차적으로 실행할 뿐이다. 비동기 처리에서 소스코드의 평가와 실행을 제외한 모든 처리는 자바스크립트 엔진을 구동하는 환경인 브라우저 또는 Node.js가 담당한다.
setTimeout 비동기 함수를 예로 들면, setTimeout의 콜백 함수는 콜 스택에 푸시되는 것이 아니라 태스크 큐에 푸시되어 대기하다 콜 스택이 비게 되면 콜 스택에 푸시되어 실행된다.
for(var i = 0; i < 3; i++) {
setTimeout(()=> {
console.log(i)
}, i * 1000)
}
클로저를 공부하면서 봤던 코드다. for문을 실행하면서 setTimout이 실행되지만 콜 스택에 쌓이지 않고 태스크 큐에 저장되었다가 for문이 종료되면 콜백 함수가 실행된다.
✅ Call back
자바스크립트는 비동기 처리를 위한 하나의 패턴으로 콜백 함수를 사용한다. 이 콜백 함수는 콜백 헬을 만들어 낼 수 있다.
콜백 패턴의 단점
const get = url => {
const xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.send();
xhr.onload = () => {
if(xhr.status === 200){
return JSON.parse(xhr.response);
} else {
console.error(`${xhr.status} ${xhr.statusText}`);
}
};
};
const response = get('https://jsonplaceholder.typicode.com/posts/1');
console.log(response);
코드 실행 결과를 예측해보면, onload 함수가 발생하면 xhr.response 값을 리턴한다. 동기적으로 실행되었다면 response 변수에 return 값이 들어있으리라 예상할 수 있다. 하지만 onload 이벤트 핸들러가 비동기적으로 동작하기 때문에, get 함수를 실행하면 단순히 onload 이벤트 핸들러를 등록하고 종료된다. 따로 return하는 값이 없기 때문에 console.log(response)는 undefined를 출력한다.
콜백 함수는 콜 스택이 비어있을 경우 태스크 큐에서 콜 스택으로 이동해서 실행된다. 따라서 비동기 함수 외부에서 비동기 함수 처리 결과에 접근할 수 있는 방법이 없다. 따라서 사용할 수 있는 방법은 비동기 함수에 비동기 처리 결과에 대한 후속 처리를 수행하는 콜백 함수를 전달하는 것이다. 콜백 헬의 시작이다.
const get = (url, callback) => {
const xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.send();
xhr.onload = () => {
if(xhr.status === 200) {
callback(JSON.parse(xhr.response));
}else {
console.error(`${xhr.status} ${xhr.statusText}`);
}
}
};
const url = 'https://jsonplaceholder.typicode.com";
get(`{url}/posts/1`, ({userId}) => {
console.log(userId);
get(`${url}/users/${userId}`, userInfo => {
console.log(userInfo);
});
});
참고: 모던 자바스크립트 Deep Dive
✅ 정리
Promise, Async Await을 정리하기 전, 부족하다고 생각했던 동기 처리 방식과 비동기 처리방식에 대해서 복습하고, 이벤트 루프와 태스크 큐에 대해 정리했습니다. 또한 콜백에 대해 정리하면서 콜백 헬이 발생하는 이유와 Promise, Async Await의 필요성에 대해서도 알게 되었습니다. 내일은 Promise...😂
Author And Source
이 문제에 관하여([programmers] TIL_DAY-16), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@93minki/programmers-TILDAY-16저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)