Code&Data Insights

[JavaScript] 비동기 프로그래밍 - Callback 함수, Async/Await, Promise 본문

Web Development/Front-end

[JavaScript] 비동기 프로그래밍 - Callback 함수, Async/Await, Promise

paka_corn 2024. 4. 29. 11:09

동기(Synchronous) vs 비동기(Asynchronous)

동기(Synchronous) 프로그래밍
- 코드가 작성된 순서대로 차례대로 실행
- 각 작업이 완료될 때까지 다음 작업이 시작되지 않음

 

비동기(Asynchronous) 프로그래밍
- 코드가 작성된 순서와 상관없이 실행
- 한 작업이 완료될 때까지 기다리지 않고 다른 작업을 동시에 수행할 수 있음

 

비동기를 사용하는 주요 이유?

=> 멀티태스킹을 구현하여 시스템 자원을 효율적으로 사용하기 위해서! 

=> 여러 스레드나 프로세스가 동시에 실행됨 

 

 

 

비동기 프로그래밍의 발전 순서 

1) Callback 함수

:  함수를 등록하고, 어떤 이벤트가 발생하거나 특정 시점에 도달했을 때 시스템에서 호출해서 실행하는 함수 

- 초기 비동기 프로그래밍에서는 콜백 함수를 사용하여 비동기 작업을 처리
=> 특정 작업이 완료되면 콜백 함수를 호출하여 다음 작업을 수행함. 

 

(ex) 이벤트 핸들러 -> 특정이벤트가 발생했을 때

<input type ="button" onClick="function(){...} />

 

** 그러나 콜백 함수가 중첩되면서 '콜백 지옥(Callback Hell)'이 발생하여 코드가 복잡해지고 가독성 & 유지보수성이 떨어지는 문제가 발생!! 

// 중첩된 콜백 (콜백 지옥)
firstTask(() => {
    secondTask(() => {
        thirdTask(() => {
            fourthTask(() => {
                console.log('모든 작업 완료');
            });
        });
    });
});

 

2) Promise 객체

: Promise는 콜백 지옥 문제를 해결하기 위해 등장


- Promise는 비동기 작업이 성공하면 값을 반환하고, 실패하면 에러를 반환

- then 메서드를 사용하여 비동기 작업의 성공과 실패에 대한 콜백 함수를 정의할 수 있음


** 그러나 .then 체인이 길어지면 여전히 코드가 복잡해질 수 있음! 

// Promise 예시
function firstTask() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('Data received');
        }, 1000);
    });
}

// 길어진 then 체인
firstTask()
    .then(result => {
        return secondTask(result);
    })
    .then(result => {
        return thirdTask(result);
    })
    .then(result => {
        return fourthTask(result);
    })
    .then(result => {
        console.log('모든 작업 완료:', result);
    })
    .catch(error => {
        console.error('에러 발생:', error);
    });

 

++ Promise.all

: 여러 비동기 작업을 병렬로 처리하고, 모든 작업이 완료될 때까지 기다렸다가 결과를 반환하는 기능을 제공

-> 하나의 Promise를 반환, 전달된 모든 Promise가 해결될 때까지 대기

-> 만약 하나의 Promise라도 실패하면, Promise.all은 즉시 거부되고 에러를 반환

 

 

3) Async/Await

: async와 await 키워드는 Promise의 복잡성을 줄이고 가독성을 높이기 위해 도입,  

=> 비동기 코드를 동기 코드처럼 작성할 수 있어 가독성이 크게 향상


- async 키워드는 비동기 함수를 정의하고, 해당 함수는 항상 Promise를 반환!! 
- await 키워드는 Promise가 해결될 때까지 함수 실행을 일시 중단하고, 해결된 값을 반환

// Async, Await 예시
async function fetchData() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('Data received');
        }, 1000);
    });
}

// async/await를 사용하여 개선한 예시 
async function executeTasks() {
    try {
        const firstResult = await firstTask();
        const secondResult = await secondTask(firstResult);
        const thirdResult = await thirdTask(secondResult);
        const fourthResult = await fourthTask(thirdResult);
        console.log('모든 작업 완료:', fourthResult);
    } catch (error) {
        console.error('에러 발생:', error);
    }
}

 

 

 

Reference 

https://buildfire.com/synchronous-vs-asynchronous-programming/

Comments