블로킹 이라는 말을 처음 들었을때, 대충 추상적으로
아 다른 함수가 실행중일때 다른 함수를 실행못하게 막는건가...??
라고 막연하게 생각했었는데 이번에 동기님들의 스터디 발표와
여러 참고자료를 보고 정리를 해보려고한다.
동기(Synchronous) 와 비동기(Asynchronous) 의 차이부터 알아보자.
먼저, 동기와 비동기의 실행방법과 나눠진 이유를 알아보려면
스레드(Thread)라는 것을 알아야한다.
자바스크립트는 싱글 스레드(Single Thread) 언어라고 불린다.
스레드 - 프로세스 내에서 실행되는 흐름의 최소 단위
즉, 쉽게말해 프로세스 내에서 실제 작업을 하고있는 주체라고 생각하면 된다.
그리고, 스레드는 자신만의 프로그램 카운터와 시스템 레지스터, 스택을 가진다.
따라서, 자바스크립트 엔진은 하나의 스레드를 사용하는 싱글스레드 방식이다.
즉, 하나의 레지스터, 카운터, 스택을 가지며 한번에 하나의 작업만 수행
어떤 함수를 호출하면 함수에 전달되는 인자, 함수 내에서 사용하는 변수, 그리고 함수의 실행이 종료되고
되돌아갈 주소 값 등을 실행 컨텍스트라는 객체를 생성한 후 콜스택에 push함.
스택에 push되면 바로 함수가 실행되며, 실행이 종료되면 실행 컨텍스트에서 다시 pop되어 제거.
❓ 그럼 동기 와 비동기는 뭐고 뭐가 어떻게다른데??
동기 / 비동기는 다음 작업이 요청되는 시간과 관련이 있다.
동기(Synchronous)
- 순차적 / 직렬적으로 태스크를 수행
- 함수를 호출하는 곳에서 호출되는 함수가 결과를 반환할 때까지 대기
- 현재 작업의 응답이 끝남과 동시에 다음 작업을 요청
- 작업 완료 여부를 계속 확인
비동기(Asynchronous)
- 병렬적으로 태스크를 수행
- 함수를 호출하는 곳에서 결과를 기다리지 않고, 다른 함수(callback)에서 결과 처리
- 현재 작업의 진행이 끝나지 않은 상태에서 다음 작업이 요청됨.
- 작업 완료 여부를 확인하지 않음
동기방식 - 현재 작업의 응답과 다음 작업의 요청이 동시에 발생하는 것
즉, 현재 작업의 응답이 발생함과 동시에 다음 작업을 요청한다는 것은
작업이 어떠한 순서를 가지고 진행된다는 것을 의미
동기 방식 + 블로킹 방식
우리가 가장 흔하게 접하게 되는 동기 방식의 예가 동기 & 블로킹 방식이다.
동기 방식이기 때문에 작업의 흐름도 순차적으로 진행이 되고,
블로킹 방식이기 때문에 어떠한 작업이 진행 중일때는
다른 작업을 동시에 진행할 수 없다.
위의 코드를 보면 자연스럽게 작업들이 순서를 가지고 진행될 것인걸 알 수 있다.
내부적으로 하나의 콜 스택에 작업을 넣고 LIFO(Last In First Out)으로 진행되기 때문
동기 방식 + 논블로킹 방식
아직 제너레이터에 대한 공부는 안했지만 여기저기 찾아보고 정리를 해본다.
결국 동기 라는 것은 작업들이 순차적인 흐름을 가지고 있다는 것을 의미.
이 전제만 지켜지면 어떻게 뭘 하던간에 동기방식 이라는 것은 변하지 않음.
제너레이터를 이용하여 작업의 순서를 지키면서, 상위 프로세스가 다른작업을 하도록 해보자.
위의 예제를 보면, 상위 프로세스인 boss 함수는 출근하고, 하위 프로세스인 employee 함수를 호출,
사탕 포장하기 작업을 시키고 주기적으로 작업을 끝냈는지 확인함.
그리고 아직 끝나지 않았으면 사장도 열심히 축구 하이라이트 시청을 수행하고 있는 것이다.
분명 동기적인 흐름이지만, boss함수 또한 자신의 작업을 수행하고 있으므로
논블로킹 방식인 것이다.
비동기 방식 - 말 그대로 동기 방식이 아니라는 의미
즉, 현재 작업의 응답과 다음 작업의 요청의 타이밍이 일치하지 않아도 되는 것
동기 방식은 상위 프로세스가 하위 프로세스에게 작업을 지시할 때 작업의 종료 시점을 알야아함.
작업의 종료 시점은 항상 작업을 시킨 상위 프로세스가 신경쓰고 있다는 것이다.
하지만, 비동기 방식은 상위 프로세스가 작업을 지시하면, 그 다음부터는 신경을 쓰지않음. (좋은 사장님...)
따라서 작업의 종료가 순차적으로 이루어지는것은 아무도 보장하지 못함.
비동기 방식 + 논블로킹 방식
비동기 방식과 논블로킹 방식은 우리에게 엄청나게 익숙한 방식.
비동기 방식이기 때문에 상위 프로세스는 하위 프로세스의 작업 완료 여부를 신경쓰지않음.
하위 프로세스의 작업이 종료되면 스스로 상위 프로세스에게 보고를 하든 다른 프로세스에게 일을 맡기든 한다.
또한, 논블로킹 방식이므로 상위 프로세스는 하위 프로세스에게 일을 맡기고
자신의 작업을 계속 수행을 함.
위의 예제를 보면, boss함수는 employee 함수에게 사탕 100개 포장을 지시하고,
자신은 바로 퇴근을 해버렸다.
상위 프로세스인 boss함수는 employee함수의 작업이 언제 끝나는지 관심없고,
작업의 완료 신호는 콜백으로 넘겨진 사탕포장 결과 보고 작업이 대신 받아서 처리
비동기 & 논블로킹 방식은 여러개의 작업을 동시에 처리할 수 있는 부분에서 효율적,
하지만 너무 복잡하게 얽힌 비동기 처리 때문에 흐름을 읽기 어려워지는 문제.
Promise 나 async/await 와 같은 문법을 사용하는 이유도
이러한 비동기 처리의 흐름을 좀더 명확하게 인지하고자 하는 노력이다.
비동기 방식 + 블로킹 방식
이는 매우 접하긴 힘든 개념이다.
위의 예제로 예를 들면 사장과 직원은 퇴근을 그만시키고 설명을 계속 진행할 것이다.
이는 매우 비효율적이라고 생각될 것이다.
비동기 방식의 장점은 하위 프로세스의 작업이 끝나는 것을 기다리지 않고
여러개의 작업을 동시에 처리할 수 있는 것인데
블로킹이 되어버려 아무 것도 처리할 수 없게 된다.
그래서 비동기 방식 + 블로킹 방식은 되도록이면 쓰지말자!!!
건너건너 알고 대충 추상적으로만 알던 동기, 비동기
그리고 블로킹과 논블로킹에 대해 좀 더 자세히 들여보게 된 계기가 되었고,
어느정도 해석을 할 수 있겠다?? 하는 생각이 든다.
정리를 사진으로 해보자면!!
참고