Node.js

Node.js 2주차 공부

예림밈 2022. 4. 13. 15:01

1. REPL

REPL = Read(읽고), Eval(해석하고),Print(반환하고),Loop(종료할 때까지 반복)

2. 모듈

모듈: 특정한 기능을 하는 함수나 변수들의 집합, 관련된 코드들을 하나의 코드 단위로 캡슐화 하는 것

  • 모듈로 만들어두면 여러 프로그램에 해당 모듈을 재사용할 수 있다.
  • 자바스크립트에서 코드를 재사용하기 위해 함수로 만드는 것과 비슷하다.
  • 보통 파일 하나가 모듈 하나가 된다. 파일별로 코드를 모듈화할 수 있어 관리하기 편하다.

-module.exports

//var.js
const odd="홀수입니다.";
const even="짝수입니다.";

//변수들을 담은 객체를 대입, 이 파일은 모듈로서 가능-->변수들을 모아둔 모듈이 되는 것
//다른 파일에서 이 파일을 불러오면 module.exports에 대입된 값을 사용할 수 있다. (odd, even)
module.exports={
    odd,
    even,
};
//func.js

//require 함수 안에 불러올 모듈의 경로를 적는다. 
const{odd,even}=require('./var');

function checkOddOrEven(num){
    if (num%2){
        return odd
    }
    return even;
}

//module.exports에는 객체만 대입해야하는 것이 아니라 함수나 변수를 대입해도 된다.
module.exports=checkOddOrEven;
//index.js

// var.js 와 func.js 모두 참조--> 모듈 하나가 여러 개의 모듈을 사용할 수 있다.
const {odd,even}= require('./var');

//모듈로부터 값을 불러올 때 변수 이름을 다르게 지정할 수 있다. 
const checkNumber= require('./function');

function checkStringOddOrEven(str){
    if (str.length %2){
        return odd;
    }
    return even;
}

console.log(checkNumber(10)); //짝수입니다
console.log(checkStringOddOrEven('hello')); //홀수입니다

 

3. 노드 내장 객체 알아보기

1) global: 전역 객체, 모든 파일에 접근할 수 있다.

global.require, global.console →global 모두 생략해서 require*,** console 사용

//globalA.js
module.exports=()=>global.message;
//globalB.js
const A=require("./globalA");
global.message="안녈하세요";

console.log(A()); //안녕하세요

→콘솔 결과는 globalB에서 넣은 global.message 값을 globalA에서도 접근할 수 있음을 보여준다.

*global 객체의 남용: global 객체의 속성에 값을 대입하여 파일 간에 데이터를 공유할 수 있지만, 이를 남용하면 안된다. 프로그램의 규모가 커질수록 어떤 파일에서 global 객체에 값을 대입했는지 찾기 힘들어져 유지 보수에 어려움을 겪는다.

 

2) console

-console 사용

  1. 디버깅을 위해 사용
  2. 개발하면서 변수에 값이 제대로 들어 있는지 확인하기 위해 사용
  3. 에러 발생 시 에러 내용을 콘솔에 표시하기 위해 사용
  4. 코드 실행 시간을 알아보려고 할 때 사용

-console 로깅 함수

//console.js
const string='abc';
const number=1;
const boolean=true;
const obj={
    outside:{
        inside:{
            key:'value',
        },
    },
};

console.time('전체 시간');
console.log('평범한 로그입니다. 쉼표로 구분해 여러 값을 찍을 수 있습니다.');
console.log(string,number,boolean);
console.error('에러 메시지는 console.error에 담아주세요');

console.table([{name:'제로', birth:1994},{name:'hero',birth:1988}]);

console.dir(obj,{colors:false, depth:2});
console.dir(obj,{colors:true, depth:1});

console.time('시간 측정');
for (let i=0; i<100000; i++){}
console.timeEnd('시간 측정');

function b(){
    console.trace('에러 위치 추적');
}
function a() {
    b();
}
a();

console.timeEnd('전체 시간');

출력 결과

  • console.time(레이블): console.timeEnd(레이블)과 대응되어 같은 레이블을 가진 time과 timeEnd 사이의 시간을 측정
  • console.log(내용): 평범한 로그를 콘솔에 표시
  • console.error(에러 내용): 에러를 콘솔에 표시
  • console.table(배열): 배열의 요소로 객체 리터럴을 넣으면, 객체의 속성들이 테이블 형식으로 표현
  • console.dir(객체, 옵션): 객체를 콘솔에 표현할 때 사용, 옵션의 colors를 true로 하면 콘솔에 색이 추가되어 보기가 한결 편해진다, depth는 객체 안의 객체를 몇 단계까지 보여줄지를 결정
  • console.trace(레이블): 에러가 어디서 발생했는지 추적할 수 있게 한다.

3) 타이머

  • setTimeout(콜백 함수, 밀리초): 주어진 밀리초 (1000분의 1초) 이후에 콜백 함수를 실행
  • setInterval(콜백 함수, 밀리초): 주어진 밀리초마다 콜백 함수를 반복 실행
  • setImmediate(콜백 함수): 콜백 함수를 즉시 실행

→ 이 타이머 함수들은 모두 아이디를 반환한다, 아이디를 사용하여 타이머를 취소할 수 있다.

  • clearTimeout(아이디): setTimeout을 취소
  • clearInterval(아이디):setInterval을 취소
  • clearImmediate(아이디):setImmediate 취소

4) __filename, __dirname

:노드에서는 파일 사이에 모듈 관계가 있는 경우가 많으므로 때로는 현재 파일의 경로나 파일명을 알아야한다.

//filename.js
console.log(__filename); 
console.log(__dirname);

/* 출력
C:\\Users\\user\\Desktop\\sty\\filename.js
C:\\Users\\user\\Desktop\\sty
*/

5) exports,require

1) exports: module 객체 말고 exports 객체로도 모듈 생성 가능

-module.exports와 동일하게 동작 →exports와 module.exports가 같은 객체를 참조하기 때문

-exports를 사용할 때는 객체만 사용할 수 있다 (함수 대입 불가)

 

*한 모듈에 exports 객체와 module.exports를 동시에 사용하지 않는 것이 좋다. 둘 사이에 참조 관

계가 있기 때문이다.

참조관계) exports⇒module.export⇒{}

//var.js

//module.exports 객체 사용
const odd="홀수입니다.";
const even="짝수입니다.";

module.exports={
    odd,
    even,
};

//exports 객체 사용: 각각의 변수를 exports 객체에 하나씩 넣음

exports.odd="홀수입니다.";
exports.even="짝수입니다.";

2) require : 모듈을 불러오는 역할

 

6) process

: process 객체는 현재 실행되고 있는 노드 프로세스에 대한 정보를 담고 있다.

  • process.version: 설치된 노드의 버전을 보여준다.
  • process.arch: 프로세서 아키텍처 정보
  • process.platform: 운영체제 플랫폼 정보
  • process.uptime(): 프로세스가 시작된 후 후른 시간, 단위는 초 단위
  • process.pid: 현재 프로세스의 아이디
  • process.execPath: 노드의 경로
  • process.cwd() : 현재 프로세스가 실행되는 위치
  • process.cpuUsage(): 현재 cpu 사용량

6-1) process.env: REPL에 process.env를 입력하면 많은 정보가 출력된다. 대표적으로 UV_THREADPOOL_SIZE 와 NODE_OPTIONS가 있다.

  • NODE_OPTIONS: 노드를 실행할 때의 옵션들을 입력 받는 환경 변수
  • UV_THREADPOOL_SIZE: 노드에서 기본적으로 사용하는 스레드풀의 스레드 개수를 조절할 수 있게 해준다.

-process.env는 서비스의 중요한 키를 저장하는 곳으로도 사용된다.

→ 서버나 데이터베이스의 비밀번호와 각종 API 키를 코드에 직접 입력하는 것은 위험하다.

→ 중요한 비밀번호는 process.env의 속성으로 대체

const secretID=process.env.SECRET_ID;
const secretCode=process.env.SECRET_CODE;

//process.env에 직접 SECRET_ID와 SECRET_Code를 넣으면 된다. 

6-2) process.nextTick(콜백) : 이벤트 루프가 다른 콜백 함수들보다 nextTick의 콜백 함수를 우선으로 처리하도록 만든다.

setImmediate(()=>{
	console.log('immediate');
});
process.nextTick(()=>{
	console.log('nextTick');
});

setTimeout(()=>{
	console.log('timeout');
},0);
Promise.resolve()
.then(()=> console.log('promise'));

/* 출력
nextTick
promise
timeout
immediate
*/

⇒process..nextTick이 제일 먼저 실행되고, 맨 마지막에 Promise를 넣은 것은 resolve된 Promise도 nextTick처럼 다른 콜백들보다 우선시 되기 때문이다. 그래서 process.nextTick과 Promise를 마이크로태스크라고 따로 구분지어 부른다.

 

 

6-3) process.exit(코드)

: 실행 중인 노드 프로세스를 종료한다. 서버 환경에서 이 함수를 사용하면 서버가 멈추므로 특수한 경우를 제외하고는 서버에서 잘 사용하지 않는다. 하지만 서버 외의 독립적인 프로그램에서는 수동으로 노드를 멈추기 위해 사용된다.

: process.exit 메서드는 인수로 코드 번호를 줄 수 있다. 인수를 주지 않거나 0을 주면 정상 종료를 뜻하고 1을 주면 비정상 종료를 뜻한다. 만약에 에러가 발생해서 종료하는 경우에는 1을 넣으면 된다.

 

4. 노드 내장 모듈 사용하기

1. os

  • os.type() : 운영 체제의 종류를 보여줌
  • os.uptime() : 운영체제 부팅 이후 흐른 시간 (초)을 보여줌
  • os.hostname() :컴퓨터의 이름을 보여줌
  • os.release(): 운영체제의 버전을 보여줌
  • os.homedir(): 홈 디렉터리 경로를 보여줌
  • os.tmpdir() : 임시 파일 저장 경로를 보여줌
  • os.cpus() : 컴퓨터의 코어 정보를 보여줌
  • os.freemem() : 사용가능한 메모리를 보여줌
  • os.totalmem() : 전체 메모리 용량을 보여줌

2.  path

//path.js
const { normalize } = require('path');

const path = require('path'); 
const string=__filename;

console.log('path.sep:',path.sep);

console.log('path.delimiter:',path.delimiter);
console.log('-------------------------------')

console.log('path.dirname():',path.dirname(string));

console.log('path.extname():',path.extname(string));

console.log('path.basename():',path.basename(string));
console.log('-------------------------------')
console.log('path.parse():',path.parse(string));

console.log('path.format():',path.format({
    dir:'C:\\\\users\\\\zerocho',
    name:'path',
    ext:'.js',
}));
console.log('-------------------------------');
console.log('path.isAbsolute(C:\\\\):',path.isAbsolute('C:\\\\'));
console.log('path.isAbsolute(./home):',path.isAbsolute('./home'));
console.log('-------------------------------')
console.log('path.relative():',path.relative('C:\\\\users\\\\zerocho\\\\path.js','C:\\\\'));
console.log('path.join():',path.join(__dirname,'..','..','/users','.','zerocho'));
console.log('path.resolve():',path.resolve(__dirname,'..','/users','.','zerocho'));

 

//출력
path.sep: \\
path.delimiter: ;
-------------------------------
path.dirname(): C:\\Users\\zerocho
path.extname(): .js
path.basename(): path.js
-------------------------------
path.parse(): {
  root: 'C:\\\\',
  dir: 'C:\\\\Users\\\\zerocho',
  base: 'path.js',
  ext: '.js',
  name: 'path'
}
path.format(): C:\\users\\zerocho\\path.js
-------------------------------
path.isAbsolute(C:\\): true
path.isAbsolute(./home): false
-------------------------------
path.relative(): ..\\..\\..
path.join(): C:\\Users\\zerocho
path.resolve(): C:\\zerocho
  • path.sep : 경로의 구분자 
  • path.delimiter: 환경 변수의 구분자 ;
  • path.dirname(경로): 파일이 위치한 폴더 경로를 보여줌
  • path.extname(경로): 파일의 확장자를 보여줌
  • path.basename(경로, 확장자): 파일의 이름 (확장자 포함)
  • path.parse(경로): 파일 경로를 root, dir, base, ext, name 으로 분리
  • path.format(경로): path.parse()한 객체를 파일 경로로 합침
  • path.normalize(경로) : / 나 \ 를 실수로 여러 번 사용했거나 혼용했을 때 정상적인 경로로 변환
  • path.isAbsolute(경로): 파일의 경로가 절대 경로인지 상대 경로인지를 true나 false로 알림
  • path.realative(경로) : 경로를 두 개 넣으면 첫 번째 경로에서 두번째 경로로 가는 방법을 알림
  • path.join(경로,..) : 여러 인수를 넣으면 하나의 경로로 합침
  • path.resolve(경로, ..): path.join과 비슷하지만 차이가 있다.

*join/resolve 차이: /를 만나면 resolve는 절대 경로로 인식해서 앞의 경로를 무시하고, join은 상대경로로 처리

→path.join(’/a’,’/b’); // 결과 : /a/b

→path.resolve(’/a’,’/b’); //결과: /b

 

*상대 경로: 현재 파일이 기준이 된다. 현재 파일과 같은 경로면 점 하나를, 현재 파일보다 한 단계 상위 경로면 점 두개를 사용해 표현

*절대 경로: 루트 폴더(C:\)나 노드 프로세스가 실행되는 위치가 기준

ex) C:\users\zero\path.js 에서 C:\로 가고 싶다면 절대 경로에서는 그냥 C:\를 입력하면 된다. 하지만 상대 경로에서는 ..\..을 해야 두 디렉토리 위로 올라가 C:\가 된다.

 

3) url

:인터넷 주소를 쉽게 조작하도록 도와주는 모듈

-기존 노드 방식

  1. url.parse(주소): 주소를 분해한다. WHATWG 방식과 비교하면 username과 password 대신 auth 속성이 있고, searchParams 대신 query가 있다.
  2. url.format(객체): WHATWG 방식 url과 기존 노드의 url을 모두 사용할 수 있다. 분해되었던 url 객체를 다시 원래 상태로 조립한다.

*host 부분 없이 pathname부분만 오는 주소인 경우에는 WHATWG 방식이 처리할 수 없다.

*WHATWG 방식은 search부분을 searchParams라는 특수한 객체로 반환하므로 유용하다.

 

4) querystring: WHATWG 방식의 url 대신 기존 노드의 url을 사용할 때 search 부분을 사용하기 쉽게 만드는 모듈

  1. ? (물음표)로 시작
  2. ? 뒤에 키= 값 형식으로 데이터를 전달
  3. 여러 키가 있을 경우에는 &로 구분
  4. 주소를 통해 데이터를 전달할 때 사용
//querystring.js
const url=require('url');
const querystring= require('querystring');

const parsedUrl=url.parse('<http://www.gilbut.co.kr/?page=3&limit=10&category=node.js&category=javascript>');
const query= querystring.parse(parsedUrl.query);
console.log('querystring.parse():',query);
console.log('querystring.stringify():',querystring.stringify(query));

/*출력
querystring.parse(): [Object: null prototype] {
  page: '3',
  limit: '10',
  category: [ 'node.js', 'javascript' ]
}
querystring.stringify(): page=3&limit=10&category=node.js&category=javascript
*/
  • querystring.parse(쿼리): url의 query 부분을 자바스크립트 객체로 분해
  • querystring.stringfy(객체): 분해된 query 객체를 문자열로 다시 조립

5) crypto

: 다양한 방식의 암호화를 도와주는 모듈 ex)비밀번호

  1. 단방향 암호화: 복호화(암호화된 문자열을 원래 문자열로 되돌려놓는 것)할 수 없는 암호화 방식
  2. 비밀번호는 보통 단방향 암호화 알고리즘을 사용해서 암호화
  3. 한 번 암호화하면 원래 문자열을 찾을 수 없다. → 복호화할 수 없으므로 암호화라고 표현하는 대신 해시 함수라고 부르기도 함

- 해시 기법 (어떠한 문자열을 고정된 길이의 다른 문자열로 바꿔버리는 방식)사용

  • createHash(알고리즘): 사용할 해시 알고리즘을 넣는다. 현재는 sha512 정도로 충분하지만 나중에 sha512 마저도 취약해지면 더 강화된 알고리즘을 바꿔야 한다.
  • update(문자열): 변환할 문자열을 넣는다.
  • digest(인코딩): 인코딩할 알고리즘을 넣는다. base64, hex,latin1 이 주로 사용되는데 base64가 결과 문자열이 가장 짧아 애용됨, 결과물로 반환된 문자열을 반환

2. 양방향 암호화

: 암호화된 문자열을 복호화할 수 있으며, 키 (열쇠)라는 것이 사용된다. 대칭형 암호화에서 암호를 복호화하려면 암호화할 때 사용한 키와 같은 키를 사용해야 한다.

6) util

:각종 편의 기능을 모아둔 모듈

  • util.deprecate: 함수가 deprecated 처리 되었음을 알린다. 첫 번째 인수로 넣은 함수를 사용했을 때 경고 메시지가 출력된다. 두번째 인수로 경고 메시지를 넣으면 된다. 함수가 조만간 사라지거나 변경될 때 알려줄 수 있어 편리하다.
  • util.promisify: 콜백 패턴을 프로미스 패턴으로 바꾼다. 바꿀 함수를 인수로 제공하면 된다.

7) child_process

: 노드에서 다른 프로그램을 실행하거나 명령어를 수행하고 싶을 때 사용하는 모듈

: 이 모듈을 통해 다른 언어의 코드를 실행하고 결괏값을 받을 수 있다.

:이름이 child_process인 이유는 현재 노드 프로세스 외에 새로운 프로세스를 띄워서 명령을 수행하고, 노드 프로세스에 결과를 알려주기 때문.

const { stderr } = require('process');

//exec: 셸을 실행해서 명령어를 수행
const exec= require('child_process').exec; 
const process= exec('dir');

//stdout: 표준출력
process.stdout.on('data', function(data) {
    console.log(data.toString());
});

//stderr: 표준에러
process.stderr.on('data',function(data){
    console.error(data.toString());
});

/*출력
(현재 폴더의 파일 목록 표시)
*/
//test.py
print("파이썬 실행")

//spawn.js

const spawn =require('child_process').spawn;
const process = spawn('python',['test.py']);

process.stdout.on('data', function(data) {
    console.log(data.toString());
});

process.stderr.on('data',function(data){
    console.error(data.toString());
});

*exec와 spawn 차이점: exec은 셸을 실행해서 명령어를 수행하고, spawn은 새로운 프로세스를 띄우면서 명령어를 실행, spawn에서도 세 번째 인수로 {shell: true} 를 제공하면 exec처럼 셸을 실행해서 명령어를 수행

 

 

'Node.js' 카테고리의 다른 글

Node.js 2주차 공부 (2주차)  (0) 2022.04.18
Node.js 시작하기 (교재: Node.js 교과서)  (0) 2022.04.12