리셋 되지 말자

[nodejs 교과서] 1장 본문

NodeJS

[nodejs 교과서] 1장

kyeongjun-dev 2020. 10. 16. 13:07

1.1.2 자바스크립트 런타임

Node.js® is a JavaScript runtime built on 
Chrome's V8 JavaScript engine.

공식 사이트에 게시된 노드에 대한 설명은 위와 같다.

노드는 자바스크립트 런타임이다.

런타임은 특정 언어로 만든 프로그램들을 실행할 수 있는 환경을 뜻한다.

즉, 노드는 자바스크립트 프로그램을 실행할 수 있도록 하는 자바스크립트 실행기라고 할 수 있다.

 

노드의 내부 구조

노드는 V8과 libuv라는 라이브러리를 사용한다. 둘 다 C, C++로 구현되어 있다. 우리가 코딩하는 자바스크립트 코드를 노드가 알아서 V8과 libuv에 연결해준다.

libuv 라이브러리는 노드의 특성인 이벤트 기반, 논 블로킹 I/O 모델을 구현하고 있다.

 

1.1.3 이벤트 기반

이벤트 기반(event-driven)이란 이벤트가 발생할 때 미리 지정해둔 작업을 수행하는 방식을 의미한다. 클릭이나 네트워크 요청 등이 있을 수 있다.

이벤트 기반 시스템에서는 특정 이벤트가 발생할 때 무엇을 할지 미리 등록해두어야 한다. 이를 이벤트 리스너(event listener)에 콜백(callback) 함수를 등록한다고 표현한다. 예를 들어 클릭 이벤트 리스너에 경고창을 띄우는 콜백 함수를 등록 해두면 클릭 이벤트가 발생할 때마다 콜백 함수가 실행되어 경고창이 뜨게 된다.

노드도 이벤트 기반 방식으로 동작하므로, 이벤트가 발생하면 이벤트 리스너에 등록해둔 콜백 함수를 호출한다. 발생한 이벤트가 없거나 발생했던 이벤트를 전부 처리하면, 노드는 다음 이벤트가 발생할 때까지 대기한다.

이벤트 기반

https://developer.mozilla.org/ko/docs/Web/JavaScript/EventLoop#%EB%9F%B0%ED%83%80%EC%9E%84_%EA%B0%9C%EB%85%90 런타임 및 이벤트 루프에 대한 MDN 설명

이벤트 기반 모델에서는 이벤트 루프(event loop)라는 개념이 등장한다. 여러 이벤트가 동시에 발생했을 때 어떤 순서로 콜백 함수를 호출할지를 이벤트 루프가 판단한다.

노드는 Javascript 코드의 맨 위부터 한 줄씩 실행한다. 함수 호출 부분을 발견하면 호출한 함수를 호출 스택(call stack) 또는 프레임 스택(frame stack), 결국 스택(stack)에 넣는다. 

  • setTimeout 예제
function run(){
    console.log('3초 후 실행');
}

console.log('시작');
setTimeout(run, 3000);
console.log('끝');

setTimeout의 콜백인 run 함수가 언제 호출 스택에 들어갔는지 파악하기 힘들다. 이를 파악하기 위해서 이벤트 루프, 태스크 큐(task queue), 백그라운드(background)를 알아야 한다.

 

  • 이벤트 루프

이벤트 발생 시 호출할 콜백 함수들을 관리하고, 호출된 콜백 함수의 실행 순서를 결정하는 역할을 담당한다. 노드가 종료될 때까지 이벤트 처리를 위한 작업을 반복하므로 루프(loop)라고 부른다.

 

  • 백그라운드

setTimeout 같은 타이머나 이벤트 리스너들이 대기하는 곳이다. 자바스크립트가 아닌 다른 언어로 작성된 프로그램이라고 봐도 된다. 여러 작업이 동시에 실행될 수 있다.

 

  • 테스크 큐

이벤트 발생 후, 백그라운드에서는 태스크 큐로 타이머나 이벤트 리스너의 콜백 함수를 보낸다. 정해진 순서대로 콜백들이 줄을 서있으므로 콜백 큐라고도 부른다. 콜백들은 보통 완료된 순서대로 줄을 서 있지만 특정한 경우에는 순서가 바뀌기도 한다.

 

  • setTimeout의 이벤트 루프 내부 과정 설명

이벤트 루프 1

전역 컨텍스트인 main()이 호출 스택에 들어간다. 그 뒤에 console.log('시작')이 호출 스택에 들어간 뒤, 실행되어 화면에 '시작'이 출력된다.

그리고 setTimeout(run, 3000)이 호출스택에 올라간 뒤 실행된다. setTimeout이 실행되면 타이머와 함께 run 콜백을 백그라운드로 보내고 setTimeout(run, 3000)은 호출 스택에서 빠진다. 이때 3초를 센다.

console.log('끝')이 호출스택에 올라갔다가 빠지면서 '끝'이 화면에 출력되고, main()이 스택에서 빠진다. 3초가 다 되면, 백그라운드에서 run() 을 테스크 큐로 보낸다. 

main() 전역 컨텍스트까지 호출 스택에서 빠지면 호출 스택이 비어지게 되는데, 이벤트 루프는 호출 스택이 비어 있으면 태스크 큐에서 함수를 하나씩 가져와 호출 스택에 넣고 실행한다.

run()까지 실행되어 호출 스택이 비어지면, 이벤트 루프는 태스크 큐에 콜백 함수가 들어올 때까지 대기한다.

setTImeout의 시간은 '최소 시간의 보장'이지 정확한 시간을 보장하지 않는다. 왜냐하면 호출 스택에 함수가 많이 들어있으면 테스크 큐에서 호출 스택으로 가져오지 못하기 때문이다.

 

1.1.4 논 블로킹 I/O

이벤트 루프를 잘 활용하면 오래 걸리는 작업을 효출적으로 처리할 수 있다.

작업에는 동시에 실행될 수 있는 작업, 동시에 실행될 수 없는 작업 두 종류가 있다. 기본적으로 자바스크립트 코드는 동시에 실행될 수 없지만 자바스크립트 상에서 돌아가는 것이 아닌 I/O 작업 같은 것은 동시에 처리될 수 있다.

I(input)/O(output)작업에는 파일 시스템 접근(파일 읽기, 쓰기, 폴더 생성 등)이나 네트워크를 통한 요청 작업 등이 있다.

논 블로킹이란 이전 작업이 완료될 때까지 대기하지 않고 다음 작업을 수행함을 뜻한다. 블로킹 방식보다 처리 시간이 빠르지만, 작업들이 동시에 처리될 수 있는 작업이라는 전제가 깔린다.

노드는 I/O 작업을 백그라운드로 넘겨 동시에 처리하곤 하므로, 동시에 처리될 수 있는 작업들을 최대한 묶어서 백그라운드로 넘겨야 시간을 절약할 수 있게 된다.

 

1.1.5 싱글 스레드

자바스크립트 코드가 동시에 실행될 수 없는 이유이기도 하다. 하지만 노드가 싱글 스레드라는건 잘못된 표현

스레드는 프로세스 내에서 실행되는 흐름의 단위이다. 하나의 프로세스 내에서 여러 스레드를 생성하여 여러 작업을 동시에 처리할 수 있다. 스레드는 부모 프로세스의 자원을 공유한다.

노드를 실행하면 프로세스가 하나 생성이 되고 생성된 프로세스는 스레드들을 생성한다. 노드가 싱글 스레드라는 말은 내가 직접 제어할 수 있는 스레드가 생성된 스레드들 중에 하나이기 때문이다. 

멀티 스레드와 논 블로킹 방식을 사용하면 좋지만, 멀티 스레드 방식은 프로그래밍하기가 까다로워서 대신 멀티 프로세싱을 사용한다고 한다. I/O 요청에는 멀티 프로세싱이 더 효율적이다.

 

멀티 스레딩 멀티 프로세싱
하나의 프로세스 안에서 여러 개의 스레드 사용 여러 개의 프로세스 사용
CPU 작업이 많을 때 사용 I/O 요청이 많을 때 사용
프로그래밍의 어려움 프로그래밍이 비교적 쉬움
스레드풀과 워커 스레드

노드가 싱글 스레드로 동작하지 않는 두 가지 경우가 있다.

스레드풀(thread pool)은 특정 동작(대표적으로 암호화, 파일 입출력, 압축)을 수행할 때 스스로 멀티 스레드를 사용

워커 스레드(worker thread)로 인해 노드에서도 멀티 스레드를 사용할 수 있게 됨

https://psyhm.tistory.com/45
스레드 생성과 작업 시간 비교

 

1.5 함께 보면 좋은 자료

이벤트 루프 설명 : https://nodejs.org.ko/docs/nodejs.org/ko/docs/guides/event-loop-timers-and-nexttick/ 

 

Node.js 이벤트 루프, 타이머, `process.nextTick()` | Node.js

Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.

nodejs.org

이벤트 루프에 대한 시각적 설명 : latentflip.com/loupe/?code=JC5vbignYnV0dG9uJywgJ2NsaWNrJywgZnVuY3Rpb24gb25DbGljaygpIHsKICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gdGltZXIoKSB7CiAgICAgICAgY29uc29sZS5sb2coJ1lvdSBjbGlja2VkIHRoZSBidXR0b24hJyk7ICAgIAogICAgfSwgMjAwMCk7Cn0pOwoKY29uc29sZS5sb2coIkhpISIpOwoKc2V0VGltZW91dChmdW5jdGlvbiB0aW1lb3V0KCkgewogICAgY29uc29sZS5sb2coIkNsaWNrIHRoZSBidXR0b24hIik7Cn0sIDUwMDApOwoKY29uc29sZS5sb2coIldlbGNvbWUgdG8gbG91cGUuIik7!!!PGJ1dHRvbj5DbGljayBtZSE8L2J1dHRvbj4%3D

 

http://latentflip.com/loupe/?code=JC5vbignYnV0dG9uJywgJ2NsaWNrJywgZnVuY3Rpb24gb25DbGljaygpIHsKICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gdGltZXIoKSB7CiAgICAgICAgY29uc29sZS5sb2coJ1lvdSBjbGlja2VkIHRoZSBidXR0b24hJyk7ICAgIAogICAgfSwgMjAwMCk7Cn0pOwoKY29uc29sZS5sb2coIkhpISIpOwoKc2V0VGltZW91dChmdW5jdGlvbiB0aW1lb3V0KCkgewogICAgY29uc29sZS5sb2coIkNsaWNrIHRoZSBidXR0b24hIik7Cn0sIDUwMDApOwoKY29uc29sZS5sb2coIldlbGNvbWUgdG8gbG91cGUuIik7!!!PGJ1dHRvbj5DbGljayBtZSE8L2J1dHRvbj4%3D

 

latentflip.com

 

 

Comments