Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions contributions/65301.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
pr-url: https://github.com/nodejs/node/pull/65301
---

## 문제 내용

- `lib/internal/streams/fast-utf8-stream.js`의 `Utf8Stream#write()`는 `contentMode`가 `'buffer'`일 때 `Buffer` 인스턴스만 받도록 되어 있었습니다. 정작 내부 구현(`#writeBuffer`, `mergeBuf()`, `Buffer.concat()` 등)이 필요로 하는 건 바이트 단위로 접근 가능한 데이터일 뿐이라, `TypedArray`나 `DataView` 같은 다른 `ArrayBufferView`를 넘기려면 호출부에서 매번 `Buffer.from()`으로 감싸야 했습니다.
- 해당 위치에는 이미 `TODO(@jasnell): Support any ArrayBufferView type here, not just Buffer.`라는 주석이 남아 있어서, 실제로 필요한 확장이 무엇인지 코드 상에 명시되어 있었습니다. 이 TODO를 구현했습니다.
- 코드에 남아 있는 TODO 주석을 찾아 해결하는 접근 방식 자체는 [PR #60161](https://github.com/nodejs/node/pull/60161)(`buffer: remove unreachable overflow check in atob`)을 참고했습니다. 해당 PR도 `lib/buffer.js`의 TODO 주석을 근거로 죽은 코드를 제거한 사례라, "TODO 검색 → 필요성 확인 → 최소 범위로 구현/정리"라는 흐름을 그대로 따랐습니다.

## 해결 과정과 검증

- 상태: `Review 중` (리뷰 요청: `@nodejs/streams`, 아직 리뷰 없음 — GitHub Actions/Linter/Test/Coverage 등 CI 전부 통과)
- `data`가 `ArrayBufferView`인지 먼저 확인(`isArrayBufferView`)하고, `Buffer`가 아닌 뷰라면 단일 진입점에서만 `Buffer.from(data.buffer, data.byteOffset, data.byteLength)`로 변환해 이후 로직은 항상 `Buffer`를 다루도록 했습니다.
- 이때 `byteOffset`/`byteLength`를 기준으로 변환한 것이 핵심입니다. `data.length`(요소 개수)를 그대로 쓰면 `Float64Array`처럼 요소당 8바이트인 타입에서 실제 바이트 수보다 훨씬 작은 값이 되어, `mergeBuf()`/`Buffer.concat()`이나 write-release 로직에서 쓰는 길이 계산이 틀어질 수 있습니다. `lib/zlib.js`의 `zlibBuffer()`가 쓰는 패턴을 그대로 참고했습니다.
- 검증을 위해 `test/parallel/test-fastutf8stream-write-arraybufferview.js`를 새로 추가했습니다. `Uint8Array`/`DataView`/`Float64Array`가 정상적으로 받아들여지는지, `byteOffset`이 0이 아닌 부분 뷰(공유 버퍼의 일부)가 해당 범위만 기록하는지, `ArrayBufferView`가 아닌 값(문자열, 일반 배열)은 여전히 `ERR_INVALID_ARG_TYPE`으로 거부되는지를 `sync: true/false` 두 경우 모두에서 확인했습니다.
- 문서(`doc/api/fs.md`)의 `data` 타입 설명도 `{Buffer}` → `{Buffer|TypedArray|DataView}`로 함께 갱신했습니다.

## 기여 회고

- 새 기능을 스스로 구상하기보다, 코드베이스에 이미 남아 있는 `TODO` 주석을 찾아 그 필요성과 범위가 명확한 작업부터 구현하는 방식으로 접근했습니다.
- zero-copy로 뷰를 재해석할 때 "요소 개수"와 "바이트 길이"를 혼동하지 않는 것, 그리고 그 차이가 실제로 드러나는 타입(`Float64Array` 등)으로 테스트를 짜는 것이 검증의 핵심이라는 걸 확인할 수 있었습니다.