NPM
버전 정의
- npm 패키지 버전 : Major.Minor.Patch
- Major : 이전 버전과 호환되지 않으면 변경
- Minor : 이전 버전과 호환되면서 신규 기능 추가
- Patch : 이전 버전과 호환되면서 버그 수정
- ^1.2.2 : [1.2.2, 2.0.0) 호환
- ~1.2.2 : [1.2.2, 1.3) 호환
- 1.2.2-1.4.4 : 직접 지정
- 1.2.x : 와일드카드
0이 아닌 최초 버전의 하위 버전 변경 모두를 포함
지정된 버전의 상위 버전 변경 전까지 모두를 포함
>=1.2.2 <=1.4.4와 동일
프로젝트 의존성 관리
↓shell
package.json
아래 예시는 다른 패키지의 것들을 맘대로 섞은 것임
↓javascript
패키지 배포
참고자료
프로젝트 설정
- 프로젝트를 위한 GitHub 저장소가 없다면 하나 생성
- 작업 환경에 GitHub 저장소 클론
- npm 프로젝트 설정이 안 됐다면 $ npm init으로 package.json 초기화
- 프로젝트 이름에 GitHub 사용자/조직 이름을 포함하여 구분시키기
e.g. @aws-sdk/client-s3
NPM 계정 생성
- signup
- $ npm login
배포 관련 커맨드
↓shell
프로덕션 사용을 위한 설정
CommonJS와 ECMAScript Module 모두 지원하기
- TypeScript 설치
- 공통 설정 파일 작성
- CommonJS 타입을 위한 설정 파일 작성
- ECMAScript Module 타입을 위한 설정 파일 작성
- 빌드 산출물을 모두 포함하도록 package.json 설정
- 모듈 로더에 따라 적절한 위치에서 파일을 찾도록 package.json 설정
- CJS 산출물에 맞춰 package.json 기본값 설정
- package.json에 빌드 커맨드 설정
↓configs/tsconfig.base.json
↓configs/tsconfig.cjs.json
↓configs/tsconfig.esm.json
↓package.json
↓package.json
↓package.json
↓package.json
테스트 코드 작성
- mocha 패키지 : 테스트 실행 라이브러리
- chai 패키지 : assertion 라이브러리
- ts-node 패키지 : TypeScript 코드 즉시 실행 라이브러리
- 테스트 실행 설정
- tests 디렉터리에 테스트 코드 작성
- package.json에 테스트 커맨드 설정
↓.mocharc.json
↓package.json
eslint 설정
- $ npx eslint --init으로 초기화
- VS Code eslint 확장 프로그램이 낮은 버전의 기본 설치 Node를 이용하는 경우 런타임 변경
- VS Code에서 파일 저장시 자동으로 수정사항 적용
↓.eslintrc.json
↓settings.json
↓settings.json
패키지를 배포하기 전에 작동하는지 확인
- 라이브러리 프로젝트 디렉터리에서, 번들 생성
- 라이브러리를 사용할 프로젝트 디렉터리에서, 번들 설치
↓shell
↓shell
TypeScript
- JavaScript에 타입이 추가된 수퍼셋. 컴파일하면 자바스크립트 코드가 된다
- 타입스크립트에서는 생성자 매개변수 앞에 public/private 접근한정자가 있으면 자동으로 클래스의 속성으로 선언한다
- VS Code의 타입스크립트 컴파일러를 npm 패키지로 설정
↓shell
"typescript.tsdk": "C:/Users/name/AppData/Roaming/npm/node_modules/typescript/bin/tsc"
디버깅
- 코드 사이에 중단점 삽입
- node 실행 시 디버깅 켜기
- 자동으로 디버깅 포트를 열며, chrome://inspect 등으로도 이용 가능
- 명령어
- n : 다음 문장; next
- c : 다음 중단점; continue
- s : step into
- o : step out
- watch(expr) : expr 평가 감시
- exec(expr) : expr 평가
- repl : 디버깅 REPL에서 직접 코드로 확인
- help
- .exit
↓javascript
↓shell
Lib/Cluster
- 멀티 코어 CPU의 성능을 이용하기 위해, 동일한 로직을 이용하는 멀티 프로세스 생성/관리 기능 제공
- 프로세스는 마스터(cluster.isMaster)와 워커로 구성
- 자식(워커) 프로세스들은 부모 프로세스와 TCP 연결을 공유할 수 있다
Lib/Console
↓javascript
Lib/Events
- class EventEmitter
- 이벤트 발행 주체
- events 모듈의 exports 자체가 EventEmitter 클래스다
- EventEmitter.defaultMaxListeners
- emitter.on(string|symbol eventName, Function listener)
- emitter.once(string|symbol eventName, Function listener) + prependOnceListener
- emitter.emit(string|symbol eventName[, any ...args])
- 이벤트 발행
- 이벤트 핸들러는 동기적으로 실행되며, 반환값은 무시된다
- 핸들러 내에서 this 키워드는 이벤트를 발행한 EventEmitter 인스턴스를 가리킨다
- emitter.eventNames()
- emitter.getMaxListeners() + setMaxListeners
- emitter.listeners(string|symbol eventName) + listenerCount, rawListeners Since 9.4
- error 이벤트
- newListener, removeListener 이벤트
- events.once(EventEmitter emitter, string name) : Promise Since 11.13
- events.on(EventEmitter emitter, string|symbol eventName) : AsyncIterator
기본적으로 이벤트 구독/해지에 대해 자동으로 'newListener', 'removeListener' 이벤트 발행
↓javascript
기본값 10
이벤트 핸들러 등록(구독)
== addListener ↔ off, + removeListener, prependListener, removeAllListeners
이벤트 1회 구독
구독자가 있으면 true, 없으면 false 반환
단, 람다 함수에서는 this 키워드가 EventEmitter 인스턴스를 가리키지 않는다
사용자가 구독 요청한 이벤트 이름들을 배열로 반환
'error' 이벤트 구독자가 없는 경우, EventEmitter 내의 예외는 밖으로 던져지고 프로세스는 종료된다
핸들러 : (string|symbol eventName, Function listener)
name 이벤트 발행 또는 'error' 이벤트 발행시 emit()의 args 그대로 Promise가 실행된다
eventName 이벤트 발행 시 emit()의 args를 배열로 받는다
↓javascript
Lib/Globals
- this == global
- TextDecoder Since 11 == util.TextDecoder
- TextEncoder Since 11 == util.TextEncoder
- URL == url.URL
- URLSearchParams Since 10 == url.URLSearchParams
- WebAssembly Since 8
- class Buffer
- __filename, __dirname : 실행 중인 소스 파일 정보. REPL 모드에서는 당연히 없다
- console : 콘솔 관련
- exports, module, require() : 모듈 관련
- process : 프로세스 관련
- setTimeout, clearTimeout, setInterval, clearInterval, setImmediate, clearImmediate : timer 관련
- queueMicrotask(Function callback) Since 11
아직 개발중인 웹 어셈블리와의 호환을 위한 네임스페이스
"microtask queue"는 V8 엔진이 관리하며, 동작은 process.nextTick()과 유사하다. 이벤트 루프 어느 페이즈에서든지 "next tick queue"가 항상 "microtask queue"보다 먼저 실행된다
Lib/HTTP, HTTPS
- HTTP, HTTPS Client 예
↓javascript
Lib/Modules
- require(string id)
- 각 파일들은 별개의 모듈로 취급된다
- 로드된 모듈은 캐시되므로, 반복적인 require()는 같은 객체를 반환한다
- 모듈이 Node에 의해 직접 실행되는 경우, require.main으로 설정된다
- 모듈 사이에 require() 사이클이 존재하는 경우, 초기화 완료되지 않은 exports 객체를 반환하여 무한 반복을 방지한다
- 모듈을 /usr/lib/node_modules/{name}/{version} 경로로 관리하면 효율적인 require() 가능
- require알고리즘
- 선두 '/', './', '../' 없이 요구된 모듈
- core 모듈이면 해당 모듈 로드
- ROOT 디렉터리에 도달할 때까지, {부모 디렉터리}/node_modules/{X} 모듈을 탐색
- 아무데서도 모듈을 찾지 못한 경우, $NODE_PATH 환경변수의 디렉터리를 탐색하지만, $NODE_PATH 사용은 권장되지 않는다
- 디렉터리를 모듈로
- package.json
- index.js
- 로드된 모듈의 실행은 아래와 유사하다
- 모듈 top-level에 정의된 변수들이 모듈 스코프에 존재
- 모듈 밖에서는 exports를 공유
- 모듈 안에서는 __filename, __dirname을 편리하게 획득
require('./foo/bar.js');
require()가 두 개 이상의 파일을 찾은 경우, 요구한 이름의 대소문자를 바꾼 경우 등은 예외
따라서 require.main === module로 현재 모듈이 메인인지 판별 가능하다
확장자 없는 파일 X, X.js 파일, X.json 파일, X.node 파일, X/index.js 디렉터리, X/package.json 디렉터리 등을 적절히 처리
↓javascript
↓javascript
최초 exports는 module.exports를 가리키므로, exports에 다른 객체를 할당하는 경우, 해당 부분은 외부와 공유되지 않는다. 외부에 공유하려면 module.exports = exports = newObject
Lib/Process
- Event 'beforeExit'
- Event 'exit'
- Event 'multipleResolves' Since 10.12
- 임의 Promise의 두 번째 resolve 또는 reject 호출부터 콜백이 호출된다
- 콜백 : (string type, Promise promise, any value)
- process.abort()
- process.chdir(directory)
- string[] process.argv
- Object process.env
- string process.execPath
- string[] process.execArgv
- process.nextTick(Function callback[, any ...args])
- integer process.pid
- integer process.ppid Since 9.2, Since 8.10
- Stream process.stdin, stdout, stderr
정상 종료 전, process.exitCode를 인자로 콜백이 호출된다. process.exit() 등으로 종료하는 경우 호출되지 않는다. 콜백에서 비동기 호출로 프로그램 종료를 지연시킬 수 있다
정상 종료 및 process.exit() 호출 시 process.exitCode를 인자로 콜백이 호출된다. 콜백은 동기적 연산만 수행해야 한다
Promise.race() 호출처럼, 경우에 따라서 이 이벤트 발생이 에러가 아닐수도 있다
강제 종료. Worker 스레드에서는 실행 불가
실행 위치 변경
callback을 "next tick queue"에 추가한다. args는 callback의 인자가 된다. callback은 현재 페이즈에서 실행 중인 코드가 모두 완료된 후 즉시 실행되며, setImmediate()보다 빠르게 실행된다
부모 프로세스 PID
3rd/CryptoJS
해싱, 암/복호화, 인코딩/디코딩 관련 함수 제공
3rd/express : Web Framework
- 정적 리소스 제공에는 Nginx, CDN, Amazon S3 등을 고려함이 좋다
- Quick start
- 서버 시작
- 실행 환경
- 환경 변수 이름 : NODE_ENV
- 기본 : development
- 릴리스 : production
- process.env.NODE_ENV로 획득 가능
- 서버 설정
- Method 라우팅
- 응답
- Middleware : 요청 처리 체인의 앞부분에서 전처리를 하며, 다음으로 넘어갈지 결정
- static 파일 전송 미들웨어
- static 디렉터리 파일들을 전송하는 미들웨어 사용
- 요청 URL과 실제 디렉터리 경로를 다르게 하고 싶은 경우
- 세션
아래 명령으로 프로젝트 골격을 빠르게 구성할 수 있다
↓shell
↓javascript
| app.set(name, value) | 예약된 키워드들이 있음에 유의 |
| app.set('port', process.env.PORT || 55555) | 서버 포트 |
| app.set('views', path.join(__dirname, 'templates')) | 템플릿 디렉터리 |
| app.set('view engine', 'pug') | 템플릿 확장자 |
path에는 regex 사용 가능
↓javascript
↓javascript
↓javascript
↓javascript
↓javascript
cookie-parser, express-session 모듈 이용
3rd/fastify : Web Framework
- 보다 효율적으로 요청을 처리하는 웹 프레임워크
- CORS만 적용한 기본 프로젝트 예.
테스트 조건 하에서, 초당 5만건 이상의 Hello World 응답 처리
3rd/forever : 종료 시 자동 재시작
- 스크립트 영구 실행
- forever 모듈을 코드에서 호출하는 경우, forever-monitor가 도움이 된다
- CLI 호출
↓shell
↓javascript
3rd/Pug : 템플릿 엔진(구 Jade)
- pug -P // Pretty
- ↓ 아래 코드들은 1.11.0 버전 결과임
- 주석
- Plain Text
- 코드 실행
- 태그 속성
- 다른 문서 포함
- 템플릿 - mixin
- 템플릿 - extends
기본 옵션은 불필요한 공백 제거
3rd/mocha : 테스트 프레임워크
- 설치
- 비동기 코드 테스트
- 테스트 함수가 콜백을 인자로 받아 비동기 작업 완료 후 호출
- 예외 발생 시 예외 객체 그대로 전달하면 알아서 fail로 간주
- 콜백이 2회 이상 호출된 경우 fail로 간주
- 또는 그냥 Promise를 반환하면 알아서 성공/실패 판단
- 실행 환경이 지원한다면, 테스트 함수 자체를 async로 해도 무방
- Hooking
- before : 첫 번째 테스트 실행 전 한 번만 실행
- beforeEach : 매 테스트 실행 전 한 번씩 실행
- after : 마지막 테스트 실행 후 한 번만 실행
- afterEach : 매 테스트 실행 후 한 번씩 실행
- 각 hook들은 비동기 테스트 코드처럼 done을 받는 비동기 작업을 해도 된다
- describe.only(), it.only() : only 붙은 것만 테스트
- describe.skip(), it.skip() : 스킵
- this.retries(n) : (행위) 테스트에서 재시도를 하도록 설정
- 시간 제한 : this.timeout(n), setTimeout(done, 300)
↓shell
↓javascript
this.skip()으로 런타임 중 스킵 가능 ← 테스트 함수 및 'before' hook 안에서 사용 가능
3rd/mongodb : MongoDB 공식 드라이버
- http://mongodb.github.io/node-mongodb-native/3.6/tutorials/
- http://mongodb.github.io/node-mongodb-native/3.6/api/