Deno Watch Mode 시그널 처리에 대한 나의 솔루션

발행: (2025년 12월 14일 오후 03:13 GMT+9)
4 min read
원문: Dev.to

Source: Dev.to

문제 개요

Deno watch 모드 문제를 해결하기 위해 Deno와 Node.js를 모두 조사했습니다. Node.js의 접근 방식을 채택하고 싶었지만, Deno에서는 Rust로 구현하고자 했습니다.

Rust에는 JavaScript의 process.kill()처럼 신호를 보내는 내장 함수가 없지만, 채널을 사용해 이를 시뮬레이션할 수 있습니다. 채널을 만들면 송신자(Tx)와 수신자(Rx)가 함께 동작하여 레이스 컨디션을 방지하는 데 도움이 됩니다.

저는 워커 프로세스가 INT 신호를 처리했을 때 감시자 프로세스에 알릴 수 있도록 채널을 사용하는 pull request (PR)를 만들었습니다. 이제 감시자 프로세스가 직접 신호를 처리하고 무시하는 대신 워커가 이를 알려줍니다.

해결책

핵심 아이디어는 채널 송신자를 워커 프로세스에 전달하고, 워커가 Ctrl+C를 처리했을 때 감시자에게 알리는 것입니다. 감시자는 이제 신호를 직접 처리하는 대신 채널을 통해 알림을 받습니다.

채널 생성

// Create a channel before starting the worker process
let (ctrl_c_tx, mut ctrl_c_rx) = tokio::sync::mpsc::unbounded_channel::();

송신자를 워커에 전달

let watcher_communicator = Arc::new(WatcherCommunicator::new(
    WatcherCommunicatorOptions {
        // Pass the sender to the worker
        ctrl_c_tx: ctrl_c_tx.clone(),
    },
));

워커가 감시자에게 알림

impl WatcherCommunicator {
    // Public function to inform the watcher process
    pub fn handle_ctrl_c(&self) -> Result> {
        self.ctrl_c_tx.send(())
    }
}

INT 핸들러 교체

// _ = deno_signals::ctrl_c() => {
_ = ctrl_c_rx.recv() => {

구현 세부 사항

Deno에서 신호 API가 어떻게 구현되어 있는지 이해하는 것이 중요합니다. Signal.rs 파일을 보면 Deno.addSignalListener() 혹은 process.on(signalName, callback) API가 어떻게 동작하는지 확인할 수 있습니다. 기존 동작을 깨뜨리지 않으면서 채널 송신자를 트리거할 최적의 위치를 아직 찾고 있습니다.

결론

이 기능을 구현하는 것은 최근에 직면한 가장 어려운 작업이었습니다. 세 달 전만 해도 Rust 코드를 한 줄도 작성해 본 적이 없었지만, 이제는 Deno에 의미 있는 Rust 코드를 기여하고 있습니다. 수업 시간에 모두가 오픈소스 커뮤니티에 참여하도록 독려해 주신 교수님, humphd께 감사드립니다. 이번 학기는 정말 놀라운 학습 경험이었습니다.

Back to Blog

관련 글

더 보기 »

고성능 GPGPU와 Rust 및 wgpu

컴퓨트 애플리케이션의 아키텍처 GPGPU 애플리케이션은 전통적인 렌더링 루프와 크게 다릅니다. 그래픽 컨텍스트에서 파이프라인은 c...