Profile img

Hi, I'm who's behind Fedify, Hollo, BotKit, and this website, Hackers' Pub! My main account is at @hongminhee洪 民憙 (Hong Minhee) :nonbinary:.

Fedify, Hollo, BotKit, 그리고 보고 계신 이 사이트 Hackers' Pub을 만들고 있습니다. 제 메인 계정은: @hongminhee洪 民憙 (Hong Minhee) :nonbinary:.

FedifyHolloBotKit、そしてこのサイト、Hackers' Pubを作っています。私のメインアカウントは「@hongminhee洪 民憙 (Hong Minhee) :nonbinary:」に。

Website
hongminhee.org
GitHub
@dahlia
Hollo
@hongminhee@hollo.social
DEV
@hongminhee
velog
@hongminhee
Qiita
@hongminhee
Zenn
@hongminhee
Matrix
@hongminhee:matrix.org
X
@hongminhee

연휴 시작을 맞아 TUI 웹 브라우저 만들기를 해 보았다. 에이전트를 쓸 수 있는 상황에 전적으로 의지해서. 프로젝트 이름은 glance로 했다. 일단은 간단히 읽기 정도만 돌아가도록. 주로 테스트한 곳이 이 곳 Hackers' Pub인데 ActivityPub이 어떻게 돌아가는지 잘 몰라서 처리를 못했다. JSON 보고 링크를 따라가면 되는 것 아닌가 싶기도 하고. 이제 공부해야지.

2

洪 民憙 (Hong Minhee) shared the below article:

일주일만에 새로운 엑셀 라이브러리를 만들다

Haze @nebuleto@hackers.pub

저는 회사에서 주로 TypeScript로 Node.js 환경에서 개발을 하고 있습니다. 대량의 엑셀 데이터를 업로드해서 bulk 처리하는 기능이 필요했고, 그 데이터를 받기 위한 템플릿 엑셀 파일도 동적으로 생성해야 했습니다. 템플릿 안에는 데이터 유효성 검사와 조건부 서식, 드롭다운 같은 기능이 들어가야 했고요.

기존에 쓰던 Node.js 엑셀 라이브러리들은 각자 한계가 있었습니다. 하나는 커뮤니티 버전과 유료 버전이 분리되어 있어 기능 제약이 아쉬웠습니다. 다른 하나는 내부 구현과 TypeScript 타이핑 사이에 괴리가 있었고, 성능 문제로 인해 원하는 작업을 빠르게 처리하기 어려웠습니다. 저장소에는 PR이 쌓여 있었지만 더 이상 업데이트되지 않는 상태였습니다.

평소에 알고 있던 Go 생태계의 Excelize 프로젝트를 다시 들여다보았습니다. 차트, 조건부 서식, 수식, 데이터 검증처럼 OOXML 스펙의 큰 기능들을 잘 구현해둔 라이브러리였습니다. Excelize를 보면서 이 정도의 라이브러리를 TypeScript에서도 쓸 수 있으면 좋겠다는 생각이 들었습니다.

코딩 에이전트들의 역량은 계속 좋아지고 있다는 감각을 꾸준히 느꼈고, 제가 설계와 의사결정을 하되 모든 구현을 에이전트에게 위임하는 방식으로 만들어보면 어떨까하는 생각이 들었습니다. 저는 지난주 수요일(2월 4일)에 Excelize와 여러 엑셀 라이브러리들의 기능 목록과 구현 방식을 분석했고, 지난주 토요일(7일) 밤부터 실제 코드 작성에 들어갔습니다.

그렇게 SheetKit을 만들었습니다.

  • 저장소
  • 문서 (Getting Started)
  • 벤치마크 결과 (실행 환경, 실행 방법, 픽스처 포함)
    • Node.js 라이브러리간 비교
    • Rust 비교
    • 픽스처 정의

이 글은 두 파트로 구성됩니다. 지금 읽고 계신 글에서는 SheetKit 소개와 함께, 첫 릴리즈부터 오늘(2월 14일) 배포한 v0.5.0까지 1주일간의 개발 과정을 시간순으로 기록합니다. 다음 글에서는 코딩 에이전트와 어떻게 협업했는지, 어떤 작업에서 사람이 판단해야 했는지 같은 이야기를 더 구체적으로 다룰 예정입니다.


일주일간의 릴리즈 타임라인

표의 날짜는 crates.io와 npm 배포를 기준입니다. (정확한 타임스탬프보다 "무슨 일이 언제 있었는지"를 보여주기 위한 표입니다.)

버전 시점(상대) 날짜 핵심
v0.1.0 일요일(지난주) 2026-02-08 첫 배포(초기 형태)
v0.1.2 월요일 새벽(지난주) 2026-02-09 첫 공개로 부를 만한 스냅샷
v0.2.0 월요일 아침(지난주) 2026-02-09 Buffer I/O, 수식 헬퍼
v0.3.0 화요일 새벽(지난주) 2026-02-10 raw buffer FFI, 배치 API, 벤치마크 구축
v0.4.0 화요일 오후(지난주) 2026-02-10 기능 확장 + 문서 사이트
v0.5.0 토요일 아침(오늘) 2026-02-14 lazy loading / stream, COW save, 벤치마크 룰 개선

SheetKit은 어떤 라이브러리인가요?

SheetKit은 Rust로 작성된 스프레드시트(.xlsx, .xlsm 등의 OOXML 규격) 라이브러리입니다. Rust 코어 위에 napi-rs 기반 Node.js 바인딩이 올라가는 구조이고, Bun과 Deno와 같이 Node-API를 지원하는 다른 런타임에서도 그대로 쓸 수 있습니다.

이런 파일들은 OOXML(Office Open XML) 형식으로 내부적으론 ZIP 아카이브 안에 XML 파트들이 들어 있는 구조입니다. SheetKit은 이 ZIP 파일을 열어서 각 XML 파트를 Rust 구조체로 역직렬화하고, 조작한 뒤 다시 직렬화해서 저장합니다.

Rust 쪽은 세 개의 crate으로 나뉩니다.

  • sheetkit-xml: OOXML 스키마에 대응하는 저수준 XML 데이터 구조
  • sheetkit-core: 모든 비즈니스 로직
  • sheetkit: 라이브러리 사용자를 위한 facade crate

Node.js 바인딩은 packages/sheetkit에 있고, #[napi] 매크로로 Rust API를 JavaScript에 노출합니다.

바로 써보고 싶다면 Getting Started 문서가 가장 빠릅니다.


토요일 밤부터 첫 배포까지 (v0.1.x)

지난주 토요일(2월 7일) 밤에 코드 작성을 시작했고, 다음 날에 첫 배포(v0.1.0)를 찍었습니다. 그리고 9일 월요일 새벽에는 "이 정도면 우선 공개해볼 수 있겠다" 싶은 MVP(v0.1.2)를 만들었습니다.

수요일에 OOXML 스펙과 기존 라이브러리들의 기능 구현 방식을 먼저 분석하고 계획을 자세히 세워 코딩 에이전트에게 작업을 위임해서 짧은 시간 안에 형태를 잡을 수 있었습니다.

작업 방식은 단순했습니다.

  • 설계에 대한 판단과 구조에 대한 결정은 제가 합니다. 그 과정에서 필요한 분석 작업에도 Claude Code, Codex 등과 같은 코딩 에이전트의 도움을 받았습니다.
  • 구현은 코딩 에이전트에게 전적으로 위임합니다. 구현 전에 플랜을 매우 상세하게 세운 뒤, 메인 에이전트는 직접 작업을 하는 것이 아니라 Orchestrator 에이전트로서 각 기능 파트마다 서브 에이전트를 병렬로 돌리고 관리합니다.
  • 구현이 끝나면 별도의 에이전트를 통해 코드 리뷰를 거친 다음, 제가 직접 확인합니다.

다음 글에서는 이 방식이 실제로 어느 지점에서 잘 먹히고, 어느 지점에서 사람이 개입해야 했는지를 더 구체적으로 적을 예정입니다.


월요일: 성능을 생각하기 시작하다 (v0.2.0 ~ v0.3.0)

Buffer I/O (v0.2.0)

첫 릴리즈 이후 얼마 지나지 않은 월요일(9일) 아침에 v0.2.0을 올렸습니다.

핵심은 Buffer I/O였습니다. 파일 경로 없이 메모리 상의 버퍼로 .xlsx를 읽고 쓸 수 있게 하는 기능입니다. 서버 환경에서는 파일 시스템을 거치지 않고 HTTP 요청의 바이너리를 바로 처리하거나, 생성된 엑셀을 바로 응답으로 내려줘야 하는 경우가 많습니다. fill_formula 같은 수식 헬퍼도 이때 함께 넣었습니다.

Buffer I/O를 붙이고 나서부터 "실제 서비스에서 하던 일"과 비슷한 시나리오 테스트를 돌리기 시작했고, 여기서 진짜 병목을 만났습니다.

napi 경계의 오버헤드를 해결하기 위해 Raw Buffer로 전환 (v0.3.0)

초기에는 셀 단위로 자바스크립트 객체를 만들어 Rust와 자바스크립트 경계를 넘기는 형태로 시작했습니다. 50,000행 x 20열 같은 파일을 "행 단위 배열"로 한 번에 꺼내오면, 당연하지만 아주 많은 자바스크립트 객체가 만들어집니다. 이 구조는 GC 압력과 메모리 사용량을 빠르게 올립니다.

oxc 프로젝트에서 효율적으로 Rust로 빠르게 AST 데이터를 자바스크립트 영역으로 전달하는 방식에서 영감을 받아서 다음과 같이 방향을 바꿨습니다. (참고 문서)

  • 셀 단위 객체를 만들지 않습니다.
  • 전체 시트를 compact binary buffer로 직렬화합니다.
  • FFI 경계를 "한 번만" 넘깁니다.

또한 이 방식에는 시트 내 셀이 얼마나 있는지에 따라 dense / sparse 레이아웃을 자동으로 선택하는 방식도 같이 들어갔습니다. Buffer를 그대로 주고받기 때문에 TypeScript로도 한번 더 버퍼 규격에 맞는 파서를 작성하였습니다.

v0.3.0에서 첫 번째 버전의 버퍼 포맷을 구현했고, 이후 v0.5.0에서 지연 로딩과 인라인 string을 지원하는 새로운 포맷으로 개선했습니다.

또한 Rust의 XML을 처리하는 레이어에서도 함께 수정한 것들이 있습니다. "힙 할당을 줄이고, 자주 접근하는 경로를 단순하게 만든다"가 기준이었습니다.

변경 이유
셀 레퍼런스("A1")를 String 대신 고정 길이 인라인 배열로 저장 셀 레퍼런스는 최댓값이 정해져 있어서 힙을 쓰지 않아도 됩니다
타입 문자열을 1바이트 태그로 정규화 XML 속성 문자열을 그대로 들고 다니지 않게 합니다
행 내 셀 검색을 선형 탐색에서 이진 탐색으로 전환 접근 비용을 줄입니다
지표 변경 전 변경 후
100k행 기준 메모리 (RSS) 361MB 13.5MB
Node.js 읽기 오버헤드 (Rust 네이티브 대비) ~4%
GC 압력 100만+ 객체 생성 단일 Buffer 전송

벤치마크를 만들고 숫자를 고정하기

이 시점에 벤치마크 스위트를 만들었습니다. Node.js와 Rust 생태계의 기존 라이브러리들과 성능 지표를 비교하는 벤치마크입니다. 벤치마크 프로그램을 실행하면 결과를 마크다운 문서로 자동으로 출력해주며 여기에는 실행 환경, 반복 횟수 등을 같이 정리해두었습니다.

  • Node.js와 Rust에서의 비교(중앙값, 1 warmup + 5 runs): Apple M4 Pro, 24GB RAM / Node v25.3.0 / Rust 1.93.0
  • 테스트를 위한 스프레드시트 파일의 픽스처는 결정론적으로 생성되고 행 수에는 헤더 행이 포함됩니다
  • RSS/heapUsed는 피크(peak) 값이 아니라 작업 전후의 잔류(residual) 델타 값입니다

50,000행 x 20열 스프레드시트 파일을 기준으로 Node.js 바인딩에서 기본 읽기(getRows())는 541ms, 쓰기는 469ms가 소요되었습니다. 같은 워크로드에서 자바스크립트로 작성된 다른 라이브러리는 읽기에 1.24 ~ 1.56초, 쓰기에 1.09 ~ 2.62초가 소요되었습니다. 그리고 개선을 거치면서 heapUsed 증가분이 0MB로 찍히는 형태를 만들 수 있어서 자바스크립트 객체를 쌓지 않는다는 목표가 결과로 확인할 수 있었습니다.

결국 중요한 건 성능을 측정하고, 수치를 비교하고, 이상한 점이 보이면 원인을 끝까지 추적하는 과정이라고 생각합니다. 벤치마크를 돌렸을 때 Rust 생태계의 한 라이브러리(edit-xlsx)가 읽기에서 이상하게 빠른 결과를 보여주었는데, 이 시점에서는 원인을 알 수 없었습니다. 나중에 v0.5.0 작업 중 정확한 원인을 파악하게 되는데, 이 이야기는 해당 섹션에서 다루겠습니다.


화요일: 빠르게 기능 격차를 줄이다 (v0.4.0)

화요일(2월 10일)에는 v0.4.0을 올렸습니다. 이 릴리즈는 성능보다 부족한 기능을 채우는 것을 목표했습니다.

다른 엑셀 라이브러리들에는 있지만 SheetKit에 없는 기능이 무엇인지 비교하고 OOXML 스펙과 기대 동작을 다시 정리했습니다. 도형, 슬라이서, 양식 컨트롤, 메모, VBA 추출, CLI 같은 기능을 이때 한꺼번에 붙였습니다. 수식 함수도 추가로 늘렸습니다.

메모리 최적화도 계속되었습니다. 셀 구조체와 SST(Shared Strings Table)의 메모리 레이아웃을 개선해서, Node.js에서 동기 API로 읽었을 때 기준 RSS(Resident Set Size)가 349MB에서 195MB로 44% 감소했습니다. 비동기 읽기에서는 RSS가 17MB까지 내려갔습니다.

이 시점에서 문서도 웹 페이지로 관리하고 싶다는 생각이 들어서 VitePress를 활용해서 만들게 되었습니다.


그리고 오늘까지: 구조를 다시 생각하다 (v0.5.0)

이 글을 쓰는 2월 14일 오늘 저녁에 v0.5.0을 릴리즈했습니다.

이전까지는 라이브러리 API에 큰 breaking changes 없이 기능을 추가하고 최적화를 해왔다면, v0.5.0에선 Node.js API 구조를 재설계하고 Rust에서의 코어도 같이 바꾸는 작업이었습니다.

비동기, 그리고 지연 로딩을 기본으로

기존 open()을 통해 시트를 열면 호출 시점에 스프레드시트 파일 내 XML 파트를 한 번에 파싱했습니다. 그만큼 큰 파일을 열면 접근하지 않는 시트의 데이터까지 메모리에 한번에 올라갑니다. 그래서 v0.5.0에서는 읽기 모드를 세 가지로 나누게 되었습니다.

  • lazy(ReadMode::Lazy, 기본값): ZIP 인덱스/메타데이터만 읽고, 시트는 처음 접근할 때 파싱합니다
  • eager(ReadMode::Eager): 모든 시트를 즉시 파싱합니다
  • stream(ReadMode::Lazy): 제한된 메모리 안에서 순방향으로만 읽습니다

스트리밍 리더

대용량 파일에서 전체를 메모리에 올리지 않고 행 단위로 순차 처리할 수 있는 forward-only 리더입니다.

const wb = await Workbook.open("huge.xlsx", { readMode: "stream" });
const reader = await wb.openSheetReader("Sheet1", { batchSize: 1000 });

for await (const batch of reader) {
  for (const row of batch) {
    // 한 번에 한 배치만 메모리에 존재합니다
  }
}

copy-on-write 저장

지연 로딩 모드로 열린 워크북을 저장할 때, 변경되지 않은 시트는 원본 ZIP 엔트리에서 직접 전달합니다. 파싱과 직렬화 왕복을 거치지 않기 때문에, 큰 워크북에서 일부 시트 / 일부 셀만 수정하는 워크로드에서 저장 시간이 줄어듭니다.

제가 실제로 겪는 템플릿 생성 시나리오("대부분은 그대로 두고 일부 셀만 채워서 내려주기")가 딱 이 케이스였고, 이게 v0.5.0에서 개선한 방향이었습니다.

edit-xlsx 라이브러리의 읽기 이상치와 벤치마크 비교 규칙

v0.3.0 이후로 벤치마크를 만들고 관리하면서 실행해보면 이상치가 나옵니다. Rust 비교 벤치마크에서 edit-xlsx가 읽기에서 비정상적으로 짧은 시간을 찍는 경우가 있었고, 자세히 들여다보니 rows/cells 카운트가 0으로 떨어지는 케이스가 섞여 있었습니다.

그래서 “비교 가능성 규칙(comparability rules)”을 도입했습니다.

  • rows / cells 카운트가 기대치와 맞는지 확인
  • 동일 좌표의 값 검증(value probe)이 맞는지 확인
  • 하나라도 어긋나면 결과를 비교할 수 없다고 표시

벤치마크는 숫자를 뽑는 도구이기도 하지만, 이상치를 잡아내는 도구이기도 합니다. 이 규칙을 넣고 나서부터는 “빠른데 뭔가 이상한 결과”를 자동으로 걸러낼 수 있게 됐습니다.

이 이후에 왜 이런 결과가 나왔을까 궁금해서 edit-xlsx 라이브러리를 분석하게 되었습니다. SpreadsheetML 규격에서 workbook.xmlfileVersion, workbookPr, bookViews는 선택 요소입니다. 하지만 이 라이브러리에서는 파싱 과정에서 이 요소들을 필수로 요구하고 있었습니다. 라이브러리에서 파싱과 역직렬화에 실패하면 기본 구조체로 대체되는데, 이 과정에서 rows와 cells의 수가 0이 나오고 매우 짧은 실행 시간을 기록하게 됩니다. 즉, 데이터를 실제로 읽지 않았기 때문에 빠른 것이었습니다.

그래서 SheetKit에서도 호환을 위해 파일을 저장할 때 workbook.xml에서 fileVersion, workbookPr 값이 아예 없을 경우에는 해당 값들에 대해 Microsoft Excel를 참고해 유사한 기본 값을 넣어주게 되었습니다.


바인딩을 거쳤는데 오히려 더 빠르다고?

Rust 라이브러리와 Node 바인딩을 같이 돌려보면 흥미로운 결과가 나오는 케이스가 있습니다. 일부 쓰기 시나리오에서 Node.js 바인딩이 Rust 네이티브보다 오히려 빠르다는 점입니다.

시나리오 Rust Node.js 오버헤드
50k행 x 20열 쓰기 544ms 469ms -14% (Node.js가 빠름)
20k행 텍스트 쓰기 108ms 86ms -20% (Node.js가 빠름)

왜 이런 결과가 나올 수 있었을까요? 내부적으로 SST 데이터를 구성하는 과정에서 V8의 문자열 인터닝과 메모리 관리가 효율적으로 작동한 결과입니다. napi 경계를 넘는 오버헤드보다 V8 엔진 자체의 최적화가 더 큰 이득을 준 셈입니다. Rust 위에 바인딩을 올리는 작업을 하면서, JavaScript 엔진의 최적화가 얼마나 정교한지 다시 한 번 느끼게 되었습니다.


SheetKit, 열심히 개밥먹기 중

저는 회사에서 SheetKit을 개밥먹기(dogfooding)하고 있습니다. 기존 라이브러리를 걷어내고 교체한 뒤에도, 템플릿 생성과 업로드 처리 플로우에서 필요한 기능들을 무리 없이 소화하고 있습니다.

SheetKit 프로젝트는 글을 쓰고 있는 2월 14일 오늘 기준, 다음과 같이 지원합니다.

  • Node.js와 Rust에서 스트리밍 읽기 / 쓰기
  • 164개의 다양한 수식 함수 지원
  • 43개의 다양한 차트 타입 지원
  • 다양한 이미지 포맷을 지원

Node.js - Rust간 오버헤드는 읽기 항목에서 ~ 4% 정도이며, 쓰기 시나리오에서는 케이스에 따라 오히려 Node.js가 빠른 결과를 가져온 케이스도 있었습니다. 자세한 내용은 문서 사이트에서 확인하실 수 있습니다.

SheetKit은 아직 개선할 점들이 있고 API도 변경될 수 있습니다. 하지만 실제로 적용해서 쓰면서 고치고, 성능을 측정하고 분석해서 고치는 방식은 계속 유지할 생각입니다. 궁금한 점이 있으면 편하게 물어봐주시고, 이슈와 PR 모두 환영합니다.


다음 글에서는...

이번 글에서는 일주일동안 어떻게 무엇을 만들었는지를 자세히 적어보았습니다. 다음 글에서는 Claude Code와 Codex 등 코딩 에이전트와 협업한 방식(작업의 워크플로우, 제약사항, 서브 에이전트 구조, 사람의 리뷰 전 별도 에이전트로 리뷰 후 피드백 루프를 만든 점, 사람이 어떻게 개입했는지)과 그 과정에서 느낀 점, 배운 점들을 더 구체적으로 적어보려고 합니다.

Read more →
4

洪 民憙 (Hong Minhee) shared the below article:

Building a New Excel Library in One Week

Haze @nebuleto@hackers.pub

These days I work primarily in TypeScript on Node.js. I needed to handle bulk uploads of large Excel data and dynamically generate template Excel files to collect that data. Those templates had to include data validation, conditional formatting, dropdowns, and so on.

The existing Node.js Excel libraries each had problems. One split its functionality between a community edition and a paid edition, which meant features I needed were locked away. The other had a gap between its internal implementation and its TypeScript typings, and it was too slow for what I was trying to do. Pull requests had piled up in the repository, but the project was no longer being maintained.

I had known about Excelize, the Go library, for a while. Charts, conditional formatting, formulas, data validation: it covers a lot of the OOXML spec and does it well. I kept thinking I wanted something at that level in TypeScript.

Coding agents have gotten noticeably better in the past year or so, and I wanted to try a specific way of working: I make all the design and architecture decisions, and agents handle the implementation. On Wednesday of last week (February 4th) I started analyzing Excelize and other Excel libraries. By Saturday night (February 7th) I was writing code.

That's SheetKit.

  • Repository
  • Documentation (Getting Started)
  • Benchmark results (environment, methodology, fixtures included):
    • Node.js library comparison
    • Rust comparison
    • Fixture definitions

This is the first of two posts. This one covers what SheetKit is and how the week went, from first release to the v0.5.0 I shipped this evening (February 14th). The second post will be about working with coding agents: what I delegated, how, and where it broke down.


Release Timeline

Dates are crates.io / npm publish timestamps. Approximate, not to-the-minute.

Version When Date What
v0.1.0 Sunday (last week) 2026-02-08 First publish (initial form)
v0.1.2 Monday early morning (last week) 2026-02-09 First snapshot worth calling a public release
v0.2.0 Monday morning (last week) 2026-02-09 Buffer I/O, formula helpers
v0.3.0 Tuesday early morning (last week) 2026-02-10 Raw buffer FFI, batch APIs, benchmark suite
v0.4.0 Tuesday afternoon (last week) 2026-02-10 Feature expansion + documentation site
v0.5.0 Saturday evening (today) 2026-02-14 Lazy loading / streaming, COW save, benchmark rule improvements

What Is SheetKit?

SheetKit is a Rust spreadsheet library for OOXML formats (.xlsx, .xlsm, etc.) with Node.js bindings via napi-rs. Bun and Deno work too, since they support Node-API.

.xlsx files are ZIP archives containing XML parts. SheetKit opens the ZIP, deserializes each XML part into Rust structs, lets you manipulate them, and serializes everything back on save.

Three crates on the Rust side:

  • sheetkit-xml: Low-level XML data structures mapping to OOXML schemas
  • sheetkit-core: All business logic
  • sheetkit: Facade crate for library consumers

Node.js bindings live in packages/sheetkit and expose the Rust API via #[napi] macros.

To get started: sheetkit.dev/getting-started.


Saturday Night to First Release (v0.1.x)

I started coding Saturday night (February 7th) and pushed v0.1.0 the next day. By early Monday morning I had v0.1.2, which was the first version I'd actually call releasable.

I had spent Wednesday analyzing the OOXML spec and how existing libraries implemented features, so by Saturday I had a detailed plan ready. I handed implementation to coding agents (Claude Code and Codex). The setup was: a main orchestrator agent receives the plan, then spawns sub-agents in parallel for each feature area. It burns through tokens fast, but it gets a large plan done quickly. After the agents finish, a separate agent does code review before I look at it.

More on this workflow in the next post.

v0.1.2 was an MVP. It had 44,000+ lines, 1,533 tests, 110 formula functions, charts, images, conditional formatting, data validation, StreamWriter, and builds for 8 platform targets. But it could only read/write via file paths (no Buffer I/O), and I hadn't measured performance at all. It worked, but that was about it.


Monday: Starting to Think About Performance (v0.2.0 – v0.3.0)

Buffer I/O (v0.2.0)

v0.2.0 went up Monday morning, a few hours after v0.1.2.

I added Buffer I/O: read and write .xlsx directly from in-memory buffers, no filesystem needed. In a server you're usually processing binary from an HTTP request or streaming a generated file back in the response, so this had to come early. fill_formula and other formula helpers went in at the same time.

With Buffer I/O in place I could run tests closer to real production workloads. That's where the problems showed up.

Switching to Raw Buffers (v0.3.0)

The initial implementation created a JS object per cell and passed it across the Rust/JS FFI boundary. Pull a 50k×20 sheet as a row array and that's a million-plus JS objects. GC pressure and memory usage went through the roof.

I got the idea from oxc, which transfers Rust AST data to JS as raw buffers instead of object trees. Same principle here:

  • Don't create per-cell objects.
  • Serialize the entire sheet into a compact binary buffer.
  • Cross the FFI boundary once.

The encoder picks dense or sparse layout automatically based on cell occupancy (threshold: 30%). Since the JS side receives a raw buffer, I also wrote a TypeScript parser for the format.

v0.3.0 shipped the first version of this buffer protocol. v0.5.0 later replaced it with a v2 format that supports inline strings and incremental row-by-row decoding.

I also made changes in the Rust XML layer. The goal was fewer heap allocations and simpler hot paths.

Change Why
Cell references ("A1") stored as [u8; 10] inline arrays, not heap Strings Max cell ref is "XFD1048576" (10 bytes). No need for the heap.
Cell type attribute normalized to a 1-byte enum Stops carrying raw XML attribute strings around
Binary search for cells within a row, replacing linear scan
Metric Before After
Memory (RSS) at 100k rows 361 MB 13.5 MB
Node.js read overhead vs. native Rust ~4%
GC pressure 1M+ object creations Single buffer transfer

Benchmarks

This is when I built the benchmark suite, comparing SheetKit against existing Node.js and Rust libraries. The runner outputs Markdown with environment info, iteration counts, and raw numbers.

Setup: Apple M4 Pro, 24 GB / Node v25.3.0 / Rust 1.93.0. Median of 5 runs after 1 warmup. RSS/heapUsed are residual deltas (before vs. after), not peaks. Fixtures are generated deterministically; row counts include the header.

50k rows × 20 columns: SheetKit read 541 ms, write 469 ms. The JS-only libraries: 1.24–1.56s read, 1.09–2.62s write. heapUsed delta: 0 MB, which confirmed that the JS side was no longer accumulating objects.

One odd thing: edit-xlsx, a Rust library, was showing suspiciously fast read times. I didn't understand why at this point. The explanation came during the v0.5.0 work (covered below).


Tuesday: Closing Feature Gaps (v0.4.0)

v0.4.0 shipped Tuesday afternoon. This one was about features, not performance.

I went through what other Excel libraries supported and listed what SheetKit was still missing. Shapes, slicers, form controls, threaded comments, VBA extraction, a CLI. I also added 54 more formula functions (total: 164), mostly financial and engineering.

Same orchestrator/sub-agent setup as before: write a detailed plan for each feature, have the agents implement in parallel, agent review first, then my review.

Memory optimization continued on the side. Reworking the Cell struct and SST memory layout cut RSS from 349 MB to 195 MB for sync reads (44% drop). Async reads: 17 MB.

I also set up a VitePress documentation site around this time.


Today: Rethinking the Architecture (v0.5.0)

v0.5.0 went out this evening. Unlike the previous releases, which added features on top of the same API shape, this one changed the Node.js API structure and parts of the Rust core.

Lazy Loading by Default

Before v0.5.0, open() parsed every XML part upfront. Open a 50k-row file and all sheets load into memory, even the ones you never touch. Now there are three read modes:

  • lazy (default): reads ZIP index and metadata only. Sheets parse on first access.
  • eager: the old behavior. Parse everything immediately.
  • stream: forward-only, bounded memory.

Lazy open costs less than 30% of eager, and pre-access memory is under 20% of eager. Auxiliary parts (comments, charts, images, pivot tables) also defer parsing until you actually call a method that needs them.

Streaming Reader

Forward-only reader for large files. One batch in memory at a time.

const wb = await Workbook.open("huge.xlsx", { readMode: "stream" });
const reader = await wb.openSheetReader("Sheet1", { batchSize: 1000 });

for await (const batch of reader) {
  for (const row of batch) {
    // process
  }
}

Copy-on-Write Save

When you save a lazily-opened workbook, unchanged sheets pass through directly from the original ZIP entry. No parse-serialize round trip. At work I generate files by opening a template, filling in a few cells, and sending it back. That's exactly the workload this helps.

The edit-xlsx Read Anomaly

Back when I built the benchmarks, edit-xlsx was recording very fast read times on some files. Rows/cells count was dropping to zero.

I added comparability rules to the benchmark:

  • Check that rows/cells count matches expectations
  • Value-probe a few cells at known coordinates
  • If either fails, mark the result non-comparable

Then I dug into why. In SpreadsheetML, fileVersion, workbookPr, and bookViews in workbook.xml are optional. edit-xlsx 0.4.x treats them as required. When deserialization fails on a file missing these elements, it falls back to a default struct: rows=0, cells=0, near-zero runtime. It was fast because it wasn't reading anything.

SheetKit now writes default values for fileVersion and workbookPr (matching Excel's own defaults) when they're absent, for compatibility.


Node.js Bindings Faster Than Native Rust?

In some write scenarios, the Node.js bindings beat native Rust.

Scenario Rust Node.js Overhead
Write 50k rows × 20 cols 544 ms 469 ms −14% (Node.js faster)
Write 20k text-heavy rows 108 ms 86 ms −20% (Node.js faster)

This happens because V8 is very good at string interning and memory management when building SST data through the batch API (setSheetData). The napi crossing costs less than what V8 saves. I did not expect to see negative overhead, but here we are.


Dogfooding SheetKit

I replaced our previous library with SheetKit at work. Template generation and bulk upload processing have been running fine.

Where it stands today (February 14th):

  • Streaming read/write in both Node.js and Rust
  • 164 formula functions
  • 43 chart types
  • Multiple image formats

Read overhead (Node.js vs. Rust): ~4%. Some write scenarios are faster from Node.js. Details at sheetkit.dev.

The library is still experimental and APIs may change. I'll keep using it in production, measuring, and fixing things as they come up. Issues and PRs are always welcome.


Next Post

This covered the what and when. The next post is about the how: orchestrator/sub-agent structure, how I used Claude Code and Codex, the agentic code review loop, where I had to step in, and what I'd do differently.

Read more →
4
2
3
4
1
1
0
1
1

洪 民憙 (Hong Minhee) shared the below article:

Functional Programming in Lean 한국어 번역 - 소개 및 감사의 글

초무 @2chanhaeng@hackers.pub

Note

이 글은 Lean 공식 문서에 소개된 Functional Programming in Lean을 작성자가 읽기 위한 목적으로 Kagi Translate를 통해 1차로 기계 번역 후 보완한 글입니다. 원문과의 차이가 있을 수 있으며 정식 내용은 항상 원문을 통해 확인 바랍니다. 원문이 Creative Commons Attribution 4.0 International License를 기반으로 배포된 것을 존중하여 이 글 또한 CC BY 4.0 하에 배포합니다.

소개

Lean은 의존 타입 이론을 기반으로 하는 대화형 정리 증명기 입니다. 원래 Microsoft Research에서 개발되었으나, 현재는 Lean FRO에서 개발이 진행되고 있습니다. 의존 타입 이론은 프로그램과 증명의 세계를 하나로 묶어주기 때문에 Lean은 프로그래밍 언어이기도 합니다. Lean은 이러한 이중적 특성을 진지하게 받아들이며, 범용 프로그래밍 언어로 사용하기에 적합하도록 설계되었습니다. 심지어 Lean은 Lean 자체로 구현되어 있습니다. 이 책은 Lean으로 프로그램을 작성하는 법에 관한 것입니다.

프로그래밍 언어로서의 Lean은 의존 타입을 가진 엄격한 순수 함수형 언어입니다. Lean으로 프로그래밍하는 법을 배우는 과정의 상당 부분은 이러한 각 속성이 프로그램 작성 방식에 어떤 영향을 미치는지, 그리고 어떻게 함수형 프로그래머처럼 생각할 수 있는지를 익히는 것으로 구성됩니다. 엄격성 은 Lean의 함수 호출이 대부분의 언어와 유사하게 작동하는 것을 의미합니다. 즉, 함수의 본문이 실행되기 전에 인자값이 완전히 계산된다는 의미입니다. 순수성 은 프로그램에서 타입에 명시되지 않는 한, Lean 프로그램이 메모리 위치 수정, 이메일 전송, 파일 삭제와 같은 부수 효과(side effect)를 가질 수 없음을 의미합니다. Lean이 함수형 언어라는 것은 함수가 다른 값들과 마찬가지로 일급 객체이며, 실행 모델이 수학적 표현식의 평가에서 영감을 얻었음을 뜻합니다. Lean의 가장 독특한 특징인 의존 타입은 타입을 언어의 일급 구성 요소로 만들어, 타입이 프로그램을 포함하거나 프로그램이 타입을 계산할 수 있게 합니다.

이 책은 Lean을 배우고 싶지만 반드시 함수형 프로그래밍 언어를 사용해 본 적은 없는 프로그래머들을 대상으로 합니다. Haskell, OCaml, F# 같은 함수형 언어에 익숙할 필요는 없습니다. 반면, 이 책은 대부분의 프로그래밍 언어에서 공통적으로 쓰이는 루프, 함수, 데이터 구조와 같은 개념에 대한 지식은 갖추고 있다고 가정합니다. 이 책이 함수형 프로그래밍에 관한 좋은 입문서가 될 수는 있지만, 프로그래밍 전반에 관한 입문서로는 적합하지 않습니다.

Lean을 증명 보조기로 사용하는 수학자들도 언젠가는 맞춤형 증명 자동화 도구를 작성해야 할 때가 올 것입니다. 이 책은 그분들을 위한 것이기도 합니다. 이러한 도구들이 정교해질수록 함수형 언어의 프로그램과 닮아가지만, 대부분의 현직 수학자들은 Python이나 Mathematica 같은 언어에 익숙합니다. 이 책은 그 간극을 메워줌으로써 더 많은 수학자가 유지보수 가능하고 이해하기 쉬운 증명 자동화 도구를 작성할 수 있도록 도울 것입니다.

이 책은 처음부터 끝까지 순서대로 읽도록 구성되었습니다. 개념은 하나씩 도입되며, 뒷부분은 앞부분의 내용을 숙지하고 있다고 가정합니다. 때로는 앞서 짧게 다루었던 주제를 나중에 더 깊이 있게 파고들기도 합니다. 책의 일부 섹션에는 연습 문제가 포함되어 있습니다. 해당 섹션의 이해를 공고히 하기 위해 풀어볼 가치가 있습니다. 또한 책을 읽으면서 배운 내용을 창의적이고 새로운 방식으로 활용하며 Lean을 직접 탐구해 보는 것도 유익합니다.

Lean 시작하기

Lean으로 작성된 프로그램을 작성하고 실행하기 전에, 먼저 컴퓨터에 Lean을 설치해야 합니다. Lean 도구 모음은 다음과 같이 구성됩니다:

  • elanrustup이나 ghcup과 유사하게 Lean 컴파일러 툴체인을 관리합니다.
  • lakecargo, make, 또는 Gradle과 유사하게 Lean 패키지와 그 의존성을 빌드합니다.
  • lean은 개별 Lean 파일의 타입을 검사하고 컴파일하며, 현재 작성 중인 파일에 대한 정보를 프로그래머 도구에 제공합니다. 보통 lean은 사용자가 직접 실행하기보다는 다른 도구에 의해 호출됩니다.
  • Visual Studio Code나 Emacs와 같은 에디터용 플러그인은 lean과 통신하여 관련 정보를 편리하게 보여줍니다.

Lean 설치에 관한 최신 지침은 Lean 매뉴얼을 참조하시기 바랍니다.

타이포그래피 관례

Lean에 입력으로 제공되는 코드 예제는 다음과 같은 형식으로 표시됩니다:

def add1 (n : Nat) : Nat := n + 1
#eval add1 7

위의 마지막 줄(#eval로 시작하는 줄)은 Lean에게 답을 계산하도록 지시하는 명령입니다. Lean의 응답은 다음과 같은 형식으로 표시됩니다:

8

Lean이 반환하는 오류 메시지는 다음과 같은 형식으로 표시됩니다:

Application type mismatch: The argument
  "seven"
has type
  String
but is expected to have type
  Nat
in the application
  add1 "seven"

경고는 다음과 같은 형식으로 표시됩니다:

declaration uses 'sorry'

유니코드

관용적인 Lean 코드는 ASCII에 포함되지 않는 다양한 유니코드 문자를 사용합니다. 예를 들어, 그리스 문자 α, β 및 화살표 는 모두 이 책의 첫 번째 장에 등장합니다. 이를 통해 Lean 코드는 일반적인 수학적 표기법과 더 유사해질 수 있습니다.

기본 Lean 설정에서 Visual Studio Code와 Emacs 모두 백슬래시(\) 뒤에 이름을 입력하여 이러한 문자를 입력할 수 있습니다. 예를 들어, α를 입력하려면 \alpha를 입력합니다. Visual Studio Code에서 문자를 입력하는 방법을 알아보려면 해당 문자 위에 마우스를 올려 툴팁을 확인하세요. Emacs에서는 해당 문자 위에 커서를 두고 C-c C-k를 사용하세요.

저자 소개

David Thrane Christiansen 은 20년 동안 함수형 언어를 사용해 왔으며, 의존 타입을 사용한 지는 10년이 되었습니다. 그는 Daniel P. Friedman과 함께 의존 자료형 이론의 핵심 아이디어를 소개하는 The Little Typer 를 집필했습니다. 코펜하겐 IT 대학교에서 박사 학위를 받았으며, 재학 시절 Idris 언어의 첫 번째 버전에 주요 기여자로 참여했습니다. 학계를 떠난 후에는 미국 오리건주 포틀랜드의 Galois와 덴마크 코펜하겐의 Deon Digital에서 소프트웨어 개발자로 일했으며, Haskell Foundation의 상임 이사를 역임했습니다. 집필 당시 그는 Lean Focused Research Organization 에 소속되어 풀타임으로 Lean 프로젝트에 매진하고 있습니다.

감사의 글

이 무료 온라인 도서는 Microsoft Research의 아낌없는 지원 덕분에 집필 및 무료 배포가 가능했습니다. 집필 과정에서 그들은 Lean 개발팀의 전문 지식을 제공하여 제 질문에 답해주고 Lean을 더 사용하기 쉽게 만들어 주었습니다. 특히 Leonardo de Moura는 이 프로젝트를 시작하고 제가 첫발을 뗄 수 있게 도와주었으며, Chris Lovett은 CI 및 배포 자동화를 구축하고 테스트 독자로서 훌륭한 피드백을 주었습니다. Gabriel Ebner는 기술 검토를 맡았고, Sarah Smith는 행정적인 업무가 원활히 돌아가도록 힘써주었으며, Vanessa Rodriguez는 소스 코드 하이라이트 라이브러리와 특정 버전의 iOS용 Safari 간의 까다로운 상호작용 문제를 진단하는 데 도움을 주었습니다.

이 책을 쓰는 데는 평소 근무 시간 외에도 많은 시간이 소요되었습니다. 제 아내 Ellie Thrane Christiansen은 평소보다 더 많은 가사 분담을 도맡아 주었으며, 아내의 헌신이 없었다면 이 책은 존재할 수 없었을 것입니다. 매주 하루씩 추가로 일하는 것이 가족들에게 쉽지 않은 일이었음에도, 집필 기간 동안 인내심을 갖고 지지해 준 가족들에게 감사의 마음을 전합니다.

Lean을 둘러싼 온라인 커뮤니티는 기술적으로나 정서적으로 이 프로젝트에 열렬한 지지를 보내주었습니다. 특히 Sebastian Ullrich는 에러 메시지 텍스트를 CI에서 확인하고 책에 쉽게 포함할 수 있도록 지원 코드를 작성할 때, 제가 Lean의 메타프로그래밍 시스템을 익히는 데 핵심적인 도움을 주었습니다. 새로운 개정판을 게시한 지 불과 몇 시간 만에 열정적인 독자들이 오류를 찾아내고, 제안을 건네며, 따뜻한 격려를 보내주었습니다. 특히 문체와 기술적인 면에서 많은 제안을 주신 Arien Malec, Asta Halkjær From, Bulhwi Cha, Craig Stuntz, Daniel Fabian, Evgenia Karunus, eyelash, Floris van Doorn, František Silváši, Henrik Böving, Ian Young, Jeremy Salwen, Jireh Loreaux, Kevin Buzzard, Lars Ericson, Liu Yuxi, Mac Malone, Malcolm Langfield, Mario Carneiro, Newell Jensen, Patrick Massot, Paul Chisholm, Pietro Monticone, Tomas Puverle, Yaël Dillies, Zhiyuan Bao, 그리고 Zyad Hassan에게 감사의 인사를 전하고 싶습니다.

Read more →
2
2
1
  • zellij 를 MacOS + Ghostty 조합에서 사용할 때 한글 폴더명의 깨짐현상이 있다.

  • (초성만 노출되는 문제) https://github.com/zellij-org/zellij/issues/3148

  • Claude Code (Opus 4.6 Model) 의 도움을 받아 수정했고 로컬에서 빌드해서 쓰고 있다.

  • PR 도 보냈는데, 근본적인 해결책은 되지 못해, 커밋이 병합되지는 못했다.

  • 그래서 결론 - 이 커밋은 나만 쓰게 되었다. 😂

3

지난 주말부터 열심히 토큰을 팍팍 태워 만든 TypeScript/Rust용 엑셀 라이브러리 SheetKit, 방금 0.4.0를 배포했습니다.

문서 퀄리티가 아직 좋다고는 말을 못해도 API 레퍼런스와 문서 웹도 생겼고, 단순한 값 읽기/쓰기를 넘어 복잡한 기능들도 많이 추가되었습니다. 이제 폭발적인 구현보다는 적당한 스피드로 문서의 완성도를 높이고 WebAssembly나 Bun/Deno/Python 등에 대한 바인딩 등을 고민해볼 계획입니다. 문서의 완성도도 좀 어느 정도 올라간다면 이리저리 SheetKit을 소개하는 정식 글도 한번 여기저기에 올려보려고 합니다.

이미 Node.js쪽 binding은 열심히 개밥먹기하고 있는 중인데, Rust나 Node.js 환경에서 엑셀 파일을 다룰 일이 있는 분들은 한번 써보시고 이슈나 피드백을 남겨주시면 너무 좋을 것 같습니다.

Node.js에서 SheetKit은 다른 라이브러리에 비해 거의 모든 벤치마크 테스트에서 성능 우위를 보였습니다. 웹 문서에는 SheetKit이 어떻게 메모리를 덜 사용하고 Node.js 바인딩에서 영역 전환 시의 오버헤드를 줄였는지도 정리되어 있습니다.

https://github.com/Nebu1eto/sheetkit

SheetKit은 처음으로 설계나 의사 결정 외에는 모든 구현을 코딩 에이전트에게 위임하면서 만들었습니다. 이 과정에서 코딩 에이전트로 어떻게 큰 작업을 효율적으로 하는지, 또 어떻게 코딩 에이전트와 함께 잘 작업할 수 있을지 등을 많이 배웠습니다.

이 경험에 대해서도 시간 여유가 될 때 정식으로 글로 적어보고자 합니다.

3

지난 주말부터 열심히 토큰을 팍팍 태워 만든 TypeScript/Rust용 엑셀 라이브러리 SheetKit, 방금 0.4.0를 배포했습니다.

문서 퀄리티가 아직 좋다고는 말을 못해도 API 레퍼런스와 문서 웹도 생겼고, 단순한 값 읽기/쓰기를 넘어 복잡한 기능들도 많이 추가되었습니다. 이제 폭발적인 구현보다는 적당한 스피드로 문서의 완성도를 높이고 WebAssembly나 Bun/Deno/Python 등에 대한 바인딩 등을 고민해볼 계획입니다. 문서의 완성도도 좀 어느 정도 올라간다면 이리저리 SheetKit을 소개하는 정식 글도 한번 여기저기에 올려보려고 합니다.

이미 Node.js쪽 binding은 열심히 개밥먹기하고 있는 중인데, Rust나 Node.js 환경에서 엑셀 파일을 다룰 일이 있는 분들은 한번 써보시고 이슈나 피드백을 남겨주시면 너무 좋을 것 같습니다.

Node.js에서 SheetKit은 다른 라이브러리에 비해 거의 모든 벤치마크 테스트에서 성능 우위를 보였습니다. 웹 문서에는 SheetKit이 어떻게 메모리를 덜 사용하고 Node.js 바인딩에서 영역 전환 시의 오버헤드를 줄였는지도 정리되어 있습니다.

https://github.com/Nebu1eto/sheetkit

3

연합우주 설계에서 도메인 네임 재사용이 배제되어 있는 건 아쉬운 일임. 브랜드에 관심 없는 개발자들답다면 다운데, 이게 생각보다 꽤 서비스 관점에서는 단점이 된다.

1
3
2

코딩 에이전트를 풀로 활용해서 나보단 코딩 에이전트가 만들고 있는 TypeScript와 Rust를 위한 스프레드시트 라이브러리. 타입스크립트에서 xlsx 파일을 다루는 라이브러리들 쓰다가 너무 괴로워서 만들게 되었다. (GitHub Actions 배포 이슈는 내일 마저 잡는걸로…)

https://github.com/Nebu1eto/sheetkit

기존 ExcelJS를 쓰던 프로젝트에 SheetKit을 붙이다가 문득 궁금해져서 벤치마크 스크립트를 만들어보게 시켜보았다. 데이터 유효성 검사 설정을 많이 추가해둔 기존 템플릿 파일에서 SheetKit이 최대 10000배 이상 빠른 결과가 나왔다. 바퀴 재발명 야크 셰이빙이 뿌듯해지는 순간이다.

SheetKit과 ExcelJS의 벤치마크 결과, 모든 영역에서 ExcelJS보다 빠른 결과를 보여주었다.

       Create + Write              12.8x faster
       Buffer Read                  3.1x faster
       Large Write                  2.2x faster
       Large Buffer Read            1.8x faster
       Template (11K)           14376.6x faster
       Template (13K)            5771.4x faster
       EUCAST (2.5MB)               3.3x faster
5
3
1

코딩 에이전트를 풀로 활용해서 나보단 코딩 에이전트가 만들고 있는 TypeScript와 Rust를 위한 스프레드시트 라이브러리. 타입스크립트에서 xlsx 파일을 다루는 라이브러리들 쓰다가 너무 괴로워서 만들게 되었다. (GitHub Actions 배포 이슈는 내일 마저 잡는걸로…)

https://github.com/Nebu1eto/sheetkit

5

.NET IDE의 핵심은 벤더 락인에 묶여 있고, GUI 프레임워크는 Windows에 치중되어 있습니다. 저는 이 문제를 AI 코딩 에이전트의 힘을 빌어 풀어보기 위해 저와 같이 닷넷데브 운영진으로 활동하시는 송영재 님께서 만든 크로스플랫폼 UI 프레임워크 MewUI로 오픈소스 .NET IDE, LibraStudio를 만들기 시작했습니다.

그러나 난관은 AI가 이 프레임워크를 전혀 모른다는 것. 제가 만든 HandMirror MCP로 어셈블리를 직접 검사해 AI에게 정확한 API 정보를 제공하여, 첫 빌드만에 오류 단 3개로 빠르게 구현을 마칠 수 있었습니다. 그 과정을 정리하여 공유합니다.

👉 https://devwrite.ai/ko/posts/why-i-use-handmirror-mcp/

4

mise WARN env value contains '$' which will be expanded in a future release. Set env_shell_expand = true to opt in or env_shell_expand = false to keep current behavior and suppress this warning.

켜고 싶다면 VAR = "foo$$bar" 처럼 고쳐야 됨. VAR = '''foo$bar''' 이런거 안 됨. 난 꺼버렸음.

1

클로드가 2주 동안 gcc 호환되는 컴파일러를 만들어서 다들 놀라고 있다.

한가지 고려해야할 부분은, 애초에 소프트웨어 공학 자체가 큰틀에서 설계를 잘하면(클로드는 이미 현존하는 가장 훌륭한 설계도 알고 있을 것이다) 나머지는 꾸역꾸역 코드를 짜서 제품을 완성할수 있게하는게 목표란거다. 그러니까 클로드가 C 파서를 짰다고 하면 2026년 지금은 아무도 안놀라겠지. 근데 소프트웨어 공학 지식은 C 파서를 짤수 있는 인간이 더 많은 시간을 투자하면 C 컴파일러도 짤수 있게 해준다.

그래서 모델의 성능이 좋아질수록 마치 RPG에서 레벨이 오르면 새로운 장비를 착용할수 있게 되어 급격히 강해지는것과 같은 일을 보게될거 같다. 하지만 이때 장비를 착용할수 있는 능력과 장비를 만들 수 있는 능력을 구분할 필요는 있다. 이제 후자가 AI 회사의 다음 목표인셈인데..

4
2

Daum (Kakao) 우편번호 서비스 도메인 & JS API 네임스페이스 변경 안내 (사전 공지)

https://github.com/daumPostcode/QnA/issues/1498

GeekNews에도 올리기는 했는데, 아무래도 국내 서비스에는 영향을 받는 곳이 많다보니, Hackers' Pub에도 공유해 둡니다.

  1. 공식 가이드 페이지
  1. CDN 도메인 변경 (적용 완료)
  1. 서비스 도메인 변경 일정 (예정)
  1. JavaScript API 네임스페이스 변경 안내
  • 기존 new daum.Postcode({...
  • 변경 new kakao.Postcode({...
  1. 서비스 종료 예정 도메인 안내 (중요)
  1. 도메인 변경 사전 안내 및 네임스페이스 변경에 대한 안내
  • 기존 도메인 종료에 대한 상세 일정은 3월 10일 전후 공지에서 다시 안내
  • 서비스 중단 방지를 위해 사전 점검 및 점진적 전환을 권장
2

일을 대하는 태도가 많이 바뀔수밖에 없다. 예전 같으면 코드를 직접 작성하는게 시간적으로 해결못할 일이니 그냥 그대로 두거나 넘어갔다.

이제 개념적으로 이해할 수 있는 일이라면 코딩 자체는 문제가 아니니 문제와 해결법에 더 집중 가능한 형태가 된듯

ㅋㅋㅋ 예전 같으면 넘어갔을 아주 사소한 변경을 오픈 소스에 기여하고 거창한 말을 해보았음ㅋㅋㅋ

결론적으론 뿌듯하다

https://github.com/SchemaStore/schemastore/pull/5332

1
0

이때 막 프라그마 써가면서 Either의 ToJSON 인스턴스를 원하는대로 구현하려고 애썼는데 알고 보니까 더 쉬운 다른 방법이 있었다. 다음과 같이 sumEncoding이라는 옵션을 이용하면 된다.

toJSON = genericToJSON defaultOptions
  { sumEncoding = UntaggedValue }

전에는 이렇게 좋아하는 언어의 소소한 팁을 라이브러리 문서에서 찾았을 때 SNS에 공유하는 게 삶의 낙이었는데 요즘 같은 LLM 에이전트 딸깍 시대에는 이런 게 다 무슨 소용인가 싶어서 우울하다.

7
1
2
5

日本(일본)의 TypeScript 컨퍼런스인 TSKaigi 2026이 5() 22()(())–23()(())에 東京(도쿄)에서 開催(개최)된다고 합니다. 함께 가실 韓國(한국) 분 계실까요?

一旦(일단) 저랑 @2chanhaeng초무 님하고 @kodingwarriorJaeyeol Lee (a.k.a. kodingwarrior) :vim: 님이 같이 가실 것 같습니다.

5
2
1
1
4
7

얼마 전 Oh My OpenCode이 한창 바이럴 될 때 에이전트 사용법이 재밌다고 느끼면서도 저렇게 누군가 만들어 놓은 걸 그대로 가져다 쓰는 건 별 의미가 없고 스스로가 쓸 도구 모음을 구축하고 (그걸 운영할 수 있는 기술을 가지고) 싶다는 생각을 했는데 Pi가 어느 정도 그것에 대한 실마리를 제공해 주었다고 생각함. (Armin Ronacher가 쓴 Pi: The Minimal Agent Within OpenClaw를 보고 알게 됨.)

2
3

Nix + Agent(LLM) 쓰는 거 너무 좋다

그냥 느낌대로 대책없이 (수동 바이브) 리팩토링했는데, 에이전트한테 리팩토링 하기 전 커밋 ID 알려주고 리팩토링이므로 검증해달라고 하면 편집한 부분 설정값 nix eval로 촤라락 비교해주고, nix-diff도 해주고, dry-build해서도 확인해주니까 든든하다

1
8
5