Node.js는 크롬 V8 자바스크립트 엔진으로 빌드된 자바스크립트 런타임입니다. Node.js는 이벤트 기반, 논블로킹 I/O 모델을 사용해 가볍고 효율적입니다. Node.js의 패키지 생태계인 npm은 세계에서 가장 큰 오픈 소스 라이브러리 생태계입니다.
Node.js is Not Server but Runtime
Node.js는 JavaScript 런타임이다.
런타임: 특정 언어로 만든 프로그램들을 실행할 수 있는 환경
⇒ Node.js는 자바스크립트 프로그램을 컴퓨터에서 실행할 수 있게 해준다.
기존 JavaScript는 브라우저에서만 실행이 가능했으며,
브라우저 이외 환경에서는 실행 속도 문제로 크게 활용되지 못했음
2008년 - 구글이 V8 엔진을 사용한 크롬을 출시
다른 JavaScript 엔진에 비해 매우 빠른 속도를 자랑했으며, 오픈 소스로 코드가 공개됨
2009년 - Ryan Dahl은 V8 엔진 기반의 노드 프로젝트를 시작
이벤트가 발생할 때 미리 지정해둔 작업을 수행하는 방식을 의미
이벤트: 클릭, 네트워크 요청 등
이벤트 기반 시스템은 특정 이벤트가 발생할 때 무엇을 할지 미리 등록해두어야함
⇒ Event Listner에 callBack 함수를 등록해 두어야함
버튼을 누르면 경고 창을 띄우도록 설정
⇒ 클릭 이벤트 리스너에 경고 창을 띄우는 콜백 함수를 등록
Node는 이벤트 기반 방식
function first() {
second();
console.log('첫 번째');
}
function second() {
third();
console.log('두 번째');
}
function third() {
console.log('세 번째');
}
first();
세 번째
두 번째
첫 번째
위 코드를 실행 시
main 함수가 호출 스택에 들어감
first() 함수 호출
second() 함수 호출
third() 함수 호출
호출스택은 아래와 같이 쌓임
즉, 쌓인(호출된) 순서와 반대로 실행된다.
함수 실행이 완료되면 호출 스택에서 지워지며, third, second, first, main 순으로 지워지며, main 함수까지 모두 완료 시 호출 스택은 비어짐
function run() {
console.log('3초 후 실행');
}
console.log('시작');
setTimeout(run, 3000);
console.log('끝');
시작
끝
3초 후 실행
호출 스택에 쌓이는 순서
호출 스택 실행 순서
run
callBack을 백그라운드로 보냄 (호출 스택에서 setTimeout 삭제)만약에 호출 스택에 함수가 굉장히 많아서 3초후에도 호출 스택에 실행할 함수가 남아있다면, run 함수는 호출 스택에 그만큼 더 늦게 올라오고 3초가 지난 후에도 실행되지 않을 수 있음
⇒ setTimeout의 시간이 정확하지 않을 수도 있는 이유!
논블로킹: 이전 작업이 완료될 때까지 멈추지 않고 다음 작업을 수행하는 것
블로킹보다 논블로킹 방식에서 같은 작업을 더 짧은 시간에 처리
but. 싱글 스레드라는 한계로 인해 JavaScript의 모든 코드가 이 방식으로 시간적 이득을 볼 수 없음
I/O
입력(Input) & 출력(Output)을 의미
예시: 파일 시스템 접근(파일 읽기, 쓰기, 폴더 만들기 등), 네트워크 요청 작업
블로킹 - 논블로킹 & 동기 - 비동기
엄연히 따지면 다른 개념이지만, 동기-블로킹, 비동기-논블로킹이 유사한 관계라고 볼 수 있음
function longRunningTask() {
// 오래 걸리는 작업
console.log('작업 끝');
}
console.log('시작');
longRunningTask();
console.log('다음 작업');
시작
작업 끝
다음 작업
longRunningTask
함수가 호출되면,
이 작업이 완료되기 전까지 console.log('다음 작업')
이 호출되지 않음
function longRunningTask() {
// 오래 걸리는 작업
console.log('작업 끝');
}
console.log('시작');
setTimeout(longRunningTask, 0);
console.log('다음 작업');
시작
다음 작업
작업 끝
setTimeout
을 통해 콜백 함수(longRunningTask
)가 태스크 큐로 보내짐
다음 작업이 먼저 실행된 후 오래걸리는 작업이 완료됨
setTimeout(콜백, 0)
주어진 작업을 스레드 하나로 혼자 처리해야함
Thread: 컴퓨터 작업을 처리할 수 있는 일손
Multi-Thread: 여러 개의 스레드가 일을 나눠서 처리할 수 있음
JavaScript, Node는 싱글 스레드
한 번에 한 가지 일만 처리하므로 어떤 작업에서 블로킹이 발생하면, 다음 일을 처리하지 못함
Multi Thread가 Single Thread 보다 나은가? No.
한 음식점에 점원이 한 명 - 손님이 여러 명일 때 (싱글 스레드)
한 음식점에 점원이 여러 명, 손님이 여러 명일 때 (멀티 스레드)
멀티스레드 - 블로킹 모델
손님 한 명당 점원이 한 명씩 맡아 주문을 받고 서빙
장점: 손님 처리에 장점, 점원 한 명에게 문제가 생겨도 다른 점원으로 대체 가능
단점**: 손님의 수가 늘어날수록 → 점원의 수 증가 // 손님 수가 감소하면 → 노는 점원이 발생
프로세스 vs 스레드
프로세스(Process): 운영체제에서 할당하는 작업의 단위
(Node, Internet Browser 등은 개별적인 프로세스 → 프로세스 간 메모리 등 자원 공유는 일어나지 않음)
스레드(Thread): 프로세스 내에서 실행되는 흐름의 단위
(하나의 프로세스는 여러 개의 스레드로 구성되며, 스레드들은 부모 프로세스의 자원을 공유)
Node도 내부적으로는 여러 개의 Thread를 가지고 있지만, 우리가 제어할 수 있는건 하나뿐 ⇒ 싱글 스레드
Thread를 늘리는 대신 Process를 복사해 여러 작업을 동시에 처리하는 Multi Processing 방식을 채택
(JavaScript 언어 자체가 Single Thread 특성을 띄고 있기 때문에 Multi Processing 방식을 채택)