Group Study (2022-2023)/Node.js

[Node.js 입문] 3주차 스터디

🌊유파도🌊 2022. 10. 30. 17:25

노드의 동작원리

먼저 저번주에 자바스크립트의 동기와 비동기에 대해서 설명을 잘 해주셨는데, 조오금만 더 보충설명하고 싶어서 언급하려고 한다.

우선 Node = js Runtime(실행환경) 이다.

따라서 동기코드, 비동기 코드가 어떻게 실행되는지는 노드에서만의 방식이 아니라 js의 방식이고 마찬가지로 브라우저에서도 거의 유사한 방식으로 코드가 처리된다.

우선 알아야하는 노드(js 런타임)의 중요한 특징에 대해 꼽자면

  1. 싱글 스레드
  2. Nonblocking I/O( 논블락킹 입출력)
  3. event-driven 방식

이 3가지이다. 아래의 이미지로 어떻게 노드가 동작하고 왜 위 3가지 특징이 생기는지 간략하게 설명하겠다.

(노드로 더 깔끔한 이미지를 찾고 싶었는데, 안나온다. 어차피 js 실행환경이 노드니까 별 차이 없이 생각해도 무방하다)

우선 JS는 싱글스레드로 동작하는 언어이다. 즉 사진상의 Call Stack 부분이 하나의 메인 스레드를 의미한다. 코드가 실행되며 함수가 호출되어 해당 콜스택에 쌓인다. 즉 동기적 코드들은 콜스택에 차례로 쌓여 한번에 하나씩 동기적으로(순차적으로) 실행된다.

그럼 JS는 어떻게 비동기 코드를 실행하는 것일까?

바로 비동기 코드는 다른 친구에게 줘버리면 된다.

여기서 말하는 다른친구가 *Web APIs(Node에서는 node api, 또는 입출력 작업등)*이다.

싱글스레드로 코드를 한줄한줄 실행하다가 비동기 코드가 나오면,
 ‘엇 내가 못하는 코드인데…?’
하면서 해당 코드를 실행가능한 다른 주체(api가 될 수도 있고, DB가 될 수 있고)에 넘겨준다. 
그리고 싱글스레드는 맘 편하게 비동기 이후 코드를 다시 한줄 한줄 실행해 나간다.

엥 그럼 비동기 코드가 끝나면 어떻게 가져오나요? 싱글스레드가 하나하나 비동기 처리가 끝났는지 확인하면 실행속도는 엄청나게 느려질 것이다.

이 문제는 **Task Queue(사진상의 Callback Queue)**와 Event Loop로 해결된다.

굳이 싱글스레드가 확인할 필요없이 비동기처리가 끝나면 싱글스레드로 신호를 보내주는 것이다. 이 신호는 이벤트로, 비동기 코드와 함께 보내지는 콜백이다. 비동기 처리가 끝나면 콜백함수가 실행되어 끝났다는 신호를 준다.

이 과정을 위의 예시에 추가하면

싱글스레드로 코드를 한줄한줄 실행하다가 비동기 코드가 나오면,
 ‘엇 내가 못하는 코드인데…?’
하면서 해당 코드를 실행가능한 다른 주체에게 콜백함수와 함께 넘겨준다. 

싱글스레드는 맘 편하게 비동기 이후 코드를 다시 한줄 한줄 실행해 나가고,
그와 동시에 다른 주체(Web api, node api, DB....)는 넘겨받은 비동기 코드를 실행해 나간다.
비동기 코드를 다 실행했으면 다른 주체는 Task Queu에 싱글스레드로 부터 받은 콜백을 전달한다.

그렇게 Task Queue에는 비동기처리와 함께 보내진 콜백함수가 쌓이는데,...
이를 비우는 것은 Event Loop가 싱글스레드(Call Stack)을 수시로 확인해, 
Call Stack가 다 비워지면(동기코드의 실행이 끝나면) Task Queue에서 콜백들을 꺼내 실행한다.

초반에 말한 노드의 중요한 3가지 특징은 위의 동작방식을 말하고 있다.

  1. 싱글 스레드 : 일꾼이 하나
  2. Nonblocking I/O( 논블락킹 입출력) : DB와 같은 입출력 작업(비동기작업)을 실행하는 동안 Nonblocking(싱글 스레드는 비동기코드의 결과를 무작정 기다리지 않고 이후 코드를 계속 실행해 나감)
  3. event-driven 방식 : 비동기 작업이 끝나면 등록한 이벤트를 발생시킴(콜백을 실행시킴)

이런 동작방식을 유의해서 process.nextTick() 함수나 promise 객체를 좀 더 효율적을 사용 할 수 있다.(+ promise를 만들어도 그 안에 코드가 비동기코드가 아니면 비동기로 동작하지 않는다)