Node.js를 공부하다가 동기와 비동기에대한 개념을 한번 정리해보았다. Node.js는 비동기방식의 대표적인 플랫폼으로 비동기에 대한 특성과 예제를 적어보고 싶었다.
동기 방식이란?
동기식 처리 모델(Synchronous Processing Model)은 직렬적으로 일을 처리한다.
즉, 요청이 들어오면 순차적으로 작업을 수행하고, 해당 작업이 수행중이면 다음 작업은 대기하게 된다.
서버는 한번에 많은 요청이 들어오고 동시에 많은 요청을 처리해야하기 때문에 이러한 방식과는 맞지 않는다. 만약 서버가 동기식으로 되어있다면, 수만명이 서버에 한번에 요청을 보냈을때, 가장 마지막에 요청을 보낸 사람은 앞에 9999명의 요청이 모두 처리될때까지 기다려야하는 눈뜨고는 보지 못하는 일이 발생할 수 있다.
비동기 방식이란?
비동기식 처리 모델(Asynchronous Processing Model or Non-Blocking Processing Model)은 병렬적으로 일을 처리한다.
즉, 요청이 들어오면 해당 요청에 의한 작업이 끝나지 않았더라도 계속 요청을 받는다. 그리고 작업이 끝났다는 이벤트가 오면 해당 요청을 처리한다.
이처럼 비동기 방식은 네트워크 관리에 최적화된 모델이다. Node.js도 이벤트 기반, Non-Blocking I/O모델을 사용하고 있다. 비동기 처리 모델을 활용해서 요청 처리와 응답 속도를 환상적으로 올려주고 있는 것이다.
위의 내용들을 코드를 활용해서 알아보자.
아래 코드는 JavaScript로 작성되었다. JS코드는 아래 사이트에서 간단하게 구현하고 결과를 출력해 볼 수 있다.
•
동기식 (Syncronous)
동기식은 위에서 설명했듯이 순차적으로 일을 처리한다. 특정 작업이 수행중이라면 다음작업을 받지 않고 해당 작업이 끝날때까지 기다린다.
위의 코드를 토대로 설명하자면,
func1이 실행되는동안은 다른 작업들을 수행하지 못하도록 block해둔다. 그래서 func2와 func3은 func1이 끝날때까지 대기를 하게 된다. 이제 Console에 1을 출력하는 func1이 끝나고 나면 다음 업무에 대한 입력을 받게된다. 이렇게 func2, func3에 대한 처리를 끝낸 후 위의 코드가 끝나게 된다.
•
비동기식 (Asyncronous)
비동기식은 동기식과 다르게 들어오는 모든 일을 우선 받아두고 끝났다는 이벤트가 전달되면 해당 이벤트를 처리한다.
위의 코드를 살펴보면 setTimeout이라는 함수가 있다. 이 함수는 비동기 함수이다. 따라서 func1을 거쳐 func2를 만나면 이 함수는 비동기 함수이므로 바로 다음 함수를 처리하기위해 받게 된다. 따라서 func3함수를 실행하고 func2함수의 종료 이벤트가 도착하면 해당 함수를 처리한다.
모든 함수들이 비동기 함수이면 어떻게 될까. 아래 영상을 보자.
func1 함수는 1000ms, func2함수는 500ms, func3함수는 1500ms의 대기 시간을 설정해두고 실행해 보았다. 일단 출력으로 보이는 내용은 역시나 대기가 끝나는 순서대로 숫자를 출력해주게 된다. 내부적으로는 어떤식으로 작동할까.
func2가 call stack에 쌓이고 setTimeout함수가 호출되면 setTimeout의 callback함수는 즉시 실행되는것이 아니라 대기시간만큼 기다리다가 "tick"이벤트가 발생하면 이벤트큐로 이동한 후 Call Stack이 비어졌을 때, Call Stack으로 이동되어 실행된다. 자세한 내용은 아래의 링크를 보면 이해가 쉬울 것이다.
비동기 키워드들
Callback
Promise
Promise.all
async / await
< 추가로 참고한 출처 >
동기, 비동기 방식 설명 및 이미지