티스토리 뷰

개발공부/🟩 Node.js

[NodeJS] Node.js 이해하기

2022. 7. 26. 18:56

 

 

Node.js

Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.

nodejs.org

 

 

 Node.js의 등장 배경 

 

WEB 1.0   :   단방향 통신 위주

→  WEB 2.0   :   사용자와 상호작용

→  웹페이지의 자바스크립트 동작이 복잡해지면서 고성능의 자바스크립트 실행기가 필요

 

구글에서 크롬을 위한 V8엔진 개발  →  자바스크립트의 실행속도가 대폭 향상됨

 

V8엔진은 오픈소스 프로젝트로

이를 이용해 자바스크립트를 웹브라우저에서 뿐만 아니라 어느 환경에서나 동작할 수 있게 만든 것이 Node.js

≫ Node.js는 자바스크립트를 어느 환경에서나 실행할 수 있게 해주는 실행기

 

 

브라우저의 JavaScript          vs.           Node.js

브라우저에서 실행                                    크로스 플랫폼 실행

웹 내부 제한된 동작                                  제한없는 동작

웹 프론트 개발자의 언어                          다양한 어플리케이션 개발

 

 

Node.js로

1) 프론트엔드  :  React.js

2) 백엔드  :  express.js

3) 모바일앱   :  React-Native  → 한가지 코드로 iOS와 Android 개발

4) 데스크탑앱  :  Electron  →  디스코드, 슬랙 등 앱 데스크탑앱 개발

5) 머신러닝  :  Brain.js  → 자바스크립트로 구현하는 딥러닝

 

등을 할 수 있다.

 

 

 

 Node.js의 특징 

 

싱글 쓰레드 - 비동기 - 이벤트 기반

→ Node.js는 싱글 쓰레드이기 때문에 비동기 동작 필요. 비동기 동작을 구현하기 위해 이벤트 기반의 동작 방식 사용

 

▶  쓰레드란?

명령을 실행하는 단위

1개의 쓰레드는 한번에 1가지 동작만 실행 가능

 

- 싱글 쓰레드  :  한 번에 한가지 동작만 수행함

- 멀티 쓰레드  :  동시에 여러 동작 수행 가능

 

싱글 쓰레드의 장점  :  쓰레드가 늘어나지 않기 때문에 리소스 관리에 효율적

싱글 쓰레드의 단점  :  쓰레드 기반의 작업들의 효율이 떨어짐 ex) CPU 연산 작업

≫ 그래서 Node.js는 비동기 동작으로 쓰레드 기반의 작업을 최소화 함

 

▶  비동기란?

- 동작을 실행한 후 완료가 되길 기다리지 않는 방식

- 동작의 완료를 기다리지 않기 때문에 다른 동작을 바로 실행 가능

- Node.js는 싱글 쓰레드이기 때문에 비동기 방식을 사용함

 

▶  이벤트 기반이란?

- 비동기 동작의 완료를 처리하는 방법

- 비동기 방식은 특정 동작을 실행한 후, 해당 동작을 전혀 신경 쓰지 않음

- 대신 해당 동작이 완료될 겨웅 실행할 함수를 미리 등록 (= 이벤트를 등록한다)

- 비동기 동작이 완료가 되면 미리 등록된 함수(=이벤트)를 실행

 

 

 

 ES6 

ECMAScript 버전 6 이후를 통틀어 일반적으로 ES6라 한다

 

▶ ECMAScript

- 계속해서 발전해나가는 자바스크립트의 표준문법

- 2015년, ECMAScript 버전 6 이후로 많은 현대적인 문법이 추가됨

→ 현대적인 문법은 코드가 간결해지고 이는 생산성 향상에 도움을 줌

 

- Node.js는 빠르게 최신 ECMAScript를 지원 중 → ES6의 모든 문법을 지원하는 것은 아님

 

 

▶ 자주 사용되는 ES6 문법

 

1) let, const

- 기존 문법  :  var는 상수와 변수의 구분이 없음

- ES6  :  let은 변수, cosnt는 상수

// 기존문법 : 상수와 변수의 구분이 없음
var TITLE = 'NODE.JS';
var director = 'elice';
director = 'rabbit';
TITLE = 'ES6' // 오류 없음


// ES6 : 상수와 변수를 구분 가능
const TITLE = 'NODE.JS';
let director = 'elice';
director = 'rabbit';
TITLE = 'ES6'; // 오류 발생

 

 

2) Template String

- 기존 문법  :  +기호를 사용해 문자열과 변수를 연결, 줄바꿈문자 \n 사용 필요  

- ES6  :  ``(백틱)을 사용하여 문자열 사이에 간단하게 변수 사용 가능, 따옴표 가능, 줄바꿈 지원

// 기존 문법 : + 를 사용해 문자열과 변수 연결. 줄 바꿈 문자 \n 사용 필요
var name = 'elice';
var age = 5;
var hi = 'My name is '
	+ name 
	+ '.\n I\'m ' 
	+ age 
	+ 'years old.';
    
console.log(hi);


// ES6 : 백틱(`)을 사용하여 문자열 사이에 변수, 따옴표 등을 간단하게 사용 가능. 줄 바꿈 지원
const name = 'elice';
const age = 5;
const hi = `My name is ${name}.
I'm ${age} years old`;

console.log(hi);

 

 

3) arrow function

- 화살표 함수를 통해 간결하게 함수를 표현 가능

- 같은 이름의 함수 재선언 불가

// 기존 문법 ===========================================
// 기본함수 표현방법
function doSometing(param) {
    ...
}

// 익명함수 표현방법
setTimeout(function(param) {
    ...
}, 0);

// 같은 이름의 함수 재선언 가능
function doSometing() {
    ...
}

// ES6 ===========================================
// 상수형으로 표현 가능
const doSomething = (param) => {
    ...
}

// 익명함수 간결하게 표현가능
setTimeout((param) => {
    ...
}, 0);

// 같은 이름의 함수 재선언 불가능
doSomething = () => {
    ...
}

 

 

4) class

- 기존 문법  :  일반적인 형태의 class 구현 가능

- ES6  :  일반적인 형태의 class 구현 가능

// 기존문법 : prototype으로 class 함수 구현
function Model(name, age) {
    this.name = name;
    this.age = age;
}

Model.prototype.getInfo = function() {
    console.log(this.name, this.age);
}

var model = new Model('elice', 5);
model.getInfo();


// ES6 : 일반적인 형태의 class 구현 가능
class Model {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    getInfo() {
    	console.log(this.name, this.age);
    }
}

const model = new Model('elice', 5);
model.getInfo();

 

 

5) destructing

// 기존 문법
var obj = {name: 'elice', age: 5};
var name = obj.name;
var age = obj.age;
var arr = ['some', 'values'];
var first = arr[0];
var second = arr[1];


// ES6
const obj = {name: 'elice', age: 5};
const { name, age } = obj;		// Object의 key와 같은 이름으로 변수 선언 가능
const { name: n1, age: a1 } = obj;	// 다른 이름으로 변수 선언하는 방법

const arr = ['some', 'values'];
const [first, second] = arr;		// arr에서 순차적으로 변수 선언 가능

 

 

 

 

 비동기 코딩 

 

▶ 비동기 코딩이란?

비동기-이벤트 기반 동작을 코드로 구현하는 방법

 

 

▶ Node.js에서 비동기 동작을 구현하는 세 가지 방법

 

1) Callback  :  전통적인 자바스크립트 이벤트 기반 코딩 방식

db.getUsers((err, users) => {
	console.log(users);
});

 

async1, async2, async3 …를 동기적으로 실행해야 할 경우,

Node.js는 기본적으로 비동기 동작을 callback으로 처리하기 때문에

계속해서 callback의 callback의 callback의 callback  . . .    ≫   콜백지옥

 

db.getUsers((err, users) => {
	if (err) { 
        ...
        return;
	}
	async1(users, (r1) => {
		async2(r1, (r2) => {
			async3(r2, (r3) => {
            	...
            });
		});
	});
});

 

2) Promise  :  callback의 단점을 보완한 비동기 코딩 방식

-  동작이 완료되면 then에 등록된 callback 실행

-  오류가 발생하면 catch에 등록된 callback 실행

db.getUsersPromise()
	.then((users) => {
		return promise1(users);
	})
	.then(r1 => promise2(r1))
	.catch(...);

 

callback 기반 함수를 Promise함수로 변경하는 방법

- resolve는 then에 등록된 callback 실행

- reject는 catch에 등록된 callback 실행

function getUsersPromise(params) {
	return new Promise((resolve, reject) => {
    	getUsers(params, (err, users) => {
        	if(err) {
            	reject(err);
                return;
            }
            resolve(users);
        });
    });
}

 

 

promise3 함수가 promise1와 promise2의 결괏값을 같이 사용하고 싶다면 콜백 지옥과 유사해짐

promise1()
	.then(r1 => {
		return promise2(r1)
			.then(r2 => promise3(r1, r2))
});

 

3) Async-Await  :  promise의 단점을 보완한 비동기 코딩 방식

-  async-await은 promise의 다른 문법

-  async함수 내에서 promise함수의 결과는 await으로 받을 수 있음

-  await한 promise함수가 완료될 때 까지 다음 라인으로 넘어가지 않음 => 순차적 프로그래밍처럼 작성 가능

-  async함수의 return은 Promise

async function doSomething() => {
    const r1 = await promise1();
    const r2 = await promise2(r1);
    const r3 = await promise3(r1, r2);
    . . .
    return r3;
});
   
doSomething().then(r3 => {
    console.log(r3);
});
// Promise 오류 처리 - .then() / .catch()
function doSomething(msg) {
    return promise1()
    	.then(r => {
    		console.log(r)
    	})
    	.catch(e => {
    		console.error(e)
    	});
}


// async 오류처리 - try{} / catch{}
async function doSomething(msg) {
    try {
        const r = await promise1();
        console.log(r);
    } catch(e) {
    	console.error(e);
    }
}

 

 

≫  위 코드들은 주로 비동기 동작을 동기적으로 처리하는 방식

비동기 동작을 동기적으로 처리할 필요가 없다면 여러 동작을 동시에 실행하는 것이 유용

→ Promise.all()은 여러 Promise를 동시에 실행시키고 등록된 모든 함수가 마무리되면 한꺼번에 결과값을 반환

// promise1 실행 소요시간 1초
// promise2 실행 소요시간 2초

async function sync() {
    const r1 = await promise1();
    const r2 = await promise2();
    console.log(r1, r2);
}
// 3초 소요

async function parallel() {
    const [r1, r2] = await Promise.all([
        promise1(),
        promise2(),
    ]);
    console.log(r1, r2);
}
// 2초 소요

 

 

 

 

 이벤트 루프 

 

▶ 이벤트 루프란?

이벤트(event)를 처리하는 반복되는 동작(loop)

→ Node.js가 비동기-이벤트 동작을 처리하는 일련의 반복 동작

 

이벤트 루프는 자바스크립트의 일반적인 동작 방식으로 브라우저에도 있음

브라우저와 Node.js의 이벤트 루프는 기본적인 동작방식에 큰 차이가 없음

 

 

▶ 이벤트 루프의 주요 구성요소

 

1) Call Stack

작성된 함수들이 등록되는 스택 - Last In First Out 

이벤트 루프는 콜스택이 비어있을 때까지 스택의 함수를 실행

 

이미지출처 : 엘리스 Node.js와 MongoDB Ⅰ - 01 Node.js 이해하기 강의자료

 

 

 

2) Message Queue

setTimeout같은 지연실행 함수를 등록하는 큐 - First In First Out

정해진 timing이 끝나고, 콜스택이 비어있을 경우 등록된 함수를 콜스택에 추가

 

≫ setTimeout은 콜스택이 비어있을 때 실행됨

 

이미지출처 : 엘리스 Node.js와 MongoDB Ⅰ - 01 Node.js 이해하기 강의자료

 

 

 

3) Job Queue

Promise에 등록된 콜백을 등록하는 큐 - First In First Out

상위함수가 종료되기 전에 콜스택이 비어있지않더라도 잡큐에 등록된 콜백을 콜스택에 추가

 

≫ Promise는 상위함수가 종료되기 전에 실행됨

 

이미지출처 : 엘리스 Node.js와 MongoDB Ⅰ - 01 Node.js 이해하기 강의자료

 

 

 

 

 

 


 이 글은 엘리스 AI트랙 5기 강의를 들으며 정리한 내용입니다.

반응형

'개발공부 > 🟩 Node.js' 카테고리의 다른 글

[NodeJS] Node.js와 MongoDB  (0) 2022.07.31
[NodeJS] Express.js로 REST API 구현하기  (0) 2022.07.30
[NodeJS] Express.js의 Middleware  (0) 2022.07.28
[NodeJS] 웹과 Express.js  (0) 2022.07.27
[NodeJS] NPM과 모듈  (0) 2022.07.27
프로필사진
개발자 삐롱히

프론트엔드 개발자 삐롱히의 개발 & 공부 기록 블로그