CS/기타

자바스크립트(Javascript) 비동기의 역사

여행 가고싶다 2023. 4. 6. 16:55

자바스크립트에서 비동기를 처리할 때 다음 3가지를 사용하면 된다.

 

Callback, Promise, Async/Await

하지만 이것들은 언제 어떻게 쓰이는지, 어떤 차이가 있는지, 그렇다면 어떤 걸 써야 하는지 헷갈릴 수 있기 때문에 정리를 하려 한다.

 

 

Callback

function add(a, callback){
	setTimeout(()=> callback(a + 10), 100);
}

add(5, res => {
	add(res, res =>{
		add(res, res =>{
			console.log(res)
		})
	})
}); // 35

console.log(a) // undefined

이 콜백 예제에서 함수 add의 리턴 값이 얼마인지를 보는 것은 중요하지 않다.

setTimeout이 일어나는 코드적 상황이 끝나고 콜백 호출부를 평가해 보면 함수를 실행한 context만 남아있다.

콜백은 실행하고 나면 더 이상 어떠한 일도 할 수 없다. 넘겨진 context의 함수를 통해서만 무언가를 이어나갈 수 있다.

따라서 그 함수 안에서 모든 것을 처리해야 해서 콜백지옥이 탄생하게 된다..

 

Callback Hell(콜백지옥)?

콜백지옥은 아래와 같이 비동기로 처리한 함수를 비동기로 처리하고.. 반복하다 보면 콜백지옥이 생겨버린다.

step1(function (value1) {
    step2(function (value2) {
        step3(function (value3) {
            step4(function (value4) {
                step5(function (value5) {
                    step6(function (value6) {
                        // Do something with value6
                    });
                });
            });
        });
    });
});

이 콜백지옥을 해결하기 위해서 Promise가 탄생했다

 

Promise

Promise는 두 가지의 콜백함수를 받는다.

  • 성공 시 받는 호출되는 resolve
  • 실패 시 받는 호출되는 reject

그리고 반환되는 두 가지의 콜백함수를 처리하는 then으로 이루어져 있는데, 이를 통해 콜백지옥을 해결할 수 있다.

 

Promise를 통해 위의 콜백지옥을 해결해 보자.

step1()
    .then(function (value1) {
        return step2();
    })
    .then(function (value2) {
        return step3();
    })
    .then(function (value3) {
        return step4();
    })
    .then(function (value4) {
        return step5();
    })
    .then(function (value5) {
        return step6();
    })
    .then(function (value6) {
        // Do something with value6
    })
    .catch(function (error) {
        // Handle errors
    });

이런 식으로 콜백함수를 해결할 수 있다.

 

하지만 이렇게 프로미스 체인이 길어지면 여전히 가독성은 떨어진다. 또한 에러처리를 위한 코드가 복잡해질 수 도있기 때문에 Async/Await이 탄생했다.

 

Async/Await

Async/Await는 비동기 처리 코드를 동기식으로 작성할 수 있어 가독성이 향상된다. 또한 에러 처리도 try-catch문으로 간단하게 처리가 가능하다.

 

그렇다면 위의 Promise 코드의 가독성을 올리기 위해 Async/Await로 처리하면 다음과 같다.

async function doSomething() {
    try {
        const value1 = await step1();
        const value2 = await step2();
        const value3 = await step3();
        const value4 = await step4();
        const value5 = await step5();
        const value6 = await step6();
        // Do something with value6
    } catch (error) {
        // Handle errors
    }
}

 

처음 콜백함수 보다 훨씬 더 읽기 좋고 코드도 간결하다.