교육/엘리스 SW 학습 내용

[엘리스sw] 5주차 1일 - Node.js와 MongoDB I

꼽파 2024. 1. 20. 18:40


◆  Node.js 이해
◆  Node.js 특징
◆  Node.js 시작하기
◆  ES6
◆  비동기 코딩
◆  이벤트 루프


Node.js 이해

Node.js 등장 배경

  • 단방향 통신 위주였던 WEB 1.0에서 사용자와 상호작용하는 WEB 2.0으로 발전하게 되면서 웹페이지의 자바스크립트 동작이 복잡해졌고, 이를 실행하기 위해 고성능의 JavaScript 실행기가 필요하게 됨.
  • 구글에서는 크롬웹브라우저를 위한 v8이라는 자바스크립트 엔진을 만들게 됨.

 

Node.js의 탄생

  • V8엔진으로 자바스크립트 실행 속도가 굉장히 빨라졌음.
  • Node.js는 자바스크립트를 어느 환경에서나 실행할 수 있게 해주는 실행기

 

Node.js vs Browser

Browser의 JavaScript node.js
브라우저에서 실행 크로스 플랫폼 실행
웹 내부 제한된 동작 제한 없는 동작
웹 프론트 개발자의 언어 다양한 어플리케이션 개발

 

Node.js로 할 수 있는 것들

  • Front-End : React.js - 웹서비스
  • Back-End : Express.js - 웹서비스
  • Mobile-App : React-Native - 한 가지 코드로 iOS와 Android개발
  • Desktop-App : Electron - discord, Slack 등 앱 개발
  • Machine-Learning : Brain.js - JavaScript로 구현하는 딥러닝

Node.js 특징

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

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

· 쓰레드 : 명령을 실행하는 단위
· 한 개의 쓰레드는 한번에 한 가지 동작만 실행 가능

  • 싱글 쓰레드 : 한번에 한 가지 동작만 수행함
  • 멀티 쓰레드 : 동시에 여러 동작 수행 가능

싱글 쓰레드의 장점과 단점

  • 장점 : 쓰레드가 늘어나지 않기 때문에 리소스 관리에 효율적
  • 단점 : 쓰레드 기반의 작업들의 효율이 떨어짐 (ex. CPU 연산 작업)
  • Node.js는 비동기 동작으로 쓰레드 기반의 작업을 최소화함.

비동기

  • 동작을 실행한 후 완료가 되길 기다리지 않는 방식
  • 동작의 완료를 기다리지 않기 때문에 다른 동작을 바로 실행 가능
  • Node.js는 싱글 쓰레드이기 때문에 비동기 방식을 사용함

이벤트 기반

  • 비동기 동작의 완료를 처리하는 방법
  • 비동기 방식은 특정 동작을 실행한 후, 해당 동작을 전혀 신경쓰지 않음.
  • 대신 해당 동작이 완료될 경우 실행할 함수를 미리 등록함.
  • 비동기 동작이 완료되면 미리 등록된 함수를 실행함.

Node.js 시작하기

어떤 버전으로 시작해야하까?
· Node.js는 빠르게 개발 중
· 보안 이슈 및 버그 수정, 최신기술 빠르게 적용
· 급변하는 기술은 가장 안정적인 최신 버전을 선택하는 것이 최선

LTS Long-Term Support 버전
Node.js의 안정적이고 오래 지원하는 버전명
ES6 ECMAScript 버전 6 이후를 통틀어 일반적으로 ES6이라고 부름
ECMAScript 계속해서 발전해가는 javaScript의 표준문법
2015년, ECMAScript 버전 6 이후로 많은 현대적인 문법이 추가됨.

ES6

ES6 사용하는 이유
· 현대적인 문법으로 생산성 향상에 도움이 됨.
· Node.js는 빠르게 최신 ECMAScript를 지원함. ES6의 모든 문법을 지원하지는 않음.
· 자주 사용되는 유용한 문법을 익히고 필요한 부분에 적절하게 활용하는 것이 좋음.

  • let, const
  • Template String (``, ${})
  • arrow function
  • class
  • destructuring

arrow function

// 상수 함수 선언
const doSomething = () => {
    console.log('안녕하세요');
};

// 화살표 문법을 사용하여 간결하게 표현된 익명 함수
setTimeout(() => {
    console.log('이름 없는 함수');
}, 0);

// 상수 변수에 새로운 값을 할당하려는 시도 (에러 발생)
// 'const'로 선언된 상수는 재할당할 수 없음
// doSomething = () => {
//     console.log('안녕');
// };

 

class와 destructuring

class Model {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }

    displayInfo() {
        console.log(`이름: ${this.name}, 나이: ${this.age}`);
    }
}

// Model 클래스의 인스턴스 생성
const myModel = new Model('홍길동', 30);

// 객체 속성을 해체하여 추출
const { name, age } = myModel;
console.log(`해체된 이름: ${name}, 해체된 나이: ${age}`);

myModel.displayInfo();

 

비동기 코딩

· 비동기 : 이벤트 기반 동작을 코드로 구현하는 방법
· Node.js에서 비동기 동작을 구현하는 세 가지 방법을 학습

• Callback : 전통적인 JavaScript의 이벤트 기반 코딩 방식
Promise : callback의 단점을 보완한 비동기 코딩 방식
• Async-Await : promise의 단점을 보완한 비동기 코딩 방식

 

Callback

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

 

  • 비동기 동작 : db.getUsers 함수는 데이터베이스에서 유저목록을 찾아오는 비동기 동작을 수행
  • 이벤트 등록/실행 : 쿼리가 완료되면 오류가 있는지, 혹은 유저목록의 결과로 미리 등록된 callback 함수를 실행
  • callback의 표준 : 에러와 결과를 같이 전달하는 것이 표준으로 자리잡혀 있음.
  • 콜백 지옥 우려

 

Promise

· Promise 함수는 동작이 완료되면 then에 등록된 callback 실행
· 오류가 발생한 경우 catch에 등록된 callback 실행
· Chaining을 사용해 코드를 간결하게 Short-hand 표현 방법으로 더욱 간결하게
- Return 생략 가능
- 인자가 하나인 경우 () 생략 가능

db.getUsersPromise()
	.then((users) => {
		return promise1(users)
	})
	.then(r1 => promise2(r1))
	.catch();
function doSomething(msg) {
	return promise1()
		.then(r => {
			console.log(r)
		})
		.catch(e => {
			console.error(e)
		});
}

 

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

· Promise는 resolve, reject 두 가지 함수를 가짐.
· async1 함수의 실행 결과에 따라 resolve, reject로 분리

  • reject : catch에 등록된 callback을 실행
  • resolve : then에 등록된 callback을 실행
function getUsersPromise(params) {
  return new Promise((resolve, reject) => {
    getUsers(params, (err, users) => {
      if (err) {
        reject(err);
        return;
      }
      resolve(users);
    });
  });
}

 

promise의 병렬 실행

· Promise.all : promise 함수를 동시에 실행시키고 등록된 모든 함수가 마무리되면 결과값을 한꺼번에 반환

async function sync() {
	const r1 = await promise1();
	const r2 = await promise2();
	console.log(r1, r2);
}

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

 

Async - Await

· 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)
});
async function doSomething(msg) {
	try {
		const r= await promise1();
		console.log(r);
	} catch(e) {
		console.error(e);
	}
}

 

  • callback지옥 → promise chaining으로 해결
  • promise 지옥  → async-await으로 해결

현대 JavaSript에서는 대부분 가독성이 좋은 async-await를 지향하지만,
특정 상황에 맞는 비동기 코딩 방법들을 구사할 줄 알아야 함.


이벤트 루프

· 이벤트(event)를 처리하는 반복되는 동작(loop)
· Node.js가 비동기-이벤트 동작을 처리하는 일련의 반복 동작

· 브라우저와 Node.js의 이벤트 루프
· 이벤트 루프는 JavaScript의 일반적인 동작 방식으로, 브라우저에도 있음.
· 브라우저와 Node.js의 이벤트 루프는 기본적인 동작방식에 큰 차이가 없음.
· 이벤트루프의 기본적인 동작 원리를 이해하는 것이 중요함.

이벤트 루프 구성요소

Call Stack 작성된 함수들이 등록되는 LIFO 스택
이벤트 루프는 콜스택이 비어있을 때까지 스택의 함수를 실행
Message Queuse  setTimeut과 같은 지연실행 함수를 등록하는 FIFO 큐
정해진 timing이 끝나고, 콜스택이 비어있을 경우 등록된 함수를 콜스택에 추가
Job Queuse Promise에 등록된 콜백을 등록하는 FIFO 큐
상위 함수가 종료되기 전에 콜스택이 비어있지 않더라도 잡큐에 등록된 콜백을 콜스택에 추가


· 비동기 동작의 실행 타이밍을 이해하는 것이 중요
· setTimeout은 콜스택이 비어있을 때 실행됨.
· Promise는 상위함수가 종료되기 전에 실행됨.

 

728x90