본문 바로가기

Back-End/Node.js

[Node.js 교과서] 1. 노드 시작하기

반응형

1. 핵심 개념 이해하기

전반적으로 노드로 서버를 실행하는 방법을 다루고, 일부는 서버 외의 자바스크립트 프로그램을 실행하는 런타임으로 사용하는 방법을 배운다. 따라서 서버와 런타임이 무엇인지 알아보자.

 

1.1 서버

노드는 서버 애플리케이션을 실행하는데 가장 많이 사용된다. 그럼 서버는 무엇일까?

 

서버

네트워크를 통해 클라이언트에 정보나 서비스를 제공하는 컴퓨터 또는 프로그램. (*클라이언트: 요청을 보내는 주체)

즉, 서버는 클라이언트의 요청에 대해 응답을 한다. 

 

요청에 대한 응답으로서의 서버

  • ex1) 네이버 웹 사이트를 방문하는 경우
    • 요청: 주소창에 네이버 웹 사이트 주소를 입력한다. 
    • 응답: 브라우저는 그 주소에 해당되는 네이버 컴퓨터의 위치를 파악하고, 그 컴퓨터로부터 웹 사이트 페이지를 받아와서 요청자의 브라우저(클라이언트)에 띄운다.
  • ex2) 모바일 앱을 설치하는 경우
    • 요청: 구글 플레이 스토어나 애플 앱스토어에서 원하는 앱을 고르고 설치 버튼을 누른다.
    • 응답: 내려받기가 시작된다. ex1와 같이, 앱 설치 파일은 이미 어딘가(구글과 애플의 서버)에 저장되어 있으므로 그곳에서 데이터를 받아와 모바일 기기에 설치한다.
    • 여기서 플레이 스토어와 앱스토어가 클라이언트 역할을 한다.
  • ex3) 웹/앱을 사용할 때 우리의 데이터(아이디, 비번, 이메일 등)와 서비스의 데이터가 생성된다. 그리고 이 데이터를 서버에 저장하고, 필요할 때마다 서버에서 클라이언트로 데이터를 받아온다.

 

다른 서버에 요청을 보내는 서버

다른 서버로 요청을 보낼 수도 있다. 이때 요청을 보낸 서버가 클라이언트 역할을 한다.

 

 

1.2 자바스크립트 런타임

노드는 자바스크립트 프로그램이 서버로서 기능하기 위한 도구를 제공하기 때문에 서버 역할을 수행할 수 있다.

그렇다면 왜 다른 언어를 사용하지 않고 노드를 사용해 서버를 만들까? 노드의 특성을 살펴보자.

 

노드의 특성: 자바스크립트 런타임

공식 사이트에 게시된 노드 소개글을 보자.

Node.js는 Chrome V8 Javascript 엔진으로 빌드된 Javascript 런타임입니다.

노드는 자바스크립트 런타임이다. (*런타임: 특정 언어로 만든 프로그램들을 실행할 수 있는 환경)

따라서 노드는 자바스크립트 프로그램을 컴퓨터에서 실행할 수 있는, 자바스크립트 실행기이다.

 

노드의 탄생

  1. 기존에는 자바스크립트 프로그램을 웹 브라우저 위에서만 실행할 수 있었다(웹 브라우저는 자바스크립트 런타임을 내장하고 있음). 브라우저 외 환경에서 자바스크립트를 실행하려했으나 자바스크립트의 실행 속도에 문제가 있었다.
  2. 2008년 구글이 V8 엔진을 사용하여 크롬을 출시했고, 다른 자바스크립트 엔진과 달리 속도가 빠른 V8 엔진으로 인해 속도 문제가 해결되었다.
  3. 2009년 라이언 달은 V8 엔진 기반의 노드 프로젝트를 시작했다.

 

노드의 내부 구조

노드의 내부 구조

노드는 C와 C++로 구현된 V8libuv라는 라이브러리를 사용한다. 우리가 자바스크립트를 코딩하면 노드가 알아서 V8과 libuv에 연결해준다.

 

 

1.3 이벤트 기반

libuv 라이브러리는 노드의 특성인 이벤트 기반, 논 블로킹 I/O 모델을 구현한다. 이 모델들에 대해 살펴보자.

 

이벤트 기반

이벤트(ex. 클릭, 네트워크 요청 등)가 발생할 때 미리 지정해둔 작업을 수행하는 방식이다.

이벤트 기반

 

이벤트 리스너(event listener)와 콜백 함수(callback)

이벤트 기반 시스템에서는 특정 이벤트가 발생하면 무엇을 할지 미리 등록을 해두는데, 이를 이벤트 리스너에 콜백 함수를 등록한다고 한다.

  • ex) 버튼을 클릭할 때 경고창 띄우기
    • 이벤트 리스너 : click event listener
    • 콜백 함수 : 경고창 띄우기
    • ➡ 이벤트가 발생할 때마다 콜백함수가 실행된다.

발생한 이벤트가 없거나 발생했던 이벤트를 모두 처리하고 나면 다음 이벤트가 발생할 때까지 대기한다.

 

호출 스택(call stack)

노드는 자바스크립트 코드 맨 위에서부터 한 줄씩 실행하면서, 함수가 호출될 때마다 함수를 호출 스택(call stack - LIFO Last In First Out)에 넣는다. 그리고 함수 실행이 완료되면 호출 스택에서 지워진다. 

(예제 1)

function first() {
    second();
    console.log('첫 번째');
}
function second() {
    third();
    console.log('두 번째');
}
function third() {
    console.log('세 번째');
}
first();
  • 호출 순서(=호출 스택에 넣는 순서): anoymous ➡ first() ➡ second() ➡ third()
  • 실행 순서(=호출 스택에서 지워지는 순서): third() ➡ second() ➡ first() ➡ anonymous
  • 콘솔 결과
세 번째
두 번째
첫 번째

anonymous 함수

처음 실행 시의 전역 컨텍스트(global context). (*컨텍스트 : 함수가 호출되었을 때 생성되는 환경)

즉, 자바스크립트 코드가 실행되면 기본적으로 전역 컨텍스트 안에서 돌아간다. 

(예제 2)

function run() {
    console.log('3초 후 실행');
}
console.log('시작');
setTimeout(run, 3000);
console.log('끝');
  • 콘솔 결과
시작
끝
3초 후 실행

예제 1와 다르게 예제 2는 호출 스택으로 설명하기 어렵다. setTimeout()의 콜백인 run()이 언제 호출 스택에 들어가는지 모르기 때문이다.

이를 알기 위해선 이벤트 루프, 태스크 큐(task queue), 백그라운드(background)를 알아야 한다.

 

이벤트 루프(event loop)

  • 이벤트 루프: 여러 이벤트가 동시에 발생했을 때 어떤 순서로 콜백 함수를 호출할지 판단한다. 노드가 종료될 때까지 이벤트 처리 작업을 반복하므로 루프라고 한다.
  • 백그라운드: 타이머나 이벤트 리스너들이 대기하는 곳. 여러 작업이 동시에 실행될 수 있다.
  • 태스크 큐(Queue - FIFO First In First Out): 타이머나 이벤트 리스너가 발생하면 백그라운드에서 태스크 큐에 콜백함수를 넣는다. 보통 완료된 순서대로 콜백함수가 줄서지만, 특정 경우에는 순서가 바뀌기도 한다.

  1. 전역 컨텍스트(anonymous)가 호출 스택에 들어간다.
  2. setTimeout()이 호출 스택에 들어간다.
  3. setTimeout()이 실행된다.
  4. 타이머와 콜백함수 run()을 백그라운드로 보내고, setTimeout()은 호출 스택에서 빠진다.
  5. 백그라운드에서 3초를 센 후 run()을 태스크 큐로 보낸다.

호출 스택에서 anonymous까지 실행이 완료되어 호출 스택이 비어있는 상황

이벤트 루프는 호출 스택이 비어 있으면 태스크 큐에서 함수를 하나씩 가져와 호출 스택에 넣고 실행한다.

이벤트 루프가 콜백함수 run()을 태스크 큐에서 꺼내 호출 스택으로 올린 상황

호출 스택에 있는 run()이 실행되고, 실행완료 후 호출 스택에서 비워진다.

이벤트 루프는 태스크 큐에 콜백 함수가 또 들어올 때까지 계속 대기한다.

 

만약 호출 스택에 함수가 너무 많다면, 3초가 지나도 run()이 실행되지 않을 수 있다. 왜냐하면 호출 스택이 비어있을 때만 태스크 큐에 있는 함수를 호출 스택으로 가져오기 때문이다.

 

 ❗ 순서 

호출 스택(타이머 & 이벤트 리스너)

➡ 백그라운드(n초, 콜백함수) 

(n초 후) 태스크 큐(콜백함수)

➡ (호출 스택이 비었을 때) 호출 스택(콜백함수 1개)

➡ 콜백함수 1개 실행 및 호출 스택에서 사라짐

 

 

1.4 논 블로킹 I/O

노드는 논 블로킹 방식으로 Input(입력)/Output(출력) 작업을 동시에 처리할 수 있다.

  • (ex) 파일 시스템 접근(파일 읽기, 파일 쓰기, 폴더 만들기 등)이나 네트워크를 통한 요청 같은 작업

 

논 블로킹과 블로킹

  • 논 블로킹 : 이전 작업이 완료될 떄까지 대기하지 않고 다음 작업을 수행하는 것 ➡ 동시 처리 O
  • 블로킹 : 이전 작업이 끝나야만 다음 작업을 수행하는 것 ➡ 동시 처리 X

 

동시 처리로 얻는 시간적 이득

작업 순서에 따라 성능이 크게 달라진다. 동시에 처리될 수 있는 I/O 작업이라도 논 블로킹 방식으로 코딩하지 않으면 의미가 퇴색되므로, 논 블로킹 방식으로 코딩하는 습관을 들여야 한다.

ex 1) 블로킹 방식의 코드

function longRunningTask() {
    // 오래 걸리는 작업
    console.log('끝');
}

consonle.log('시작');
longRunningTask();
console.log('다음 작업');
  • 콘솔 결과
시작
작업 끝
다음 작업

블로킹 방식의 I/O 작업을 하면, 작업이 완료되기 전까지 '다음 작업'이 호출되지 않는다. 

부가 설명

anonymous에 있는 코드들은 위에서부터 순서대로 실행된다. 여기서 타이머나 이벤트 리스너 코드를 발견하면 이를 백그라운드로 이동한다.

하지만 위의 코드에서는 타이머나 이벤트 리스너가 없다. 따라서 호출 스택에 있는 anonymous가 먼저 실행되고, longRunningTask()를 발견하면 호출 스택에 쌓는다. 함수가 실행 완료되면 호출 스택에서 사라지고, 다시 anonymous의 코드가 실행된다.

부가 설명 그림

ex 2) 논 블로킹 방식의 코드

function longRunningTask() {
    // 오래 걸리는 작업
    console.log('작업 끝');
}

console.log('시작');
setTimeout(longRunningTask, 0);
console.log('다음 작업');
  • 콘솔 결과
시작
다음 작업
작업 끝

setTimeout()를 사용하여 논 블로킹 방식의 I/O 작업을 하면, 타이머의 콜백 함수인 longRunningTask가 태스크 큐로 보내지므로 순서대로 실행되지 않는다.

setTimeout(콜백, 0)은 코드를 논 블로킹으로 만들기 위해 사용되는 기법 중 하나이지만, 노드에서는 주로 setImmediate() 방식(3.4.3절)을 사용한다.

하지만 우리가 코드를 작성하면 코드가 서로 동시에 실행되지 않기 때문에 전체 소요 시간이 짧아지지는 않고, 단순히 실행 순서만 바뀐다. 그렇지만 I/O 작업이 없다고 해도 위와 같이 오래 걸리는 작업이 있는 경우에 논 블로킹 방식으로 실행 순서를 바꾸면서 간단한 작업들이 대기하는 상황을 막을 수 있다.

 ❗ 논 블로킹 ≠ 동시 작업

➡ 동시성: (동시 처리가 가능한 작업) + (논 블로킹 처리)

 

 

1.5 싱글 스레드

싱글 스레드

스레드가 하나인 것.

  • 우리가 작성한 자바스크립트 코드가 동시에 실행될 수 없는 이유이기도 함

 

프로세스와 스레드

  • 프로세스 : 운영체제에서 할당하는 작업의 단위. 노드나 웹 브라우저는 개별 프로세스이다. 프로세스 간에는 메모리와 같은 자원을 공유하지 않는다.
  • 스레드 : 프로세스 내에서 실행되는 흐름의 단위. 스레드를 여러 개 생성하여 여러 작업을 동시에 처리할 수 있다. 부모 프로세스의 자원을 공유하므로, 같은 주소의 메모리에 접근 가능하므로 데이터를 공유할 수 있다.
  • 관계 : 프로세스(1) ⊃ 스레드(多)

 

노드는 싱글 스레드?

노드를 실행하면 프로세스 하나가 생성되고, 그 프로세스에서 내부적으로 여러 개의 스레드들을 생성한다. 그중에서 우리가 직접 제어할 수 있는 스레드는 하나이다. 그래서 노드는 싱글 스레드가 아니지만, 싱글 스레드로 여겨진다.

  • 즉, 하나의 스레드만 직접 조작할 수 있으므로 일손이 하나인 셈.
  • 따라서 요청이 많이 들어오면 한 번에 하나씩 요청을 처리한다.
  • 블로킹이 발생할 것 같은 경우에 논 블로킹 방법으로 대기 시간을 최대한 줄이기만 하면 스레드 하나로도 충분하다.

 

멀티 스레딩 & 멀티 프로세싱

멀티 스레딩 멀티 프로세싱
하나의 프로세스 내에 여러 개 스레드 사용 여러 개 프로세스 사용
CPU 작업이 많을 때 사용 I/O 요청이 많을 때 사용
프로그래밍이 어렵다 프로그래밍이 비교적 쉽다

따라서 노드는 멀티 프로세싱을 많이 한다.(3.5.7절 참고)

 

 

2. 서버로서의 노드

노드를 사용한 서버는 노드의 특성(〓자바스크립트 언어의 특성)인 싱글 스레드, 논 블로킹 모델의 장단점과 같다.

2.1 특성

  1. I/O 요청이 많이 발생하는 서버로 사용하기 좋다.
  2. 우리가 논 블로킹 방식으로 코드를 작성하면 libuv 라이브러리로 I/O 작업을 논 블로킹 방식으로 처리한다. 따라서 싱글 스레드로 많은 I/O를 처리할 수 있다.
  3. CPU 부하가 큰 작업에 적합하지 않다.
    • 모든 코드가 싱글 스레드로 처리되므로, CPU 연산을 많이 요구하는 코드일 경우에 감당하기 어렵다.

 

2.2 적합한 사용법

위의 특성을 고려하면, 노드는 개수는 많고 크기는 작은 데이터를 실시간으로 주고받는 데 적합하다.

  • 네트워크, 데이터베이스, 디스크 작업 같은 I/O
  • ex) 실시간 채팅 애플리케이션, 주식 차트, JSON 데이터를 제공하는 API 서버 등

 

2.3 장점과 단점

장점

  1. 노드에는 웹 서버가 내장되어 있어서 편리하다.
    • ↔ 노드 외의 서버를 개발하려면 아파치, nginx, IIS처럼 별도의 웹 서버를 설치해야 한다. 이 경우 프로그래밍 외에도 웹 서버 사용법을 익혀야 한다.
    • 하지만 노드도 서버 규모가 커지면 웹 서버를 노드 서버와 연결해야 한다.
  2. 자바스크립트를 언어로 사용한다.
    • 하나의 언어로 웹 사이트를 개발할 수 있으므로 생산성이 매우 높다.
  3. JSON을 쉽게 처리할 수 있다.
    • 데이터를 주고 받는 JSON이 자바스크립트 형식이기 때문이다.

 

단점

정적 파일 제공, 로드 밸런싱에 특화된 웹 서버에 비해선 속도가 느리다.

장점 단점
멀티 스레드 방식보다 컴퓨터 자원을 적게 사용한다. 싱글 스레드라서 CPU 코어를 하나만 사용한다.
I/O 작업이 많은 서버로 적합하다. CPU 작업이 많은 서버로 부적합하다.
멀티 스레드 방식보다 쉽다. 하나뿐인 스레드가 멈추지 않도록 관리해야 한다.
웹 서버가 내장되어 있다. 서버 규모가 커졌을 때 서버를 관리하기 어렵다.
언어로 자바스크립트를 사용한다. 성능이 어중간하다.
JSON 형식과 쉽게 호환된다.  

 

 

3. 서버 외의 노드

처음에는 서버로만 사용되었지만, 최근에는 웹, 모바일, 데스크톱 애플리케이션 개발에도 사용된다.

웹 프레임워크

노드 기반으로 돌아가는 웹 프레임워크로는 앵귤러(Angular), 리액트(React), 뷰(Vue) 등이 있다.

  • 앵귤러: 구글 진영에서 프론트엔드 앱을 만들 때 주로 사용된다.
  • 리액트: 페이스북 진영에서 주로 사용된다.
  • 리액트 네이티브: 모바일 개발도구로 주로 사용된다. 페이스북, 인스타그램, 핀터레스트, 월마트, 테슬라 등이 리액트 네이티브로 모바일 앱을 운영 중이다.
  • 일렉트론: 데스크톱 개발도구로 주로 사용된다. Atom, Slack, Discord, Visual Studio Code 프로그램이 일렉트론으로 만들어졌다.

 

 

4. 개발 환경 설정하기

  • 에디터 - Visual Studio Code(VS Code)

4.1 노드 설치하기

노드 공식 사이트에 접속하여 Current 버전을 설치한다. 'Next' 버튼들을 눌러 설치를 완료한다.

설치가 정상적으로 완료되었는지 확인하기 위해 명령 프롬프트에서 아래 명령어를 입력한다. 노드의 버전이 출력되면 올바르게 설치된 것이다.

$ node -v

npm(node package manager)도 제대로 설치되었는지 확인한다. npm은 노드와 함께 자동적으로 설치된다.

$ npm -v

 

4.2 npm 버전 업데이트하기

명령 프롬프트 혹은 터미널에 아래 명령어를 입력하여 npm을 최신 버전으로 업데이트할 수 있다.

$ npm install -g npm

 

4.3 Visual Studio Code 설치하기

비주얼 스튜디오 코드는 마이크로소프트 사에서 만든 소스 코드 편집기이며, 노드 기반의 데스크톱 개발도구인 일렉트론으로 만들어졌다. 즉, 노드로 만들어진 에디터로 다시 노드 프로그래밍을 하는 상황인 셈.

VS Code 공식 사이트에 들어가서 다운받을 수 있다.

반응형

'Back-End > Node.js' 카테고리의 다른 글

AJAX  (0) 2021.04.11
[Node.js 교과서] 2. 알아두어야 할 자바스크립트  (0) 2021.04.08
Node.js에서 JSON 파일에 데이터를 저장하고 읽는 방법  (0) 2020.10.02
Node.js 입력 받기  (0) 2020.09.18
빙고 게임 만들기  (0) 2020.09.09