What is Hackers' Pub?

Hackers' Pub is a place for software engineers to share their knowledge and experience with each other. It's also an ActivityPub-enabled social network, so you can follow your favorite hackers in the fediverse and get their latest posts in your feed.

0
0
0

็พๅฏฆๆ˜ฏๅพˆๆฎ˜้…ท็š„๏ผŒใ€Š่ฟทๅฎฎ้ฃฏใ€‹้€™้ƒจๆผซ็•ซ๏ผŒๅฆ‚ๆžœๆฒ’ๆœ‰ๅ…ˆ่ฅฟ็š„่ฉฑ๏ผŒๅพˆๅคง้ƒจๅˆ†ๆˆ็ซ‹ไธไบ†๏ผŒไฝ†ๅ…ˆ่ฅฟ็š„ๅ‘จ้‚Šๆฐธ้ ้ƒฝๆ˜ฏๅ‰ฉไธ‹็š„้‚ฃๅ€‹......

0
0
0
0
0

์—ฌ๋Ÿฌ๋ถ„, ๋ธ”์Šค ๋“ฑ์˜ ๋‹คํฌ ๋ชจ๋“œ์˜ ์—ญ์‚ฌ๊ฐ€ ์ƒ๊ฐ๋ณด๋‹ค ์˜ค๋ž˜๋˜์—ˆ๋‹ค๋Š” ๊ฑธ ์•„์‹œ๋‚˜์š”? ๊ฒ€์€ ๊ธฐ๋„์„œ๋ผ๊ณ  ์ˆ˜๋ฐฑ๋…„ ์ „์—๋„ ์‚ฌ๋žŒ๋“ค์€ ๊ฒ€์€ ๊ฒƒ์€ ๊ธ€์”จ์š”, ํฐ ๊ฒƒ์€ ์ข…์ด์— ์งˆ๋ ค์„œ ๊ฒ€์€ ๋ฐ”ํƒ•์— ํฐ ๊ธ€์”จ ๊ธฐ๋„์„œ๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค!ใ…‹ใ…‹ใ…‹ใ…‹ ๋ฌผ๋ก  ๊ทธ ๋‹น์‹œ์— ์ง€๊ธˆ์˜ ์šฐ๋ฆฌ์ฒ˜๋Ÿผ ๋ฐค์— ๋” ์ž˜๋ณด๋ ค๊ณ ๋Š” ์•„๋‹ˆ์—ˆ๊ฒ ์ฃ .....์—ญ์‹œ ํ”Œ๋ ‰์Šค์˜€๊ฒ ์ฃ ? en.wikipedia.org/wiki/Black_b...

Black books of hours - Wikiped...

0
0
0
0
0
0
1
0
0
0
0

์ดˆ๋ฌด 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.xml์˜ fileVersion, 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 โ†’
7
0
0
0
1
0
0
1
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
1
1
0
0
0
0
0
0
0
0
0
0
0
0
1
0
0
0