Webpack5 설정
개요
- no config 가 유행이지만 적용할 체계에 맞게 튜닝하려면 모든 옵션을 꿰고 있어야할 것이다.
전체 설정
1 | const path = require("path"); |
기본 값 확인
- 옵션 별 기본 값은 문서상으로 알 수 없는 경우가 있었다.
- 아래 소스에서 확인 가능했다.
- webpack/lib/config/defaults.js
- webpack/test/Defaults.unittest.js
1 | const path = require("path"); |
delay, catchError, delayWhen
의 조건만 다르게 하여 사용하면 된다.1 | import { EMPTY, from, of } from "rxjs"; |
jest
에서 done callback 을 적절히 호출해주자.Performance (특히 CLS)와 Privacy 가 행사 전반에 녹아있었다. 가장 중요했던 건 이제 Web Vitals 수치가 SEO 에 반영이 된다는 것이다.
1 | const connection = navigator.connection.effectiveType; |
best editor
처럼 여러 검색 결과가 나오는 경우에는 page experience 가 표시에 더 많은 영향을 준다.Great relevant content > Page experience
1 | .content { |
swap
폰트 로드로 인해 레이아웃이 변경되는 구조를 막을 수 있다.ascent-override, descent-override, line-gap-override
Chrome87 부터 가능하다.portal
을 18년 소개 후부터 미는데… 브라우저 지원이 없어서 아직까진 잘 모르겠다.Cross-Origin-Opener-Policy: same-origin
코옵Cross-Origin-Embedder-Policy: required-corp
코엡1 | # 타 도메인 리소스 |
conversiondestination, impressiondata, reportingorigin
가 추가된다.chrome://conversion-internals
에서 디버깅 가능하다./[\p{L} ]+/u
1 | <input |
type="number"
가 아닌 type="text", inputmode="numeric"
을 사용해야한다.@${bound-domain} #${OTP}
처럼 넣어주면 브라우저에서 파싱이 가능하다. (e.g. @gracefullight.dev #123456
)CSS.paintWorklet.addModule
로 바로 가져와서 쓸 수 있다고 강조했다.ES2017
은 유저 중 94% 가 다 사용할 수 있으므로 더 높은 버전 사용시에는 이 버전을 타켓으로 해야한다. (ES2021
은 70%)ESnext > ES2017 > ES2015
처럼 ES2017
을 한번 더 말아서 따로 제공해야한다. 필요 없는 코드가 너무 많이 들어가기 때문이다.navigator.runOnOsLogin
window.getScreens(), internal/external
manifest.display_override: "tabbed"
TimestampTrigger
manifest.capture_links, manifest.url_handlers
manifest.file_handlers, launchQueue
fetch event
가 정의되어있는지만 확인하는데 이제는 offine 시에 200 이 반환되어야한다.check-offline-capability
플래그를 활성화하여 테스트 가능하다.bubblewrap/cli
사용하여서 TWA 를 만드는 방법PaymentRequest
로 PWA 와 구글 결제 연동 가능1 | const s = document.createElement('script'); |
schema-dts, react-schemaorg
패키지도 있다.블루투스 기기가 자동 연동될 때 쉘에서 직접 차단을 할 수 있다.
option + shift
후에 블루투스 상태창을 클릭하면 MAC 주소(Media Access Control Address)를 알 수 있다.
블루투스 정보는 com.apple.Bluetooth.plist
에서 관리한다.
1 | # 설정파일을 xml 형식으로 변환한다. |
이제 더 이상 모르는 기기로부터의 연결을 요청받지 않아도 된다.
빅서로 업데이트 후부터 알 수 없는 맥 어드레스의 기기가 자동 연결되면서 매직 키보드와 트랙패드의 연결이 유실되는 현상이 있어서 무시하는 법을 찾기 시작하였는데, 비슷한 버그가 발생하는 것 같다.
쿠버네티스 환경에서는 Node.js 이미지를 올릴 시 종종 아래와 같은 IP 반환 에러메세지가 보인다.
이는 서비스 연결조차 불가능하게 만들어 운영에 지장을 주었다.
1 | Error: getaddrinfo EAI_AGAIN your-service |
먼저 Node.js 레벨에서부터 확인을 시작하였다.
Node.js Man 을 보면 다음과 같은 주의사항이 있다.
Though the call to
dns.lookup()
will be asynchronous from JavaScript’s perspective, it is implemented as a synchronous call to getaddrinfo(3) that runs on libuv’s threadpool. This can have surprising negative performance implications for some applications, see the UV_THREADPOOL_SIZE documentation for more information.
연관된 UV_HTREADPOOL_SIZE 문서는 다음과 같다.
Asynchronous system APIs are used by Node.js whenever possible, but where they do not exist, libuv’s threadpool is used to create asynchronous node APIs based on synchronous system APIs.
스레드 풀을 사용하는 API 는 다음과 같다.
이 메소드들을 사용할 때는 병렬 요청과 부하에 신경을 써야하며 UV_THREADPOOL_SIZE
사이즈를 Node.js 기본값인 4에서 적절히 증가시켜줘야한다.
dns.lookup
가 비동기인척하는 동기 메소드임을 확인할 수 있었다.
보통 이 메소드를 직접 사용하는 경우는 거의 없다.
axios
등 http 연결을 하는 라이브러리에서 Hostname 을 IP 로 변경하기 위해 사용한다.
java 는 30s¹, php 는 120s²의 도메인 캐시를 기본으로 제공하지만 Node.js 에서는 그런 것이 없다.
Node.js 커뮤니티에서는 native dns lookup cache 기능이 제안 되었지만, dns.resolve4
와 dns.resolve6
에 서버에서 반환하는 ttl
값을 사용할 수 있게 추가되어 이걸 사용하여 DNS 캐싱을 하게 권장되었다.
alpine 이미지에는 musl 을 사용하므로 다음과 같은 이슈가 발생할 수 있으나 해당 서비스는 그렇지 않았다.
남은 건 쿠버네티스 환경이었다. kube-dns 대신 dnsmasq 를 사용하자 제안이 있었고, DNS intermittent delays of 5s 이슈와 공식 문서의 NodeLocal DNS Cache Daemonset 으로 이 문제를 해결할 수 있어보였다.
클러스터에서 데몬셋을 통해 캐싱된 DNS 를 리졸브하는 완전한 해결책이였으나 클라우드에는 접근 권한이 없어 이슈 내용을 공유할 수 밖에 없었다.
그렇다면 어플리케이션에서 해결할 방법을 찾아야했다.
Node.js 의 HTTP 모듈에서는 lookup 속성을 지원하며 이는 기본값으로 dns.lookup
을 사용한다.
결국 Node.js(HTTP -> dns.lookup) -> Alpine(getaddrinfo) -> K8S(socket)
의 어느 구간이라도 캐싱을 하면 되는 것이다.
dns.lookup
대신에 dns.resolve4
를 사용하며 Map
기반으로 캐시키를 관리하는 라이브러리로 Cachable Lookup 을 찾을 수 있었다.
axios
라이브러리는 lookup 속성을 지원하지 않으므로 http.globalAgent
에 다음과 같이 추가해야했다.
1 | import CacheableLookup from "cacheable-lookup"; |
전역 agent 를 오염시키는 느낌이라 아예 HTTP 라이브러리를 got
으로 변경하였다.got
에서는 dnsCache: true
를 주어 이 기능을 쉽게 활성화 할 수 있었다.
deno
에선 reqwest 모듈 위에 HTTP 를 올려놓았는데, trust-dns
란 DNS 캐시 모듈을 활성화하는 옵션은 들어가있지 않았다. 따라서 쿠버네티스 환경에서 같은 오류를 뱉을지 테스트해보고 싶다.뉴런에서 신호를 받는 과정은 4단계로 나눌 수 있다.
1
, 비활성화는 0
이므로 이를 만들어주는 활성화 함수 (계단 함수)가 필요하다.1 | ↘ |
w'
를 곱해준다. 잘 발달된 경우 1
에 가까운 값을 주면 된다.1 | ↘ |
w"
를 곱해준다.1 | ↘ |
이 연결을 여러 개로 구성한다면
1 | ↘ |
이를 가운데 부분만 떼어내 퍼셉트론 모델을 만들 수 있다.
1 | → ( × W₁ ) ↘ |
이 인공뉴런을 기본 단위로 지능을 갖게 되는데 여기서 학습을 통해 정해지는 값은 W
이다.
각각의 W
값이 0이되면 연결 소멸, 0보다 크면 연결 생성, 값이 커지면 연결 강화, 기존보다 작아지면 연결 약화가 된다. 학습을 통해 이 값이 최적화 되면 이후 학습한 일을 언제든지 수행 가능하다.
Q
함수에 현재 상태와 하고싶은 일인 action
을 정해 물어보고 현재 상태에서 그 일이 얼마나 유익한지를 받아 학습할 수 있다.Progressive Neural Network
가 고안되었다.1
, 0
으로 사물을 나타낸다.[1, 0, 0]
, [0, 1, 0]
처럼 항목별로 나누기에 비효율적[1, 1, 0]
, [0.5, 0.5, 0]
처럼 여러 요소를 저장MAN - WOMAN
=== UNCLE - AUNT
KING - KINGS
=== QUEEN - QUEENS
기억은 뉴런들의 연결 강화 또는 약화이다.
undefined
로 초기화된 함수 변수들this
참조prototype
이란 속성을 가지고 있고, prototype은 Object.prototype
에 대한 delegation link와 constructor
속성을 가진 객체의 참조를 가진다.constructor
속성은 함수 객체에 대한 역참조를 가지고 있다.Function.prototype
에 대한 델리게이션 링크를 가지고 있어 apply
와 call
을 상속받는다.활성 객체를 재사용하므로 재귀 함수 호출을 반복문만큼 빠르게 처리 가능하다.
try
블록의 꼬리 호출은 최적화되지 않는다.
1 | ; recursion |
1 | (function loop() { |
1 | // ❌ |
0~65535 사이의 크기를 가지는 Immutable unsigned int16 배열이다.
SurrogatePair = ((High - 0xD800) * 0x400) + (Low - 0xDC00) + 0x10000;
이다."\uD83D\uDE03" === "\u{1F603}"
String.fromCharCode(55357, 56835) === String.fromCodePoint(128515);
1 | SurrogatePair = SurrogatePair - 0x10000; |
전세계 사람들과 대화하기 위해 필요한 문자 대부분을 BMP에서 찾을 수 있지만, 유니코드 프로그램을 만들 경우에는 써로게이트 페어를 항상 염두해야한다. Unicode-aware 로 적혀지는 듯 하다.
1 | // 예시 1 |
항상 WeakMap
, WeakSet
을 어떤 방식으로 쓸까 많이 고민되었다.
참조가 없는 경우 메모리를 반환하는데에 이점이 있는데, 여러 활용방안이 있었다.
1 | // 📁 cache.js |
값을 봉인하고 box
를 반환해 box
object 전체가 와야만 내부값을 알 수 있게 해준다.
1 | function sealerFactory() { |
1 | // Execute a callback on everything stored inside an object |
대부분의 포스트에서는 qs.stringify
와 qs.parse
는 확장된 쿼리스트링 변환이 가능하다고 나온다.
기본 모듈인 querystring.stringify
, querystring.parse
대비 쿼리스트링의 중첩을 가능하게한 모듈인데, 다른 변경점이 하나 더 있다.
rfc3986은 !, ', (, ), *
문자에 대해 추가적으로 엔티티화 한다.
자바스크립트에서 이 스펙을 준수하려면 다음과 같이 encodeURIComponent
함수를 합성해야한다.
노드에서도 이는 마찬가지이며 querystring
모듈은 이 스펙을 준수하지 않았다.
1 | function fixedEncodeURIComponent(str) { |
하지만 qs
모듈은 이 스펙을 기본으로 준수한다.
RFC3986 used as default option and encodes ’ ’ to %20 which is backward compatible.
In the same time, output can be stringified as per RFC1738 with ’ ’ equal to ‘+’.
따라서 언어 간 호환성 및 표준을 맞추기 위해는 qs 모듈을 사용하는 것이 마음이 편하다.