티스토리 뷰
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
이벤트 루프는 콜스택이 비어있을 때까지 스택의 함수를 실행
2) Message Queue
setTimeout같은 지연실행 함수를 등록하는 큐 - First In First Out
정해진 timing이 끝나고, 콜스택이 비어있을 경우 등록된 함수를 콜스택에 추가
≫ setTimeout은 콜스택이 비어있을 때 실행됨
3) Job Queue
Promise에 등록된 콜백을 등록하는 큐 - First In First Out
상위함수가 종료되기 전에 콜스택이 비어있지않더라도 잡큐에 등록된 콜백을 콜스택에 추가
≫ Promise는 상위함수가 종료되기 전에 실행됨
이 글은 엘리스 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 |
프론트엔드 개발자 삐롱히의 개발 & 공부 기록 블로그