본문 바로가기
프로그래밍/HTML & CSS & JavaScript

[JavaScript] 콜백 함수, Promise, async & await

by 일상 속 둔치 2020. 7. 23.

JavaScript는 싱글 스레드로 작동한다.

 

그래서 자바스크립트는 한번에 하나의 작업밖에 수행하지 못한다.

 

- 끝 -

 

 

 

이 아니라 동시성 프로그래밍을 위해 비동기처리를 한다.

 

사실 비동기처리를 해도 싱글스레드인데 네트워크 통신을 하면서 UI 작업을 하는 등 동시성을 보일 수 있는지 궁금 할 것이다.

 

해당 내용을 다루기 위해서는 JavaScript 엔진과 Web API, Task Queue, Event Loop 등을 다루어야 하는데 나중에 다른 게시글로 다루겠다. (궁금한 분은 구글링)

 

* 동기 프로그래밍?

console.log('1');

setTimeout(()=>{
	console.log('2');
},3000);

console.log('3');

Javascript가 아닌 Java나 C, Python 등의 프로그래밍 언어들만 접해보신 분들은 당연히 1,2,3이 순서대로 출력될 것으로 예상한다.

 

그러나 아쉽게도(?) JavaScript는 비동기 처리를 하기 때문에 1이 출력되고 setTimeout으로 3초간 기다리는 것을 뒤로한채 3이 먼저 출력되고 그 후 2가 출력된다.

 

위 예시는 JavaScript의 비동기를 설명하는 가장 대표적인 예시이다.

 

무튼 비동기가 장점으로 작용할 때도 있지만 사실 비동기로 작동해서 머리가 아픈게 이만저만이 아니다.

 

특히, 저자는 비동기가 익숙하지 않아서 머리가 아주 아팠ㄷ,,,(결과 값을 받고 넘어 가라고,,ㅜㅜ)

 

JavaScript는 비동기로 작동하지만 동기처리가 필요할 때가 있다!

 

우리는 그때 사용할 수 있는 방법이 3가지가 있다.

 

콜백함수, Promise, async & await

 

다 동일한 파워를 가지고 있다!

 

 

1. 콜백함수

var func1 = function(param, callback){ console.log(param); callback(param+1); }
var func2 = function(param, callback){ console.log(param); callback(param+2); }
var func3 = function(param, callback){ console.log(param); callback(param+3); }

var start = 1;
func1(start, result => { // 1을 받고 1+1인 2를 오른쪽 result로 전달
	func2(result, result => { //2를 받고 2+2인 4를 오른쪽 result로 전달
		func3(resul, result =>{ //4를 받고 4+3인 7을 오른쪽 result로 전달
			console.log(result); // 7출력
		)};
	)};
)};

// 결과는 1,2,4,7이 출력 될 것이다.

함수의 매개변수로 함수를 전달하여 호출하는 방식이다.

 

지금 3개만 콜백했는데도 인덴테이션이 흠쓰,,,

 

콜백함수가 늘어나면 안으로 계속 들어가고,, 코드를 읽기 힘들어진다.

 

이런 걸보고 콜백 지옥이라고 부르는데 관련해서 콜백아래와 같은 짤이 돌아다닌다

 

무튼, 콜백 함수가 많아질 수록 코드 가독성이 매우 매우 떨어진다.

 

우리는 JavaScript를 쓰면 안된다

 

-끝-

 

 

 

이 아니라 이를 해소해주는 Promise와 async & await을 알아보자

 

2. Promise

function func1(param){
	return new Promise(function(resolve, reject){
    	console.log(param);
    	resolve(param+1);
    }
}

function func2(param){
	return new Promise(function(resolve, reject){
    	console.log(param);
    	resolve(param+2);
    }
}

function func3(param){
	return new Promise(function(resolve, reject){
    	console.log(param);
    	resolve(param+3);
    }
}

var start = 1;

func1(start).then(func2).then(func3).then(result =>{console.log(result);})

위의 콜백 함수와 동일한 기능을 한다. ES6에서 처음 도입되었다. Promise는 뜻과 비슷하게 약속하는 것이다.

 

Promise 객체는 약속한(Promise) 비동기 처리가 끝나면(then) then을 실행시킨다!

 

resolve 함수는 처리가 성공적으로 끝났음을 알리고 reject는 처리가 실패했을 때 함수 호출을 하여 사용할 수 있다.

 

Promise가 resolve함수를 만나면 then으로 넘어가서 그 다음을 처리하게 된다.

 

이때, resolve에 매개변수를 넘겨주어 그 다음 함수에서 또 사용할 수 있다.

 

 

3. async & await

async function example(start){ // 1
	const first = await func1(start); // 2
	const second = await func2(first); // 4
	const third = await func3(second); // 7
    
	console.log(third); // 7
}

ES8부터 지원한 문법이다. Promise와 동일한 효과를 지니고 있다!

 

간단히 말해서 async가 붙은 함수 내에서 await이 붙은 함수가 종료될 때까지 async함수는 실행을 일시 중지한다.

 

즉, 좀 더 명확하게 동기처리가 가능하다!

 

주의해야할 점은 await으로 기다리는 함수는 모두 promise여야한다.

 

async 함수도 promise를 반환해야한다.

 

await은 async 함수 내에서만 사용이 가능하다.

 

사실 처음 사용하다보면 헷갈리고 익숙하지 않을 수 있다.

 

그래도,, 열심히 해보자..!

 

promise와 async & await은 취향 차이라고 하나 그래도 최신 문법이 더 좋으려나 고민 고민

 

 

- 끝 -

댓글