[Wecode] Node.js

김택수·2022년 9월 28일
0

1. Node.js가 무엇인지 한 문장으로 설명할 수 있고, 무엇을 위해서 만들어진 기술인지 설명할 수 있습니다.

Chrome 브라우저의 V8 Javascript 엔진을 탑재한 Server Side 오픈소스 Javascript 런타임 이며,
브라우저에서만 실행가능했던 Javascript를 또 다른 실행환경으로 빼내서 브라우저 밖에서도 Javascript를 사용할 수 있도록 한 실행환경(Runtime).

2. Javascript, V8 엔진, Server-side, Runtime에 대해서 설명할 수 있습니다.

  • Javascript : 브라우저에서 HTML 요소생성부터 페이지 및 기능을 동적으로 처리할 수 있는 프로그래밍 언어. 2005년 구글 맵스는 웹에서 Javascript의 가능성을 보여줬고, Javascript로 웹 서비스를 개발하려는 시도가 늘어났다. 이러한 과정을 거치면서 브라우저는 Javascript를 더욱 빠르게 실행 할 수 있는 엔진이 필요해졌다.

  • V8 엔진 : 고성능 엔진의 필요성에 따라 Google이 주도하여 만든 V8 엔진은, Javascript로 작성된 코드를 컴퓨터가 해석하기 쉬운 바이트 코드로 변환하는 역할을 수행한다. 바이트 코트란 직접 CPU 내의 레지스터와 누산기를 어떤 식으로 사용하라고 명령하는 명령문이기 때문에 사람은 이해하기 어렵지만 컴퓨터가 이해하기 쉬운 장점이 있어 V8 엔진은 Javascript 코드의 속도를 더욱 비약적으로 상승시키며 생태계를 키워나갈 수 있었고, Javascript를 브라우저 밖으로 꺼내려는 움직임들이 나타났다.

  • Server-side : 라이언 달은 Node.js를 발표하면서 운영체제의 파일 시스템에 접근해서 파일을 조작하게 하는 등의 기능을 가능하게 했으며, 네트워크 서버를 만드는 것에 목적이 있었다. 당시 인기있는 웹 서버인 Apache Server가 최대 10,000개 이상의 동시 요청을 다루는데 어려움이 있었고 Javscript를 통해 이를 해결하는 것이 목적이 있었기에 Node.js는 Server-side Runtime이라고 할 수 있다.

3. Node.js로 개발하면서 얻을 수 있는 장점과 사용하는 이유에 대해서 설명할 수 있습니다.

1) FE와 BE의 기술 스택 통합

  • 양쪽을 동일한 언어로 사용하면 코드를 모듈로 만들어서 재사용이 가능하다.
  • Javascript를 사용하는 개발자는 FE와 BE 모두를 학습하는데 용이하다.
  • 개발팀의 생산성 향상에 도움이 된다.

2) 빠른 처리속도와 동시 요청 처리 성능

  • Node.js는 인터프리터 방식이 아닌 바이트 코드로 변환하는 JIT 컴파일 방식을 채택하여 처리속도가 굉장히 빠르다
  • libuv 라는 비동기 I/O를 중점으로 한 오픈 소스 라이브러리를 사용함으로써 이벤트 기반, Single Thread, non-blocking I/O모델을 구현하여 지연없이 빠르게 동시 요청을 처리 할 수 있다.

인터프리터 방식 : 기본적으로 Javascript는 인터프리터 방식인데 작성된 코드를 런타임 이전에 기계어로 바로 변환하는 것이 아닌 런타임 이후에 인터프리터라는 해석기를 한 줄 씩 돌려 해석하기 때문에 속도는 컴파일러 방식에 비해 느릴 수 있으나, 실시간 코드 수정이 가능한 장점이 있다.

3) MSA(Micro Service Application)에 적합함

  • MSA 구조는 기능이 추가될 때 마다 기존 시스템과 분리된 다른 시스템을 구축하는 방법으로 확장하는 구조를 말하는데, Node.js는 상대적으로 가벼운 런타임이기 때문에 MSA 구조와 조화롭게 사용이 가능하다.

4. REPL (Read Eval Print Loop)과 .js 파일을 사용해서 javascript 코드를 node.js(실행환경)에서 실행할 수 있습니다.

1. REPL

REPL 환경이란 Javascript코드와 Node.js의 다양한 표현식을 실시간으로 처리하는 대화형 쉘을 의미한다. 대화형 쉘은 입력한 Javascript 코드를 읽고(Read), 코드를 해석한 결과를 평가하고(Eval), 결과를 사용자에게 출력하고(Print), 종료 신호를 보낼때까지 반복한다.(Loop) 쉽게는 대화형 쉘을 이용하여 js파일 없이도 Javascript 코드를 테스트하는 방법이다.

2. .js파일 이용하여 node에서 실행

node가 설치된 환경에서 터미널에 접속하여 node 파일명.js 를 입력하면 node환경에서 js파일을 실행 할 수 있다.

5. Node.js의 모듈 시스템에 대해서 설명할 수 있고, Custom 모듈을 직접 만들 수 있습니다.

Module System

모듈이란 쉽게 레고의 블럭이라고 생각하면 쉽게 이해가 가능하다. 어떠한 기능을 하는 블럭을 조합하느냐에 따라서 결과가 달라지듯이, 이미 어떠한 기능을 하게끔 만들어져있는 모듈을 조합하여 쉽게 웹 서비스를 만들어 낼 수 있다.

Node.js의 Module System

CommonJS라는 모듈명세를 따른다. 이 명세는 모듈화에 필요한 것을 크게 세가지로 나눈다.

1. 모든 모듈은 자신만의 독립적인 실행 영역이 있어야 한다.
쉽게는 전역변수와 지역변수를 분리하는 것을 의미하며, 파일마다 독립적인 파일스코프가 있기 때문에 파일 하나에 모듈 하나를 작성하는 방법으로 독립적인 실행 영역을 만든다.

2. 모듈을 외부에서 사용할 수 있도록 공개한다.
파일마다 독립된 모듈을 가지고 있고, 이 모듈은 외부에서 사용할 수 있도록 exports라는 저역 객체를 이용해 외부로 공개할 수 있다.

3. 모듈을 사용하는 영역에서는 require() 함수를 이용해 모듈을 불러온다.

Custom Module 만들기

1. exports 객체를 사용해 Module을 만드는 방법

// calculator.js

const initialNumber = 0;

exports.add = (x, y) => initialNumber + x + y; //export 객체에 add method를 정의한 것
exports.substract = (x, y) => initialNumber + x - y; //export 객체에 substract method를 정의 한 것

// index.js

const calculator = require("./calculator.js");

console.log(calculator.add(1,5)); // 6

1. module.exports를 사용해 Module을 만드는 방법

// calculator.js

const initialNumber = 0;

const add = (x, y) => { return  x + y; } // add method를 정의한 것
const substract = (x, y) => { return x - y; } // substract method를 정의 한 것

module.exports = {add, substract}

// index.js

const {add, substract} = require("./calculator.js");

console.log(add(1,5)); // 6

6. Node.js에 내장되어 있는 모듈 중에 가장 중요한 file system 모듈을 사용할 수 있으며, 동기/비동기에 대한 개념에 대해서 이해할 수 있습니다.

file system module이란 node.js에 내장되어있는 fs모듈을 불러와 File에 접근해서 읽고 쓰는 역할을 하는 모듈을 말한다.

이 때, 파일을 불러오는 두 가지 방법이 있는데 동기와 비동기로 파일을 불러오는 방법이다.
동기(Synchoronic) : 동시에 동작하지 않고, 하나의 동작이 끝난 후 다음 동작을 시작하는 동작방법
비동기(Asynchoronic) : 동시에 작업을 수행하는 방법.

동기적으로 File System을 이용해 File을 다루는 방법

Method 자체에 sync가 붙어있기 때문에 위에서 아래로 내려가면서 명령을 수행한다. 이전 명령이 완료되지 않으면 다음 명령이 실행되지 않기 때문에 순서를 보장받을 수 있고, 미리 불러온 정보를 수정해야하는 코드가 하단에 있을 때 유용하게 사용할 수 있다.

ex) HTML 요소를 불러오지 않고 js파일을 먼저 불러들이면, HTML 요소가 존재하지 않는다는 Error를 띄우는 것.

// info.txt
Name: Harry Potter
Age : 22

// index.js
const fs = require('fs');

const readTxt = fs.readFileSync("./info.txt", "utf-8");
console.log(readTxt) // info.txt의 내용을 불러왔음.

const addInfo = `${readTxt}PhoneNumber : 000-0000-0000\nModified at: ${Date.Now()}` 

fs.writeFileSync("./info.txt", addInfo); // 불러온 readTxt에 다음 내용을 추가

const updateInfo = fs.readFileSync("./info.txt", "utf-8");
console.log(updateInfo) // 내용이 추가된 addInfo를 불러옴
// Name: Harry Potter
// Age : 22
// PhoneNumber : 000-0000-0000
// Modified at: 15616546515

console.log("추가적으로 실행되어야 하는 코드 1"); 
console.log("추가적으로 실행되어야 하는 코드 2");
console.log("추가적으로 실행되어야 하는 코드 3");
console.log("추가적으로 실행되어야 하는 코드 4");

비동기적으로 File System을 이용해 File을 다루는 방법

같은 로직에서 비동기적으로 File을 다루려면, readFile 같은 sync가 빠진 Method를 사용하여야하며, 3번째 인자로 콜백함수가 들어간다. 위에서 아래로 내려가면서 수행되는것이 아닌 전체 코드가 백그라운드에서 동시에 실행되기 때문에, 실행순서를 보장받을 수 없다.

// info.txt
Name: Harry Potter
Age : 22

// index.js
const fs = require('fs');

const readTxt = fs.readFile("./info.txt", "utf-8", (err, data) => {
	console.log(data)  // info.txt의 내용을 불러왔음.

	const addInfo = `${readTxt}PhoneNumber : 000-0000-0000\nModified at: ${Date.Now()}`  // 불러온 readTxt에 다음 내용을 추가
    
    fs.writeFile("./info.txt", addInfo, "utf-8", (err, data) => { // 불러온 readTxt에 다음 내용을 추가
    	
       fs.readFile("./info.txt", "utf-8", (err, data) => {
		console.log(data)
	};
    }); 
};
// 내용이 추가된 addInfo를 불러옴
// Name: Harry Potter
// Age : 22
// PhoneNumber : 000-0000-0000
// Modified at: 15616546515

console.log("추가적으로 실행되어야 하는 코드 1"); 
console.log("추가적으로 실행되어야 하는 코드 2");
console.log("추가적으로 실행되어야 하는 코드 3");
console.log("추가적으로 실행되어야 하는 코드 4");
profile
개발자 키우기 Lv1

0개의 댓글