동기 : 일을 순차적으로 처리하는 것, 전 일의 완료 시점과 다음 일의 시작 시점이 같다.
비동기 : 전 일의 완료 시점과 다음 일의 시작 시점이 같을 필요가 없다.
그림으로 나타내면 다음과 같다.

위 그림에서 동기 방식에 비해 비동기 방식이 같은 일을 하는데 걸리는 시간이 훨씬 짧은 것을 알 수 있다.
쉬운 예시를 들자면, 커피를 주문을 받는 과정을 생각해볼 수 있다.
만약 커피 주문이 동기적으로 작용한다면, 다음과 같은 과정을 거친다.
이렇게 되면 손님 2는 손님 1이 아메리카노를 전달받을 때까지 주문을 하지 못하고 대기열에 머물러 있어야 한다.
한편 커피 주문이 비동기적으로 작용한다면, 다음과 같은 방식으로 동작한다.
이 경우 손님 2는 손님 1이 아메리카노를 받을 때까지 주문을 기다릴 필요가 없다.
웹사이트 등은 대부분 클라이언트와 서버 간의 통신에 의해 작동한다.
이렇듯 클라이언트와 서버가 통신할 때 동기 방식을 사용할 때보다 비동기 방식을 사용할 때의 장점이 확연히 드러난다.

그림에서 확인할 수 있듯, 같은 시간 동안 클라이언트가 상대적으로 훨씬 더 많은 일을 처리할 수 있게 된다.
서버의 응답을 가만히 기다리는 시간 동안 다른 일을 처리할 수 있기 때문이다.
const printString = (string) => {
setTimeout (
() => {
console.log(string)
},
Math.floor(Math.random() * 100) + 1
)
}
const printAll = () => {
printString("A")
printString("B")
printString("C")
}
printAll()
위 코드는 랜덤한 시간 이후에 문자 'A', 'B', 'C'를 각각 출력하는 비동기 방식의 코드이다.
위 코드는 A, B, C의 순서가 랜덤으로 출력되며, 해당 순서를 조절할 수는 없다.
그렇다면 A, B, C의 출력 순서를 조절하려면 어떻게 해야 할까?
const printString = (string, callback) => {
setTimeout (
() => {
console.log(string)
callback()
},
Math.floor(Math.random() * 100) + 1
)
}
const printAll = () => {
printString("A", () => {
printString("B", () => {
printString("C", () => {})
})
})
}
printAll()
이는 callback 함수를 통해 해결할 수 있다.
callback 함수 인자로서 다음으로 출력할 함수를 전달하는 방식이다.
그러나 이는 동기로 실행할 함수가 많아질수록 계속 함수가 밀린다는 문제가 있다. (callback hell)
이를 해결하기 위해 Promise 방식을 이용한다.
const printString = (string) => {
return new Promise((resolve, reject) =>
setTimeout (
() => {
console.log(string)
callback()
},
Math.floor(Math.random() * 100) + 1
)
})
}
const printAll = () => {
printString("A")
.then(() => {
return printString("B")
})
.then(() => {
return printString("C")
})
}
printAll()
함수 선언 시 callback 함수를 받지 않고, return문에 Promise 함수를 사용한다.
그러면 함수의 실행 순서를 .then을 사용해 조절할 수 있다.
Promise - then은 js 내장 함수로, .then()으로 작업 성공 시의 task, .catch()으로 작업 실패 시의 task를 따로 지정해줄 수 있다.
자세한 내용은 #Promise.prototype.then 링크에서 확인할 수 있다.
function printA() {
return new Promise((resolve, reject) => {
setTimeout(() => { resolve('A')}, 100)
})
}
function printB() {
return new Promise((resolve, reject) => {
setTimeout(() => { resolve('B')}, 100)
})
}
function printC() {
return new Promise((resolve, reject) => {
setTimeout(() => { resolve('C')}, 100)
})
}
function printD() {
return new Promise((resolve, reject) => {
setTimeout(() => { resolve('D')}, 100)
})
}
const result = async () => {
const one = await printA();
console.log(one)
const two = await printA();
console.log(two)
const three = await printA();
console.log(three)
const four = await printA();
console.log(four)
}
result();
promise와 같은 구조, 표기만 조금 다른 것.
비동기함수를 동기함수인것처럼 실행한다.