본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 07. 10:45

Scarab Diagnostic Suite 현장 테스트 #014: Deno Stdin 스트림 리소스 경계

요약

Deno 런타임에서 JavaScript 스트림 취소와 네이티브 리소스 생명주기 간의 불일치로 인해 발생하는 프로세스 중단 문제를 분석합니다. 스트림 취소 시 하단의 네이티브 stdin 읽기 작업도 함께 종료되도록 수정하는 과정을 다룹니다.

핵심 포인트

  • JS 스트림 취소와 네이티브 리소스 생명주기 간의 불일치 해결
  • Deno.stdin.readable 취소 시 프로세스 종료 보장
  • 리소스 경계 실패로 인한 미묘한 버그 및 프로세스 멈춤 현상 분석
  • 회귀 테스트를 통한 수정 사항 검증 및 안정성 확보

이 현장 테스트는 Deno를 대상으로 진행되었습니다.

해당 이슈는 Deno #30652였습니다:

https://github.com/denoland/deno/issues/30652

공개된 PR(Pull Request)은 여기 있습니다:

https://github.com/denoland/deno/pull/34979

보고된 문제는 Deno.stdin.readable 및 스트림 취소(stream cancellation)와 관련이 있었습니다.

유용한 진단 경계(diagnostic boundary)는 다음과 같았습니다:

JavaScript 읽기 가능 스트림(readable stream) 취소 → 네이티브 stdin 읽기 작업(native stdin read operation) → 런타임 리소스 생명주기(runtime resource lifecycle)

이것이 중요한 이유는 Deno가 단순한 애플리케이션 프레임워크가 아니기 때문입니다.

Deno는 런타임(runtime)입니다.

런타임은 애플리케이션, 스크립트, CLI, 서버, 테스트 하네스(test harnesses), 자동화 및 개발 도구의 하단에 위치합니다. 런타임 API가 스트림이 취소되었다고 말할 때, 그 아래에 있는 네이티브 리소스 경로(native resource path)도 이에 동의해야 합니다.

버그의 형태는 미묘했습니다.

JavaScript 측면에서는 reader.cancel()이 resolve(해결)될 수 있었습니다.

하지만 그 아래의 stdin 읽기 작업은 여전히 살아있는 상태로 남아있을 수 있었습니다.

이는 공개 API가 말하는 내용과 런타임이 내부적으로 여전히 수행하고 있는 작업 사이에 불일치를 생성합니다.

쉬운 말로 설명하자면:

스트림은 취소되었다고 말하지만, 네이티브 리소스가 프로세스를 계속 유지하고 있을 수 있다는 것입니다.

이것은 리소스 생명주기 경계(resource lifecycle boundary)의 실패입니다.

수정 사항은 의도적으로 좁게 설계되었습니다.

Deno I/O를 재설계하지 않습니다.

스트림을 광범위하게 다시 작성하지도 않습니다.

Deno.stdin.readable 취소를 그 아래에 있는 리소스 기반의 취소/닫기(cancel/close) 경로와 일치시키는 데 집중합니다.

패치는 취소가 하단의 리소스 생명주기에 제대로 도달할 수 있도록 stdin의 읽기 가능 스트림 경로를 변경합니다. 또한, 대기 중인 stdin 읽기를 취소한 후 프로세스가 멈춰 있는 경우 실패하는 회귀 테스트(regression test)를 추가합니다.

이 테스트는 Deno.stdin.readable 리더를 생성하고, 읽기를 시작한 뒤, 리더를 취소하며, 더 많은 stdin 입력이 들어올 때까지 살아있는 대신 프로세스가 깔끔하게 종료되는지 확인합니다.

다음 항목에 대해 로컬 검증을 통과했습니다:

  • ./x fmt
  • ./x lint
  • stdin 읽기 가능 취소에 대한 집중 통합 회귀 테스트(focused integration regression)
  • git diff --check

전체 Deno 테스트 스위트(test suite) 실행은 확인되지 않았습니다.

현장 테스트 #014

  • 프로젝트: Deno
  • 이슈 유형: stdin 읽기 가능 스트림 취소 (stdin readable stream cancellation) / 프로세스 중단 (process hang)
  • 경계: JavaScript 스트림 취소 vs 네이티브 리소스 생명주기 (native resource lifecycle)
  • 결과: 국소적 런타임 수정 및 회귀 테스트 (narrow runtime repair and regression test)
  • 상태: 공개 PR 오픈됨; 메인테이너 리뷰 대기 중

이 현장 테스트가 중요한 이유는 Scarab가 런타임 계층(runtime-layer)의 결함으로 진입했기 때문입니다.

이는 애플리케이션 버그와는 차원이 다른 수준입니다.

애플리케이션에서는 버그가 보통 해당 애플리케이션에만 영향을 미칩니다.

하지만 런타임에서는 버그가 해당 런타임 위에 구축된 모든 것에 영향을 미칠 수 있습니다.

공개 API (public API), 스트림 추상화 (stream abstraction), 네이티브 연산 (native operation), 그리고 프로세스 생명주기 (process lifecycle)가 모두 일치해야 합니다. 만약 한 계층이 "완료"되었다고 말하는 동안 다른 계층이 여전히 프로세스를 열어두고 있다면, 시스템은 더 이상 스스로의 진실을 보존하지 못하는 것입니다.

이것이 바로 Scarab가 드러내도록 설계된 경계의 종류입니다.

단순히:

코드가 통과했는가?

가 아니라:

공개 API의 진실이 그 아래의 런타임 동작과 일치하는가?

를 묻는 것입니다.

이것은 광범위한 중요성을 지닌 작은 수정 경계(repair boundary)의 또 다른 사례입니다.

수정이 중요하기 위해 반드시 거대할 필요는 없습니다.

시스템이 스스로의 상태와 일치하기를 멈춘 바로 그 지점을 건드리면 됩니다.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0