자바스크립트는 스크립트 언어라서 즉석에서 코드 실행 가능
노드는 Javascript 코드를 모듈화 가능
// var.js
const odd = '홀수';
const even = '짝수';
exports.odd = odd;
exports.even = even;
// func.js
const { odd, even} = require('./var');
function checkOddOrEven(num){
if(num % 2){
return odd;
}
return even;
}
module.exports = checkOddOrEven;
// index.js
const{ odd, even } = require('./var');
const checkNumber = require('./func');
function checkStringOddOrEven(str){
if(str.length % 2){
return odd;
}
return even;
}
console.log(checkNumber(10));
console.log(checkStringOddOrEven('hello'));
console.log(this); // {}
console.log(this === module.exports) // true
function a(){
console.log(this === global);
}
a(); // true
노드의 전역 객체
시스템 환경 변수들이 들어있는 객체
const secretId = process.env.SECRET_ID;
const secretCode = process.env.SECRET_CODE;
NODE_OPTIONS=--max-old-space-size=8192
UV_THREADPOOL_SIZE=8
path.join('/a', '/b', 'c'); // 결과 : /a/b/c
path.resolve('/a', '/b', 'c'); // 결과 /b/c
// url.js
const url = require('url');
const { URL } = url;
const myURL = new URL('https://github.com/yeobi01/Algorithm/tree/master/solved.ac?name=yeobi_01');
console.log('new URL(): ', myURL);
console.log('url.format(): ', url.format(myURL));
// console 출력
new URL(): URL {
href: 'https://github.com/yeobi01/Algorithm/tree/master/solved.ac?name=yeobi_01',
origin: 'https://github.com',
protocol: 'https:',
username: '',
password: '',
host: 'github.com',
hostname: 'github.com',
port: '',
pathname: '/yeobi01/Algorithm/tree/master/solved.ac',
search: '?name=yeobi_01',
searchParams: URLSearchParams { 'name' => 'yeobi_01' },
hash: ''
}
url.format(): https://github.com/yeobi01/Algorithm/tree/master/solved.ac?name=yeobi_01
const myURL = new URL('http://www.gilbut.co.kr/?page=3&limit=10&categor=modejs&category=javascript');
console.log('searchParams:', myURL.searchParams);
console.log('searchParams.getAll():', myURL.searchParams.getAll('category'));
console.log('searchParams.get():', myURL.searchParams.get('limit'));
console.log('searchParams.has():', myURL.searchParams.has('page'));
console.log('searchParams.keys():', myURL.searchParams.keys());
console.log('searchParams.values():', myURL.searchParams.values());
myURL.searchParams.append('filter','es3');
myURL.searchParams.append('filter','es5');
console.log(myURL.searchParams.getAll('filter'));
myURL.searchParams.set('filter', 'es6');
console.log(myURL.searchParams.getAll('filter'));
myURL.searchParams.delete('filter');
console.log(myURL.searchParams.getAll('filter'));
console.log('searchParams.toString():',myURL.searchParams.toString());
myURL.search = myURL.searchParams.toString();
$ node searchParams
searchParams: URLSearchParams {
'page' => '3',
'limit' => '10',
'categor' => 'modejs',
'category' => 'javascript' }
searchParams.getAll(): [ 'javascript' ]
searchParams.get(): 10
searchParams.has(): true
searchParams.keys(): URLSearchParams Iterator { 'page', 'limit', 'categor', 'category' }
searchParams.values(): URLSearchParams Iterator { '3', '10', 'modejs', 'javascript' }[ 'es3', 'es5' ]
[ 'es6' ]
[]
searchParams.toString(): page=3&limit=10&categor=modejs&category=javascript
// dns.mjs
import dns from 'dns/promises';
const ip = await dns.lookup('gilbut.co.kr');
console.log('IP', ip);
const a = await dns.resolve('gilbut.co.kr', 'A');
console.log('A', a);
const mx = await dns.resolve('gilbut.co.kr','MX');
console.log('MX', mx);
const cname = await dns.resolve('www.gilbut.co.kr', 'CNAME');
console.log('CNAME', cname);
const any = await dns.resolve('gilbut.co.kr', 'ANY');
console.log('ANY', any);
$ node dns.mjs
IP { address: '49.236.151.220', family: 4 }
A [ '49.236.151.220' ]
MX [
{ exchange: 'aspmx2.googlemail.com', priority: 10 },
{ exchange: 'aspmx3.googlemail.com', priority: 10 },
{ exchange: 'alt2.aspmx.l.google.com', priority: 5 },
{ exchange: 'alt1.aspmx.l.google.com', priority: 5 },
{ exchange: 'aspmx.l.google.com', priority: 1 }
]
CNAME [ 'slb-1088813.ncloudslb.com' ]
ANY [
{ value: 'ns1-2.ns-ncloud.com', type: 'NS' },
{ value: 'ns1-1.ns-ncloud.com', type: 'NS' },
{
nsname: 'ns1-1.ns-ncloud.com',
hostmaster: 'ns1-2.ns-ncloud.com',
serial: 47,
refresh: 21600,
retry: 1800,
expire: 1209600,
minttl: 300,
type: 'SOA'
}
]
// hash.js
const crypto = require('crypto');
console.log('base64:', crypto.createHash('sha512').update('비밀번호').digest('base64'));
console.log('hex:', crypto.createHash('sha512').update('비밀번호').digest('hex'));
console.log('base64:',crypto.createHash('sha512').update('다른 비밀번호').digest('base64'));
$ node hash
base64: dvfV6nyLRRt3NxKSlTHOkkEGgqW2HRtfu19Ou/psUXvwlebbXCboxIPmDYOFRIpqav2eUTBFuHaZri5x+usy1g==
hex: 76f7d5ea7c8b451b773712929531ce92410682a5b61d1b5fbb5f4ebbfa6c517bf095e6db5c26e8c483e60d8385448a6a6afd9e513045b87699ae2e71faeb32d6
base64: cx49cjC8ctKtMzwJGBY853itZeb6qxzXGvuUJkbWTGn5VXAFbAwXGEOxU2Qksoj+aM2GWPhc1O7mmkyohXMsQw==
const crypto = require('crypto');
crypto.randomBytes(64, (err, buf) => {
const salt = buf.toString('base64');
console.log('salt:', salt);
crypto.pbkdf2('비밀번호', salt, 100000, 64, 'sha512', (err, key) => {
console.log('password:', key.toString('base64'));
});
});
$ node pbkdf2
salt: 8pmiSd8eB02Y7KawklY4vphs3qZVRWgfIRJMGnorH5u9Cb0pXy2i7g0rUwNW0rchZTqLva4e5o0RW+gMxlRECQ==
password: OKqb3FD5yaFN+YJhoSNqdsgq+ZwCl4r7sn+zVKTJ3jRYuobNdBsh9R7eWVP+kPNddqpmzKo5tU5HW8YK0hnu+g==
// util.js
const util = require('util');
const crypto = require('crypto');
const dontUseMe = util.deprecate((x, y) => {
console.log(x + y);
}, 'dontUseMe 함수는 deprecated되었으니 더 이상 사용하지 마세요!');
dontUseMe(1, 2);
const randomBytesPromise = util.promisify(crypto.randomBytes);
randomBytesPromise(64)
.then((buf) => {
console.log(buf.toString('base64'));
})
.catch((error) => {
console.error(error);
});
$ node util
(node:27980) DeprecationWarning: dontUseMe 함수는 deprecated되었으니 더 이상 사용하지
마세요!
(Use `node --trace-deprecation ...` to show where the warning was created)
YMNmZVFzN0zy3O0kHADaj3BhgyyA8PzKFb1TpMqaj2kP2oRORiPbVjwatz4KiV0KhmnXflAcsxy/1J2SgN2+ag==
노드에서 멀티 스레드 방식으로 작업 가능
// 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());
});
// 파일 읽기
const fs = require('fs').promises;
fs.readFile('./readme.txt')
.then((data) => {
console.log(data);
console.log(data.toString());
})
.catch((err) => {
throw err;
});
// 파일 쓰기
const fs = require('fs').promises;
fs.writeFile('./writeme.txt','글이 입력됩니다.')
.then((data) => {
return fs.readFile('./writeme.txt');
})
.then((data) => {
console.log(data.toString());
})
.catch((err) => {
throw err;
});
// 비동기(async) 확인하기
// 출력은 1234 랜덤적으로 나옴. ex) 3241
const fs = require('fs');
fs.readFile('./readme.txt', (err, data) => {
if(err) throw err;
console.log('1번', data.toString());
});
fs.readFile('./readme.txt', (err, data) => {
if(err) throw err;
console.log('2번', data.toString());
});
fs.readFile('./readme.txt', (err, data) => {
if(err) throw err;
console.log('3번', data.toString());
});
fs.readFile('./readme.txt', (err, data) => {
if(err) throw err;
console.log('4번', data.toString());
});
// 출력 : 1 -> 2 -> 3 -> 4
const fs = require('fs');
let data = fs.readFileSync('./readme.txt');
console.log('1번', data.toString());
data = fs.readFileSync('./readme.txt');
console.log('2번', data.toString());
data = fs.readFileSync('./readme.txt');
console.log('3번', data.toString());
data = fs.readFileSync('./readme.txt');
console.log('4번', data.toString());
const fs = require('fs').promises;
fs.readFile('./readme.txt')
.then((data) => {
console.log('1번', data.toString());
return fs.readFile('./readme.txt');
})
.then((data) => {
console.log('2번', data.toString());
return fs.readFile('./readme.txt');
})
.then((data) => {
console.log('3번', data.toString());
return fs.readFile('./readme.txt');
})
.then((data) => {
console.log('4번', data.toString());
return fs.readFile('./readme.txt');
})
.catch((err) => {
throw err;
})
const fs = require('fs').promises;
async function main() {
try{
let data = await fs.readFile('./readme.txt');
console.log('1번', data.toString());
data = await fs.readFile('./readme.txt');
console.log('2번', data.toString());
data = await fs.readFile('./readme.txt');
console.log('3번', data.toString());
data = await fs.readFile('./readme.txt');
console.log('4번', data.toString());
} catch(err) {
console.error(err);
}
}
main();
const buffer = Buffer.from('저를 버퍼로 바꿔보세요');
console.log(buffer);
console.log(buffer.length);
console.log(buffer.toString());
const array = [Buffer.from('띄엄 '), Buffer.from('띄엄 '), Buffer.from('띄어쓰기')];
console.log(Buffer.concat(array).toString());
console.log(Buffer.alloc(5));
//출력
<Buffer ec a0 80 eb a5 bc 20 eb b2 84 ed 8d bc eb a1 9c 20 eb b0 94 ea bf 94 eb b3 b4 ec 84 b8 ec 9a 94>
32
저를 버퍼로 바꿔보세요
띄엄 띄엄 띄어쓰기
<Buffer 00 00 00 00 00>
// 예제 확인을 위해 highWaterMark를 16으로 해서 16byte씩 끊어서 출력
const fs = require('fs');
const readStream = fs.createReadStream('./readme3.txt', {highWaterMark : 16});
const data = [];
readStream.on('data', (chunk) => {
data.push(chunk);
console.log('data:', chunk, chunk.length);
});
readStream.on('end', () => {
console.log('end:', Buffer.concat(data).toString());
})
readStream.on('error', (err) => {
console.log('error:', err);
});
//출력
data: <Buffer ec a0 80 eb 8a 94 20 ec a1 b0 ea b8 88 ec 94 a9> 16
data: <Buffer 20 ec a1 b0 ea b8 88 ec 94 a9 20 eb 82 98 eb 88> 16
data: <Buffer a0 ec 84 9c 20 ec a0 84 eb 8b ac eb 90 a9 eb 8b> 16
data: <Buffer 88 eb 8b a4 2e 20 eb 82 98 eb 88 a0 ec a7 84 20> 16
data: <Buffer ec a1 b0 ea b0 81 ec 9d 84 20 63 68 75 6e 6b eb> 16
data: <Buffer 9d bc ea b3 a0 20 eb b6 80 eb a6 85 eb 8b 88 eb> 16
data: <Buffer 8b a4 2e 0d 0a ec 95 88 eb 85 95 ed 95 98 ec 84> 16
data: <Buffer b8 ec 9a 94 2e 20 ed 97 ac eb a1 9c 20 eb 85 b8> 16
data: <Buffer eb 93 9c 20 ed 97 ac eb a1 9c 20 ec 8a a4 ed 8a> 16
data: <Buffer b8 eb a6 bc 20 ed 97 ac eb a1 9c 20 eb b2 84 ed> 16
data: <Buffer 8d bc> 2
end: 저는 조금씩 조금씩 나눠서 전달됩니다. 나눠진 조각을 chunk라고 부릅니다.
안녕하세요. 헬로 노드 헬로 스트림 헬로 버퍼
// 스트림으로 파일 쓰기 예제
const fs = require('fs');
const writeStream = fs.createWriteStream('./writeme2.txt');
writeStream.on('finish', () => {
console.log('파일 쓰기 완료');
});
writeStream.write('이 글을 씁니다\n');
writeStream.write('한 번 더 씁니다.');
writeStream.end();
// writeme2.txt
이 글을 씁니다
한 번 더 씁니다.
// console
파일 쓰기 완료
const fs = require('fs');
const zlib = require('zlib');
// pipe로 readStream과 writeStream을 합쳐서 파일 복사하기
const readStream = fs.createReadStream('./readme3.txt', {highWaterMark: 16});
const writeStream = fs.createWriteStream('./writeme3.txt');
readStream.pipe(writeStream); // <- 이 코드는 주석처리 해야함
// zlibStream으로 압축해서 파일 복사하기
const zlibStream = fs.createWriteStream('./writeme4.txt.gz');
readStream.pipe(zlibStream).pipe(writeStream);
1GB 파일을 버퍼 방식과 스트림 방식으로 생성했을 때 나타나는 메모리 효율 차이 비교하기
// folder라는 폴더가 없으면 만들고, 그 안에 file.js를 만든 후, newfile.js로 이름 바꾸기
const fs = require('fs').promises;
const constants = require('fs').constants;
fs.access('./folder', constants.F_OK | constants.W_OK | constants.R_OK)
.then(() => {
return Promise.reject('이미 폴더 있음');
})
.catch((err) => {
if(err.code === 'ENOENT'){
console.log('폴더 없음');
return fs.mkdir('./folder');
}
return Promise.reject(err);
})
.then(() => {
console.log('폴더 만들기 성공');
return fs.open('./folder/file.js', 'w');
})
.then((fd) => {
console.log('빈 파일 만들기 성공', fd);
fs.rename('./folder/file.js','./folder/newfile.js');
})
.then(() => {
console.log('이름 바꾸기 성공');
})
.catch((err) => {
console.error(err);
})
파일 및 폴더 생성, 삭제 메소드
폴더 내용 확인 및 삭제
const fs = require('fs').promises;
fs.readdir('./folder')
.then((dir) => {
console.log('폴더 내용 확인', dir);
return fs.unlink('./folder/newfile.js');
})
.then(() => {
console.log('파일 삭제 성공');
return fs.rmdir('./folder');
})
.then(() => {
console.log('폴더 삭제 성공');
})
.catch((err) => {
console.error(err);
});
const fs = require('fs').promises;
fs.copyFile('./readme4.txt', './writeme4.txt')
.then(() => {
console.log('복사 완료');
})
.catch((err) => {
console.error(err);
})
const fs = require('fs').promises;
fs.watch('./target.txt')
.then((eventType, filename) => {
console.log(eventType, filename);
});
const crypto = require('crypto');
const pass = 'pass';
const salt = 'salt';
const start = Date.now();
crypto.pbkdf2(pass, salt, 1_000_000, 128, 'sha512', () => {
console.log('1', Date.now() - start);
});
crypto.pbkdf2(pass, salt, 1_000_000, 128, 'sha512', () => {
console.log('2', Date.now() - start);
});
crypto.pbkdf2(pass, salt, 1_000_000, 128, 'sha512', () => {
console.log('3', Date.now() - start);
});
crypto.pbkdf2(pass, salt, 1_000_000, 128, 'sha512', () => {
console.log('4', Date.now() - start);
});
crypto.pbkdf2(pass, salt, 1_000_000, 128, 'sha512', () => {
console.log('5', Date.now() - start);
});
crypto.pbkdf2(pass, salt, 1_000_000, 128, 'sha512', () => {
console.log('6', Date.now() - start);
});
crypto.pbkdf2(pass, salt, 1_000_000, 128, 'sha512', () => {
console.log('7', Date.now() - start);
});
crypto.pbkdf2(pass, salt, 1_000_000, 128, 'sha512', () => {
console.log('8', Date.now() - start);
});
process.on('uncaughtException', (err) => {
console.error('예기치 못한 에러', err);
});
setInterval(() => {
throw new Error('서버를 고장내주마!');
}, 1000);
setTimeout(() => {
console.log('실행됩니다');
},2000);
// 출력
예기치 못한 에러 Error: 서버를 고장내주마!
실행됩니다
예기치 못한 에러 Error: 서버를 고장내주마!
예기치 못한 에러 Error: 서버를 고장내주마!
예기치 못한 에러 Error: 서버를 고장내주마!
// 계속 반복
// 윈도우
$ netstat -ano | findstr 포트
$ taskkill /pid 프로세스아이디 /f
// 맥/리눅스
$ lsof -i tcp:포트
$ kill -9 프로세스아이디