20.1 노드의 기초
브라우저 기반 자바스크립트는 브라우저에만 해당하는 API를 사용합니다.
노드에는 DOM이 없습니다. HTML이 없으니까요.
노드에만 해당하고 브라우저에는 존재하지 않는 API도 있습니다.
window와 document는 브라우저 환경에서 제공하는 API 입니다.
이 장에서는 노드에서 제공하는 API에 대해 설명합니다.
20.2 모듈
모듈은 패키지를 만들고 코드를 네임스페이스(namespace)로 구분하는 메커니즘이다.
네임스페이스는 이름 충돌을 방지하는 방법이다.
1 | // ## 20.2 모듈 |
1 | // ## 20.2 모듈 |
1 | //이들 모듈을 임포트함 |
- module은 노드에서 모듈을 구현하기 위해 만든 특별한 객체이다.
- export 프로퍼티에 무엇을 할당하든, 모듈은 그것을 내보낸다.
- 모듈은 어떤 타입의 값이든 내보낼 수 있다.
20.3 코어 모듈, 파일 모듈, npm 모듈
모듈은 코어 모듈, 파일 모듈, npm 모듈 3가지로 나뉜다.
코어 모듈 : fs나 os처럼 노드 자체에서 제공 하는 모듈, 모두 예약어 이다.
파일 모듈 : module.exports 에 할당되는 파일을 만들고 그 파일을 불러옴
npm 모듈 : 특별한 디렉터리 node_modules에 저장되는 모듈 파일
require 함수를 사용하면 노드는 함수의 매개변수를 보고 어떤 타입인지 판단한다.

- 코어모듈
process나 buffer 같은 일부 코어 모듈은 전역이고, 명시적인 require 문 없이도 사용할 수 있다.


모듈에 대한 상세한 API 문서(link: https://nodejs.org/api/) 를 참고
- npm 모듈
npm 모듈은 특수한 이름 표기법을 사용하는 파일 모듈이다.
node_modules 디렉터리에 직접적으로 작업하지말고, 모듈 파일 관련 작업은 npm에서 하도록 해야한다.
20.4 함수 모듈을 통한 모듈 커스터마이징
모듈은 대부분 객체를 내보내지만, 가끔 함수 하나만 내보내기도 한다.
이럴 경우 그 모듈의 함수를 즉시 호출하기 위해 사용한다.
그 함수가 아닌, 함수가 반환하는 것을 쓰게 한 것이다.
1 | const debug = require("debug")("main"); //모듈이 반환하는 함수를 즉시 호출 할 수 있다. |
debug 모듈이 반환한 것을 즉시 호출했으므로 debug 모듈이 함수를 반환한다는 것을 알 수 있고, 반환값인 함수 역시 함수를 반환하며 최종적으로 반환된 함수는 첫 번째 함수에 넘긴 문자열을 기억한다.
- 노드는 노드 앱을 실행할 때 어떤 모듈이든 단 한번만 임포트한다.
20.5 파일시스템 접근
자바스크립트는 노드가 만들어지기 전까지는 파일시스템에 접근 할 수 없었다.
- 파일을 생성하고 쓸 때는 fs.writeFile()을 사용합니다.
1 | //파일 생성하고 쓰기 |
write.js 파일을 저장한 디렉터리에 쓰기 권한이 있고, hello.txt 파일이 생성되어 글자가 써진다. 해당 애플리케이션은 자신이 실행된 현재 디렉터리를 __dirname 변수로 보관한다. 이 변수를 사용해서 write.js 파일을 고쳐 쓸 수 있다.
1 | const fs = require("fs"); |
이제 write.js가 있는 디렉터리에 hello.txt를 만든다. __dirname은 특정 운영체제에 따라 호환되지 않을 수 있다. 이럴 경우 노드의 path.join을 사용하면 모든 운영체제에서 호환 가능하다.
- 파일을 읽을때는 fs.readFile()을 사용합니다.
1 | const fs = require("fs"); |
fs.readFile()는 가공되지 않은 바이너리 데이터인 버퍼를 반환한다. 기본 문자열 인코딩은 UTF-8이다. 인코딩을 지정하면 원하는 결과를 얻을 수 있다.
1 | const fs = require("fs"); |
파일 관련 함수에는 모두 동기적으로 작업하는 짝이 있으며,
이들 이름은 Sync로 끝난다.
1 | //파일 쓰기 |
- 디렉터리에 어떤 파일이 있는지 알아보려면 fs.readdir을 사용합니다.
1 | const fs = require("fs"); |
- fs 모듈에는 이외에도
- 파일을 지우는 fs.unlink();
- 파일을 옮기거나 이름을 바꾸는 fs.rename(),
- 파일과 디렉터리의 정보를 얻는 fs.stat(),
등이 있으며 자세한 정보는 link(https://nodejs.org/api/fs.html) 을 참고
20.6 process
실행 중인 노드 프로그램은 모두 process 변수에 접근 가능
이 변수는 해당 프로그램에 관한 정보를 담고 있으며 실행 자체를 컨트롤 할 수 있다.
예를 들어, 애플리케이션이 치명적 에러를 만나서 실행하지 않는 편이 좋으면 (fatal error) process.exit를 호출해 즉시 실행을 멈춘다.
숫자형 종류 코드를 쓰면 프로그램이 성공적으로 종료됐는지, 에러가 있었는지 외부 스크립트에서 알 수 있다.
보통 에러없이 프로그램을 끝냈다면 종료코드 0을 사용한다.
1 | const fs = require("fs"); |
process 객체를 통해 프로그램에 전달된 명령줄 매개변수 배열에 접근 할 수도 있다.
명령줄 매개변수는 process.argv() 배열에 저장된다.
process.env()를 통해 환경 변수에 접근 할 수 있다.
환경 변수는 시스템 변수이며 주로 명령줄 프로그램에서 사용한다.
export VAR_NAME=value 명령으로 환경변수를 설정할 수 있다.
환경변수는 보통 전부 대문자로 표현한다.
1 | const debug = process.env.DEBUG === "1" ? console.log : function() {}; |
이 예제에서 debug 함수는 환경 변수 DEBUG가 1이면 console.log의 별칭이되고, 그렇지 않으면 null 함수가 된다. null 함수를 만들지 않으면 debug 가 정의되지 않는 경우가 생기고, 에러가 발생한다.
process.cmd 에서는 현재 작업 디렉터리가 저장되며,
process.chdir로 현재 작업 디렉터리로 바꿀 수 있습니다.
1 | //프로그램에서 현재 작업 디렉터리를 호출한다음, 프로그램이 저장된 디렉터리를 현재 작업 디렉터리로 바꾸는 경우 |
20.7 운영체제
os 모듈은 프로그램을 실행하는 컴퓨터의 운영체제에 관한 정보를 제공합니다.
1 | const os = require("os"); |
20.8 자식 프로세스
child_process 모듈은 애플리케이션에서 다른 프로그램을 실행할 때 사용.
주요함수는 exec, execFile,fork 입니다.
exec와 execFile은 운영체제에서 지원하는 실행파일은 무엇이든 실행할 수 있습니다.
exec는 명령줄에서 실행할 수 있는 것은 다 실행할 수 있다.
execFile은 셸을 통하지 않고 실행파일을 직접 실행하므로 효율적이지만 더 주의해야 할 점이 있다.
fork는 다른 노드스크립트를 실행할 때 사용한다
1 | const exec = require("child_process").exec; |
20.9 스트림
스트림은 스트림 형태의 데이터를 다루는 객체이다.
스트림은 흐름같은 느낌이고, 흐름은 비동기적으로 이루워질것이라 짐작됨
스트림에서는 읽기(read) 스트림, 쓰기(write) 스트림, 이중(duplex) 스트림이 있다.
1 | const fs = require("fs"); |
end()를 호출해서 쓰기 스트림(ws)를 종료하기 전까진 write 메서드를 통해 스트림에 쓸 수 있다.
end를 호출한 다음 write를 호출하면 에러가 발생한다.
마찬가지로 읽기 스트림을 만들어서 들어오는 데이터를 읽을 수도 있다.
1 | const fs = require("fs"); |
데이터가 스트림을 ‘흐른다’는 표현을 보면 읽기 스트림에서 데이터를 읽는 즉시 쓰기 스트림에서 쓸 수 있다. 이런 작업을 파이프(pipe)라고 한다.
예를 들어, 읽기 스트림과 쓰기 스트림을 파이프로 연결하면 파일 콘텐츠를 복사하는 효과가 있다.
1 | const fs = require("fs"); |
위 예제는 따로 인코딩을 명시할 필요없이 rs는 그냥 stream.txt의 데이터를 ws 파이프에 연결하고, ws는 그 데이터를 그대로 steam_copy.txt에 기록할 뿐이다.
20.10 웹서버
노드는 원래 웹서버를 만드는 것이 목적이였다.
http 모듈(보안 연결을 제공하는 https 모듈 역시)에는 기본적인 웹 서버를 만드는 createServer 메서드가 있다.들어오는 요청을 처리할 콜백 함수만 만들면 된다.
서버를 시작할 떈 listen 메서드를 호출하면 포트를 지정한다.
1 | const http = require("http"); |
노드를 실행하면, 브라우저 http://localhost:8080/ 에 hello world가 보인다. 터미널을 보면 모든 요청이 기록되어 있다. 요청은 메서드(여기서는 GET)과 URL 경로로 구성된다. 브라우저에서 그 URL을 방문할 때마다 요청 두 개가 기록되는 것을 보고 의이할 수 있다. 대부분의 브라우저는 요청을 보낼 때 url 막대 또는 탭에 표시할 아이콘인 파비콘을 요청한다.
노드 웹 서버서의 핵심은 들어오는 요청에 모두 응답하는 콜백함수 이다.
이 함수는 매개변수로 IncomingMessage객체(req)와 **ServerRequest객체(res)를 받는다.
IncomingMessage 객체에는 요청받은 url, 보낸 헤더, 바디에 들어있던 데이터 등 http 요청에 관한 모든 정보가 들어있다.
ServerResponse 객체에는 클라이언트(보통 브라우저)에 보낼 응답을 컨트롤하는 프로퍼티와 메서드가 들어있다.
ServerResponse 객체는 쓰기 스트림 인터페이스이며, 이를 통해 데이터 클라이언트에 보낸다.
1 | const server = http.createServer(function(req, res) { |
20.11 요약
fs,Buffer, process, stream 등 거의 모든 애플리케이션에서 사용하는 API는 이 장에서 소개했지만, 그외에 알아야할 API는 공식문서를 참고
link(https://nodejs.org/en/docs/)