동기와 비동기
console.log(1);
setTimeout(() => {
console.log(2);
}, 3000);
console.log(3);
동기란 순서대로 작업을 하나씩 처리하는 것을 말한다. 이렇게 동기적으로 작업을 처리해주는 아이가 스레드인데, 자바스크립트에는 스레드가 하나뿐이다. 그렇다면 동시에 여러 작업을 처리할 수 없는 것일까? 그렇지 않다. 실행된 작업을 브라우저 영역의 기능인 Browser APIs에게 위탁하고, 그동안 다음 작업을 실행하는 방법인 비동기가 있다.
예시 코드를 보자. 자바스크립트는 setTimeout 함수를 만나면 브라우저 APIs가 타이머를 실행하도록 하고, 그동안 다음 작업을 수행한다. 그리고 3초가 지나면 첫 번째 인자인 콜백함수를 그때서야 실행한다. 로그에는 1, 3, 2가 출력되는 형태.
비동기 작업 처리하기 1. 콜백함수
//음식을 주문하는 상황
function orderFood(callback) {
setTimeout(() => {
const food = "떡볶이";
callback(food);
}, 3000);
}
function cooldownFood(food, callback) {
setTimeout(() => {
const cooldownedFood = `식은 ${food}`;
callback(cooldownedFood);
}, 2000);
}
function freezeFood(food, callback) {
setTimeout(() => {
const freezedFood = `냉동된 ${food}`;
callback(freezedFood);
}, 1500);
}
orderFood((food) => {
console.log(food);
cooldownFood(food, (cooldownedFood) => {
console.log(cooldownedFood);
freezeFood(cooldownedFood, (freezedFood) => {
console.log(freezedFood);
});
});
});
비동기 작업의 결과를 또다른 비동기 작업의 인수로 넣어주는 것도 가능하다. 해당 비동기 작업이 실행된 후 결과값은 콜백함수의 매개변수로 넣어주고, 콜백함수는 콘솔로 cooldownedFood, freezedFood를 출력한 것을 알 수 있다.. 생각보다 어렵다!ㅠㅠ 지금까지 배운 내용들이 짬뽕되는 중 🌀🌀
이렇게 비동기 작업 내에 비동기 작업을 넣다보면 인덴트(들여쓰기)가 점점 깊어지는데, 이걸 개발자들은 '콜백 지옥'이라고 부른다고... 이걸 피하기 위해서 다음 시간에 Promise 객체를 배운다고 한다.
비동기 작업 처리하기 2. Promise
function add10(num) {
const promise = new Promise((resolve, reject) => {
// 비동기 작업 실행하는 함수
// executor
setTimeout(() => {
if (typeof num === "number") {
resolve(num + 10);
} else {
reject("num이 숫자가 아닙니다");
}
}, 2000);
});
return promise;
}
// then 메서드
// -> 그 후에
add10(0)
.then((result) => {
console.log(result);
return add10(result);
})
.then((result) => {
console.log(result);
return add10(result);
})
.then((result) => {
console.log(result);
})
.catch((error) => {
console.log(error);
});
// promise chaining
promise라는 비동기 작업을 관리하는 객체가 있다. 생성자 new Promise()로 선언하고, 생성자의 매개변수에는 전달할 비동기 작업 콜백함수(executor)를 써준다. 콜백함수의 매개변수에는 resolve, reject라는 함수가 사용된다. 각각 콜백함수가 잘 실행되었을 때, 그렇지 않을 때 실행되는 함수이다.
then 메서드를 사용하면, 콜백함수가 잘 실행된 후, resolve 함수의 인수를 result 매개변수로 받아온다.
then 메서드는 프로미스 객체를 그대로 반환할 수 있다. 그러므로 연속하여 then을 사용함으로써 비동기 작업의 결과를 또다른 비동기 작업의 인수로 쉽게 넣어줄 수 있다. 코드처럼 then 메서드가 길게 이어진 형태를 promise chaining이라고 한다.
- 콜백함수가 잘 실행되었다면 => resolve 함수 실행 => then 메서드 실행
- 콜백함수가 잘 실행되지 않았다면 => reject 함수 실행 => catch 메서드 실행
비동기 작업 처리하기 3. Async&Await
// async
// 어떤 함수를 비동기 함수로 만들어주는 키워드
// 함수가 프로미스를 반환하도록 변환해주는 키워드
async function getData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({
name: "박진주",
id: "icems0428",
});
}, 1500);
});
}
// await
// async 함수 내부에서만 사용이 가능한 키워드
// 비동기 함수가 다 처리되기를 기다리는 역할
async function printData() {
const data = await getData();
console.log(data);
}
printData();
Async 란 어떤 함수를 비동기 함수로 만들어주는 키워드이다. 즉 프로미스를 반환하도록 한다. 만약 애초에 프로미스를 반환하는 함수라면 async는 기능하지 않는다고 보면 된다.
Async은 Await과 함께 사용될 때 진가를 발휘한다. (참고로 await은 async 함수 내에서만 실행이 가능하다.) await은 비동기 함수가 실행될 때까지 기다렸다가 결과값을 받는다. 여기서 resolve나 reject 로 프로미스 작업이 완료 되었음을 명시해야 한다! 원래같았으면 getData().then((result)=>console.log(result) 같은 복잡한 문장을 썼어야 했을텐데, 훨씬 간편하게 작성 가능하다. 마치 동기 작업을 처리하듯 말이다.
자바스크립트 강의를 드디어 끝냈다! 동기 비동기, 콜백함수, 프로미스.. 마지막엔 좀 어려웠지만 어서 익숙해지면 좋겠다. 다음 시간부터 Node.js를 들어가는데 파이팅이다✊👊
'프론트엔드 > 한 입 크기로 잘라먹는 리액트' 카테고리의 다른 글
| React.js - 소개, App 생성, App 구동 (1) | 2025.01.20 |
|---|---|
| Node.js - 모듈 시스템, 라이브러리 (2) | 2025.01.20 |
| JavaScript - 배열메서드(요소 조작, 순회와 탐색, 배열 변형), Date 객체와 날짜 (2) | 2025.01.17 |
| JavaScript - 구조분해할당, Spread 연산자와 Rest 매개변수, 원시타입 VS 객체타입, 반복문으로 배열과 객체 순회하기 (1) | 2025.01.15 |
| JavaScript - 객체, 배열, Truthy와 Falsy, 단락 평가 (0) | 2025.01.13 |