프로그래밍/Node.js

Node.js 3장 (1) 노드 기능 알아보기

p-a-r-k 2019. 1. 3. 19:57
반응형

* 해당 글은 (주)길벗 `Node.js교과서` 내용을 바탕으로 복습 차 정리중입니다.


3.1 REPL

노드는 콘솔을 제공하는데..

코드를 읽고(read), 해석하고(eval), 결과물을 반환하고(print), 종료할때까지 반복(loop)한다고해서 REPL 이라고 부릅니다.

터미널을 열고 node를 입력하면 됩니다. (.exit나 컨트롤+C 두번을 눌러서 종료가 가능합니다.)

REPL은 한두줄짜리 코드를 테스트 해보는 용도로는 좋지만 여러줄을 실행하기에는 불편합니다.

긴코드는 자바스크립트 파일로 만든 후 파일 통째로 실행하는 것이 좋습니다.


3.2 JS파일 실행하기

1
2
3
4
5
6
7
8
function helloWorld() {
    console.log('hello world')
  helloNode();
}
function helloNode() {
    console.log('hello Node')
}
helloWorld();

노드에서 js파일을 실행해봅니다. 위와같이 테스트 js파일을 만들고 해당경로에서

[node 만든파일.js] 로 실행합니다. (확장자 .js는 생략해도됩니다.)


3.3 모듈로 만들기

노드는 코드를 모듈로 만들 수 있다는 점에서 *브라우저의 자바스크립트 와는 다릅니다.

모듈이란 특정한 기능을 하는 함수나 변수들의 집합입니다.

브라우저의 모듈

2015년 자바스크립트에도 import/export라는 모듈개념이 도입되었으나, 브라우저에는 구현되지 않아서 사용할 수 없었습니다.

크롬 60버전부터는 브라우저에서도 모듈을 사용할 수 있게되었습니다.

실제 모듈 만들어보기..

var.js와 func.js, index.js를 같은경로에 만들고 작성해봅니다.

1
2
3
4
5
6
7
8
// var.js
const add = '홀수입니다'
const even = '짝수입니다'
 
module.exports = {
  odd,
  even
}

module.exports에 변수들을 담은 '객체'를 대입했습니다. 이제 이 파일은 모듈로서 기능합니다.

다른파일에서 이 파일을 불러오면 module.exports에 대입된 값들을 사용할 수 있습니다.


1
2
3
4
5
6
7
8
9
10
11
12
// func.js
const { odd, even } = require('./var')
 
function checkOddOrEven(n) {
    if (n%2) {
    return odd
  }
   
  return even
}
 
module.exports = checkOddOrEven

require함수로 해당 경로의 모듈을 불러올 수 있습니다.

앞에서 배운 할당문법으로 const {odd, even} 처럼 var.js 에 있던 변수들을 가져왔습니다.

다른 모듈을 사용한 파일을 다시 module.exports로 모듈로 만들었습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
// index.js
const { odd, even } = require('./var')
const checkNumber = require('./func')
 
function checkStringOddOrEven(s) {
    if (str.length % 2) {
    return odd
  }
  return even
}
 
console.log(checkNumber(10)) // 짝수입니다
console.log(checkStringOddOrEven('hello')) // 홀수입니다

index.js는 var.js와 func.js를 모두 참조합니다. 모듈 하나가 여러개의 모듈을 사용할 수 있습니다.

또한, var.js가 func.js와 index.js에 두번 쓰인 것처럼 모듈하나가 여러개의 모듈에 사용될 수도 있습니다.

모듈로부터 값을 불러올 때 변수 이름을 다르게 지정할 수도 있습니다.

func.js의 checkOddOrEven함수를 index.js에서는 checkNumber로 가져왔습니다.

ES2015모듈

ES2015가 도입되면서 자바스크립트도 자체 모듈 시스템문법이 생겼습니다.

노드와는 문법이 조금 다릅니다. func.js를 ES2015스타일로 바꿔보면 아래와 같습니다.

1
2
3
4
5
6
7
8
9
10
11
// func.js
import { odd, even } from '.var'
 
function checkOddOrEven(n) {
    if (num%2) {
    return odd
  }
  return even
}
 
export default checkOddOrEven

노드에서도 9버전부터 확장자를 mjs로하면 ES2015문법을 사용할 수 있습니다.

혹은 ES2015로 작성해도 노드에서 돌아가게끔 변환해주는 babel 모듈을 사용할 수도 있겠습니다.

지금까지 require이나 module객체는 따로 설정없이 사용할 수 있었는데, 노드에서 기본적으로 제공하는 내장 객체이기 때문입니다.


3.4 노드 내장객체 알아보기

노드에서는 기본적인 내장 객체와 모듈을 제공하는데, 브라우저의 window객체와 비슷하다고 보면 됩니다.

3.4.1 global

브라우저의 window와 같은 전역 객체이고, 전역객체이므로 모든 파일에서 접근할 수 있습니다.

그리고 window.open메서드를 open으로 호출할 수 있는것처럼 global도 생략이 가능합니다.

위의 require함수도 global.require에서 생략된 것입니다. 노드의 console.log도 global.console.log 입니다.


테스트로 globalA.js와 globalB.js를 생성하여 global객체 접근을 테스트해봅니다.

1
2
// globalA.js
module.exports = () => global.message
1
2
3
4
5
// globalB.js
const A = require('./globalA')
 
global.message = '안녕하세요'
console.log(A()) // 안녕하세요

globalA 모듈은 global.message를 반환하고, globalB.js에서는 global.message에 값을 대입하고 그아래에서 A를 호출했습니다.

그 결과 globalB에서 대입했지만 globalA에서 가져온 global.message객체를 찍으면 값이 변경된것을 확인할 수 있습니다.


3.4.2 console

console객체는 보통 디버깅을 위해 사용됩니다. 대표적으로 console.log, console.error등이 있습니다.

console.time(레이블): console.timeEnd(레이블)과 대응되어 같은 레이블을 가진 time과 timeEnd사이의 시간을 측정합니다.

console.log(내용): 평범한 로그를 콘솔에 표시합니다. console.log(내용, 내용, ...)처럼 여러내용도 표시가능합니다.

console.error(에러): 에러를 표시합니다.

console.dir(객체, 옵션): 객체를 콘솔로 표시할때 사용합니다. 첫번째인자로 표시할 객체를 넣고 옵션을 넣습니다. (color, depth 등)

console.trace(레이블): 에러가 어디서 발생하는지 추적할 수 있게 해줍니다.


3.4.3 타이머

setTimeout(콜백함수, 밀리초): 주어진 밀리초 이후에 콜백 함수를 실행합니다.

setInterval(콜백함수, 밀리초): 주어진 밀리초마다 콜백함수를 반복합니다.

setImmediate(콜백함수): 콜백함수를 즉시 실행합니다.


위 타이머 함수들은 아이디를 반환하는데 해당 아이디로 타이머를 취소할 수 도 있습니다.

clearTimeout(아이디), clearInterval(아이디), clearImmediate(아이디)...


순서를 예측해보세요

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// timer.js
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)

결과..



3.4.4 __filename, __dirname

노드에서는 파일사이에 모듈관계가 있는 경우가 많아서 현재 파일의 경로나 파일명을 알아야하는 경우가 있습니다.

__filename과 __dirname을 사용해봅시다.

1
2
3
// filename.js
console.log(__filename)
console.log(__dirname)


경로가 문자열로 반환되기도하고, \나 /같은 구분자문제도 있어서 보통은 이를해결해주는 path모듈을 함께 사용합니다.


3.4.5 module, exports

지금까지는 모듈을 module.exports만 사용했는데, exports객체로도 만들 수 있습니다.

위의 var.js를 아래와 같이 수정해도 index.js에서는 동일하게 불러올 수 있습니다.

1
2
3
// var.js
exports.odd = '홀수입니다'
exports.even = '짝수입니다'

module.exports = {} 에 한번에 대입하는 대신 각각의 변수를 exports객체에 넣었습니다.

module.exports === exports를 비교하면 true이므로 서로 같은 객체를 참조합니다.


3.4.6 process

process객체는 현재 실행되고 있는 노드 프로세스에 대한 정보를 담고 있습니다.


3.4.6.1 process.env

REPL에 process.env를 입력하면 많은 정보가 출력되는데, 이정보들은 시스템 환경변수입니다.

서비스의 중요한 키를 저장하는 공간으로도 사용되므로 아래와같이 중요한 데이터는 env객체에 넣어 사용합니다.

1
2
const secretId = process.env.SECRET_ID
const secretCode = process.env.SECRET_CODE


3.4.6.2 process.nextTick(콜백)

이벤트 루프가 다른 콜백함수들보다 nextTick의 콜백함수를 우선으로 처리하도록 만듭니다.

1
2
3
4
5
6
7
8
9
10
11
// nextTick.js
setImmediate(() => {
    console.log('immediate')
})
process.nextTick(() => {
    console.log('nextTick')
})
setTimeout(() => {
    console.log('timeout')
}, 0)
Promise.resolve().then(() =>  console.log('promise'))

process.nextTick은 setImmediate나 setTimeout보다 먼저 실행됩니다.

코드 맨 밑에 Promise를 넣은것은 resolve된 Promise도 nextTick처럼 다른 콜백들보다 우선시 되기 때문입니다.

그래서 process.nextTick과 Promise를 마이크로 태스크라고 따로 구분지어 부릅니다.


3.4.6.3 process.exit(코드)

실행중인 노드 프로세스를 종료합니다. 서버에서 이함수를 사용하면 멈추므로 서버에서는 거의 사용하지 않습니다.

process.exit(0)이나 process.exit()는 정상종료 process.exit(1)은 비정상 종료를 뜻합니다.

반응형