27. 커스텀 ESM 로더 훅의 안정화
ESM 로더 훅 이란?
기존에 있는 코드 전 후로 추가할 수 있는
사용자 정의 함수
28. 커스텀 ESM 로더 훅의 안정화
ESM 로더 훅 이란?
ESM 모듈 임포트시 추가 가능한 사용자 정의 함수
29. 커스텀 ESM 로더 훅의 안정화
ESM 로더 훅 이란?
• ESM Loader Hook API는 18.6.0 에 릴리즈 했음
• 그런데 실수로 experimental을 빼먹고 릴리즈해서 옵션명이 --loader 가 됐음.
• 나중에 --experimental-loader를 추가
• 실수로 릴리즈 되어버려서 옵션 설명에는 --loader, --experimental-loader 둘다 병기
• Node.js 20 버전 이전까지는 메인쓰레드에서 로더 훅을 담당
• 대형 프로젝트에서는 훅을 처리하는데 시간이 많이 걸림.
• 그래서 별도의 쓰레드에서 처리하도록 Node.js 20버전에서 변경 -> import 성능향상
37. 커스텀 ESM 로더 훅의 안정화
$ node --loader=./andy.mjs --experimental-loader=./url-loader.mjs main.js
(node:97037) ExperimentalWarning: `--experimental-loader` may be removed in the future; instead use `register()`:
--import 'data:text/javascript,import { register } from "node:module"; import { pathToFileURL } from "node:url"; register("./
andy.mjs", pathToFileURL("./")); register("./url-loader.mjs", pathToFileURL("./"));'
(Use `node --trace-warnings ...` to show where the warning was created)
load >> file:///Users/gyus/VSCode/jsbackend/nodejs20_major_features/esm-loader-hook/url-loader.mjs
load >> file:///Users/gyus/VSCode/jsbackend/nodejs20_major_features/esm-loader-hook/main.js
load >> andy:andy
foo.................
Hello Node.JS! I am Andy
// console.log(rightPad('foo', 20, '.'))
// test()
38. 커스텀 ESM 로더 훅의 안정화
$ node --loader=./andy.mjs --experimental-loader=./url-loader.mjs main.js
(node:97037) ExperimentalWarning: `--experimental-loader` may be removed in the future; instead use `register()`:
--import 'data:text/javascript,import { register } from "node:module"; import { pathToFileURL } from "node:url"; register("./
andy.mjs", pathToFileURL("./")); register("./url-loader.mjs", pathToFileURL("./"));'
(Use `node --trace-warnings ...` to show where the warning was created)
load >> file:///Users/gyus/VSCode/jsbackend/nodejs20_major_features/esm-loader-hook/url-loader.mjs
load >> file:///Users/gyus/VSCode/jsbackend/nodejs20_major_features/esm-loader-hook/main.js
load >> andy:andy
foo.................
Hello Node.JS! I am Andy
// console.log(rightPad('foo', 20, '.'))
// test()
뭔가 경고문구가 장황하게 뜬다
39. 커스텀 ESM 로더 훅의 안정화
$ node --loader=./andy.mjs --experimental-loader=./url-loader.mjs main.js
(node:97037) ExperimentalWarning: `--experimental-loader` may be removed in the future; instead use `register()`:
--import 'data:text/javascript,import { register } from "node:module"; import { pathToFileURL } from "node:url"; register("./
andy.mjs", pathToFileURL("./")); register("./url-loader.mjs", pathToFileURL("./"));'
(Use `node --trace-warnings ...` to show where the warning was created)
load >> file:///Users/gyus/VSCode/jsbackend/nodejs20_major_features/esm-loader-hook/url-loader.mjs
load >> file:///Users/gyus/VSCode/jsbackend/nodejs20_major_features/esm-loader-hook/main.js
load >> andy:andy
foo.................
Hello Node.JS! I am Andy
// console.log(rightPad('foo', 20, '.'))
// test()
--loader를 사용하지 말고 register() 를 사용하라는 뜻
44. V8을 11.3으로 버전업
• String.prototype.isWellFormed, toWellFormed 함수 추가
• Array와 TypedArrray 원본 배열을 변경하지 않고 새 배열을 생성하는 메서드 추가
• ArrayBu
ff
er와 SharedArrayBu
ff
er의 크기를 동적으로 변경하기
• 정규표현식에 v 플래그가 추가됨
• 웹어셈블리에서 꼬리 물기 최적화(Tail Call Optimization)를 적용
45. V8을 11.3으로 버전업
• String.prototype.isWellFormed, toWellFormed 함수 추가
isWellFormed
올바른 유니코드 문자열인지 확인하는 함수
46. V8을 11.3으로 버전업
• String.prototype.isWellFormed, toWellFormed 함수 추가
isWellFormed
올바른 유니코드 문자열인지 확인하는 함수
유니코드에서 사용하지 않는 문자열은?
U+D800부터 U+DFFF는 utf8에서 사용하지 않음
47. V8을 11.3으로 버전업
• String.prototype.isWellFormed, toWellFormed 함수 추가
48. V8을 11.3으로 버전업
• String.prototype.isWellFormed, toWellFormed 함수 추가
toWellFormed
잘못된 유니코드 문자열을 대체가능한 문자열로 변경
U+D800을 넣어보자.
49. V8을 11.3으로 버전업
• String.prototype.isWellFormed, toWellFormed 함수 추가
toWellFormed
잘못된 유니코드 문자열을 대체가능한 문자열로 변경
는 원래의 데이터가 손상되었거나 유니코드로 변환될 수 없는 문자를 대체하는 데 사용됨
50. V8을 11.3으로 버전업
• Array와 TypedArray 원본 배열을 변경하지 않고 새 배열을 생성하는 메서드 with 추가
56. V8을 11.3으로 버전업
• 웹어셈블리에서 꼬리 물기 최적화(Tail Call Optimization)를 적용
꼬리 물기 최적화란?
57. V8을 11.3으로 버전업
• 웹어셈블리에서 꼬리 물기 최적화(Tail Call Optimization)를 적용
꼬리 물기 최적화란?
재귀 함수의 성능을 향상시키기 위한 기법
함수의 꼬리 부분(마지막)의 재귀호출을 최적화
함수의 마지막에 다른 함수를 호출 하는 방식으로 구현
66. 안정적인 테스트 러너
• 기존에는 테스트를 하려면 서드파티 라이브러리(jest, mocha등)가 필요했음.
• Node.js 20에 test_runner 모듈이 포함됨
• describe로 테스트 코드 블록을 구분할 수 있고, it 혹은 test 메서드로 테스트 코드 작성
• mock 기능이 추가됨. 클래스, 메서드, 타이머(20.4.0 에추가) 관련 모킹이 가능
• watch 모드 --watch 옵션으로 파일을 저장할 때마다 테스트를 실행
• 여러개의 테스트를 병렬로 실행가능
• --experiments-test-coverage 옵션으로 테스트 커버리지 확인 가능
• --test-concurrency 옵션으로 병렬처리 갯수 지정 가능
72. Node.js 성능향상
• state-of-nodejs-performance-2023 에서 Node의 벤치마크를 확인가능
• Node 16, 18, 20에 대해 성능테스트를 진행
• 내용이 방대하여 파일시스템, 이벤트 타겟, HTTP, 기동시간, 모듈, 스트림, URL파싱, 버
퍼, 텍스트 인코딩/디코딩, Crypto.verify 만 정리
73. Node.js 성능향상 - 파일시스템
• 16 > 18 : 인코딩이 ascii인 경우 67% 빨라짐, utf-8인 경우 12% 빨라짐
• 18 > 20 : 인코딩이 ascii인 경우 -27% 느려짐, utf-8인 경우 3% 빨라짐
76. Node.js 성능향상 - 기동시간
• 16 > 18 : 6% 빨라짐
• 18 > 20: 27% 빨라짐
• 서버리스 등에서 사용하므로 빠른 기동시간은 중요하다.
77. Node.js 성능향상 - 모듈
• require() 함수는 Node의 기동을 느리게하는 주범이었음
• 18버전에 비해 .js 파일은 4.2%, .json파일은 6.58%, 디렉터리 탐색은 9.5% 개선이 있
었음.
• 이는 초기 기동을 더 빠르게 해줌
78. Node.js 성능향상 - 스트림
• 스트림은 16에서 18버전으로 가면서 느려졌었음
• 20버전으로 가면서 다시 개선을 하여 느렸던 부분을 이전과 비슷한 수준으로 거의 개선함
79. Node.js 성능향상 - URL 파싱
• Node18에 Ada URL를 도입하면서 성능이 400%향상됨.
• Node20에서는 Ada2.0을 도입하면서 추가적인 성능 향상이 있었음
80. Node.js 성능향상 - 버퍼
• 버퍼는 바이너리 데이터를 다루는데 사용
• Node16에서 18로 업그레이드시 성능이 매우 떨어지는 현상이 있었음
• 20버전에서 느린 함수들을 다시 16버전의 수준으로 회복
• Bu
ff
er.toJSON() 함수는 16보다 88% 더 빠름
82. Node.js 성능향상 - Crypto.verify
• 디지털 서명을 만들고 확인하거나 암복호화 하는데 사용하는 함수
• Node14에는 OpenSSL 1.x를 사용했고
• Node16에서는 QUIC프로코콜을 도입. 그러나 여전히 OpenSSL 1버전을 사용
• Node 18에서 OpenSSL을 3.x (Over QUIC)으로 업그레이드 했으나. 성능이 초당 3만
개 처리에서 6~7천개 처리로 떨어짐. 아마도 OpenSSL의 버전 문제로 생각됨.
83. Node.js 성능향상 - 결론
Crypto.verify 이외에는 모든 성능이 개선됨
성능은 Node.js의 새로운 전략적 목표이고, 이에 성능팀이 생김
84. .env 지원을 내장
.env 파일
env-test.js
실행 및 결과
• 기존에는 dotenv패키지를 설치해야 했으나 --env-
fi
le 옵션을 사용하여 지원할 수 있게 변경
• .env 파일은 ini 파일 형식이어야한다
85. 그 외
• 단일 실행 파일을 만들기위한 SEA(single executable applications)
• Node.js 설치 없이도 동작하는 애플리케이션을 만들 수 있음
• 현재는 실험적 기능이며, 패키징을 하기 위해 수동으로 해야 하는 절차가 많음
• 개인적으로는 좋게 평가
• 웹의 크립토 API가 Node.js에서도 동작하도록 지원
• ARM64 윈도우 공식지원
• Node.js 내에 웹어셈블리 시스템 인터페이스(WASI) 구현 작업 진행중