본문 바로가기
전공 수업/웹 서버 프로그래밍(Node.js)

[6주 차] - Timer 모듈, __filename & __dirname, Module exports, process 객체, Node의 내장된 모듈(os, path, url)

by TwoJun 2023. 4. 7.

    과명 : 웹 서버 프로그래밍(Web Server-side programming with Node.js)

수업일자 : 2023년 04월 06일 (목)

Node.js & Express.js

 

 

 

 

 

1. Timer 모듈(함수)

(1) 자바스크립트에서 다루는 Timer 함수는 일정 시간이 경과한 후 특정 코드 또는 함수가 실행될 수 있도록 해 주고 또는 일정 시간마다 코드 또는 함수가 실행될 수 있도록 해 주는 함수를 의미하고 있습니다.

 

- 추가적으로 Timer 모듈은 Node의 전역 객체이므로 require 키워드를 요구하지 않습니다.

 

 

 

1-1. setTimeout(콜백 함수, ms)

- 주어진 ms 이후, 콜백 함수를 실행하는 Timer 함수입니다.

 

 

1-2. setInterval(콜백 함수, ms)

- 주어진 ms마다 콜백 함수를 반복해서 실행하는 Timer 함수입니다.

 

 

1-3. setImmediate(콜백 함수)

- 매개변수로 들어간 콜백 함수를 즉시 실행하는 Timer 함수입니다. 

 

 

1-4. clearTimeout()

- 주어진 ms 타이머를 중지하여 Timeout 객체를 취소합니다.

 

 

1-5. clearInterval()

- Interval 객체를 취소합니다.

 

 

1-6. clearImmediate()

- Immediate 객체를 취소합니다.

 

 

 

1-7. Timer 함수 예제

const timeout = setTimeout(() => {
  console.log('1.5초 후 실행');
}, 1500);

const interval = setInterval(() => {
  console.log('1초마다 실행');
}, 1000);

const timeout2 = setTimeout(() => {
  console.log('실행되지 않음');
}, 3000);

setTimeout(() => {
  clearTimeout(timeout2);
  clearInterval(interval);
}, 2500);

const immediate = setImmediate(() => {
  console.log("즉시 실행");
})

const immediate2 = setImmediate(() => {
  console.log("실행되지 않음");
})

clearImmediate(immediate2);

 

<실행 결과>

실행 순서 : 즉시 실행 > 1초마다 실행 > 1.5초 후 실행 > 1초마다 실행

 

 

 

 

 

 

2. __filename, __dirname

(1) Node에서는 모듈 관계에 있는 경우가 많아 현재 파일의 경로나 파일명을 알아야 하는 경우가 많은데 Node에서는 __filename, __dirname이라는 키워드를 통해 경로에 대한 정보를 제공하고 있습니다.

 

 

2-1. __filename

- 현재 파일의 경로를 출력합니다.

 

 

2-2. __dirname

- 현재 디렉토리의 경로를 출력합니다.

// file name : filename.js
// dir_path : C:\Users\82104\Desktop\nodejs

console.log(__filename);
console.log(__dirname);

 

<실행 결과>

Command : node filename.js

 

 

 

 

 

 

3. module.exports, exports

(1) 5주 차에서도 확인한 것처럼 module.exports를 통해 모듈을 생성하여 외부로 내보내기가 가능했습니다.

 

(2) module.exports 외에도 exports 키워드를 통해 모듈을 생성해 내보내기가 가능합니다.

 

(3) module.exports, exports 키워드는 모두 참조 관계(Call by reference)를 가지고 있습니다.

 

- 변수나 함수, 클래스를 선언할 때 맨 앞에 exports 키워드를 붙이면 export가 가능합니다.

 

- exports 키워드에 객체의 속성이 아닌 다른 값을 대입하면 참조 관계가 성립되지 않습니다.

exports → module.exports {}

 

 

 

<기존 방식의 module.exports : var.js>

const odd = 'odd number';
const even = 'even number'

// 기존 방식의 module.exports
module.exports = {
  odd,
  even,
};

 

 

<exports 키워드로 내보내는 경우 :  var.js>

exports.odd = 'odd number';
exports.even = 'even number';

 

 

<func.js>

const { odd, even } = require('./var');

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

console.log(checkNumber(10));
console.log(checkStringOddOrEven('hello'));

 

 

<실행 결과>

Command : node index.js

 

 

 

 

 

 

3. 전역 객체 process

3-1. process

- process 객체는 전역 객체이므로 require() 없이 사용할 수 있고, 해당 객체는 Node의 프로세스에 대한 정보를 제공하고 이를 제어할 수 있도록 하는 객체입니다.

 

 

3-2. process.verison

- 설치된 Node의 버전을 나타냅니다.

 

 

3-3. process.arch

- 프로세서 아키텍처 정보를 나타내며 arm, ia32 등의 값일 수도 있습니다.

 

 

3-4. process.platform

- 운영체제 플랫폼 정보를 나타내며 리눅스나 darwin, freebsd 등의 값일 수도 있습니다.

 

 

3-5. process.pid

- 현재 프로세스의 아이디를 나타내며 프로세스를 여러 개 가질 때 구분할 수 있습니다.

 

 

3-6. process.uptime()

- 프로세스가 시작된 후 흐른 시간을 나타내며 단위는 초(second) 단위입니다.

 

 

3-7. process.execPath

- Node의 경로를 나타냅니다.

 

 

3-8. process.cwd()

- 현재 프로세스가 실행되는 위치를 나타냅니다.

 

 

3-9. proces.cpuUsage()

- 현재 CPU(프로세서) 사용량입니다.

REPL 환경으로 접속해서 process 객체에 대한 다양한 커맨드를 줄 수 있다.

 

 

 

 

4. process.env

(1) process.env의 경우 시스템의 환경 변수들이 들어있는 객체입니다.

 

(2) 비밀 키(DB 비밀번호, 서드파티 앱 키 등)를 보관하는 용도로 사용합니다.

Command : process.env

 

 

 

 

 

 

5. process.nextTick(Callback function)

5-1. 이벤트 루프(Event loop)가 다른 콜백 함수들보다 nextTick의 콜백 함수를 우선적으로 처리합니다.

(1) 단, 너무 남용하게 되면 다른 콜백 함수의 실행이 늦어질 수 있습니다.

 

(2) 비슷한 경우로 promise가 존재합니다.

태스크 큐(Task queue)와 마이크로 태스크 큐(Microtask queue)

 

(3) 아래 예제에서 setImmediate, setTimeout 함수보다 promise, nextTick이 먼저 실행되는 것을 알 수 있습니다.

// Microtask queue<1> = nexttick(), promise
// Task-queue<2> = setInterval, setTimeout, http.get (...)

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

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

setTimeout(() => {
  console.log('timeout');
},0);

Promise.resolve().then(() => {
  console.log('promise');
})

 

<실행 결과>

Command : nexttick.js

 

 

 

 

 

6. process.exit()

(1) 현재 진행 중인 프로세스를 종료시킬 수 있습니다.

 

(2) 코드가 없거나 0이라면 정상 종료되며 이외의 코드는 비정상 종료를 의미합니다.

let number = 1;

setInterval(() => {
  if (number === 5) {
    console.log('exit');
    process.exit();
  }
  console.log(number);
  number++;
}, 1000);

 

<실행 결과>

Command : node exit.js

 

 

 

 

 

 

7. Node에 내장된 모듈 : os

(1) 실제로 개발에 많이 사용되진 않지만 운영체제와 시스템에 대한 정보를 가져올 수 있는 모듈입니다.

 

(2) 해당 모듈은 require 함수로 직접 가져와서 사용합니다.

 

 

7-1. os.arch()

- process.arch와 동일한 기능을 가지고 있습니다.

 

 

7-2. os.platform()

- process.platform과 동일한 기능을 가지고 있습니다.

 

 

7-3. os.type()

- 운영체제의 종류를 출력합니다.

 

 

7-4. os.uptime()

- 운영체제를 부팅시킨 후 흐른 시간(초, second)을 출력합니다. process.uptime()의 경우 노드 프로세스의 실행 시간을 나타내고 있습니다.

 

 

7-5. os.hostname()

- 컴퓨터의 이름을 출력합니다.

 

 

7-6. os.homedir()

- 홈 디렉토리의 경로를 출력합니다.

 

 

7-7. os.tmpdir()

- 임시 파일이 저장된 경로를 출력합니다.

 

 

7-8. os.cpus()

- 컴퓨터의 프로세스의 코어 정보를 출력합니다.

 

 

7-9. os.freemem()

-  현재 사용 가능한 메모리(RAM) 용량을 출력합니다.

 

 

7-10. os.totalmem()

- 컴퓨터의 전체 메모리 용량을 출력합니다.

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

 

<실행 결과>

Command : node os.js (1)

 

Command : node os.js (2)

 

Command : node os.js (3)

 

 

 

 

 

 

8. Node에 내장된 모듈 : path

(1) 디렉토리(폴더)와 파일의 경로를 쉽게 조작할 수 있도록 하는 Node의 내장된 모듈 중 하나입니다.

 

(2) 운영체제별로 디렉토리 및 파일의 구분자가 상이합니다

- Windows : \ (Backslash)

- POSIX : / (Slash)

 

(3) os 모듈과 동일하게 require() 함수로 모듈을 불러와서 사용합니다.

 

 

 

8-1. path.sep

- 경로의 구분자를 나타내며, Windows는 "\(Backslash)", POSIX는 "/(Slash)"입니다.

 

 

8-2. path.delimiter

- 환경 변수의 구분자입니다.

 

- process.env.PATH 커맨드를 입력하면 여러 개의 경로가 해당 구분자로 구분되어 있습니다. Windows는 ";(Semicolon)"이고, POSIX는 ":(Colon)"입니다.

 

 

8-3. path.dirname(경로)

- 해당 파일이 위치한 디렉토리의 경로를 출력합니다.

 

 

8-4. path.extname(경로)

- 해당 파일의 확장자를 출력합니다.

 

 

8-5. path.basename(경로, 확장자)

- 확장자를 포함한 파일의 이름을 출력합니다. 파일명만 표시하고 싶다면 파라미터에 확장자를 추가하지 않습니다.

 

 

8-6. path.parse(경로)

- 파일의 경로를 root, dir, base, ext, name으로 분리하여 출력합니다.

 

 

8-7. path.format(객체)

- path.parse()를 진행한 객체를 파일 경로로 합쳐서 출력합니다.

 

 

8-8. path.normalize(경로)

- "/(slash)"나 "\(backslash)"를 실수로 여러 번 사용했거나 혼용했을 때 정상적인 경로로 변환해서 출력합니다.

 

 

8-9. path.isAbsolute(경로)

- 파일의 경로가 절대 경로(Absolute path)인지 상대 경로(Relative path)인지에 대해 true나 false로 알려줍니다.

 

 

8-10. path.relative(기준 경로, 비교 경로)

- 경로를 두 개 넣으면 첫 번째 경로에서 두 번째 경로로 가는 방법을 출력합니다.

 

 

8-11. path.join(경로, .. .)

- 여러 개의 인자를 넣어주면 하나의 경로로 합쳐 출력합니다. 상대 경로인 ..(부모 디렉토리)와 .(현재 디렉토리)을 알아서 처리하여 출력합니다.

 

 

8-12. path.resolve(경로, .. .)

- path.join()과 비슷하며 동일한 기능을 수행하지만 차이점은, path.resolve()의 경우 여러 개의 인자로 받은 경로를 합쳐나가는 과정 중에서 "/(slash)"를 만나면 "/"를 절대 경로로 인식하고 나머지 경로들을 모두 무시합니다.

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

 

<실행 결과>

Command : node path.js

 

 

 

8-13. path 모듈에 대해 추가적으로 알아두어야 할 사항

(1) path.join(), path.resolve()의 차이점

- path.resolve()의 경우 "/(slash)"를 절대 경로로 처리하며 path.join()은 상대 경로로 처리합니다.

 

 

 

(2) 절대 경로(Absolute path), 상대 경로(Relative path)의 차이점

- 절대 경로(Absolute path)는 현재 작업 중인 파일의 위치와 무관하게 지정된 대상의 시작 지점과 목표 지점까지의 경로가 정확하게 기재되어 있고 어느 시점에서 봐도 절대적으로 해당 지점을 가리킬 수 있는 경로를 의미하며 특징은 최상위(루트) 디렉토리까지 포함하여 경로를 표시한다는 점입니다.

 

- 상대 경로(Relative path)는 현재 작업 중인 파일의 위치를 기준으로 지정된 대상까지의 상대적인 경로를 의미합니다.

 

- 상대 경로를 표시할 때 "./"은 작업 중인 파일의 현재 위치, "../"은 현재 위치에서 한 단계 상위 경로를 의미합니다.

 

- 절대 경로는 최상위 디렉토리부터 참조해야 할 대상까지 전부 경로를 기재하지만, 상대 경로의 경우 지정된 대상까지 상대적으로 경로를 지정해 줘야 하는 방법으로 정의와 특징만으로는 잘 이해가 되지 않을 수 있으니 아래와 같이 간단한 예를 들어보겠습니다.

 

 

Example) 현재 작업 중인 파일을 기준으로 외부 파일을 참조해야 하는 경우?

=================================================

root

      parentDir

                     currentDir

                                    subDir

                                              dynamic.js

                     running.java

                     current2Dir

                                       dynamic2.js

=================================================

 

        

 case 1)

- 현재 running.java에서 작업 중이고, 하위 디렉토리 subDir의 dynamic.js를 참조해야 하는 상황이라고 가정

- running.java 파일 관점에서 절대 경로, 상대 경로를 모두 생각해 보겠습니다.

 

- 절대 경로의 경우 최상위 디렉토리부터 목적지까지 찾아가는 방식으로 아래와 같습니다

root / parentDir / currentDir / subDir / dynamic.js

 

- 하지만 상대 경로는 현재 작업 중인 running.java 관점에서 봐야 하므로 아래와 같습니다.

   ./ subDir / dynamic.js

 

 

 case 2)

- 동일하게 running.java에서 작업 중이고, 동일 위치의 디렉토리 current2Dir의 dynamic2.js를 참조해야 하는 상황이라고 가정

 

 → 절대 경로 : root / parnetDir / currentDir2 / dynamic2.js

 

 → 상대 경로./ ../ current2Dir / dynamic2.js

 

 

 

(3) \\(Double backslash), \(Single backslash)의 차이점 

- 우선 "\(backslash)"는 Windows의 경로 구분자이며, "\\(Double backslash)"의 경우 자바스크립트에서 "\"을 특수 기호로 인식하기 때문에 경로 구분자의 의미를 주기 위해 "\\"로 작성해 줍니다. ("\\"로 이스케이프 시킨 것)

 

 

(4) Windows에서 POSIX path를 사용하고 싶다면 path.posix 객체를 사용합니다. 

 

 

 

 

 

 

 

9. Node에 내장된 모듈 : url

(1) Node에서 url 모듈은 인터넷 주소 URL을 쉽게 조작할 수 있게 하고, 인터넷 주소 정보를 url 객체로 만들 수 있는 모듈입니다.

 

(2) 요청 프로토콜을 구분하거나(HTTP, HTTPS) 또는 요청 파라미터를 확인하고 싶다면 url 모듈의 url 객체가 가지고 있는 속성 값을 체크합니다.

 

(3) url 모듈을 사용하기 위해 require() 함수를 통해 미리 모듈을 불러와야 합니다.

 

 

(3) URL 처리에 대해 크게 두 가지 방식이 있습니다.

- 기존 노드 방식, WHATWG 방식

 

 

(4) 아래 그림을 기준으로 위쪽은 기존 노드 방식, 아래쪽은 WHATWG 방식입니다.

WHATWG와 노드의 주소 체계

 

 

 

9-1. url 모듈 예제 코드 

- WHATWG의 url은, url 모듈 내부에 new 키워드로 URL 생성자가 존재합니다. 해당 생성자에 주소를 넣어 객체로 변환하면 주소가 부분별로 정리됩니다.

 

- WHATWG에만 존재하는 username, password, origin, searchParams 속성이 존재합니다.

const url = require('url');

// WHATWG
const { URL } = url;
const myURL = new URL('http://www.gilbut.co.kr/book/bookList.aspx?sercate1=001001000#anchor');
console.log('new URL():', myURL);
console.log('url.format():', url.format(myURL));
console.log('------------------------------');

// 기존 URL - search, query
const parsedUrl = url.parse('http://www.gilbut.co.kr/book/bookList.aspx?sercate1=001001000#anchor');
console.log('url.parse():', parsedUrl);
console.log('url.format():', url.format(parsedUrl));

 

<실행 결과 - WHATWG 방식>

Command : node url.js / WHATWG 방식

 

<실행 결과 - 기존 노드 방식>

Command : node url.js / 기존 노드 방식

 

 

 

 

9-2. 기존 노드 방식에서의 메소드

(1) url.parse(주소)

- 말 그대로 주소를 분해하며 WHATWG 방식과 비교해 본다면, WHATWG 방식에서 존재하는 username, password 대신에 기존 노드 방식에선 auth 속성이 존재합니다.

 

 

(2) url.format(객체)

- WHATWG 방식의 url과 기존 노드 방식의 url 모두 사용 가능하며 분해되었던 url 객체를 다시 원래 상태로 조립하는 역할을 수행합니다.

 

 

 

 

 

 

10. Reference

Node.js 교과서(Node.js Textbook) - 저자 : 조현영 

https://www.zerocho.com/book/1 

 

https://www.zerocho.com/book/1

 

www.zerocho.com

 

 

 

 

- 학부에서 수강했던 전공 수업 내용을 정리하는 포스팅입니다.

- 내용 중에서 오타 또는 잘못된 내용이 있을 시 지적해 주시기 바랍니다.

댓글