본문으로 바로가기
반응형

웹 개발에서 비동기 작업은 매우 흔하다고 한다

 

비동기 작업?

특정 코드가 끝날때 까지 코드의 실행을 멈추지 않고 다음 코드를 먼저 실행하는 것을 의미한다

 

즉 병렬적으로 처리가 가능한 작업. 

 

콜백 함수??

 

  • 콜백이란 다른 함수(A)의 전달인자(argument)로 넘겨주는 함수(B)를 말한다.
  • 매개변수를 넘겨 받은 함수(A)는 callback 함수(B)를 필요에 따라 즉시 실행(synchronously) 할 수도 있고, 아니면 나중에 (asynchronously) 실행할 수도 있다.

이제 콜백 지옥을 봐보자

getData(function(data) {
	processData(data, function(processedData) {
		renderData(processedData, function() {
			console.log('Done!');
		});
	});
});

 

  1. getData함수를 호출하고, 익명 함수를 콜백으로 전달한다
  2. getData가 작업을 완료하면 첫 번째 콜백 함수를 호출하고, 결과 data를 전달한다
  3. 콜백 함수 내부에서 processData를 호출하고 다시 익명함수를 콜백으로 전달한다.
  4. processData가 작업을 완료하면 두 번 째 콜백 함수를 호출하고, 결과 processedData를 전달한다
  5. 콜백 함수 내부에서 renderData를 호출하고, 또 다시 익명 함수를 콜백으로 전달한다
  6. renderData가 작업을 완료하면 세 번째 콜백 함수를 호출하고, 이 함수는 console.log("Done!")을 실행한다

 

위와 같은 코드를 콜백 지옥이라고 부른다

가독성이 떨어지고 오류 처리가 복잡해 질 수 있다

 

// Promise 체인 사용
getData()
    .then(data => processData(data))
    .then(processedData => renderData(processedData))
    .then(() => console.log('Done!'))
    .catch(error => console.error('Error:', error));

// 또는 async/await 사용
async function handleData() {
    try {
        const data = await getData();
        const processedData = await processData(data);
        await renderData(processedData);
        console.log('Done!');
    } catch (error) {
        console.error('Error:', error);
    }
}

handleData();

 

위와 같이 Promise를 사용하거나 async / await을 사용하면 코드가 더 선형적이고 읽기 쉬워진다.

 

물론 여기서 Promise 체인을 사용하려면 각 함수가 Promise객체를 반환해야 한다.

 

Promise 객체란?
- JavaScript에서 비동기 작업의 최종 완료(또는 실패)와 그 결과값을 나타내는 객체이다. 쉽게 말해, Promise는 "약속"과 같은 개념으로, "나중에 완료될 작업의 결과를 약속" 한다
- 작업의 결과가 promise 객체에 저장됩니다. promise 객체를 보면 작업이 성공했는지, 실패했는지 알 수 있다.

 

async / await

async는 함수의 앞에 붙어서 해당 함수가 비동기 함수임을 나타낸다.

await는 비동기 함수의 실행 결과를 기다리는 키워드이다

 

마지막으로 좀 익명 함수와 콜백이 이해가 안되서 간단한 예제를 만들어 보았으니 보면서 이해해보자

// 간단한 콜백 로그 예제
getData(function (data) { 
    console.log('1. getData의 콜백 실행');
    processData(data, function (processedData) { 
        console.log('2. processData의 콜백 실행');
        console.log('   전달받은 데이터:', processedData);
        renderData(processedData, function () { 
            console.log('3. renderData의 콜백 실행');
            console.log('4. 모든 과정 완료: Done!'); 
        }); 
    }); 
});

function getData(callback) {
    console.log('getData 함수 시작');
    // 데이터 없이 바로 콜백 호출
    callback('초기 데이터');
}

function processData(data, callback) {
    console.log('processData 함수 시작');
    console.log('받은 데이터:', data);
    // 데이터 처리 후 바로 콜백 호출
    callback('처리된 데이터');
}

function renderData(processedData, callback) {
    console.log('renderData 함수 시작');
    console.log('렌더링할 데이터:', processedData);
    // 렌더링 후 바로 콜백 호출
    callback();
}

 

출력 결과

getData 함수 시작
1. getData의 콜백 실행
processData 함수 시작
받은 데이터: 초기 데이터
2. processData의 콜백 실행
   전달받은 데이터: 처리된 데이터
renderData 함수 시작
렌더링할 데이터: 처리된 데이터
3. renderData의 콜백 실행
4. 모든 과정 완료: Done!

반응형