안녕하세요, 코린이의 코딩 학습기 채니 입니다.
[Node.js 교과서]의 책을 참고하여 포스팅한 개인 공부 내용입니다.
노드 기능 알아보기
노드 내장 모듈 사용하기
노드는 운영체제 정보에 접근, 클라이언트가 요청한 주소에 대한 정보 등을 가져올 수 있으며, 이러한 기능을 하는 모듈을 제공합니다.
os
- 노드는 os 모듈에 정보가 담겨 있어 정보를 가져올 수 있음
(웹 브라우저에 사용되는 js는 운영체제의 정보를 가져올 수 없음) - require('os') 또는 require('node:os')로 모듈을 불러옴
(os라는 파일이 존재하진 않지만, 노드가 알아서 내장 모듈인 것을 파악해 불러옴)
os.js
const os = require("os");
console.log("----- 운영 체제 정보 -----");
console.log("os.arch() : ", os.arch());
console.log("os.platform() : ", os.platform());
console.log("os.type() : ", os.type());
console.log("os.uptime() : ", os.uptime());
console.log("os.hostname() : ", os.hostname());
console.log("os.release() : ", os.release());
console.log("----- 경로 -----");
console.log("os.homedir() : ", os.homedir());
console.log("os.tmpdir() : ", os.tmpdir());
console.log("----- cpu 정보 -----");
console.log("os.cpus() : ", os.cpus());
console.log("os.cpus().length : ", os.cpus().length);
console.log("----- 메모리 정보 -----");
console.log("os.freemem() : ", os.freemem());
console.log("os.totalmem() : ", os.totalmem());
@콘솔출력값
$ node part3/os
----- 운영 체제 정보 -----
os.arch() : arm64
os.platform() : darwin
os.type() : Darwin
os.uptime() : 20217
os.hostname() : bagchaeeun-ui-Macmini.local
os.release() : 22.2.0
----- 경로 -----
os.homedir() : /Users/parkchaeeun
os.tmpdir() : /var/folders/mf/76z8f5jd7sz8bxxj8ld1bxvm0000gn/T
----- cpu 정보 -----
os.cpus() : [
{
model: 'Apple M1',
speed: 24,
times: { user: 1084000, nice: 0, sys: 710790, idle: 13938110, irq: 0 }
},
{
model: 'Apple M1',
speed: 24,
times: { user: 996140, nice: 0, sys: 651750, idle: 14092940, irq: 0 }
},
{
model: 'Apple M1',
speed: 24,
times: { user: 808850, nice: 0, sys: 525840, idle: 14420260, irq: 0 }
},
{
model: 'Apple M1',
speed: 24,
times: { user: 693990, nice: 0, sys: 440660, idle: 14631330, irq: 0 }
},
{
model: 'Apple M1',
speed: 24,
times: { user: 755440, nice: 0, sys: 170220, idle: 14859440, irq: 0 }
},
{
model: 'Apple M1',
speed: 24,
times: { user: 554510, nice: 0, sys: 130330, idle: 15104160, irq: 0 }
},
{
model: 'Apple M1',
speed: 24,
times: { user: 355150, nice: 0, sys: 69070, idle: 15369850, irq: 0 }
},
{
model: 'Apple M1',
speed: 24,
times: { user: 220740, nice: 0, sys: 39730, idle: 15537870, irq: 0 }
}
]
os.cpus().length : 8
----- 메모리 정보 -----
os.freemem() : 869531648
os.totalmem() : 17179869184
- os.arch()
- os.platform()
- os.type()
: 운영체제의 종류를 보여줌 - os.uptime()
: 운영체제 부팅 이후 흐른 시간(초)를 보여줌 (process.uptime()은 노드의 실행 시간) - os.hostname()
: 컴퓨터의 이름을 보여줌 - os.release()
: 운영체제의 버전을 보여줌 - os.homedir()
: 홈 디렉터리 경로를 보여줌 - os.tmpdir()
: 임시 파일 저장 경로를 보여줌 - os.cpus()
: 컴퓨터의 코어 정보를 보여줌 - os.freemem()
: 사용 가능한 메모리(RAM)를 보여줌 - os.totalmem()
: 전체 메모리 용량을 보여줌 - os.constants
: 각종 에로와 신호에 대한 정보를 가지고 있음
path
- 폴더와 파일의 경로를 쉽게 조작하도록 도와주는 모듈
- 운영체제별로 경로 구분자가 다르기 때문에 path 모듈이 필요
path.js
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(
"path.basename - extname : ",
path.basename(string, path.extname(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(
"path.normalize() : ",
path.normalize("C://users\\\\zerocho\\path.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")
);
@콘솔출력값
$ node part3/path
path.sep : /
path.delimiter : :
---------------------------
path.dirname() : /Users/parkchaeeun/project/playground-cepark/part3
path.extname() : .js
path.basename() : path.js
path.basename - extname : path
---------------------------
path.parse() : {
root: '/',
dir: '/Users/parkchaeeun/project/playground-cepark/part3',
base: 'path.js',
ext: '.js',
name: 'path'
}
path.format() : C:\users\zerocho/pathjs
path.normalize() : C:/users\\zerocho\path.js
---------------------------
path.isAbsolute(C:\) : false
path.isAbsolute(./home) : false
---------------------------
path.relative() : ../C:\
path.join() : /Users/parkchaeeun/project/users/zerocho
path.resolve() : /zerocho
- path.sep
: 경로 구분자 - path.delimiter
: 환경 변수 구분자 - path.dirname(경로)
: 파일이 위치한 폴더 경로를 보여줌 - path.extname(경로)
: 파일 확장자를 보여줌 - path.basename(경로, 확장자)
: 파일의 이름 (확장자 포함)을 표시, 파일의 이름만 표시하고 싶다면 basename의 두 번째 인수로 파일의 확장자를 넣어줌 - path.parse(경로)
: 파일 경로를 root, dir, base, ext, name으로 분리 - path.format(객체)
: path.parse()한 객체를 파일 경로로 합침 - path.normalize(경로)
: /나 \를 실수로 여러 번 사용했거나 혼용했을 때 정상적인 경로로 변환 - path.isAbsolute(경로)
: 파일의 경로가 절대경로인지 상대경로인지를 true/false로 알림 - path.relative(기준 경로, 비교 경로)
: 경로를 두 개 넣으면 첫 번째 경로에서 두 번째 경로로 가는 방법을 알려줌 - path.join(경로, ...)
: 여러 인수를 넣으면 하나의 경로로 합침 - path.resolve(경로, ...)
: path.join()과 비슷하지만 차이가 있음. 아래 참고
✱ path.join과 path.resolve의 차이
/ 를 만나면 path.resolve는 절대 경로로 인식해서 앞의 경로를 무시하지만,
path.join은 상대 경로로 처리합니다.
path.join('/a', '/b', 'c'); // 결과 : /a/b/c/
path.resolve('/a', '/b', 'c'); // 결과 : /b/c
url
- 인터넷 주소를 쉽게 조작하도록 도와주는 모듈
- WHATWG 방식을 이용
url.js
const url = require("url");
const { URL } = url;
const myURL = new URL(
"https://chanychu.tistory.com/manage/newpost/?type=post&returnURL=%2Fmanage%2Fposts%2F#anchor"
);
console.log("new URL() : ", myURL);
console.log("url.format() : ", url.format(myURL));
@콘솔출력값
$ node part3/url
new URL() : URL {
href: 'https://chanychu.tistory.com/manage/newpost/?type=post&returnURL=%2Fmanage%2Fposts%2F#anchor',
origin: 'https://chanychu.tistory.com',
protocol: 'https:',
username: '',
password: '',
host: 'chanychu.tistory.com',
hostname: 'chanychu.tistory.com',
port: '',
pathname: '/manage/newpost/',
search: '?type=post&returnURL=%2Fmanage%2Fposts%2F',
searchParams: URLSearchParams { 'type' => 'post', 'returnURL' => '/manage/posts/' },
hash: '#anchor'
}
url.format() : https://chanychu.tistory.com/manage/newpost/?type=post&returnURL=%2Fmanage%2Fposts%2F#anchor
URL 생성자에 주소를 넣어 객체로 만들면 주소가 부분별로 정리 되는 것을 확인할 수 있습니다.
해당 방식이 WHATWG의 url
- url.format(객체)
: 분해되었던 url 객체를 다시 원래 상태로 조립
주소가 host 부분 없이 pathname 부분만 오는 경우, new URL(pathname, host)로 처리해야 WHATWG 방식을 사용할 수 있습니다.
searchParam.js
const myURL = new URL(
"http://www.gilbut.co.kr/?page=3&limit=10&category=nodejs&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 part3/searchParams
searchParams : URLSearchParams {
'page' => '3',
'limit' => '10',
'category' => 'nodejs',
'category' => 'javascript' }
searchParams.getAll() : [ 'nodejs', 'javascript' ]
searchParams.get() : 10
searchParams.has() : true
searchParams.keys() : URLSearchParams Iterator { 'page', 'limit', 'category', 'category' }
searchParams.values() : URLSearchParams Iterator { '3', '10', 'nodejs', 'javascript' }
[ 'es3', 'es5' ]
[ 'es6' ]
[]
searchParams.toString() : page=3&limit=10&category=nodejs&category=javascript
myURL.searchParams 대신 new URLSearchParams(myURL.search)로도 같은 결과를 얻을 수 있습니다.
- getAll(키)
: 키에 해당하는 모든 값을 가져옴 - get(키)
: 키에 해당하는 첫 번째 값만 가져옴 - has(키)
: 해당 키가 있는지 없는지 검사 - keys()
: searchParams의 모든 키를 반복기 객체로 가져옴 - values()
: searchParams의 모든 값은 반복기 객체로 가져옴 - append(키, 값)
: 해당 키를 추가, 같은 키의 값이 있다면 유지하고 하나 더 추가 - set(키, 값)
: append와 비슷하지만 같은 키의 값들을 모두 지우고 새로 추가 - delete(키)
: 해당 키 제거 - toString()
: 조작한 searchParams 객체를 다시 문자열로 만듦, search에 해당 문자열을 대입하면 주소 객체에 반영
dns
- 도메인을 통해 IP나 기타 DNS 정보를 얻고자 할 때 사용
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 part3/dns.mjs
IP : { address: '49.236.151.220', family: 4 }
A [ '49.236.151.220' ]
MX [
{ exchange: 'alt2.aspmx.l.google.com', priority: 5 },
{ exchange: 'aspmx2.googlemail.com', priority: 10 },
{ exchange: 'aspmx.l.google.com', priority: 1 },
{ exchange: 'alt1.aspmx.l.google.com', priority: 5 },
{ exchange: 'aspmx3.googlemail.com', priority: 10 }
]
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: 45,
refresh: 21600,
retry: 1800,
expire: 1209600,
minttl: 300,
type: 'SOA'
}
]
- dns.lookup, dns.resolve(도메인)
: ip 주소 - A
: ipv4 주소 - AAAA
: ipv6 주소 - NS
: 네임서버 - SOA
: 도메인 정보 - CNAME
: 별칭 - MX
: 메일 서버
crypto
- 다양한 방식의 암호화를 도와주는 모듈
- 고객의 비밀번호는 반드시 암호화가 필요
단방향 암호화 (해시 함수)
- 비밀번호는 보통 단방향 암호화 알고리즘을 사용해 암호화
- 복화할 수 없는 암호화 방식을 뜻함 (복호화 : 원래 문자열로 되돌려놓는 것)
- 주로 해시 기법을 사용 (해시 기법 : 어떠한 문자열을 고정된 길이의 다른 문자열로 바꾸는 방식)
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 part3/hash
base64 : dvfV6nyLRRt3NxKSlTHOkkEGgqW2HRtfu19Ou/psUXvwlebbXCboxIPmDYOFRIpqav2eUTBFuHaZri5x+usy1g==
hex : 76f7d5ea7c8b451b773712929531ce92410682a5b61d1b5fbb5f4ebbfa6c517bf095e6db5c26e8c483e60d8385448a6a6afd9e513045b87699ae2e71faeb32d6
base64 : cx49cjC8ctKtMzwJGBY853itZeb6qxzXGvuUJkbWTGn5VXAFbAwXGEOxU2Qksoj+aM2GWPhc1O7mmkyohXMsQw==
비밀번호라는 문자열을 해시를 사용해 바꾸었습니다.
- createHash(알고리즘)
: 사용할 해시 알고리즘을 넣음. md5, sha1, sha256, sha512 등 가능하지만, 현재는 sha512로 충분 - update(문자열)
: 변환할 문자열을 넣음 - digest(인코딩)
: 인코딩할 알고리즘을 넣음. base64, hex, latin1이 주로 사용되는데 , base64가 결과 문자열이 가장 짧아 애용
변환된 문자열을 반환해줌
하지만, 가끔 서로 다른 문자열이 동일한 문자열로 변환되어 충돌이 되는 경우가 있습니다.
이러한 상황과 더욱 더 강력한 암호화를 위해 pbkdf2나 bcrypt, scrypt 알고리즘으로 비밀번호를 암호화합니다. (salt 처리)
pbkdf2.js
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 part3/pbkdf2
salt : KTqBS0xOoP1mzCB62dQDXtdTmG9RvxJj9gvDlSbi6z1t2ZxReVBIKNUcZVzr4Ps2hkcpIfZJiv5uHa9bU6kjkQ==
password : R3GP0Xr7K94fh/gV0pYruV783DCn1nJ4k3YO/G35nMzpXDnKA6bUpCMQO0efD1x62qdDnFm941E6REUdPQ54sg==
'JavaScript > Node.js' 카테고리의 다른 글
Node) http 모듈로 서버 만들기 - 쿠키와 세션, https와 http2, cluster (0) | 2022.12.28 |
---|---|
Node) http 모듈로 서버 만들기 - 요청과 응답 이해하기, REST와 라우팅 이용하기 (0) | 2022.12.27 |
Node) 노드 기능 알아보기 - 이벤트 이해하기, 예외 처리하기 (0) | 2022.12.27 |
Node) 노드 기능 알아보기 - 노드 내장 객체 알아보기 (0) | 2022.12.27 |
Node) 노드 기능 알아보기 - REPL, 모듈 사용하기 (1) | 2022.12.27 |