비동기 이벤트 주도 기반의 JavaScript 런타임
JavaScript
를 서버에서도 사용할 수 있도록 만든 프로그램JavaScript
엔진 위에서 동작하는 자바스크립트 런타임(환경)이다.Node.js
는 이벤트 리스너에 등록해둔 콜백함수를 실행하는 방식으로 동작router.get('/', (req,res,next) => {
// router.get 이벤트에 대한 콜백함수 로직
}
* 흔히 사용하고 있는 router도 이벤트 기반으로 동작
Node.js
가 비동기 작업을 관리하기 위한 구현체이다.JavaScript
의 런타임은 대표적으로 웹 브라우저가 있다. Node.js
라는 새로운 자바스크립트 런타임의 등장으로 브라우저가 아닌 곳에서도 실행될 수 있게 되었다.Node.js
는 C++
로 작성된 런타임이고 그 내부에 V8 EnGine
을 가지고 있다. 그 덕분에 크롬과 같은 브라우저에서 실행하던 JavaScript
를 로컬에서 실행할 수 있다. 여기서 중요하게 봐야하는 것은 libuv
라는 라이브러리이다.
libuv
란 C++
로 작성된 Node.js
가 사용하는 비동기 I/O 라이브러리이다. libuv
는 운영체제의 커널을 추상화한 라이브러리로 커널이 어떤 비동기 API를 지원하는지 알고있다.
우리가 libuv
에게 파일 읽기와 같은 비동기 작업을 요청하면 libuv
는 이 작업을 커널이 지원하는지 확인한다. 만약 지원한다면 libuv
가 대신 커널에게 비동기적으로 요청했다가 응답이 오면 우리에게 전달해준다.
만약 요청한 작업을 커널이 지원하지 않는다면 자신만의 워커 스레드가 담긴 스레드 풀을 사용한다.
libuv
에 대하여 자세하게 설명되어있는 블로그를 참고했다. 이곳에 정말 자세하게 잘 설명해주셨다.
결론은 Node.js
는 I/O 작업을 자신의 메인 스레드가 아닌 다른 스레드에 위임하여 싱글 스레드로 논 블로킹 I/O를 지원한다. 즉 Node.js
는 I/O 작업을 libuv
에게 위임하여 논 블로킹 I/O를 지원하고 그 기반에는 이벤트 루프가 있다.
이 블로그에 설명이 되게 잘 나와있다.
논블로킹 I/O를 알아보기 전에 동기 비동기에 대해서도 알아야 한다고 생각한다. 간단하게 비교하자면
동기(Sync) / 비동기(Async)의 차이점은 -> 코드의 순서와 실행 순서가 일치하는가?
블로킹 / 논블로킹의 차이점은 -> 코드의 실행이 다른 코드의 실행을 막는가?
Async와 Non-Blocking이 주로 짝지어지고 Sync와 Blocking이 주로 짝지어지지만, 이 둘은 완전히 동일한 개념은 아니다. Sync하면서 Non-Blocking할 수도 있고 Async하면서 Blocking할 수도 있지만, 비효율적이고 부자연스럽기 때문에 그렇게 쓰이지 않을 뿐이다.
즉, Node.js
는 작업을 수행할때, 해당 코드의 실행이 다른 코드의 실행을 막지 않기 위해 코드가 순서대로 실행되지 않는다.
Node.js는 싱글스레드, 논 블로킹 모델로 싱글 스레드가 혼자서 일을 처리하지만 들어오는 요청 순서가 아닌 논 블로킹 방식으로 이전 작업이 완료될 때까지 대기하지 않고 다음 작업을 수행한다.
참고자료
https://velog.io/@tok1324/Linux-%ED%95%99%EC%8A%B5-node.js-Runtime%EC%9D%98-%EA%B0%9C%EB%85%90
https://medium.com/@vdongbin/node-js-%EB%8F%99%EC%9E%91%EC%9B%90%EB%A6%AC-single-thread-event-driven-non-blocking-i-o-event-loop-ce97e58a8e21
https://hanamon.kr/nodejs-%EA%B0%9C%EB%85%90-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0/
https://www.korecmblog.com/node-js-event-loop/