Dev/SW Engineering

13. Asynchronous & Promise - Asynchronous JS & Callback

HJChung 2020. 7. 21. 12:45

+ Asynchronous JS & Callback 에 대해 공부한 것을 정리한 것입니다. 배우는 중이라 잘못된  내용이 있을 수 있으며 계속해서 보완해 나갈 것입니다. :)) 

1. Asynchronous(비동기) Javascript

1) Asynchronous(비동기)란 무언인가

joshua1988.github.io/web-development/javascript/javascript-asynchronous-operation/ 이 글에서 <비유로 이해하는 콜백 함수 동작 방식> 에서 너무 설명을 잘 해주셨다. 

식당을 예약한다고 할때,

① 동기적 방식으로 한다면

이런 식으로 진행된다. 원하는 동작(여기선 자리에 앉는다.에 해당)을 하기 위해서 손님은 '근처 가게에서 잠깐 쇼핑을 하지도, 다른 식당을 알아보지도 못하고' 예약한 식당에서 한없이 기다리기만 해야한다. 

서버와의 통신이 동기적 방식으로 된다고 생각해보면

유튜브 영상의 재생을 누르고   영상의 리소스를 받아오는 로딩이 될 동안  우리는 브라우저에서 아무 클릭 등 활동을 하지 못하고 로딩이 완료되기만을 기다려야 할 것이다. 

 

 

 

 

② 비동기적 방식으로 한다면

대기자 명단에 이름을 쓰고, 자리가 나면 '자리에 앉으세요'라는 전화를 주는 식당이라고 생각해보자.

그러면 

이렇게 손님들은 자리가 날 때까지 식당에서 기다리기만 해야하는게 아니라 다른 일을 하고있다가 원하는게 준비된 시점(여기선 자리가 난다 에 해당) 에 원하는 동작(여기선 자리에 앉는다.에 해당)을 할 수 있다. 

서버와의 통신이 비동기적 방식으로 된다고 생각해보면

유튜브 영상의 재생을 누르고  영상의 리소스를 받아오는 로딩이 될 동안 우리는 브라우저에서 여러 컴포넌트를 여전히 조작할 수 있다. 

 

 

 

 

 

 

2) node.js와 Asynchronous(비동기)

이후 배우게 될 node.js는 "비동기 이벤트 주도 JavaScript 런타임으로써 Node.js 는 확장성 있는 네트워크 애플리케이션을 만들 수 있도록 설계되었습니다. 다음 "hello world" 예제는 다수의 연결을 동시에 처리할 수 있습니다. 각 연결에서 콜백이 실행되는데 실행할 작업이 없다면 Node.js 는 대기합니다." 라고 공식홈페이지의 소개에 나와있다. 

즉,  비동기는 node.js의 핵심 부분으로 아래 그림의 Asynchronous(비동기) 방식처럼 작동한다. 

 출처: codestates

2. Callback

1) callback의 활용

비동기처리 방식의 '원하는게 준비된 시점'은 어떻게 알 수 있을까? 예상할 수 없다면 순서를 제어하고 싶은 경우엔 어떻게 구현 할 수 있을까?

Callback을 사용하면 된다!

 

※ Callback은 비동기일때만 사용하는 것인가? 아니다. Synchrounous callback, Asynchronous callback 모두 가능하다. 

이에 대해서는 더보기 클릭!

더보기

1) Synchronous callback의 작동 예시

console.log('1'); //1st 출력 (동기)
setTimeout(() => console.log('2'), 1000); //브라우저에게 요청(비동기) // 4th 1초 후 마지막 출력
console.log('3'); //2nd 출력 (동기)

//Synchronous callback
function printImmediately(print) {
	print();
}
printImmediately(() => console.log('hello')); //printImmediately에서 console.log('hello') 함수를 바로 호출하니까(동기) 3rd 출력

//실행결과
// 1
// 3
// hello
// 2

2) ASynchronous callback의 작동 예시

console.log('1'); //1st 출력 (동기)
setTimeout(() => console.log('2'), 1000); //브라우저에게 요청(비동기) // 1초 후 3th 출력
console.log('3'); //2nd 출력 (동기)

//Asynchronous callback
function printWithDelay(print, timeout){
	setTimeout(print, timeout)
}

printWithDelay(()=> console.log('async callback hello'), 2000);  //브라우저에게 요청(비동기) //2초 후 4th 마지막 출력

//실행결과
// 1
// 3
// 2
// async callback hello

 

마치 '비동기 처리 중인 것이 얼마나 걸릴진 모르겠지만, 그거 다 하면 내가 명시한 callback 함수 실행시켜줘' 라고 하는 것 같다.

const printString = (string, callback) => {
	setTimeout(
    	() => {
        	console.log(string)
            callback()
         },
         Math.floor(Math.random() * 100) + 1
       )
    }
    
    const printAll = () => {
    	printString("A", () => { //1번째 콜백
        	printString("B", () => { //2번째 콜백
            	       printString("C", () => {}) //3번째 콜백
            })
        })
     }
     
     printAll()
     
     //실행 결과: A B C
     
     //코드 출처: codestates   
                

2) callback을 이용한 error handling

const somethingGonnaHappen = callback => {
	waitinngUntilSomethingHappens()
    if(isSomethingGood){
    	callback(null, something)
    }
    if(isSomethingBad){
    	callback(something, null)
    }

}

//Usage
somethingGonnaHappen((err, data) => {
	if(err){
    	console.log('ERROR!');
        return;
     }
     return data;
}

//코드 출처: codestates

3) Callback지옥

  const printAll = () => {
    	printString("A", () => { //1번째 콜백
        	printString("B", () => { //2번째 콜백
            	       printString("C", () => {}) //3번째 콜백
            })
        })
     }

이 콜백을 호출하는 코드에서도 알 수 있듯이 계속해서 callback이 중첩되는 경우가 발생할 수 있고 가독성도 매우 떨어진다. 

이렇게 비동기 처리 로직을 위해 콜백함수를 연속해서 사용할 때 발생하는 문제를 '콜백 지옥(Callback hell)' 이라고 한다. 

콜백 지옥을 해결하기 위해서는 Promise & Async/Await 방식을 사용할 수 있다. 

 

이에 대해서 다음 포스트에서  Promise & Async/Await에 대해서 배운 것을 정리해 볼 것이다. 

 

 

Reference

www.youtube.com/watch?v=s1vpVCrT8f4&t=11s

joshua1988.github.io/web-development/javascript/javascript-asynchronous-operation/

+ Asynchronous JS & Callback 에 대해 공부한 것을 정리한 것입니다. 배우는 중이라 잘못된  내용이 있을 수 있으며 계속해서 보완해 나갈 것입니다. :))