자바스크립트
[자바스크립트] 동기와 비동기, 콜백 함수, Promise, async, await
front-hyun
2023. 4. 13. 19:03
동기와 비동기
동기
- 동시에 일어나는 요청과 결과가 동시에 일어난다는 약속입니다.
- 작업이 순차적으로 실행됩니다.
- 여러가지 작업을 함께 수행할 수 없으며, 어떤 작업이 수행 중이면 다음 작업은 대기 상태가 됩니다.
console.log("start");
console.log("end");
비동기
- 동시에 일어나지 않는 요청과 결과가 동시에 일어나지 않을 거라는 약속입니다.
- 작업의 병렬적 실행입니다.
- 어떤 작업을 수행하는 중에도 다른 작업을 수행할 수 있으며, 여러 작업을 동시에 수행할 수 있습니다.
비동기와 동기 비교
| 장점 | 단점 | |
| 동기 | 설계가 쉽고 직관적입니다. | 결과가 주어질 때까지 아무것도 하지 목하고 대기해야 합니다. |
| 비동기 | 여러개의 작업을 동시에 수행 가능하고, 효율적인 자원 사용 가능합니다. |
설계가 복잡합니다. |
비동기 처리 방식의 문제점
- 작업 b는 작업 a가 실행 완료된 뒤 수행되어야 하는데, 작업 a가 얼마나 많은 시간이 걸릴지 실행하기 전에 알 수 없습니다.
- 비동기 처리를 기본으로 하면서도 일부 구간에서 순차적인 처리가 필요한 경우가 존재합니다.

콜백 함수
콜백함수 vs 기본함수
- 콜백함수를 이해시키기 위해 먼저 cry, sing, dance 를 하는 함수를 먼저 생성해줍니다.
- (아래의 내용 [1.일반함수] , [2.콜백함수] 에서 모두 사용하는 함수들입니다.)
function cry() {
console.log("cry");
}
function sing() {
console.log("sing");
}
function dance() {
console.log("dance");
}
기본함수
// 1. 기본 함수
// 기분 좋을때 춤을 추고 싶으면 sing()함수에 dance()로 변경해야함
function checkMood(mood) {
if (mood === "good") {
sing();
} else {
cry();
}
}
checkMood("good");
checkMood("sad");
콜백함수
// 2. 콜백함수 (함수를 매개변수로 넣어줌)
function checkMoodCallBack(mood, goodCallback, badCallback) {
if (mood === "good") {
goodCallback();
} else {
badCallback();
}
}
checkMoodCallBack("good", dance, cry);
checkMoodCallBack("Not bad", dance, sing);
- 함수를 함수의 인수(값)로 전달하고, 인수로 전달함 함수를 나중에(필요할 때) 호출하는 것입니다.
- 유연한 비동기 처리를 위한 하나의 패턴입니다.
- 특정 로직이 끝났을 때 원하는 동작을 실행시킬 수 있습니다.
- "good"일때 dance를 하도록, checkMoodCallBack에서 호출할 함수를 지정할 수 있다. 이렇게 사용할 함수들 마져 선택해서 사용하는 것이 바로 콜백함수이다.
콜백 지옥
- 비동기 처리 로직의 처리 순서를 보장하기 위해 콜백 함수를 연속해서 사용할 때 발생하는 문제입니다.
Promise
- 자바스크립트 비동기 처리에 사용되는 객체입니다.
- 콜백 함수를 사용할 때 나타나는 문제점인 콜백 지옥과 에러 처리가 곤란하다는 점을 해결하기 위해 제안되었습니다.
promise 생성
const promise = new Promise((resolve, reject) => {
//executor
});
- executor: Promise가 만들어질 때 자동으로 실행되는 함수입니다.
- resolve, reject: 자바스크립트에서 자체 제공하는 콜백입니다.
- resolve(value) - Promise 성공 시 그 결과를 나타내는 value와 함께 호출됩니다.
- reject(error) - 에러 발생 시 에러 객체를 나타내는 error와 함께 호출됩니다.
promise의 3가지 상태
- promise는 생성되고 종료될 때까지 3가지 상태를 가집니다.
- Pending(대기): 비동기 처리 로직이 아직 완료되지 않은 상태
- Fulfilled(이행): 비동기 처리가 완료되어 프로미스가 결과 값을 반환해준 상태
- Rejected(실패): 비동기 처리가 실패하거나 오류가 발생한 상태
//처음 Promise 객체
state: "pending", result: undefined
//Promise가 성공한 경우
state: "fulfilled", result: value
//Promise가 실패한 경우
state: "rejected", result: error
promise의 후속 처리 메소드 - then
promise.then(
function(result){ //결과를 다룹니다.}
function(error){ //에러를 다룹니다. }
);
- 실패: 비동기 처리가 실패하거나 오류가 발생한 상태
- 파일 업로드 작업이 실패 or 성공인지
- then은 두 개의 인수를 받을 수 있습니다.
- 프로미스가 성공적으로 처리된 경우만 다루고 싶다면 then에 인수를 하나만 전달하면 된다.
-> 첫 번째 인수: 프로미스가 이행되었을 때 실행되는 함수
-> 두 번째 인수: 프로미스가 거부되었을 때 실행하는 함수
promise의 후속 처리 메소드 - catch
- 작업이 거부된 경우(에러 발생)만 다루고 싶을 때 사용합니다.
promise의 후속 처리 메소드 - finally
- 프로미스가 처리되면(이행 또는 거부) 항상 실행된다.
promise chaining
- 후속 처리 메소드(then, catch)를 체이닝하여서 여러 개의 프로미스를 연결하여 사용함으로써 해결합니다.
| Promise | Callback |
| 흐름이 자연스럽다. 비동기 함수 처리 결과에 따라 그다음에 무엇을 할지 코드를 작성하면 된다. | 비동기 처리 함수를 호출할 때, 콜백 함수가 미리 정의되어 있어야 한다. |
| 비동기 함수 처리 결과가 프로미스 객체에 저장되기 때문에 코드 작성이 용이해진다. | 비동기 함수 처리 결과가 필요할 때마다 콜백 함수를 호출해야 한다. |
| 원하는 만큼 then 메소드를 호출할 수 있다. | 하나의 콜백 함수만 호출할 수 있다. |
asunc/await
- Promise 객체를 좀 더 쉽게 다룰 수 있게 고안된 문법입니다.
- 비동기 작업의 순차 처리를 일반 순차 프로그래밍처럼 할 수 있습니다.
async
- 사용법: function 앞에 async 키워드를 붙여줍니다.
- async를 붙임 함수는 항상 promise를 반환합니다.
await
- 사용법: 함수의 앞부분에 async 키워드를 추가하고, 해당 함수 내부에서 Promise의 앞부분에 await 키워드를 붙여줍니다.
- Promise가 끝날 때까지 기다리고, 결과 값을 특정 변수에 담을 수 있습니다.
- 기다리는 동안 엔진이 다른 일을 할 수 있기 때문에 CPU 리소스가 낭비되지 않습니다.