본문 바로가기

Node.js

Node.js(2) - 내장객체, 내장모듈, 외장모듈, 네트워크

728x90
반응형

1) Node.js

   1-1) 내장객체

   1-2) 내장모듈

   1-3) 외장모듈

   1-4) 네트워크

 

 

 

 

 

1) Node.js

1-1) 내장객체
내장객체를 배우는 이유

브라우저에서 자주 쓰는 것들을 내장객체로 만들어 두었다!
브라우저의 window(전역객체)
항상 브라우저가 자바스크립트를 실행할 때 window(전역객체) 객체를 넣어놓고 실행해준다!
그리고 window 객체 안에는 브라우저를 조작할 수 있는 다양한 메서드들을 제공해주고 있는데
이 중에 대표적인 것이 바로 DOM을 배울 때 확인한 document이다!

"내장객체"는 자주 사용하는 것에 대한 내용을 미리 만들어 둔 것으로 볼 수 있는데 우리는 지금까지 이를 그저 가져다 쓰는 입장이었다.
내장객체를 이해하는 방법으로 공식 문서를 참고하는 것이 가장 좋다고 볼 수 있다!

global(전역객체) 객체의 구성도를 자바스크립트 코드로 표현한 것

const global = {
	AbortController: class {

    },
    Buffer: class {

    },
    __dirname: '',
    __filename: '',
    console {
        log: function() {}
    },
};

console.log(); // 우리가 브라우저에서 window 객체를 생략하고 썼듯이 global 객체 또한 생략 가능하다!
global.console.log();


repl

> global
> global.console
> global.module

 

 

 

 

 

 

> global.module.exports

 

단, global 객체는 마치 우리가 winodw 객체를 생략 가능했듯이 "module.exports"로 사용 가능함!!

 


1.js

module.exports = {
	name: "sangbeom",
	age: 27,
};

console.log(module.exports);


1.js

const a = 100;

module.exports = {
	name: "a",
};

// 여기서 module.exports 변수의 값에 대해 재할당이 이루어져서 module.exports를 콘솔로 출력할 시 "{ name: 'sangbeom', age: 27 }"이 출력됨!
module.exports = {
	name: "sangbeom",
	age: 27,
};

console.log(module.exports);


2.js

const a = require("./1.js"); // require를 통해 1.js의 module.exports의 결과물이 a 변수에 담긴다!
console.log(a); // { name: 'sangbeom', age: 27 }

 


1.js

const a = 100;
const b = 100;

module.exports = {
	name: "sangbeom",
	age: 27,
	b: b,
};


2.js

const a = require("./1.js"); // require를 통해 1.js의 module.exports의 결과물이 a 변수에 담긴다!
const b = 100;
console.log(a); // { name: 'sangbeom', age: 27 }


2.js 파일 실행(repl이 아닌 shell에서 실행)

$ node 2


프로세스는 반드시 하나이다!
변수 공유가 안 된다!
global 객체는 프로세스 간에 공유가 가능하다!(나머지 다른 객체들은 공유가 불가능하다!)

 


서로가 서로를 호출할 경우, 무한루프를 돌게 된다!! => 이것을 "순환참조"라 한다!
1.js

const b = require("./2.js");

module.exports = {
	name: "sangbeom",
	age: 27,
	b: b,
};


2.js

const a = require("./1.js");
console.log(a);

 

2.js 파일 실행(repl이 아닌 shell에서 실행)

$ node 2

 



캐싱
파일을 읽고 실행하는 것도 컴퓨터 입장에선 연산이다!!
예를 들어 피보나치 수열 함수의 경우, 10만이 넘어가면 연산을 너무 많이 하다보니 실행이 느려졌다!
이를 해결하기 위해 사용한 기법이 바로 "메모이제이션"이었다!

메모이제이션 : 한 번 연산한 결과물을 변수에 저장하는 것
즉, 메모이제이션은 메모리를 사용해 연산한 결과물을 넣어놓는 것을 말하는데 이것과 똑같은 것이 바로 "require"이다!!

 

 

3.js

module.exports = {
  a: 1,
  b: 2,
};
// 바로 위의 module.exports 객체와 동일한 코드임!!
exports.a = 1;
exports.b = 2;

 

4.js

const data = require("./3.js");
console.log(data);

 

위의 3.js의 두 버전 모두 4.js 파일을 실행할 시 동일한 결과를 출력함!

 

+) 참고

// 함수를 선언할 시 바로 exports.a, exports.b로 받아서 할당하는 것이 효율적인 방법이다!!
exports.a = (a, b) => a + b;
exports.b = (a, b) => a - b;

 

 

5.js

// module.exports = {}
// module.exports의 default 값은 빈 객체이다!!
console.log(module.exports === exports); // true

// 아래 3가지 표현방식은 모두 동일한 출력 결과를 가짐!!
module.exports = { name: "sangbeom" };
module.exports.name = "sangbeom";
exports.name = "sangbeom";

// 함수를 넘길 경우, 아래와 같은 표현방식을 많이 사용함!!
exports.name = () => {
  return "hello world!";
};

 

 

__dirname, __filename

6.js

console.log(__filename); // __filename : 내 파일의 절대경로를 출력해 줌(실행한 경로의 파일명까지 출력해 줌)
console.log(__dirname); // __dirname : 실행한 경로까지만 출력해 줌

 

7.js

console.log(process); // 프로세스 정보를 출력해 줌!

// 자주 쓰이는 객체들
// env: 시스템 변수를 뜻하며, 이는 OS 변수에 해당한다!!
console.log(process.env); // 매우 중요한데 Node.js에서 해당 코드를 실행할 시 이는 "echo $path"와 같다!!
// 암호화할 때 환경변수를 사용함!
// 또는 AWS, 개인키와 같이 매우 중요한 정보를 환경 변수(env)에 담는다!
// 그 후 환경 변수에서 내용을 가져온다!

// 나중에 가면 백엔드 개발 시 NODE_ENV를 만들고 시작하는데 이를 배포용, 개발용, 테스트용으로 각각 구분하여 환경 변수를 만든다!
// NODE_ENV
// product(배포용 코드)
// development(개발용 코드)
// test(테스트용 코드)
const ip = process.env.NODE_ENV === "development" ? "a" : "b";

// console.log(process.pid);
// console.log(process.arch);
// console.log(process.platform);

// echo $path => Linux에서 이렇게 입력하면 path가 나왔음!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1-2) 내장모듈

Node.js가 기본적으로 제공하는 모듈이 "내장모듈"이다!

 

자주 사용되는 내장모듈

  • Buffer
  • Stream
  • fs
  • path(가장 많이 사용함!!)

 

require('path'); // 'require'의 경우, 내장모듈은 그냥 모듈이름만 적어주면 됨!

 

8.js

const path = require("path");

/*
// 아래의 코드를 사용하지 않고 보다 쉽게 자동으로 OS별 경로를 처리하기 위해 path 모듈을 사용함!!
if (process.platform === "win32") {
  // OS가 Windows인 경우
  path = "C:\\";
} else {
  // OS가 Linux 혹은 MacOS인 경우
  path = "/";
}
*/

/*
// 내가 실행한 위치를 출력 + 9.js
console.log(__dirname + "/9.js");

if (process.platform === "win32") {
  // OS가 Windows인 경우
  console.log(__dirname + "\\9.js");
} else {
  // OS가 Linux 혹은 MacOS인 경우
  console.log(__dirname + "/9.js");
}
*/

console.log(path);
const newPath = path.join(__dirname, "9.js");
console.log(newPath);

 

 

 

 

 

1-3) 외장모듈

- apt    => Linux의 경우
- brew    => MacOs의 경우

apt, brew 모두 결국에는 인터넷을 사용하여 압축파일을 받고 해당 압축파일을 풀어서 설치하는 방식이다!!

npm(Node Package Manager) : 인터넷에서 다른 사람이 만든 자바스크립트 파일을 쉽게 다운로드받을 수 있게 해주는 tool
npm은 Node.js 설치 시 기본으로 설치되는 tool이다!!

server.js

const express = require("express");
const app = express();

app.get("/", (req, res) => {
  console.log(req.query);
  res.send("hello server!!!");
});

app.listen(3000, () => {
  console.log("express server!");
});
// "localhost:3000" 서버에서 내용 확인 가능!!

 

$ npm init => 이를 실행하면 "package.json" 파일이 생성됨!

 

 

 

 

외장모듈 설치

$ npm install [패키지명]
$ npm install express => 이를 실행(최초 외장모듈 설치 시)하면 "node_modules"라는 directory가 하나 생성됨!

$ npm install => 이를 수행하면 기본적으로 "package.json" 파일을 쭈욱 살펴보고 필요한 모듈을 알아서 다운로드해 줌!(예를 들어 express 모듈을 사용해야 하는 js 파일의 경우, express 모듈이 없으면 실행을 시킬 수 없음!! >> 본인의 작업폴더가 어떤 외장모듈에 의존하는지는 package.json 파일 상의 "dependencies" 부분에 명시되어 있음!!)
(중요!!) 그렇기 때문에 github에 공유할 때는 .gitignore 파일에 꼭 node_modules directory를 기재하여 해당 폴더를 꼭 삭제하여 보내줌!(github에 공유된 파일을 실행할 시 npm으로 금방 필요한 모듈 설치가 가능하기에 굳이 node_modules와 같이 큰 폴더를 보내 필요가 없기 때문!!)

 

 

 

 

 

express : Node.js에서 웹 서버를 만들 수 있는 마이크로 프레임워크

 


http://localhost:3000
http://localhost:3000/?name=sangbeom

 

 

+) 참고

  • 프레임워크 : 프로그램을 개발하기 위한 구조를 제공하는 개발 환경
  • 라이브러리 : 개발 시 사용되는 프로그램의 구성 요소로 프로그램을 개발하는 데 공통으로 사용될 수 있는 특정 기능과 함수들의 집합체

 

 

1-4) 네트워크

OSI 7계층

개념

  • 개방형 시스템 상호 연결 모델의 표준임
  • 실제 인터넷에서 사용되는 TCP/IP 는 OSI 참조 모델을 기반으로 상업적이고 실무적으로 이용될 수 있도록 단순화한 것임

탄생 배경

  • 초기 여러 정보 통신 업체 장비들은 자신의 업체 장비들끼리만 연결이 되었기에 호환성이 없었음
  • 모든 시스템들의 상호 연결에 있어 문제 없도록 표준을 정한 것이 OSI 7계층
  • 표준(호환성)과 학습도구에 의미로 제작

작동원리

  1. OSI 7계층은 응용, 표현, 세션, 전송, 네트워크, 데이터 링크, 물리 계층으로 나뉨.
  2. 전송 시 7계층에서 1계층으로 각각의 층마다 인식할 수 있어야 하는 헤더를 붙임(캡슐화)
  3. 수신 시 1계층에서 7계층으로 헤더를 떼어냄(디캡슐화)
  4. 출발지에서 데이터가 전송될 때 헤더가 추가되는데 2계층에서만 오류제어를 위해 꼬리부분에 추가됨
  5. 물리계층에서 1, 0의 신호가 되어 전송매체(동축 케이블, 광섬유 등)를 통해 전송

 

물리계층(Physical Layer)

  • 7계층 중 최하위 계층
  • 주로 전기적, 기계적, 기능적인 특성을 이용해 데이터를 전송
  • 데이터는 0과 1의 비트열, 즉 On, Off의 전기적 신호 상태로 이루어져 해당 계층은 단지 데이터를 전달
  • 단지 데이터 전달의 역할을 할 뿐이라 알고리즘, 오류제어 기능이 없음
  • 장비로는 케이블, 리피터, 허브가 있음

데이터링크 계층(Data-Link Layer)

  • 물리적인 연결을 통하여 인접한 두 장치 간의 신뢰성 있는 정보 전송을 담당(Point-To-Point 전송)
  • 안전한 정보의 전달이라는 것은 오류나 재전송하는 기능이 존재
  • MAC 주소를 통해서 통신
  • 데이터 링크 계층에서 데이터 단위는 프레임(Frame)
  • 장비로는 브리지, 스위치가 있음

네트워크 계층(Network Layer)

  • 중계 노드를 통하여 전송하는 경우 어떻게 중계할 것인가를 규정
  • 라우팅 기능을 맡고 있는 계층으로 목적지까지 가장 안전하고 빠르게 데이터를 보내는 기능을 가지고 있음(최적의 경로를 설정가능)
  • 컴퓨터에게 데이터를 전송할지 주소를 갖고 있어서 통신가능(=우리가 자주 듣는 IP 주소가 바로 네트워크 계층 헤더에 속함)
  • 네트워크 계층에서 데이터 단위는 패킷(Packet)
  • 장비로는 라우터, L3 스위치가 있음

전송 계층(Transport Layer)

  • 종단 간 신뢰성 있고 정확한 데이터 전송을 담당
  • 송신자와 수신자 간의 신뢰성있고 효율적인 데이터를 전송하기 위하여 오류검출 및 복구, 흐름제어와 중복검사 등을 수행
  • 데이터 전송을 위해서 Port 번호를 사용함(대표적인 프로토콜로 TCP와 UDP가 있음)
  • TCP: 순차적으로 데이터를 받음 / UDP: 무작위로 데이터를 받음
  • 전송 계층에서 데이터 단위는 세그먼트(Segment)

세션 계층(Session Layer)

  • 통신 장치 간 상호작용 및 동기화를 제공
  • 연결 세션에서 데이터 교환과 에러 발생 시의 복구를 관리

표현 계층(Presentation Layer)

  • 데이터를 어떻게 표현할지 정하는 역할을 하는 계층
  • 표현 계층은 세가지의 기능을 갖고 있습니다.
    1. 송신자에서 온 데이터를 해석하기 위한 응용계층 데이터 부호화, 변화
    2. 수신자에서 데이터의 압축을 풀수 있는 방식으로 된 데이터 압축
    3. 데이터의 암호화와 복호화
      (MIME 인코딩이나 암호화 등의 동작이 표현계층에서 이루어짐. EBCDIC로 인코딩된 파일을 ASCII 로 인코딩된 파일로 바꿔주는 것이 한가지 예임)

응용 계층(Application Layer)

  • 사용자와 가장 밀접한 계층으로 인터페이스 역할
  • 응용 프로세스 간의 정보 교환을 담당
  • ex) 전자메일, 인터넷, 동영상 플레이어 등

 

 

+) 참고

- Buffer
- Stream
- 글자셋: 아스키 코드(ASCII Code), 유니코드

 

아스키 코드(ASCII Code) : 영문 알파벳을 사용하는 대표적인 문자 인코딩

  • 8bit로 모든 글자를 표현하기 위해 만들어진 것
  • 글자를 1 byte(=8bit =2nibble  =>  2자리 숫자)로 표현하기 위해 사용함
  • 영어를 쓸 때 사용함

 

유니코드 : 전세계의 모든 문자를 컴퓨터에서 일관되게 다루도록 설계된 표준 문자 전산 처리 방식

  • 한글을 쓸 때 사용함

※ 2진수가 보기 힘들기 때문에 이를 일반적으로 16진수로 변환하여 사용하는데 이로 인해 Buffer("Buffer"는 데이터를 16진수로 저장함!)를 주로 사용함!!

 

 

인코딩(encoding)

사람이 인지할 수 있는 문자(언어)를 약속된 규칙에 따라 컴퓨터가 이해하는 언어(0, 1)로 이루어진 코드로 바꾸는 것을 통틀어 일컫는다.

즉, "encoding"이란 정해진 규칙에 따라 코드화, 암호화, 부호화하는 것을 말한다.

이렇게 인코딩을 하는 이유는 정보의 형태 표준화, 보안, 저장 공간 절약 등을 위해서이다.

영화에 자주 등장하는 모스 부호(Morse Code)도 대표적인 인코딩 방식이다.

인코딩의 종류는 여러가지가 있는데 우리는 이번에 문자 인코딩만 살펴볼 예정이다.

 

문자 인코딩(Character Encoding)

문자 인코딩은 "문자"를 "bytes(바이트)"로 인코딩(변환)시킨다.

컴퓨터는 오직 binary data(이진 숫자 시스템으로 표현된 데이터의 한 타입)만 이해하기 때문에

우리 인간들이 사용하는 문자(언어)들은 numeric codes, 숫자 표현 코드로 변환되어야 한다.

이러한 문자 인코딩의 종류는 총 6가지(HTML Encoding, URL Encoding, UNICODE Encoding,

Base64 Encoding, ASCII Encoding, Hex Encoding)가 있다.

 

디코딩

"디코딩(decoding)"이란 인코딩의 반대되는 개념으로 복호화, 역코드화의 의미를 가진다.

저장 공간 효율화, 보안 등의 이유로 인코딩을 한 데이터를 다시 디코딩을 해서 사용할 수 있다.

위에서 설명한 여러 인코딩 방식들이 있었는데 어떠한 특정 인코딩 방식으로 인코딩이 된 데이터를

동일한 방식으로 디코딩을 해주면 데이터를 읽어올 수 있다.

 

인코딩 -> 디코딩 -> 인코딩 -> 디코딩 -> ... 이런 식으로 인코딩과 디코딩은 순환 구조를 갖는다.