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 사용
- 디버깅을 위해 사용
- 개발하면서 변수에 값이 제대로 들어 있는지 확인하기 위해 사용
- 에러 발생 시 에러 내용을 콘솔에 표시하기 위해 사용
- 코드 실행 시간을 알아보려고 할 때 사용
-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
:인터넷 주소를 쉽게 조작하도록 도와주는 모듈
-기존 노드 방식
- url.parse(주소): 주소를 분해한다. WHATWG 방식과 비교하면 username과 password 대신 auth 속성이 있고, searchParams 대신 query가 있다.
- url.format(객체): WHATWG 방식 url과 기존 노드의 url을 모두 사용할 수 있다. 분해되었던 url 객체를 다시 원래 상태로 조립한다.
*host 부분 없이 pathname부분만 오는 주소인 경우에는 WHATWG 방식이 처리할 수 없다.
*WHATWG 방식은 search부분을 searchParams라는 특수한 객체로 반환하므로 유용하다.
4) querystring: WHATWG 방식의 url 대신 기존 노드의 url을 사용할 때 search 부분을 사용하기 쉽게 만드는 모듈
- ? (물음표)로 시작
- ? 뒤에 키= 값 형식으로 데이터를 전달
- 여러 키가 있을 경우에는 &로 구분
- 주소를 통해 데이터를 전달할 때 사용
//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)비밀번호
- 단방향 암호화: 복호화(암호화된 문자열을 원래 문자열로 되돌려놓는 것)할 수 없는 암호화 방식
- 비밀번호는 보통 단방향 암호화 알고리즘을 사용해서 암호화
- 한 번 암호화하면 원래 문자열을 찾을 수 없다. → 복호화할 수 없으므로 암호화라고 표현하는 대신 해시 함수라고 부르기도 함
- 해시 기법 (어떠한 문자열을 고정된 길이의 다른 문자열로 바꿔버리는 방식)사용
- 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 |