반응형

# worker_threads

  • 노드에서 멀티 스레드 방식으로 작업할 수 있음. (암호화, 압축 작업 말고는 대부분 싱글 스레드를 함)
  • isMainThread : 현재 코드가 메인 스레드에서 실행되는지, 워커 스레드에서 실행되는지 구분
  • 메인 스레드에서는 new Worker를 통해 현재 파일(__filename)을 워커 스레드에서 실행시킴
  • worker.postMessage로 부모에서 워커로 데이터를 보냄
  • parentPort.on('message')로 부모로부터 데이터를 받고, postMessage로 데이터를 보냄
console.log('--------------worker_threads-------------')
const { isMainThread, parentPort } = require('worker_threads');

if (isMainThread) { // 메인스레드
    const worker = new Worker(__filename);
    worker.on('message', (value) => console.log('워커로부터', value));

    worker.postMessage('ping');
} else {    // 워커스레드
    parentPort.on('message', (value) => {
        console.log('부모로부터', value);
        parentPort.postMessage('pong');
        parentPort.close();
    });
}
  • worker 여러개 생성해서 하는 예 (싱글워커)
console.log('--------------worker_threads-------------')
const { Worker, isMainThread, parentPort, workerData } = require('worker_threads');

if (isMainThread) { // 메인스레드
    const threads = new Set();
    threads.add(new Worker(__filename, {
        workerData: { start: 1 },
    }));
    threads.add(new Worker(__filename, {
        workerData: { start: 2 },
    }));
    for (let worker of threads) {
        worker.on('message', (value) => console.log('워커로부터 ', value));
        worker.on('exit', () => {
            threads.delete(worker);
            if (threads.size === 0) {
                console.log('워커 끝~');
            }
        });
    }
} else {    // 워커스레드
    const data = workerData;
    parentPort.postMessage(data.start * 100);
}
  • worker_threads 사용 2 ~ 천만 사이 소수찾는 예
const min = 2;
const max = 10_000_000;
const primes = [];

// 에라토스테네스의 체
function generatePrimes(start, range) {
    let isPrime = true;
    const end = start + range;
    for (let i = start; i < end; i++) {
        for (let j = min; j < Math.sqrt(end); j++) {
            if (i !== j && i % j ===0) {
                isPrime = false;
                break;
            }
        }
        if (isPrime) {
                primes.push(i);
        }
        isPrime = true;
    }
}
console.time('prime');
generatePrimes(min, max);
console.timeEnd('prime');
console.log(primes.length);


출력 결과
prime: 11.416s
664579
  • 각 워커에게 일 분배를 해주는 코드를 짜야함. (멀티 스레드 사용)
const { Worker, isMainThread, parentPort, workerData } = require('worker_threads');

const min = 2;
let primes = [];

function findPrimes(start, range) {
    let isPrime = true;
    const end = start + range;
    for (let i = start; i < end; i++) {
        for (let j = min; j < Math.sqrt(end); j++) {
            if (i !== j && i % j ===0) {
                isPrime = false;
                break;
            }
        }
        if (isPrime) {
                primes.push(i);
        }
        isPrime = true;
    }
}

if (isMainThread) {
    const max = 10_000_000;
    const threadCount = 8;
    const threads = new Set();
    const range = Math.ceil((max - min) / threadCount);
    let start = min;
    console.time('prime');
    for (let i = 0; i < threadCount - 1; i++) {
        const wStart = start;
        threads.add(new Worker(__filename, { workerData : { start : wStart, range }}));
        start += range;
    }
    threads.add(new Worker(__filename, { workerData : { start, range : range + ((max - min + 1) % threadCount)}}));
    for (let worker of threads) {
        worker.on('error', (err) => {
            throw err;
        });
        worker.on('exit', () => {
            threads.delete(worker);
            if (threads.size === 0) {
                console.timeEnd('prime');
                console.log(primes.length);
            }
        });
        worker.on('message', (msg) => {
            primes = primes.concat(msg);
        });
    }
} else {
    findPrimes(workerData.start, workerData.range);
    parentPort.postMessage(primes);
}

출력 결과
prime: 1.854s
664579
  • 멀티 스레드를 Node 보다는 다른 언어로 하는게 좋음.

 

# child_process

const exec = require('child_process').exec;

var process = exec('dir');

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

process.stderr.on('data', function (data) {
    console.error(data.toString());
});
  • spawn.js 에서 test.py 호출 예 (단, 다른 언어를 호출 할 때는 해당 언어가 설치되어있어야 함_노드가 실행 요청을 하는 것.)
# 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());
});



# test.py 파일
print('hello python')


node spawn 실행 시 출력 결과
hello python

 

# 기타 모듈

  • assert : 값을 비교하여 프로그램이 제대로 동작하는지 테스트하는 데 사용.
  • dns : 도메인 이름에 대한 IP 주소를 얻어내는데 사용.
  • net : HTTP 보다 로우 레벨인 TCP 나 IPC 통신을 할 때 사용.
  • string_decoder : 버퍼 데이터를 문자열로 바꾸는 데 사용.
  • tls : TLS와 SSL에 관련된 작업을 할 때 사용.
  • tty : 터미널과 관련된 작업을 할 때 사용.
  • dgram : UDP와 관련된 작업을 할 때 사용.
  • v8 : V8 엔진에 직접 접근할 때 사용.
  • vm : 가상 머신에 직접 접근할 때 사용.

 

 

반응형
반응형

# 노드 내장 모듈

## OS 모듈 메서드

  • 노드에서 os 제공, 운영체제의 정보를 담고 있다.
  • 모듈은 require로 가져옴 (내장 모듈이라 경로 대신 이름만 적어줘도 됨)
  • os.arch() : process.arch와 동일
  • os.platform() : process.platform과 동일
  • os.type() : 운영체제의 종류를 보여줌
  • os.uptime() : 운영체제 부팅 이후 흐른 시간(초)을 보여줌. (process.uptime()은 노드의 실행 시간)
  • os.hostname() : 컴퓨터의 이름을 보여줌
  • os.release() : 운영체제의 버전을 보여줌
  • os.homedir() : 홈 디렉터리 경로를 보여줌
  • os.tmpdir() : 임시 파일 저장 경로를 보여줌
  • os.cpus() : 컴퓨터의 코어 정보를 보여줌
  • os.freemem() : 사용 가능한 메모리(RAM)을 보여줌
  • os.totalmem() : 전체 메모리 용량을 보여줌
  • https://nodejs.org/dist/latest-v14.x/docs/api/
 

Index | Node.js v14.18.0 Documentation

 

nodejs.org

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());

## path

  • 폴더와 파일의 경로를 쉽게 조작하도록 도와주는 모듈
  • 운영체제별로 경로 구분자가 다름(Windows : '\', POSXI : '/')
  • path.sep : 경로의 구분자 (Windows : \, POSIX : /)
  • path.delimiter : 환경 변수의 구분자. process.env.PATH를 입력하면 여러 개의 경로가 이 구분자로 구분되어 있다. (Windows : tpalzhffhs(;), POSIX : 콜론(:))
  • path.dirname(경로) : 파일이 위치한 폴더 겨올를 보여줌
  • path.extname(경로) : 파일의 확장자를 보여줌
  • path.basename(경로, 확장자) : 파일의 이름(확장자 포함)을 보여줌. 파일의 이름만 표시하고 싶다면 basename의 두 번째 인자로 파일의 확장자를 넣어주면 됨
  • path.parse(경로) : 파일 경로를 roow, dir, base, ext, name으로 분리
  • path.format(객체) : path.parse()한 객체를 파일 경로로 합친다.
  • path.normalize(경로) : /나 \를 실수로 여러 번 사용했거나 혼용했을 때 정상적인 경로로 변환해줌.
  • path.isAbsolute(경로) : 파일의 경로가 절대경로인지, 상대경로인지 true나 false로 알려줌
  • path.relative(기준경로, 비교경로) : 경로를 두 개 넣으면 첫 번째 경로에서 두 번째 경로로가는 방법을 알려줌
  • path.join(경로, .. .) : 여러 인자를 넣으면 하나의 경로로 합쳐준다. 상대경로인 .. (부모 디렉터리)와 . (현 위치)도 알아서 처리해줌
  • path.resolve(경로, .. .) : path.join()과 비슷하지만 차이가 있다.
const path = require('path');

const string = __filename;

console.log('----------path-------------------')
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\\zero',
    name : 'path',
    ext : '.js',
}));
console.log('path.normalize() : ', path.normalize('C://users\\\\zero\\\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\\zero\\path.js', 'C:\\'));
console.log('path.join() : ', path.join(__dirname, '..', '/users', '.', '/zero'));

## url

최신 방식은 WHATWG  인데, 기존 방법이 쓰이기도 함. 아래 공식문서 참고.

https://nodejs.org/dist/latest-v14.x/docs/api/url.html

 

URL | Node.js v14.18.0 Documentation

URL# Source Code: lib/url.js The url module provides utilities for URL resolution and parsing. It can be accessed using: const url = require('url'); URL strings and URL objects# A URL string is a structured string containing multiple meaningful components.

nodejs.org

## searchParams

  • WHATWG 방식에서 쿼리스트링(search) 부분 처리를 도와주는 객체
  • 쿼리스트링 : 주소에 데이터가 담겨있는 부분.
?page=3&limit=10&category=nodejs&category=javascript 부분
  • getAll(키) : 키에 해당하는 모든 값들을 가져옴. 위에서 category 키에는 두 가지 값, 즉 nodejs와 javascript의 값이 들어있음.
  • get(키) : 키에 해당하는 첫 번째 값만 가져옴
  • has(키) : 해당 키가 있는지 없는지를 검사
  • keys() : searchParams의 모든 키를 반복기(iterator, ES2015 문법) 객체로 가져옴
  • values() : searchParams의 모든 값을 반복기 객체로 가져옴
  • append(키, 값) : 해당 키를 추가. 같은 키의 값이 있다면 유지하고 하나 더 추가.
  • set(키, 값) : append와 비슷하지만, 같은 키의 값들을 모두 지우고 새로 추가.
  • delete(키) : 해당 키를 제거
  • toString() : 조작한 searchParams 객체를 다시 문자열로 만든다. 이 문자열을 search에 대입하면 주소 객체에 반영됨.

## 단방향 암호화(crypto)

  • 암호화는 가능하짐나 복호화는 불가능
  • 암호화 : 평문을 암호로 만듦
  • 복호화 : 암호를 평문으로 해독
  • 단방향 암호화의 대표 주자는 해시 기법이다. (문자열을 고정된 길이의 다른 문자열로 바꾸는 방식으로, abcdefg 문자열을 -> qvew 등으로 바꿈)

### Hash 사용하기(sha512)

  • createHash(알고리즘) : 사용할 해시 알고리즘을 넣어줍니다.
md5, sha1, sha256, sha512 등이 가능하지만, md5와 sha1은 이미 취약점이 발견됨.
현재는 sha512 정도로 충분하지만 나중에 sha512마저도 취약해지면 더 강화된 알고리즘으로 바꿔야 함.
  • update(문자열) : 변환할 문자열을 넣어줍니다.
  • digest(인코딩) : 인코딩할 알고리즘을 넣어줍니다.
base64, hax, latin1이 주로 사용되는데, 그중 base64가 결과 문자열이 가장 짧아 애용된다.
결과물로 변환된 문자열을 반환한다.

### pbkdf2

  • 컴퓨터의 발달로 기존 암호화 알고리즘이 위협받고 있음.
sha512가 취약해지면 sha3으로 넘어가야 함.
현재는 pdkdf2나 bcrypt, scrypt 알고리즘으로 비밀번호를 암호화.
Node는 pbkdf2와 scrypt 지원.
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'));
    });
});

 

## 양방향 암호화

  • 대칭형 암호화(암호문 복호화 가능)
  • Key가 사용됨
  • 암호화할 때와 복호화 할 때 같은 Key를 사용해야 함
const crypto = require('crypto');

const algorithm = 'aes-256-cbc';
const key = 'abcdefghijklmnopqrstuvwxyz123456';
const iv = '1234567890123456';

const cipher = crypto.createCipheriv(algorithm, key, iv);
let result = cipher.update('암호화할 문장', 'utf8', 'base64');
result += cipher.final('base64');
console.log('암호화 : ', result);

const decipher = crypto.createDecipheriv(algorithm, key, iv);
let result2 = decipher.update(result, 'base64', 'utf8');
result2 += decipher.final('utf8');
console.log('복호화 : ', result2);
  • crypto.createCipheriv(알고리즘, 키, iv) : 암호화 알고리즘과 키, 초기화백터를 넣어줍니다.
암호화 알고리즘은 aes-256-cbc를 사용. 다른 알고리즘을 사용해도 됨.
사용 가능한 알고리즘 목록은 crypto.getCiphers()를 하면 볼 수 있다.
키는 32바이트, 초기화백터(iv)는 16바이트로 고정.

 

  • cipher.update(문자열, 인코딩, 출력 인코딩) : 암호화할 대상과 대상의 인코딩, 출력 결과물의 인코딩을 넣어줍니다.
보통 문자열은 utf8 인코딩을 / 암호는 base64를 많이 사용함.
  • cipher.final(출력 인코딩) : 출력 결과물의 인코딩을 넣어주면 암호화가 안료된다.
  • crypto.createDecipheriv(알고리즘, 키, iv) : 복호화할 때 사용. 암호화할 때 사용했던 알고리즘과 키, iv를 그대로 넣어줘야 한다.
  • decipher.update(문자열, 인코딩, 출력 인코딩) : 암호화된 문장, 그 문장의 인코딩, 복호화할 인코딩을 넣어줍니다.
createCipher의 update()에서 utf8, base64 순으로 넣었다면
createDecipher의 update()에서 base64, utf8 순으로 넣으면 된다.
  • decipher.final(출력 인코딩) : 복호화 결과물의 인코딩을 넣어줍니다.
  • aws kms : 비밀번호 관리 전략을 위한 자동화 서비스? 사용 하기도 함.

## util

  • 각종 편의 기능을 모아둔 모듈
  • deprecated와 promisify가 자주 쓰인다.
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);
    });
  • util.deprecate : 함수가 deprecated 처리되었음을 알려줍니다. (deprecated란 '중요도가 떨어져 더 이상 사용되지 않고 앞으로는 사라지게 될' 것이라는 뜻으로 새로운 기능이 나와 기존 기능보다 더 좋을 때, 기존 기능을 deprecated 처리하곤 함. 이전 사용 기능을 제거하지는 않지만 곧 없앨 예정이므로 더 이상 사용하지 말라는 의미.)
첫 번째 인자로 넣은 함수를 사용했을 때 경고 메시지가 출력됩니다.
두 번째 인자로 경고 메시지 내용을 넣으면 됨. 함수가 조만간 사라지거나 변경될 때 알려줄 수 있어 유용함.
  • util.promisify : 콜백 패턴을 프로미스 패턴으로 바꿔줍니다.
바꿀 함수를 인자로 제공하면 된다. 이렇게 바꾸어두면 async/await 패턴까지 사용할 수 있어 좋다.
(단, 콜백이 (error, data) => {} 형식이어야 함)
반응형
반응형

# REPL 사용

  • 자바스크립트는 스크립트 언어라 즉석에서 코드를 실행할 수 있다.
  • REPL이라는 콘솔을 제공 (Read / Evaluate / Print / Loop)
  • 윈도에서는 명령 프롬프트, 맥이나 리눅스에서는 터미널에 node 입력 (cmd 또는 VS Code 파워쉘(Ctrl + `(백틱))에서 node 입력 / node exit의 경우 .exit 입력 또는 Ctrl + C 입력)

  • repl의 경우 한줄 짜리 코드 실행 등에만 사용 (평소에는 거의 사용하는일 없음)

 

# JS 파일을 만들어서 실행하기

  • 자바스크립트 파일을 만들어 통째로 코드를 실행하는 방법 
아무 폴더(디렉터리)에서 helloWorld.js 생성
node [자바스크립트 파일 경로]로 실행
실행 결괏값이 출력됨

  • VS Code 파워쉘 -> cmd 변경 (아래와 같이 우측 하단 + 클릭하여 cmd로 변경) (파워쉘 사용의 경우 추후 문제발생 가능성 있다고 함)

 

# 모듈 생성 (module.exports / require)

  • 모듈 : 특정한 기능을 하는 함수나 변수들의 집합
  • 모듈로 만들면 여러 프로그램에서 재사용 가능
  • module.exports : 모듈로 생성
  • const 변수명 = require('경로'); 로 받아서 사용.
  • 객체를 넘겨서 사용할 경우

  • 배열을 넘겨서 사용할 경우

  • 구조분해 할당도 가능하여 아래와 같이 func.js에서 사용 가능
# 기존
const value = require('./var');

console.log(value);


# 구조 분해 할당
const { odd, even } = require('./var');
  • module.exports로 넘겨받은걸 또 module.exports하여 다른쪽으로 넘길수 있음.
const { odd, even } = require('./var');

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


module.exports = {
    checkOddOrEven,
    odd,
    even,
};
  • module.exports는 파일에서 단 한번만 사용해야 함.
  • var.js
const odd = '홀수입니다.';
const even = '짝수입니다.';

module.exports = {odd, even};
  • func.js
const { odd, even } = require('./var');

function checkOddOrEven(number) {
    if (number % 2 ) {
        return odd;
    } else {
        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;
    } else {
        return even;
    }
}

console.log(checkNumber(10));
console.log(checkStringOddOrEven('hello'));
  • ES2015 모듈_자바스크립트 자체 모듈 시스템 문법이 생김. 아직 노드에서의 지원은 완벽하지 않음. mjs 확장자를 사용해야 함. 크게는 require 대신 import / module.exports 대신 export default를 쓰는 것으로 바뀜
  • func.mjs
import { odd, even } from './var';

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


export default checkOddOrEven;

 

# 노드의 내장 객체

## global과 콘솔, 타이머

1. global

  • 브라우저의 window같은 역할
  • 모든 파일에서 접근 가능
  • window처럼 생략 가능(console, require도 global의 속성)
  • global 속성에 값을 대입하면 다른 파일에서도 사용 가능하다. (하지만, 이렇게 하는건 좋지 않음.)
1. globalA.js
module.exports = () => global.message;

2. globalB.js
const A = require('./globalA');

global message = '안녕하세요.';
console.log(A());

2. console 객체

  • 브라우저의 console 객체와 매우 유사.
  • console.time / console.timeEnd : 시간 로깅
  • console.error : 에러 로깅
  • console.log : 평범한 로그
  • console.dir : 객체 로깅
  • console.trace : 호출스택 로깅 (함수 안에서 사용하면 호출스택 보여줌)
  • console.table([{ name: '제로', phone: '123-123'}, { name: '케이', phone: '125-125'}]) : 테이블 형식으로 보여줌

3. 타이머 메서드

  • set 메서드에 clear 메서드가 대응됨
  • setTimeout(콜백 함수, 밀리초) : 주어진 밀리초(1000분의 1초) 이후에 콜백 함수를 실행
  • setInterval(콜백 함수, 밀리초) : 주어진 밀리초마다 콜백 함수를 반복 실행
  • setImmediate(콜백 함수) : 콜백 함수를 즉시 실행
  • clearTimeout(아이디) : setTimeout을 취소
  • clearInterval(아이디) : setInterval을 취소
  • clearImmediate(아이디) : setImmediate를 취소 
  • setTimeout / setInterval / setImmediate : 함수를 백그라운드로 보내는 대표적인 비 동기 코드
1. 2초 후 hello 출력
setTimeout(() => console.log('hello'), 2000)


2. 2초 마다 kkkkk 출력
const hello = setInterval(() => console.log('kkkkk'), 2000)
 
clearInterval(hello)	// 종료 시(hello 변수 취소)


3. 바로 실행
setImmediate(() => console.log('hi'))

## exports와 this

  • __filename : 현재 파일 경로
  • __dirname : 현재 폴더(디렉터리) 경로
  • __ (언더바 2개 붙은것. dunderscore 라고 함)
  • path 등에 사용.
  • 1개만 exports 하는 경우 module.exports / 2개 이상 exports 하는 경우 exports. 사용. (exports. 사용한 경우 module.exports 사용하면 안됨)
const odd = '홀수 입니다.';
const even = '짝수 입니다.';

module.exports === exports === {} // 초기값이 빈 객체임.


1. 1가지만 넣고 싶을 때 (1개만 exports)
const { odd, even } = require('./var');

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

module.exports = chcekOddOrEven;


2. 2개 이상 넣고 싶을때 예_1 (2개 이상 exports)
module.exports === exports === { odd, even }

module.exports = {
	odd,
    even,
}

2-1. 2개 이상 넣고 싶을 때 예_2 (2개 이상 exports)
exports.odd = odd;
exports.even = even;
이때 exports를 사용했다면 module.exports를 사용하면 안됨. 
(module.exports 하는 순간 기존에 위에 exports.odd 등이 참조관계가 바뀌어 무시됨)
  • this는 전역객체를 가리킴. (this === module.exports === { } === exports)
console.log(this);  // global ?
// console.log(this === module.exports === {} === exports}
console.log(this === module.exports);

function a() {
    console.log(this === global);    
}

a();

출력결과 :
{}
true
true

## require의 특징

  • require가 제일 위에 올 필요는 없음
  • require.cache에 한 번 require 한 모듈에 대한 캐싱 정보가 들어있음. ( require로 파일을 한 번 불러오면 불러온 파일을 읽고 캐시에 저장해 둠, 그래서 두 번째 불러올땐 실제 파일을 읽는게 아닌 캐시(메모리)에 저장된 파일을 읽는다. (효율적) )
  • require.main은 노드 실행 시 첫 모듈을 가리킴.
다른 파일을 실행만 하고싶은 경우.
(다른 파일을 실행만 하고 다른 파일에 있는 변수 등을 가져오고 싶지 않을 때)
require('./var');
  • 자바스크립트를 node로 실행할 경우 해당 파일들은 거의 모듈이 됨. (빈 객체를 다른 파일에서 사용할 수 있게 되는 모듈이 됨)
  • require.main으로 어떤 파일을 실행한건지 알아낼 수 있다.
  • 캐시를 delete 해서 초기화 할 순 있지만 사용하진 않음. (내장객체를 손대는 건 위험한 행동)
  • 캐싱 : 하드디스크에 있는 정보를 메모리로 옮겨오는 걸 캐싱이라고 함.

## 순환참조

  • 아래와 같이 순한참조(무한 사이클) 일어나는 경우 
1. dep1.js
require('./dep2');

2. dep2.js
require('./dep1');

위의 경우 무한 사이클 발생.
  • 노드가 자동으로 순환참조를 막아줌 (순환참조 발생 시 빈 객체로 바꿔버림 {} )
1. dep1.js
require('./dep2');

2. dep2.js
require('./dep1');

module.exports = {
	hello: 'zero';
};

이 경우 dep1.js로 돌아갔을 때 빈 객체{} 로 바꿔버림
  • 순환참조는 직관적이지 않으므로 순환참조가 발생하는 상황을 만들지 않도록 하는게 좋음.

## process

  • 노드에서 process 입력 시 다양한 값들이 보임
process.version	// 설치된 노드의 버전

process.arch	// 프로세서 아키텍처 정보 x64, arm, ia32 등의 값일 수 있음.

process.platform	// 운영체제 플랫폼 정보. win32, linux나 darwin, freebsd 등의 값일 수 있음.

process.pid	// 현재 프로세스의 아이디. 프로세스를 여러 개 가질 때 구분할 수 있음.

process.uptime()	// 프로세스가 시작된 후 흐른 시간. 단위는 초

process.execPath	// 노드의 경로

process.cwd()	// 현재 프로세스가 실행되는 위치. (=노드 명령어를 어디서 실행됐는지. 자주 사용됨)

process.cpuUsage()	// 현재 cpu 사용량.
  • process.env : 시스템 환경 변수들이 들어있는 객체
비밀키(데이터베이스 비밀번호, 서드파티 앱 키 등)를 보관하는 용도로도 사용.

환경 변수는 process.env로 접근 가능.
const secretId = process.env.SECRET_ID;
const secretCode = process.env.SEVRET_CODE;

일부 환경 변수는 노드 실행 시 영향을 미친다.
예) NODE_OPTIONS(노드 실행 옵션) / UV_THREADPOOL_SIZE(스레드풀 개수)
max-old-space-size는 노드가 사용할 수 있는 메모리를 지정하는 옵션.
  • process.nextTick(콜백) : 이벤트 루프가 다른 콜백 함수들보다 nextTick의 콜백 함수를 우선적으로 처리함
너무 남용하면 다른 콜백 함수들 실행이 늦어진다.

비슷한 경우로 promise가 있다. (promise도 nextTick 처럼 우선순위가 높음)
  • process.exit(코드) : 현재의 프로세스를 멈춤
코드가 없거나 0이면 정상 종료

이외의 코드는 비 정상 종료를 의미함.

process.exit(1); // 서버에서 에러 났다는걸 알리고, 종료하기 위해 사용.
반응형
반응형

# 자바스크립트_화살표 함수

  • this를 사용할 경우 function을 사용 / 그게 아니라면 모두 화살표 함수로 통일. (권장)
# 상황1
function add1(x, y) {
	return x + y;
}


1. 화살표 함수 사용
const add2 = (x, y) => {
	return x + y;
};

2. 중괄호 다음 바로 return 나오면 아래와 같이 생략 가능.
const add3 = (x, y) => x + y;

2-1. return 값을 괄호로 묶어줌
const add4 = (x, y) => (x + y);

3. 객체를 return 하는경우 소괄호 필수!
const obj = {x, y} => ({x, y})


# 상황2
function not1(x) {
	return !x;
}

1. 매개변수가 1개, 중괄호 다음 바로 return 나오는 경우
const not2 = x => !x;
  •  화살표 함수는 function을 완벽히 대체할 수 없음. (this 때문)
var relationship1 = {
	name: 'zero',
    friends: ['nero', 'hero', 'xero'],
    logFriends: function () {
    	var that = this;	// relationship1을 가리키는 this를 that에 저장
        this.friends.forEach(function (friend) {
        	console.log(that.name, friend);
        });
    },
};

relationship1.logFriends();
= function에서 this를 다른 함수에서 사용하기 위해선 that 등을 사용해야 함. 
(function은 자신만의 this를 가짐)



화살표 함수 사용
const relationship2 = {
	name: 'zero',
    friends = ['nero', 'hero', 'xero'],
    logFriends() {
    	this.friends.forEach(friend => {
        	console.log(this.name, friend);
        });
    }
};

relationship2.logRfiends();
= 화살표 함수는 자신만의 this를 갖지 않고, 무조건 부모 function의 this를 물려받음.

 

# 자바스크립트_비구조화 할당(구조분해 할당)

  • 구조분해 문법 (배열, 객체)
1. 객체 구조 분해 문법 예시
const example = {a: 123, b: {c: 135, d: 146}}
const a = example.a;
const d = example.b.d;


# 구조 분해 문법(객체)	// 객체는 키가 정확히 일치해야 함.
const {a, b: { d}} = example;
console.log(a);	// 123
console.log(d);	// 146



2. 배열 구조 분해 문법 예시
arr = [1, 2, 3, 4, 5]
const x = arr[0]
const y = arr[1]
const z = arr[4]


# 구조 분해 문법(배열)	// 배열은 자리가 동일해야 함.
const [x, y, , , z] = arr;	// 자릿수 맞춰주는 것

 

  • this를 사용하고 있는 경우 구조분해 할당 시 문제 발생
const candyMachine = {
	status: {
    	name: 'node',
        count: 5,
    },
    getCandy() {
    	this.status.count--;
        return this.status.count;
    },
};
const { getCandy, status: { count }} = candyMachine;

 

# 자바스크립트_클래스

  • 클래스는 프로토타입이다. 프로토타입의 문법을 깔끔하게 만들어 주는 것. (Constructor(생성자), Extends(상속) 등을 깔끔하게 처리할 수 있다. / 코드가 그룹화되어 가독성이 향상된다.)
# 이전 클래스 문법(생성자 함수)
var Human = function(type) {
	this.type = type || 'human';
};

Human.isHuman = function(human) {
	return human instanceof Human;
}

Human.prototype.breathe = function() {
	alert('h-a-a-a-m');
};

var Zero = function(type, firstName, lastName) {
	Human.apply(this, arguments);
    this.firstName = firstName;
    this.lastName = lastName;
};

Zero.prototype = Object.create(Human, prototype);
Zero.prototype.constructor = Zero;	// 상속하는 부분
Zero.prototype.sayName = fuunction() {
	alert(this.firstName + ' ' + this.lastName);
};
var oldZero = new Zero('human', 'Zero', 'Cho');
Human.isHuman(oldZero);	// true



# 변경 클래스 문법
Class Human {
	constructor(type = 'human') {
    	this.type = type;
    }
    
    static isHuman(human) {
    	return human instanceof Human;
    }
    
    breathe() {
    	alert('h-a-a-a-m');
    }
}

Class Zero extends human {
	constructor(type, firstName, lastName) {
    	super(type);
        this.firstName = firstName;
        this.lastName = lastName;
    }
}

sayName() {
	super.breathe();
    alert('${this.firstName} ${this.lastName}');
}


const NewZero = new Zero('human', 'Zero', 'Cho');

 

# 자바스크립트_Promise, async/await

## 자바사크립트 프로미스(Promise)

  • 콜백 헬이라고 불리는 지저분한 자바스크립트 코드의 해결책이다.
  • 프로미스 : 내용이 실행 되었지만, 결과를 아직 반환하지 않은 객체
  • Then을 붙이면 결과를 반환함
  • 실행이 완료되지 않았으면 완료된 후 Then 내부 함수가 실행된다.
  • Resolve (성공리터값) -> then 으로 연결
  • Reject (실패리턴값) -> catch로 연결
  • Finally 부분은 무조건 실행된다.
# 프로미스 사용 시 코드 분리 가능.
const promise = setTimeoutPromise(3000)

console.log('다른업무');
console.log('다른업무');
console.log('다른업무');
console.log('다른업무');
console.log('다른업무');

promist.then(() => {
	지금 실행.
});
  • Promise.all(배열) : 여러 개의 프로미스를 동시에 실행. 하나라도 실패하면 catch로 감. allSettled로 실패한 것만 추려낼 수 있다.

## 자바스크립트 에이싱크/어웨잇(async/await)

  • 변수 = await 프로미스; 인 경우 프로미스가 resolve된 값이 변수에 저장(await이 then 역할)
  • 변수 await 값; 인 경우 그 값이 변수에 저장
  • async/await의 실행 순서는 오른쪽에서 왼쪽방향임.
async function findAndSaveUser(Users) {
	let user = await Users.findOne({});
    user.name = 'zero';
    user = await user.save();
    user = await Users.findOne({ gender : 'm' });
    // 생략
}



async에서 return한 경우 무조건 then으로 받아야 함. (async도 프로미스임)
const promise = new Promise(...)
promise.then((result) => ...)


async function main() {
	const result = await promise;
    return result;
}

main().then((name) => ...) 또는 const name = await main() 가능.


async/await의 경우 result만 있고, reject를 처리할 수 있는 부분이 없어서 
reject를 처리하기 위해 try~catch를 사용해야함
async function main() {
	try{
		const result = await promise;
    	return result;
	} catch (error) {
    	console.error(error);
    }
}
  • for await (변수 or 프로미스 배열) : 노드 10부터 지원, resolve된 프로미스가 변수에 담겨 나온다. await을 사용하기 때문에 async 함수 안에서 해야함 (프로미스 반복 시 사용)
const promise1 = Promise.resolve('성공1');
const promise2 = Promise.resolve('성공2');

(async () => {
	for await (promise of [promise1, promise2]) {
    	console.log(promise);
    }
})();
반응형

+ Recent posts