Javascript의 비동기 처리
JS는 Single Thread 환경의 언어이다. 따라서 한번에 여러가지 작업을 수행하기 어려운데 이를 극복하기 위하여 비동기 처리라는 방식을 채택하였다.
JS의 비동기 처리는 코드의 실행 순서를 보장하지 않기 때문에 아래와 같은 3가지 방식을 이용하여 처리하는 것이 대표적인 처리 방식이다.
1. 콜백함수(Call-Back Function) -ES6이전
2. 프로미스(Promise) - ES6
3. async await - ES8
콜백함수
콜백함수는 말 그대로 함수 안에 함수를 넣어서 실행 순서를 보장시키는 방식이다.
setTimeout(()=>{
console.log("1초 뒤")
setTimeout(()=>{
console.log("2초 뒤")
},1000)
},1000)
setTimeout 안에 setTimeout을 넣어서 1초의 간격으로 로그가 찍히는 것을 볼 수 있다. 주로 제이쿼리의 ajax를 처음 배우는 경우 콜백지옥을 경험할 수 있다.
Promise
이러한 콜백지옥을 해결하기 위해서 Promise 문법이 나왔다.
Promise 문법은 함수를 짤 때 리턴값으로 Promise 객체를 던져주도록 하고 Promise 객체 안에는 성공했을 시 리턴하는 resolve, 에러가 났을 시 리턴하는 reject에 대한 코드를 짜준다. 이후, 해당 함수를 호출하여 프로미스 객체를 받고 거기에 .then() 혹은 .catch()로 프로미스 체인을 만들어 순서를 보장받으며 코드를 짤 수 있다. 주로 서버와의 통신(AJAX, axios 등)에서 사용되므로 프론트엔드 개발자라면 필히 숙지해야 할 문법이라고 할 수 있다.
Promise는 총 3가지의 상태 값을 가지는데
자세한 정보는 MDN 사이트를 참고하자
대략적인 설명 : https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise
Promise - JavaScript | MDN
Promise 객체는 비동기 작업이 맞이할 미래의 완료 또는 실패와 그 결과 값을 나타냅니다.
developer.mozilla.org
더욱 자세한 설명 : https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Using_promises
Using promises - JavaScript | MDN
Promise는 비동기 작업의 최종 완료 또는 실패를 나타내는 객체입니다. 대부분 여러분은 이미 만들어진 promise를 사용했었기 때문에 이 가이드에서는 어떻게 promise를 만드는지 설명하기에 앞서
developer.mozilla.org
위와같이 유용하게 사용되던 Promise에도 단점이 발생하였는데, 그것은 바로 Promise Chaining에서 에러가 났을 때 어떤 단계(순서)에서 에러가 났는지를 명확하게 알기 힘들다는 점이었다. 왜냐하면 Promise Chain은 에러가 발생 했을 때, 순서에 상관없이 하나의 catch로 귀결되기 때문이다.
async await
위와같은 Promise의 단점을 극복하기 위해 ES8에서 async-await 문법이 나왔다.
이 문법을 사용하면 각 단계별로 try-catch문을 활용하여 블럭 단위로 코드를 쪼갤 수 있기 때문에, 비동기 함수들을 동기적으로 활용하면서 동시에 예외처리도 명확하게 할 수 있기 때문이다.
async await의 기본적인 모양은 다음과 같다.
async function getAsyncAwait() {
let res1;
let res2;
let res3;
try {
res1 = await addPromse(10);
console.log(`first: ${res1}`); // first: 20
} catch(error) {
console.log(error);
}
try {
res2 = await addPromse(res1);
console.log(`second: ${res2}`); // second: 40
} catch(error) {
console.log(error)
}
try {
res3 = await addPromse(res2);
console.log(`third: ${res3}`); // third: 80
} catch(error) {
console.log(error);
}
}
getAsyncAwait();
await는 어떠한 함수를 실행하고 그 함수의 값을 변수에 저장할 때 사용할 수 있으며 무조건 async로 정의된 함수의 내부에 위치해 있어야 한다. (await만 별개로 사용 불가)
위에서 말했듯, await를 이용하여 비동기처리를 동기처리 형식으로 사용하기 위해서는 부모 함수 앞에 async라는 예약어를설정해 주어야 사용이 가능함을 잊지 말자!