프레임 헤더의 수수께끼였던 RSV1 비트가 주인을 만난다 — 메시지를 DEFLATE로 압축하는 유일한 표준 확장 permessage-deflate. Sec-WebSocket-Extensions 협상, 꼬리 4바이트 절단, context takeover의 압축률↔메모리 저울, 그리고 CRIME 계열 공격 때문에 기본으로 켜지 않는 이유까지.
HTTP/2는 Upgrade와 101을 아예 제거했다 — 연결이 스트림의 다발이 된 세계에서 "연결 통째로 전환"은 성립하지 않기 때문. 그 대신 생긴 문 Extended CONNECT의 세 단계(SETTINGS 능력 광고 → CONNECT + :protocol → 200), 사라진 헤더와 살아남은 헤더, 그리고 실전에서는 왜 여전히 소켓이 http/1.1로 열리는지까지.
연결은 "살아 있다"고 말해주지 않는다 — 침묵할 뿐이다. 그 침묵이 유휴인지 죽음인지 구분하는 프로토콜의 장치 ping/pong, 브라우저가 그 장치를 JS에 숨겨버린 탓에 래퍼가 앱 수준 하트비트를 직접 구현하게 된 사연, 그리고 주기·타임아웃을 정하는 실무 기준까지.
재연결 래퍼의 모든 판단 — "이 끊김은 재연결해야 하는 끊김인가?" — 의 스펙 근거를 본다. Close 프레임 교환 절차, wasClean과 readyState 상태 기계, 1006이 와이어에 존재하지 않는 이유, 브라우저 close()의 코드 제약, 그리고 지수 백오프가 스펙의 SHOULD인 이유까지.
ws.send("Hello") 한 줄이 와이어에 놓는 실제 11바이트를 RFC 6455 §5.2 다이어그램 그대로 읽는다. 2바이트 헤더에 압축된 FIN·opcode·MASK·길이, 컨트롤 프레임이 데이터 조각 사이에 끼어드는 원리, 그리고 마스킹이 암호화가 아니라 캐시 오염 방어인 이유까지.
매일 쓰는 new WebSocket(url) 한 줄 뒤에서 정확히 무슨 일이 일어나는지, RFC 6455 원문 수준에서 본다. WebSocket은 HTTP로 시작하지만 HTTP가 아니다 — 열림 핸드셰이크의 실물, Sec-WebSocket-Key의 진짜 목적, 그리고 IETF/WHATWG 이중 표준 구조까지.
WebSocket 프로토콜 시리즈에서 쓰는 용어를 한곳에 정리한다. 열림 핸드셰이크부터 프레임, opcode, 마스킹, 단편화, 종료 핸드셰이크와 close code, HTTP/2·3의 Extended CONNECT, permessage-deflate 압축 확장까지 — 모든 레슨은 이 용어집의 표기를 따르며, 새 용어는 등장한 레슨에서 추가된다.
Abdul Bari 의 MVC 설명 영상을 정리했다. 모든 공학 제품은 사용자 인터페이스·메커니즘·저장소 세 부분으로 나뉜다는 관점에서 출발해, 소프트웨어의 View / Controller / Model 로 대응시키고, 세 컴포넌트의 상호작용과 각각을 만드는 역할·기술까지 다룬다.
Abdul Bari 의 클라우드 컴퓨팅 4부작을 한 편으로 정리했다. 데스크톱 → 클라이언트-서버 → 클러스터 → 그리드로 이어지는 컴퓨팅 모델의 진화, ARPANET 에서 데이터센터까지의 역사, 웨딩홀 비유로 푸는 IaaS/PaaS/SaaS, 그리고 클라우드의 9가지 장점.
TanStack Intent 는 Agent Skills 를 npm 패키지에 번들해서 라이브러리 버전과 스킬 버전을 동기화하려는 시도다. 아이디어는 좋지만 AGENTS.md 에 LLM 으로 복사하는 방식이라 동기화가 다시 깨진다. 에이전트 설정 파일로 node_modules 안의 스킬을 직접 참조하는 편이 낫다.
display: none ↔ display: grid 전환은 discrete 속성이라 transition 이 안 걸렸다. transition-behavior: allow-discrete 로 닫힐 때의 페이드아웃을, @starting-style 로 열릴 때의 시작 상태를 지정하면 양방향 모두 transition 된다. 두 줄이면 끝난다.
flexbox 는 직계 자식에만 적용되기 때문에, 그룹핑용 wrapper div 를 추가하는 순간 레이아웃이 깨지고 wrapper 안에 같은 flexbox 코드를 또 써야 했다. display: contents 한 줄이면 wrapper 를 레이아웃 흐름에서 지워서 자식들이 원래 flex 컨테이너의 아이템처럼 배치된다. 대신 wrapper 의 시각적 스타일이 전부 사라지는 함정을 알아야 한다.
'a' | 'b' | 'c' 에서 'c' 만 빼고 싶다. 객체나 배열은 map 으로 순회하면 되는데, 유니온의 iterator 는 뭘까? 답은 "직접 순회할 필요가 없다" — 조건부 타입이 유니온을 만나면 TypeScript 가 멤버 하나하나에 자동으로 분배(distribute)해 준다. Matt Pocock 의 영상을 보고 정리했다.
두 텍스트를 비교하는 PegDiff 를 짰다. 핵심은 diff 알고리즘을 한 줄도 안 짰다는 것 — diff·diff-match-patch 같은 라이브러리도 안 썼다. 비교 자체는 Monaco 의 DiffEditor 에 통째로 위임하고, 내가 짠 코드는 전부 diff *바깥*에 있다: 청크 네비게이션, 추가/삭제 통계, localStorage 영속, 그리고 Monaco 위젯을 깔끔하게 떼어내는 두 개의 war story.
예전에 nostrss.me에 JS 플레이그라운드를 한 번 짰었다. 이번엔 Pegboard의 peg-app으로 다시 짜면서 — 같은 iframe 샌드박스 뼈대인데도 광고·공유 localStorage·스모크 게이트·GA4·타입 진단이라는 제약이 실행 엔진, 에디터 선택, 공유 방식을 전부 다시 그었다. PegCode(ADR-0014) 구현 기록.
Excalidraw 기반 화이트보드 PegDraw 를 정적 export 페그보드에 심은 이야기. SSR 끄고 lazy-load 하는 건 시작일 뿐이고, 진짜 디테일은 모듈 스코프의 비대칭(asset path는 되는데 IndexedDB는 안 되는 이유), localStorage 대신 IndexedDB 를 고른 이유, 그리고 순수 코덱과 I/O 스토리지를 갈라놓은 구조에 있었다.
정적 export(SSG) 위에서 드래그앤드롭 칸반 보드 PegKanban을 구현하면서 마주친 두 가지 비-자명한 디테일을 정리한다. (1) DndContext에 id를 박지 않으면 next dev에서만 드러나고 정적 빌드에선 잠복하는 하이드레이션 불일치, (2) localStorage 키 하나를 데이터 계약으로 삼아 오프라인 AI 채팅이 자연어로 보드를 조작하게 만든 경로. 코드를 읽으며 결정과 트레이드오프를 풀어쓴다.