Node.js

박정훈·2022년 2월 21일
0

Backend

목록 보기
1/6

등장 배경

단방향 통신 위주의 WEB 1.0에서 사용자와 상호작용 하는 WEB 2.0으로 발전하면서 웹 페이지에서의 자바스크립트 동작은 더욱 복잡해 졌고, 복잡한 자바스크립트를 실행하기 위해 고성능의 자바스크립트 실행기가 필요해졌다...😭

구글에서 크롬 웹 브자우저를 위한 V8이라는 자바스크립트 엔진을 만들었다.
V8 엔진 덕분에 자바스크립트의 실행 속도가 굉장히 빨라졌다!!👍

여기에 더해 V8 엔진은 누구나 사용 가능한 오픈소스 프로젝트였다. 여기서 라이언 달 아저씨가 나온다! (현재 라이언 달 아저씨는 Node.js에서 후회하는 점이 많다고 한다...) 이렇게 좋아진 자바스크립트를 기존의 웹 브라우저에서만 사용하는 것이 아닌 다른 곳에서도, 어느 환경에서든지 사용 가능하게 하자! 해서 라이언 달 아저씨가 프로젝트를 맡아 등장하게 된 것이 Node.js인 것이다.

한줄로

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

이제 자바스크립트는 크로스 플랫폼 실행, 제한 없는 동작과 더불어 다양한 어플리케이션 개발에 활용되고 있다.
Node.js는 프론트와 백엔드를 넘나들며 활약중인 것이다.

특징

싱글 쓰레드

쓰레드는 명령을 실행하는 단위다. 하나의 쓰레드는 한번에 한가지의 동작밖에 하지 못한다. 즉 싱글 쓰레드는 말 그대로 한 번에 한가지 동작만 수행하는 것이고, 멀티 쓰레드는 동시에 여러 동작이 가능하다는 것을 의미한다.

그래서 싱글 쓰레드가 나쁜가?

쓰레드가 늘어나지 않는 점이 리소스 관리에 있어서 효율적이다. 쓰레드가 많아진다는 것은 CPU의 자원을 그만큼 많이 쓴다는 것이다. 다만, 쓰레드 기반의 작업 효율은 떨어질 것이다. 대표적으로 CPU 연산 작업이 있다.
이러한 싱글 쓰레드의 특징으로 인해 Node.js는 비동기 동작으로 쓰레드 기반의 작업을 최소화 한다.

비동기

동작을 실행하고 완료가 되길 기다리지 않는다. 너 할거 해! 하고 자기 갈 길 가버린다. 바로 다음 동작이 실행되는 것이다.

이벤트 기반

비동기 동작의 완료를 처리하는 방법이다. 비동기 방식은 특정 동작을 실행한 후에 해당 동작에 신경 끄고 자기 갈 길 간다 그랬다. 대신!!
해당 동작이 완료될 경우에 실행 할 함수를 미리 등록해 놓는다. 그리고 비동기 동작이 완료 된다면 미리 등록된 함수를 실행한다.

Node.js는 싱글 쓰레드니까 비동기 동작이 필요하고, 비동기 동작을 구현하기 위해서 이벤트 기반의 동작 방식을 채택 한 것이다.

비동기 방식의 활용

Promise

이른 바 callback 지옥을 어느정도 해소시켜 주는 친구다. Porimise함수가 동작이 완료되면 then에 등록된 callback이, 동작에 오류가 발생했다면 catch에 등록된 callback이 실행된다.

function promiseFunc() {
  return promise1()
  	.then(console.log)
  	.catch(console.log)
}

Async-Await

syntactic sugar의 한 종류인 친구이다. 읽는 사람이나 작성하는 사람이 편하게 디자인 된 문법이다. async 함수 내에서 promise함수의 결과는 await으로 받을 수 있다. await 한 promise 함수가 완료될 때까지 다음 라인으로 넘어가지 않는다. 마치 순차적 프로그래밍처럼 작성이 가능하다. 오류처리는 try, catch문으로 가능하다.

async function func() {
  try {
    const result = await promise1();
    console.log(result);
  } catch(err) {
    console.log(err);
  }
}

promise의 병렬 실행 all

promise.all은 promise를 전부 동시에 실행시킨다. 그리고 한꺼번에 결과를 돌려받는다. promise1과 promise2는 동시에 실행 될 것이며, 등록된 두 함수가 모두 마무리 된다면 한번에, 즉 5초가 아닌 3초의 시간만에 결과값을 반환할 것이다.

function promiseAllFunc() {
  const [r1, r2] = await Promise.all([
    promise1(), // 2초 짜리 동작
    promise2(), // 3초 짜리 동작
  ]);
  console.log(r1, r2)
}

이벤트 루프

Call Stack

작성된 함수들이 등록되는 LIFO 스택이다. 이벤트 루프는 콜스택이 완전히 비어질 때까지 스택의 함수를 실행한다.

Message Queue

setTimeout같은 지연실행 함수를 등록하는 FIFO Queue다. 등록된 시간이 되면, Message Queue에 올라가고, 콜스택이 비어졌을 경우에 콜스택에 올라간다.

Job Queue

Promise에 등록 된 콜백을 등록하는 FIFO Queue다. 상위 함수가 종료되기 전에 콜스택이 비어있지 않아도 Job Queue에 등록된 콜백을 콜스택에 추가한다.

모듈

// malza.js
const name = 'malza';
const job = 'developer';
module.exports = {
  name,
  job
};

=================================외부
const Malza = require('./malza') //  { name: 'malza', job: 'developer'}

변수명으로 작성

모듈을 object로 만들고, key-value를 지정해서 내보낸다.

// malza.js
const name = 'malza';
const job = 'developer';

exports.name = name;
exports.job = job;

=================================외부
const Malza = require('./malza') //  { name: 'malza', job: 'developer'}

함수를 export 하는 모듈

모듈을 함수로 만들어서 모듈 사용 시 값을 정할 수 있게 내보낸다.

// malza.js
module.exports = (name, age, nationality) => {
  return {
    name,
  	job,
  };
};

=================================외부
const Malza = require('./malza')('malza', 'developer') //  { name: 'malza', job: 'developer'}

josn 파일

require로 json파일을 load 할 수 있다. object로 자동 파싱된다.

const data = require('./data') // json 파일

require 할 때 모듈 코드가 실행되고, 첫 require시에 caching된다.
모듈 코드를 여러 번 실행하기 위해서는 함수 모듈로 작성하자.

profile
그냥 개인적으로 공부한 글들에 불과

0개의 댓글