[JavaScript] 동기 / 비동기 처리

[JavaScript] 동기 / 비동기 처리

JavaScript의 동기 처리 방식과 비동기 처리 방식에 대해 살펴봅니다.


자바스크립트는 싱글 스레드 언어이지만 기본적으로 함수에 delay가 존재할 경우 진행을 멈추고 callback queue로 보낸 뒤 바로 다음 코드를 실행합니다. 이처럼 특정 코드의 연산이 끝날 때 까지 코드의 실행을 멈추지 않고 다음 코드를 실행하는 것을 비동기 처리라고 합니다.
만약 서버로 데이터를 요청하는 코드를 작성했을 때 서버로부터의 응답이 늦게될 경우 이는 큰 성능저하를 야기할 수 있습니다. 따라서 실행중이던 코드를 멈추고 다른 코드를 실행할 수 있는 비동기 처리의 사용은 필수적입니다.
하지만 항상 비동기 처리만을 사용하는 것은 아닙니다. 함수에 delay가 존재하더라도 바로 넘어가는 것이 아닌 대기 후 넘어가기를 원하는 경우는 분명 존재합니다. 이렇게 함수가 종료할 때 까지 기다린 후 다음 코드로 넘어가는 것을 동기 처리라고 합니다.
기본적으로 비동기 처리를 수행하기 때문에 어떻게 동기 처리로 코드를 작성하는지 살펴보겠습니다.



1. setTimeout()



1

먼저 setTimeout()입니다. 이 메소드는 파라미터로 함수와 기다릴 시간을 입력받습니다.
위 그림을 살펴보면 goMart(), pickDrink(), pay() 순으로 함수가 실행됩니다. 자바스크립트는 기본적으로 비동기 처리를 수행하기 때문에 pickDrink()를 기다리는 동안 코드가 멈추는 것이 아닌 pay(product, price)를 실행한 뒤 딜레이가 끝나고 product, price에 값을 할당하기 때문에 undefined가 출력되는 것을 확인할 수 있습니다.

2. callback function



2

비동기식으로 처리되는 것이 아닌 동기식으로 처리하고자 할 때 callback function을 사용할 수 있습니다. 위의 코드는 1번을 콜백형식으로 작성해 동기식으로 처리하는 코드입니다.
callback function을 사용하는 방법은 함수의 맨 마지막 매개변수로 함수를 받는 것입니다. 위의 코드를 살펴보면 pickDrink() 함수에 callback이라는 매개변수를 작성하였고 이는 내부에서 함수로 동작하도록 사용되었습니다. goMart()가 실행된 뒤 pay()는 pickDrink()의 매개변수로 사용되었고 값을 전부 할당한 뒤 pay()가 setTimeout() 내부에서 실행되는 것을 확인할 수 있습니다.
이 때 매개변수로 함수를 넘길 때 괄호를 작성지 않고 함수명만 작성하는 점을 유의해야 합니다.

3. callback function의 단점



3

callback function을 여러번 사용할 경우 위의 그림과 같이 코드의 가독성이 크게 떨어지는 단점이 있습니다.
이런 단점을 극복하기 위해 Promise 객체가 등장하였습니다.

4. Promise



4

Promise란 비동기 함수를 동기 처리하기 위해 만들어진 객체입니다. Promise는 함수에 대해 성공과 실패를 반환합니다. 비동기 작업이 완료된 후 다음 작업을 연결해 동기 처리할 수 있습니다.
위 그림은 3번을 Promise를 사용해 작성한 코드입니다. changeColor()는 color를 매개변수로 받고 Promise 객체를 생성합니다. 그 후 배경을 color로 변경한 뒤 정상적으로 모두 실행이 되었다면 resolve()를 실행하고 color를 반환합니다. 만약 에러가 발생할 경우 reject() 내부의 값을 반환합니다.
changColor(‘red’)가 반환한 red는 resultRed에 담겼습니다. 하지만 이 함수는 새로운 색을 매개변수로 사용해야 하기 때문에 리턴값을 담은 result___는 의미가 없지만 단순히 표현을 위해 작성하였습니다.

5. async / await



5

이러한 Promise 객체를 좀 더 이해하기 쉽고 편하게 작성하기 위해 async / await가 등장했습니다.
위의 코드는 1번과 2번을 async / await를 통해 작성한 코드입니다.
pickDrink()는 Promise 객체를 사용해 동일하게 작성합니다. 다른 점은 코드를 실행하는 excute()가 작성되었고 이 함수의 선언부 앞에 async가 작성되었습니다. excute()는 goMart(), pickDrink(), pay()를 순서대로 실행합니다.
이때 pickDrink() 앞에 await가 작성되었는데 이는 pickDrink()의 Promise가 전부 처리될 때 까지 대기한다는 뜻입니다. pickDrink()가 모두 끝나고 money값에 따라 resolve()와 reject()가 실행됩니다. money가 충분한 경우 flag를 1로 바꾼 뒤 함수를 종료하고, 부족한 경우 reject()에 값을 담아 반환한 뒤 해당 값을 log로 출력합니다. 만약 flag가 1일 경우에만 pay()가 실행됩니다.


© 2022. All rights reserved.