Notice
Recent Posts
Recent Comments
Link
«   2025/06   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Tags
more
Archives
Today
Total
관리 메뉴

개발자 도전기

[STUDY] Node js란? 본문

개발공부/CS스터디

[STUDY] Node js란?

jnnjnn 2024. 5. 29. 00:50

 

동기와 비동기 / Blocking과  Non-Blocking

 

동기와 비동기는 작업을 순차적으로 진행할 것인지, 아닌지를 말한다.

예를 들어 카페에서 이전 손님이 음료를 주문하고, 주문한 음료를 받은 후에야 다른 손님이 음료를 주문할 수 있는 것은 동기 방식, 주문 후에 음료가 빨리 제조되는 순서대로 받을 수 있는 것을 비동기 방식이라고 한다.

 

 

Blocking과 Non-Blocking은 다른 작업과 함께 실행될 수 있는지, 아니면 작업이 끝날 때까지 block되는지를 말합니다

Non-Blocking 방식에서는 FILE1, 2 작업이 동시에 실행될 수 있습니다

 

자바스크립트는 여러 함수는 비동기 처리가 가능합니다. 다음의 코드를 실행시켜 보면,

코드가 순차적으로 실행되지 않고 처리 속도가 빠른 순서대로 실행되었습니다.

console.log("시작");

setTimeout(() => {
  console.log("1초 후에 실행");
}, 1000);

console.log("끝");

 

만약 A가 실행된 후에만 실행되어야 하는 B가 있다면?

자바스크립트에서 동기 방식으로 처리하기 위해 사용하는 것이 callback입니다

function third(){
	second();
    console.log("세 번째");
}

function second(){
	first();
	console.log("두 번째");
}

function first(){
	console.log("첫 번째")
}

third();

 

 

Node.js란?

 

초기 JavaScript는 웹 브라우저에서 HTML을 동적으로 실행하기 위해 만들어진 언어로, 브라우저에서만 사용할 수 있었습니다. 브라우저마다 자바스크립트를 해석하는 엔진이 존재하는데, 그중에서도 Chrome의 V8 엔진의 성능이 뛰어났습니다.

Node.js는 그 V8 엔진을 사용해서 만들어진 런타임으로 JavaScript를 브라우저가 아닌 곳에서도 실행할 수 있게 해줍니다

 

Node.js의 특징

-single thread

-Non-Blocking I/O

 

Node.js의 강점

  • Node.js 서버로 구현하면 요청이 많거나 오래 걸리는 요청이 있어도 멈추거나 요청 대기 시간이 발생하지 않습니다. 이러한Non-blocking 덕분에 채팅이나 SNS에 자주 사용됩니다.
  • 백앤드와 프론트앤드가 동일한 언어를 사용하여 코드 재사용성이 높아지고 의사소통이 원활해집니다.

Node.js의 단점

Node.js는 모두 스레드 하나에서 처리하기 때문에 코드가 CPU 연산을 많이 요구하면 스레드 하나가 감당하기 어렵습니다. 그렇기 때문에 이미지나 비디오 처리, 대규모 데이터 처리 같이 CPU를 많이 사용하는 작업을 위한 서버로는 권장하지 않습니다.

 

 

 

Node.js의 장점과 단점을 알아보았습니다. 그런데 Node.js는 싱글 스레드라면서 어떻게 작업을 비동기로 처리할 수 있을까요? 이것은 Node.js의 구조를 살펴보면 알 수 있습니다. 마치 유튜버 침착맨의 본체가 사실은 랩틸리언 독깨팔인 것처럼 싱글 스레드인 Node.js는 멀티 스레드 작업이 가능한 libuv 라이브러리를 사용하고 있습니다.

 

 

Node.js의 구조

 

Node.js의 구조에서 눈여겨봐야 하는 것은 V8 엔진과 libuv 라이브러리입니다.

V8은 자바스크립트를 동작하게 만드는 엔진, libuv 라이브러리는 C++로 작성된 비동기 I/O 라이브러리입니다.

 

 

V8 Engine

compile & interprete

인간이 작성하는 프로그래밍 언어는 대부분 hign-level 언어로, 이러한 source code를 기계가 읽고 실행할 수 있는 low-level 언어로 해석해주어야 합니다. 이 방법에는 컴파일과 인터프리트가 있습니다.

 

V8 엔진은 코드를 해석하는데 compiler와 interpreter 두가지 모두를 사용합니다.

이로 인해 interpret 언어인 JavaScript의 단점을 극복해 더 나은 효율성과 퍼포먼스를 자랑합니다.

 

1. 컴파일

 

한번에 번역하고 한번에 실행한다. 즉, 번역과 실행이 완전히 따로 이루어진다

번역은 컴파일러를 통해 수행된다. 대표적인 예시로 C, C++, Go 등이 있다

source code를 machine code(2진법)으로 변환한다.

 

- 컴파일이 오래 걸릴 수 있다

- 이미 컴파일이 된 프로그램은 굉장히 빠른 속도로 실행이 가능하다

- 운영체제 (OS) 이식성이 낮다

 

엉터리 예시 : 책 한권을 통째로 변역하면 두고두고 볼 수 있지만 영어 -> 한국어로 번역할 경우 일본인은 볼 수 없습니다

 

2. 인터프리터 언어

 

소스 코드를 한 줄씩, 번역과 실행을 동시에 진행하여 byte code로 변환한다. 번역은 인터프리터를 통해 수행되며, 대표적인 예시로는 Python, R, JavaScript 등이 있다. byte code는 소프트웨어 프로그램인 인터프리터에 의해 실행되도록 만들어진 코드이며 인터프리터는 이를 실행 후 저장하지 않고 버린다. 따라서 인터프리터는 다음 코드를 만난다면 전과 내용이 같더라도 같은 작업을 반복해 실행한다.

 

- 줄 단위로 번역과 실행을 하기 때문에  실행이 느리다

- 디버깅이 쉽다 (개발의 편의성)

- 운영체제 이식성이 좋다

 

엉터리 예시 : 3개 국어를 할 줄 아는 통역사가 옆에서 한줄 한줄 책을 해석해줍니다

 

더보기

TMI

1. 자바는 자바 컴파일러를 통해 Java 코드를 자바 가상 머신(Java Virtual Machine, JVM)이 실행시킬 수 있는 바이트 코드로 번역하고

 

2. 자바 바이트 코드는 자바 가상 머신(JVM)의 자바 인터프리터(Java Interpreter)를 이용해 한 줄씩 실행된다.

(바이트 코드 -> 2진 코드)

 

컴파일 + 인터프리터

 

V8 엔진은 위에서 말한 compiler와 interpreter의 장점을 합쳐 사용합니다.

 

V8엔진은 초기 실행시에 인터프리터를 이용해 source code를 byte code로 변환해 실행하며 이와 동시에 자주 사용되는 코드와 패턴을 파악합니다. 이를 찾으면  Turbofan이라는 컴파일러를 이용해 해당 byte code를 machine code로 컴파일합니다.

 

이러한 방식을 JIT(Just-In-Time) Compiler이라고 합니다.

 

 

libuv의 작동방식

 

node.js는 하나(싱글스레드)의 이벤트루프로만 동작합니다. 이 이벤트 루프는 libuv의 구현체입니다.

 

이벤트루프는 비즈니스 로직을 수행하다가 수행 도중 블로킹 IO 작업을 만나면 OS 커널에 넘겨줍니다

 

OS 커널은 비동기 작업을 수행합니다. 만약 요청한 작업을 커널이 지원하지 않는다면 libuv의 스레드 풀을 사용하고, 스래드 풀의 워커 스레드 중 하나가 작업을 수행합니다. 작업을 완료한 후 Event Queue에 callback을 저장합니다.

 

이벤트 큐는 여러 개의 페이즈(phase)를 가지며, 각 페이지는 각각의 큐를 가지고 있습니다. 각각의 단계에 맞는 콜백이 큐에 위치하게 됩니다. 페이즈는 순서대로 실행되며 반복되는데, 한 페이즈에서 다음 페이즈로 넘어가는 것을 틱(Tick)이라고 합니다. 페이즈에 진입하면 이벤트 루프는 해당 큐에 담겨있는 큐를 하나씩 실행합니다. 실행이 완료되면 다음 페이즈로 넘어가게 됩니다.


즉, 싱글스레드로 작업하던 이벤트 루프가 비동기 작업들을 OS 커널에 맡겨 커널의 멀티스레드로 비동기 작업을 처리하고 받은 callback을 다시 이벤트 루프가 순차적으로 받아 처리하는 것입니다.

 

이렇게 커널을 추상화한 ilbuv 라이브러리를 사용함으로써 Node.js는 여러 동작들을 빠르게 수행할 수 있게 되었습니다