[ 백엔드 공부하기 : Node.js ] Node.js는 서버단에서 어떻게 JS를 실행할까
∇백엔드_NodeJS : NodeJS는 서버쪽에서 어떻게 돌아갈까??
목 차
1. Node.js의 구성요소.
2. JS 실행을 위한 V8엔진
3. libuv : 이벤트 루프와 운영체제단 비동기 API 및 스레드풀을 지원.
4. Node.JS 아키텍쳐
Ⅰ. Node.js의 구성요소.
※ Node.js의 소스코드는 C++와 JS, 파이썬 등으로 이우어져 있습니다.
[ 파이썬 코드는 빌드와 테스트에서만 사용된다고 합니다. ]
◎ Node.js는 각 계층이 각 하단에 있는 API를 사용하는 계층의 집합으로 설계되어 있습니다.
① 사용자 코드(JavaScript)는
② Node.js의 API를 사용하고 Node.js API는 C++에 바인딩 되어 있는 소스이거나 직접 만든
③ C++애드온을 호출합니다.
④ C++에서는 V8엔진을 활용하여 자바스크립트를 해석(JIT컴파일) 및 최적화하고,
어떤 코드냐에 따라 C/C++ 종속성이 있는 코드를 실행합니다.
⑤ DNS, HTTP파서, OPENSSL, zlib 이외의 C/C++ 코드들은
libuv의 API 를 사용해 해당 운영체제에 알맞는 API를 사용합니다.
◆ Node.js의 구성요소 중 특히 V8엔진과 libuv가 중요합니다.
- > V8엔진은 자바스크립트 코드를 실행 가능하도록 해주고,
- > libuv는 이벤트 루프 및 운영체제 계층 기능을 사용하도록 API를 제공합니다.
Ⅱ. JS 실행을 위한 V8엔진.
◎ V8은 C++ 로 만든 오픈 소스 자바스크립트 엔진입니다.
== '엔진'은 사용자가 작성한 코드를 실행시키는 프로그램을 의미합니다.
-> 엔진은 { 파서, 컴파일러, 인터프리터, 가비지컬렉터, 콜 스택, 힙 }으로 구성되어 있습니다.
== V8엔진은 자바스크립트 코드를 실행시킬 수 있는 엔진이며,
[ '인터프리터' 역할을 하는 '이그니션' ] 과 [ ' 컴파일러' 역할을 하는 '터보팬' ] 을 활용해 컴파일합니다.
① 자바스크립트 코드가 '파서'에 전달됩니다.
② '파서'에 전달된 JS코드는 '추상구문트리'로 만들어집니다.
③ 추상구문트리가 '이그니션 인터프리터에 전달되면, '바이트 코드'로 변환됩니다.
④ '최적화'까지 필요한 경우이면 '터포팬으로 바이트코드를 전달합니다
⑤ 코드를 전달받은 '터보팬'에서 컴파일 과정을 와다다 돌려주면
⑥ 바이너리 코드로 변환됩니다.
⑦ '최적화'가 잘 안된경우, 다시 최적화를 해제하고 이그니션의 인터프리터 기능을 사용합니다.
* [ '최적화의 해제 이유']
== 최적화를 시도한 코드가 디버깅이나 성능 분석을 어렵게 만들 수 있기 때문입니다.
* [ '인터프리터를 다시 사용하는 이유']
== 코드의 실행 과정을 더 쉽게 추적하고, 문제를 해결 가능하기 때문.
§ 이처럼, '인터프리터'와 '컴파일러'의 장점을 동시에 가지고 있는 프로그램이 JIT(Just-In-Time) 컴파일러입니다.
장점: 속도가 빠르며, 적재적소에 최적화 할 수 있다는 장점.
단점: 컴파일러와 인터프리터가 동시에 실행되어서, 메모리를 더 많이 활용한다는 단점.
Ⅲ. libuv : 이벤트 루프와 운영체제 단 비동기 API 및 스레드 풀 지원.
§ Node.js는 HTTP, 파일, 소켓 통신 IO 기능 등 자바스크립트에는 존재하지 않는 기능을 어떻게 제공 가능한 것인지??
★ Node.js는 'libuv' 라는 C++의 라이브러리를 사용해 해결합니다.
* libuv는 비동기 입출력 & 이벤트 기반에 초점을 맞춘 라이브러리입니다.
- JS안에서 C++ 코드를 실행가능하게 해둠.
- JS코드로 C++ 코드를 감싸서 사용합니다. (C++바인딩)
- libuv는 다양한 플랫폼에서 사용간으한 이벤트 루프를 제공합니다.
[ 리눅스는 epoll, 윈도우는 IOCP, 맥OS는 kqueue, SunOS는 이벤트 포트 ]
++ 네트워크, 파일IO, DNS, 스레드 풀 기능을 추가로 제공.
§ Node.js에서는 C++ 바인딩 기능으로, JS에서 libuv의 API를 사용합니다.
*지금까지의 요약
- Node.js는 자바스크립트 코드 실행에 필요한 V8엔진을 사용하고,
- 자바스크립트 런타임에 필요한 이벤트 루프 및 운영체제 시스템 API를 사용하는데는 libuv 라이브러리 사용.
Ⅳ. Node.JS 아키텍쳐.
① 애플리케이션에서 요청이 발생, V8엔진은 자바스크립트 코드로 된 요청을 바이트 코드나 기계어로 변환
② 자바스크립트로 작성된 Node.js의 API는 C++로 작성된 코드를 사용.
③ V8엔진은 이벤트 루프로 libuv를 사용하고 전달된 요청을 libuv 내부의 이벤트 큐 추가.
④ 이벤트 큐에 쌓인 요청은 이벤트 루프에 전달되고, 운영체제 커널에 비동기 처리를 맡깁니다.
- 운영체제 내부적으로 비동기 처리가 힘든 경우(DB, DNS 룩업, 파일 처리 등)는
워커 스레드에서 처리합니다.
⑤ 운영체제의 커널 도는 워커 스레드가 완료한 작업들은 다시 이벤트 루프로 전달됩니다.
⑥ 이벤트 루프에서는 콜백으로 전달된 요청에 대한 완료 처리를 하고 넘깁니다.
⑦ 완료 처리된 응답을 Node.js 애플리케이션으로 전달합니다.
?? Node.js는 싱글 스레드인데, 워커 스레드가 있으면 싱글 스레드가 아니니 않은가?
:: Node.js는 이벤트 루프 부분이 싱글 스레드이고,
운영체제에서 비동기 I/O를 지원하지 않거나 구현이 복잡한 경우에는 libuv 내부의 스레드 풀을 사용합니다.
즉, == Node.js의 프로세스는 이벤트 루프에 사용하는 싱글 스레드 하나와
비동기 처리를 지원하는 스레드 풀로 구성되어 있습니다.
'Back_End > Node.js' 카테고리의 다른 글
[ 백엔드 공부하기 : Node.js ] NodeJS의 NPM이란? (0) | 2024.12.07 |
---|---|
[ 백엔드 공부하기 : Node.js ] NodeJS의 기본 동작 원리와 이벤트 루프, 브라우저 환경을 벗어난 JS 실행. (1) | 2024.12.06 |
[ 백엔드 공부하기 : Node.js ] NodeJS에 활용되는 JavaScript의 기본 동작 원리와 V8엔진. (2) | 2024.12.05 |
[ 백엔드 공부하기 : Node.js ] Node의 역할. (0) | 2024.11.17 |
[ 백엔드 공부하기 : Node.js ] Node.js의 기초 정리. (0) | 2024.11.17 |