1. 노드란?
크롬 V8자바스크립트 엔진의 등장으로 느릿느릿하던 자바스크립트가 새로운 변화를 맞게되었다.
눈에 띄게 빨라진 자바스크립트 엔진을 보고 자바스크립트를 사랑하던 사람들은 드디어 자바스크립트를 브라우저로부터 탈출시킬 생각을 하게 되었다. (사실 이전에도 탈출시키려는 시도는 있었음.)
그렇게 탄생한 것이 바로 Node.js
크롬 V8 자바스크립트 엔진으로 빌드된 자바스크립트 런타임이다.
런타임 : 운영체제 위 또는 운영체제 자체에서 실행되면서, 특정언어로 만든 프로그램들을 실행할 수 있는 환경
이로써 브라우저 외부에서도 자바스크립트를 통한 프로그래밍이 가능해졌다.
예를들어서
앱제작, 데스크탑 프로그래밍, 게임제작, 서버제작 등등 이 가능해졌다.
앞으로 나는 노드를 통한 "서버제작"에 중점을 두고 노드를 학습하게 될 것이다.👍
2. 서버와 클라이언트
노드를 통한 서버제작에 들어가기 앞서 서버와 서버의 단짝 클라이언트를 알아보자
서버 : 네트워크를 통해 클라이언트에 정보나 서비스를 제공하는 컴퓨터 또는 프로그램
클라이언트 : 서버에 요청을 보내는 주체 (브라우저, 데스크탑, 모바일앱, 다른서버에 요청을 보내는 서버)
상상해보자
사용자가 있다.
이 사용자는 어떠한 정보가 담긴 웹을 보고자 하는 사용자이다.
웹을 보기위해서 사용자는 어디를 들어가게 될까.
브라우저이다. 크롬, 웨일, 엣지 등이 되겠다.
우리는 사용자가 원하는 정보를 얻어오기 위해 서버에 요청을 보내는 브라우저 같은 주체를 클라이언트라고 한다.
그럼 클라이언트는 사용자의 요청을 어디에 보낼까?
이 요청을 눈에 보이지 않는 길, 네트워크를 통해서 서버에 전달한다.
서버는 말그대로 전달해주는 아이라고 보면 된다.
전달할 내용은 어디에 있나? 정보 저장소, 데이터베이스에 있다.
서버는 데이터베이스로부터 클라이언트의 요청에 맞는 정보를 가져와서 클라이언트의 요청에 응답하게 된다.
그렇다면,
우리는 이제 노드를 통해서 만들 수 있는 서버가 무엇인지 알게 되었다.
그런데 서버제작에 꼭 노드를 써야할까?
(+ 앞에서 말했듯 노드는 런타임(실행기)이다. 우리는 노드에서 제공하는 모듈(express..)을 이용해서 서버를 만들게 된다.)
아니다.
자바의 스프링, 파이썬의 장고 등 다른 프레임워크를 사용해서도 서버를 제작할 수 있다.
그렇다면,
우리는 노드를 배우며 물음표 공격을 맞지 않기 위해,
노드를 통한 서버 개발의 장점, 특징을 알아볼 필요가 있다.
3. 노드를 통한 서버개발의 장점
노드로 서버를 개발하면,
- 단일언어 : 우선 우리가 이미 알고 있는 자바스크립트를 이용해 서버를 만들 수 있다는 독보적인 장점을 가진다. 게다가 API를 사용할 때 필요한 JSON의 당사자 언어이기에, 다른 언어들이 해야하는 수고를 노드를 사용하면 덜 수 있다.
- 경량화 : 코드 구조 모듈화로 병렬작업, 대용량 데이터 처리에 높은 성능이 보장된다. 채팅기능이나 실시간 차트를 보여주는 등의 기능에서 큰 장점을 가진다.
- 커뮤니티, 생태계 다양성 : 많은 사람들이 사용하는 언어인 만큼 넓은 생태계를 자랑한다.
- 확장성 : 새로운 모듈의 추가와 업데이트 과정이 매우 간단하다. (npm과 함께라면 어디든 갈 수 있지...)
- 비동기 이벤트 기반 환경
등등 많은 장점이 있다.
하지만!
결국 노드에게 현재의 강력한 지위를 부여한 것은
장점 "5. 비동기 이벤트 기반 환경" 이라고 나는 생각한다.
4. 노드가 가지고 있는, 가지고 있던 단점
노드는 결국 자바스크립트를 기반으로 한 언어이다.
그렇다보니 자바스크립트의 특성을 가지게 되는데,
자바스크립트의 가장 큰 특징은 "싱글 스레드"라는 것이다.
프로세스 : 운영체제에서 할당하는 작업단위. 프로세스 간 자원공유 X
스레드 : 프로세스 내에서 실행되는 작업단위. 부모프로세스 자원 공유
흔히 스레드를 직원의 수로 비유를 많이 한다.
즉, 자바스크립트는 어떤 명령들이 주어졌을때, 그 일을 한명이 처리한다고 생각하면 된다.
(노드 프로세서는 멀티 스레드로 동작한다 그러나 직접 다룰 수 있는 스레드는 결국 하나이다.)
직원이 하나라면 어떤 점이 좋을까?
- 프로그래밍 난이도 하락 : 직원이 여럿이라면 직원간의 합의가 필요하다. 이런상황 저런상황에 대해서 어떻게 처리할 것인지 미리 결정해야 오류가 없기 때문이다. 현실이라면 "아! 그냥 내가 할께 -ㅁ-" 하면 되겠지만 프로그래밍은 어렵다.
- CPU, 메모리 자원 절약 : 직원이 적기에 월급이 적게 나간다 생각하면 편하다.
- 병목현상 없다 : 두 직원이 있을때 서로가 서로에게 필요한 자원을 갖고 있으면 영원히 일이 진행되지 못할 수 있는데 이러한 일이 직원이 한명이면 발생하지 않는다.
싱글스레드에는 이러한 장점이 있지만,
단점도 있다.
간단하다.
직원이 하나이기에 그 직원이 멘붕(오류)에 빠지면 프로그램이 멈춘다는 것이다.
또 직원이 하나이기에 시간이 오래걸리는 일을 직원이 일단 시작하게 되면 다른 일들을 진행할 수 없게 된다.
(간단한 다른 일들도 실행이 저~ 만치 밀리게 된다.)
우리는 이러한 상황을 "블로킹"이라고 한다.
블로킹 : 노드프로세스에서 한 작업의 실행을 위해 다른 작업이 완료될 때까지 기다려야하는 방식
논블로킹 : A작업 중 B작업을 실행시켜야 할 때, A작업이 끝나지 않더라도 기다리지 않고 B작업이 실행될 수 있도록 하는 방식
(+블로킹은 결정적인 문제상황이었기에 기존 웹들은 스레드 기반이었다.
싱글스레드가 아닌 멀티스레드를 채택해, 요청만큼 직원을 생성해, 일들을 동시에 처리해 나갔다.
오류 발생으로 인해 직원이 멘붕에 빠지면 빠르게 직원(스레드)을 새로 생성해 문제를 극복했다.
그에반해 노드는 이벤트 기반이다.)
5. 논블로킹 모델 채택
노드는 싱글 스레드의 장점을 포기하지 않고, 블로킹을 해결하는 것으로 문제를 풀어나갔다.
(사실 JS기반이니까 선택의 여지가 없었던 것..)
간단한 해결방법...
옆집에 일 맡기기....ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
사실 자바스크립트는 싱글스레드로 돌아가지만,
브라우저는 멀티스레드이니까... 브라우저한테 슬쩌기 부탁하는 것이다.
이해하고 깔깔 웃었다...
특유의 시간이 오래걸리는 일들이 있다.
I/O작업(파일시스템접근, 네트워크요청), 압축, 암호화 같은 작업이 대표적이다.
이러한 일들을 마주하면 자바스크립트 엔진은 일을 옆집(백그라운드)에 전달한다.
동기 : 직렬적 일 처리, 순차적 일 처리, 일을 수행하는 도중이라면 다음 작업은 대기한다.
비동기 : 병렬적 일 처리, 요청에 대한 작업이 끝나지 않더라도 계속 요청을 받는다. 그리고 작업이 끝났다는 이벤트가 오면 해당 요청을 처리한다.
살짝 오해가 생길 수 있는데 비동기는 계속해서 일을 받는 것이 아니라.
나름 싱글스레드의 지조를 지키며 여전히 하나하나 일을 받아 처리하고 있는 것이다.
console.log("히힛")
과 같은 주문이 포스기에 찍혀있을때는 자기가 처리한다.
이는 간단하기 때문이다.
하지만 시간이 오래걸리는 setTimeout과 같은 주문이 포스기에 찍히게 되면,
즉각 옆집으로 일을 넘긴다.
그리고 옆집에서 일을 대신 다 해주면 그 결과만 다시 가져와 일을 마무리한다.
물론! 옆집에서 일을 대신해주는 동안에도 자바스크립트 엔진은 일을 한다.
이로써!
Node.js는
싱글스레드의 장점은 지키고,
싱글스레드의 단점은 논블로킹모델 채택을 통해 해결하며 꽤 괜찮은 런타임이 되었다.
-삼다수-
6. 호출스택과 이벤트루프
자바스크립트는 도대체 어떻게 실행되는 것일까?
어떻게 슬쩌기 일을 떠미는 것일까?
브라우저에서 자바스크립트는 자바스크립트엔진에 의해서 실행된다.
자바스크립트 엔진은 메모리 힙과 호출 스택으로 이루어져 있다.
메모리 힙 : 변수와 객체에 대한 모든 메모리 할당이 발생하는 곳
호출 스택 : 코드가 실행되며 생성되는 실행컨텍스트를 저장하는
(줄기차게 부르짖던 직원이 바로 호출스택이다. 당연히 호출스택은 하나!)
중요한 것은 호출 "스택" 이라는 것이다.
스택은 쌓이는 구조이다.
가장 먼저 쌓인 일은 가장 아래 위치하는 만큼, 가장 마지막에 처리하게 되는 구조이다.
(+개인적으로 생각하기에 스택이라는 점은 그리 중요하지 않다. 스택구조를 갖게 되는 것은 결국 JS의 동기적인 특징때문이라 생각한다. 먼저 발생한 일이 먼저 처리되기 위해서는 그 일로 인해 실행을 요청받은 일들이 처리되어야 하는 것이다.)
이 호출 스택에 일이 들어올 때,
시간이 오래 걸려 블로킹을 유발시키는 주문은 백그라운드로 전달된다.
그리고 백그라운드에서 이벤트 발생을 마친 후 호출되어야 하는 콜백함수들은 태스크큐로 이동하게 된다.
태스크큐에서 대기하고 있는 콜백함수들은 이벤트루프에 의해 호출스택으로 다시 올려져 최종 마무리 된다.
백그라운드 : 타이머나 I/O작업 콜백 이벤트리스너들이 대기 하는 공간.
태스크큐 : 이벤트 발생 후 호출되어야 할 콜백함수들이 순서대로 기다리는 공간.
이벤트루프 : 호출 순서를 결정하는 역할.
(백그라운드와 태스크큐는 JS엔진에 의해 실행되지 않는다.)
(호출스택이 비워져야 이벤트루프가 태스크큐의 콜백을 정해진 규칙에 따라 호출스택에 올린다.)
'Node.js' 카테고리의 다른 글
2. express (서버제작 level 2) [express] (0) | 2024.11.11 |
---|---|
1. http (서버제작 level 1) [express] (1) | 2024.11.05 |
3. 노드 기본 [Node] (8) | 2024.11.05 |
4. 패키지 [Node] (2) | 2024.11.04 |
2. 노드 사용법 [Node] (0) | 2024.11.03 |