[Section 03] JavaScript 동기 비동기
< 배운 내용 요약 정리 >
< 문제 풀다가 다시 정리하는 개념 >
예를 들어 count가 배열이면 count[]에서 []안의 값은 인덱스(숫자)를 의미하고,
count가 객체면 count[]에서 []안의 값은 속성의 키를 의미한다.
ex) 배열일 때
const count = [10, 20, 30];
console.log(count[1]);
ex) 객체일 때
const count = { "1": "one", "2": "two" };
console.log(count[1]);
1. 동기 vs 비동기
- 하나의 작업만 순서대로 진행 vs 작업을 기다리지 않고 다음 작업 진행
2. 일반적인 자바스크립트 엔진 vs 웹브라우저 자바스크립트 엔지
- 콜스택 vs 태스크 큐
- 비동기 함수는 콜스택이 아닌 태스크 큐에서 처리 : 이벤트 루프
3. 대표적인 비동기 함수
- setTimeout(), setInterval(), fetch()
4. 비동기 함수 처리 방법
- callback : 동기 / 비동기
- promise : 생산자 생성할 때 사용하는 표준내장객체, producer / consumer
- async ... await (오늘 안 다뤘음)
< 19. 동기와 비동기 >
1. 동기와 비동기
1.1. 동기
- 싱글 스레드를 가지고 있는 언어
- 일을 할 수 있는 작업장이 한 개하는 뜻
- 한 번에 하나의 작업만 수행하며, 코드가 작성된 순서대로 실행
1.2. 비동기
- 한 작업이 완료되기를 기다리지 않고 다음 작업으로 넘어갈 수 있음
- 자바스크립트는 기본적으로 단일 스레드로 동작하지만,
이벤트 루프
와 콜백 큐
를 통해 비동기 처리를 효율적으로 관리할 수 있음
- 이해를 도울 사이트
latentflip.com
2. 자바스크립트 엔진
2.1. 일반적인 자바스크립트 엔진
2.2. 웹 브라우저에 탑재된 자바스크립트 엔진
- 콜스택의 작업이 모두 비워진 이후, 태스크 큐에 대기하고 있던 콜백이 들어감
- 콜스택이 비워지지 않으면 태스크 큐에 대기 중인 콜백이 들어갈 수 없음
- 먼저 실행된 것이 있다면 작성 순서에 상관 없이 실행된 순서대로 대기 후 들어감
이벤트 루프
: 웹 브라우저 자바스크립트 엔진에서 일어나는 일련의 과정들
- 비동기는 웹 브라우저에 탑재되어 있는 엔진의 도움을 받아 실행 가능한 것
2.2.1. 크롬 : v8 엔진
2.2.2. 파이어폭스 : 스파이더몽키 엔진
2.2.3. 사파리 : 자바스크립트코어 엔진
3. 대표적인 비동기 함수
3.1. setTimeout()
, setInterval()
, fetch()
- WEB API에 속함, 웹 브라우저에서부터 제공을 받음
- WEB API의 공통점은 콜백이 있다는 것
- 웹 브라우저의 자바스크립트 엔진에서 실행됨
- 자바스크립트 엔진은
콜스택
을 가짐, 웹브라우저 엔진은 태스크 큐
를 가짐
setTimeout()
4. 비동기 함수를 적절하게 처리하는 방법
callback
, promise
, async...await
< 20. Callback 함수
>
1. 동기 콜백 함수
function a(callback) {
console.log("a");
callback();
}
function b() {
console.log("b");
}
a(b);
2. 비동기 콜백 함수
function a() {
setTimeout(() => {
console.log("a");
}, 0);
}
function b() {
console.log("b");
}
a();
b();
function a(callback) {
setTimeout(() => {
console.log("a");
callback();
}, 0);
}
function b() {
console.log("b");
}
a(b);
※ 화살표 함수의 탄생 배경
- 매개변수로 전달되는 callback 함수를 간단하게 하기 위해 생김
function a(callback) {
setTimeout(() => {
console.log("a");
callback();
}, 0);
}
a(() => {
console.log("b");
});
※ 비동기의 단점
- 1234순으로 출력되게 하고 싶은데 비동기 함수가 있으면 순서가 꼬임
- callback 함수 자체를 새로운 함수로 전달해서 해결할 수 있음
- 예시
function task1() {
console.log("task1");
}
function task2() {
console.log("task2");
}
function task3() {
console.log("task3");
}
function task4() {
console.log("task4");
}
task1();
task2();
task3();
task4();
function task1() {
setTimeout(() => {
console.log("task1");
});
}
function task2() {
console.log("task2");
}
function task3() {
setTimeout(() => {
console.log("task3");
});
}
function task4() {
console.log("task4");
}
task1();
task2();
task3();
task4();
function task1(callback) {
setTimeout(() => {
console.log("task1");
callback();
}, 0);
}
function task2(callback) {
console.log("task2");
callback();
}
function task3(callback) {
setTimeout(() => {
console.log("task3");
callback();
}, 0);
}
function task4() {
console.log("task4");
}
task1(() => {
task2(() => {
task3(() => {
task4();
});
});
});
< 21. Promise 함수
>
- 자바스크립트 비동기 작업을 처리하기 위한 객체
- 비동기 작업의 성공 또는 실패를 나타내는 정보를 가지고 있다.
- 보통 생성자 함수처럼
new Promise()
형태로 호출하여 인스턴스 생성
Producer
vs Consumer
역할로 구분
< 기본적인 문법 형태 >
new Promise(function(resolve, reject) {
});
1. Producer
(생산자)
2 Consumer
(소비자)
then
, catch
, finally
then
: resolve가 호출되면 실행되는 함수
catch
: reject가 호출되면 실행되는 함수
finally
: then, catch의 마지막에 보통 하나만 사용
(맨 끝 아니라도, 하나가 아니라도 가능은 함), 무조건 실행됨
- 예시
const promise = new Promise(function (resolve, reject) {
setTimeout(() => {
reject("failed");
}, 1000);
});
promise
.then((value) => {
console.log(value);
})
.catch((err) => {
console.log(err);
});
const startBooking = () => {
console.log("영화 예매 시작");
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("영화 예매 완료");
resolve("영화 예매 완료");
}, 1000);
});
};
const selectMovie = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
const movie = "어벤져스";
resolve(`${movie} 선택`);
}, 1000);
});
};
const selectSeat = () => {};
const makePayment = () => {};
const watchMovie = () => {};
startBooking()
.then((value) => selectMovie(value))
.then((value) => {
console.log(value);
});
const fetchNumber = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(2);
}, 1000);
});
fetchNumber
.then((num) => num * 2)
.then((num) => num * 2)
.then((num) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(num * 2);
}, 1000);
});
})
.then((num) => {
console.log(num);
});
3 promise then
체이닝
- 예시
const fetchNumber = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(2);
}, 1000);
});
fetchNumber
.then((num) => num * 2)
.then((num) => num * 2)
.then((num) => {
return new Promise((resolve, reject) => {
resolve(num);
});
})
.then((num) => {
console.log(num);
})
.catch(() => {});
const getSunIcon = () => {
return new Promise((resolve, _) => {
setTimeout(() => {
resolve("😄");
}, 1000);
});
};
const getPlantIcon = (water) => {
return new Promise((resolve, _) => {
setTimeout(() => {
resolve(`${water} => 😒`);
}, 1000);
});
};
getSunIcon()
.then((sun) => getPlantIcon(sun))
.then((water) => console.log(water));
4 Task Queue
와 Micro Task Queue
Task Queue
보다 Micro Task Queue
가 먼저 실행되어 출력된다.
- setTimeout과 같은 비동기 함수는
Task Queue
에 담기고, then과 catch, finally는 Micro Task Queue
에 담기므로 비동기 함수보다 then의 순서에 맞게 출력
< 하루 정리 >
오늘은 수업 시작 전 문제를 두 개 먼저 풀고 시작을 했다.
어제 팀원들이랑 공유한 부분, 그리고 용재님께서 알려주신 부분이 있어서인지
문제를 풀 때 좀 더 머리 회전이 된 것 같은 기분이었다.
(물론 엉뚱한 곳에서 시간이 오래걸려서 시간 내 제출은 못 했지만..)
수업 내용은 전반적으로 크게 어려운 느낌은 아니었지만, 그렇다고 바로 이해가 되지도 않았다.
강사님께서 여러가지 예시를 보여주시기 위해 많은 드리블(?)하셨고
그 과정에서 중간중간 놓칠 때 마다 멘탈이 흔들리기 시작했다..
저번 주부터 시작됐지만, 수업 내용이 어렵고 머릿 속에 혼란이 찾아 올 때마다
팀원들과 사이가 돈독해지고 있다 ㅋㅋㅋ
다들 나만큼은 아니더라도 어렵긴 어려운 듯...ㅠㅠ
그래도 수업 내용이 이해가 안 되는게 있으면 팀원들과 먼저 내용을 공유하고
부족한 부분을 채워나갈 수 있어서 참 좋은 것 같다.
마지막에 해결되지 않은 깃허브도 물론 강사님이 원하셨던 방법은 아니었지만,
팀원들의 도움으로 어찌 해결하긴 했다.
잠을 4시간 정도 밖에 못 자서 몸이 피곤한데도,
많은 걸 느끼고 많은 걸 배우고 많은 걸 해결해서 기운은 나는 하루!!