[Lobsters 요약] NVIDIA Jetson에서 Durable Streams를 활용한 로컬 AI 서비스 구축
2
설명
NVIDIA Jetson Orin Nano Super Kit를 활용하여 로컬 AI 모델을 안정적으로 서빙하는 방법을 소개합니다.
본문에서는 텍스트-음성 변환(TTS) 앱을 예시로, 기존의 요청-응답(Request/Response) 방식이 가진 한계를 극복하고 Durable Streams를 통해 어떻게 효율적인 아키텍처를 구축할 수 있는지 설명합니다.
이를 통해 사용자 경험 향상과 시스템의 견고성을 확보하는 방안을 제시합니다.
### 배경 설명
최근 로컬 환경에서 AI 모델을 직접 구동하고 독립적으로 서비스하려는 시도가 증가하고 있습니다. 특히 NVIDIA의 Jetson 시리즈는 저렴한 비용으로 AI 워크로드를 실행할 수 있는 강력한 하드웨어 플랫폼으로 주목받고 있습니다. 본 글의 저자는 이러한 배경 하에서 NVIDIA Jetson Orin Nano Super Kit (67 TOPS, 1024 CUDA 코어, 32 Tensor 코어)를 사용하여 텍스트-음성 변환(TTS) 애플리케이션을 개발했습니다. 이 애플리케이션은 Kokoro-82M이라는 신경망 TTS 모델을 기반으로 하며, 사용자가 텍스트를 입력하고 음성을 선택하면 해당 음성 파일의 링크를 생성하여 언제든 다시 듣거나 공유할 수 있도록 하는 것을 목표로 합니다. 궁극적으로는 웹 앱, CLI 또는 다른 서비스에서 재사용 가능한 독립적인 서빙 레이어를 구축하는 것이 목표입니다. 이를 위해 기존의 단순 요청-응답 API 방식 대신, 'Durable Streams'라는 개념을 도입하여 데이터의 영속성과 스트리밍 특성을 활용하는 새로운 아키텍처를 제안합니다.
### 기존 요청-응답 API의 한계와 Durable Streams의 필요성
기존의 요청-응답(Request/Response) 방식은 TTS와 같이 응답이 점진적으로 생성되고 시간이 소요되는 작업에 적합하지 않습니다. GPU 연산은 일반적인 웹 요청보다 느릴 수 있으며, 특히 첫 문장 생성 시 모델 워밍업으로 인해 지연이 발생할 수 있습니다. 또한, 여러 사용자가 동시에 요청할 경우 GPU 자원을 기다리는 대기열이 발생하여 성능 저하를 야기합니다. TTS의 특성상 전체 문단이 완성되기 전에 각 문장별로 음성을 생성하고 이를 실시간으로 스트리밍하는 것이 사용자 경험에 훨씬 유리합니다. 기존 방식으로는 작업 큐, 데이터베이스, 객체 스토리지, 재시도 로직, 중복 제거 로직 등 복잡한 인프라가 필요하게 됩니다. 저자는 이러한 복잡성을 피하고, '작업 제출 -> 즉시 출력 스트림 반환 -> 작업자(Worker)가 모델 출력 스트림에 추가 -> 클라이언트가 스트림 대기'라는 단순하지만 강력한 패턴을 구현하기 위해 Durable Streams를 선택했습니다. Durable Streams는 순서가 보장되고 영속적으로 저장되는 레코드(데이터 조각)의 시퀀스로, 네트워크 중단이나 클라이언트 연결 끊김에도 데이터 손실 없이 작업을 이어갈 수 있게 합니다.
### Durable Streams 아키텍처: S2-Lite를 활용한 구현
본 프로젝트에서는 S2-Lite라는 오픈 소스 구현체를 사용하여 Durable Streams API를 로컬 환경에 구축했습니다. S2-Lite는 단일 바이너리로 실행되며 로컬 디스크를 영속 스토리지로 활용합니다. 이를 통해 'append', 'read', 'tail', 'long-polling' 등의 기능을 제공합니다. 아키텍처는 'basin'이라는 네임스페이스를 중심으로 구성되며, 여러 개의 명명된 스트림을 통해 데이터 흐름을 관리합니다. 주요 스트림으로는 'jobs' (입력 작업 로그), 'jobs/_cursor' (작업자 진행 상태), 'progress/done' (완료 작업 기록), 'catalog/<id>' (레시피 정보), 'pub/casts/<id>' (최종 오디오 출력 스트림) 등이 있습니다. 각 오디오 레코드는 헤더에 문장 텍스트와 지속 시간(ms)을 포함하고, 바디에는 MP3 바이트를 담습니다. 이 스트림은 오디오 파일, 실시간 피드, 재생 로그, 진행 상황 표시 등 다양한 역할을 동시에 수행하며, 웹 서버, GPU 워커, 브라우저 간의 통신 계약 역할을 합니다. SSE나 WebSockets와 달리 S2-Lite는 데이터의 영속성을 보장하여, 클라이언트가 나중에 접속하더라도 처음부터 재생하거나 실시간으로 따라잡을 수 있습니다.
### 공정 스케줄링 및 작업 제출 메커니즘
단일 Jetson 장치에서 여러 동시 요청을 처리하기 위해 공정한 스케줄링 메커니즘이 중요합니다. 본 시스템은 'lead' 값을 계산하여 각 스트림이 재생 시점보다 얼마나 앞서 있는지 추적합니다. 'lead' 값이 양수이면 오디오가 버퍼링되어 재생보다 앞서고 있음을, 음수이면 청취자가 실시간 스트림을 따라잡고 있음을 의미합니다. 스케줄링 루프는 동시성 제한까지 작업을 허용하고, 가장 낮은 'lead' 값을 가진 활성 스트림을 선택하여 정확히 한 문장을 생성한 후 'lead' 값을 다시 계산하는 방식으로 작동합니다. 이를 통해 여러 사용자의 요청이 동시에 들어와도 특정 작업이 다른 모든 작업을 완료할 때까지 기다리는 상황을 방지하고, 각 문장 단위로 공정하게 처리합니다. 작업 제출 시에는 텍스트와 음성 정보를 검증하고, 'content-addressed' 방식으로 고유 ID를 생성합니다. 동일한 텍스트와 음성 조합은 동일한 스트림 ID를 가지므로, 반복 제출 시 캐시 히트처럼 작동합니다. 'S2'의 'match_seq_num=0' 기능을 사용하여 스트림이 비어 있을 때만 레코드를 추가함으로써, 동시 제출 시에도 단 하나의 요청만이 작업을 성공적으로 등록하도록 하여 잠금 테이블, 고유 제약 조건, 중복 제거 캐시의 필요성을 줄입니다.
### 작업자(Worker)의 역할과 내결함성
작업자(Worker)는 모델을 직접 실행하고 GPU를 사용하는 유일한 프로세스입니다. 'jobs' 스트림에서 작업을 읽어 Kokoro-82M 모델로 음성을 생성하고, 결과를 'pub/casts/<id>' 스트림에 오디오 레코드로 추가합니다. 작업자는 시작 시 'jobs/_cursor'에서 마지막으로 커밋된 오프셋을 읽어 작업을 재개합니다. 여러 활성 캐스트가 동시에 진행될 때, 작업 완료 순서가 작업 제출 순서와 다를 수 있으므로, 'contiguous-done watermark'를 사용하여 모든 이전 작업이 완료된 후에만 커서를 앞으로 이동시킵니다. 이 메커니즘은 'at-least-once' 전달을 보장하며, 'eos'(end of stream) 레코드를 통해 완료된 캐스트에 대해서는 'exactly-once'와 유사한 동작을 제공합니다. 프로세스 충돌 시에도 재시작 시 마지막 커밋된 오프셋부터 작업을 재개하며, 이미 완료된 캐스트는 'eos' 존재 여부로 건너뛰고, 미완료 캐스트는 다시 실행됩니다. 이는 복잡한 복구 프로토콜 없이도 시스템의 견고성을 유지하게 합니다. 플레이어는 최신 'start' 레코드를 재생 시점의 시작으로 간주하고 이전의 불완전한 오디오는 무시할 수 있습니다.
### 가치와 인사이트
본 프로젝트는 NVIDIA Jetson과 같은 엣지 디바이스에서 로컬 AI 모델을 안정적으로 서빙하기 위한 실용적인 아키텍처 패턴을 제시합니다. 기존의 요청-응답 방식이 가진 지연, 확장성, 복잡성 문제를 'Durable Streams' 개념을 통해 해결함으로써, 데이터의 영속성, 순서 보장, 점진적 생성 및 소비를 효과적으로 지원합니다. S2-Lite와 같은 오픈 소스 도구를 활용하여 복잡한 인프라 없이도 견고하고 확장 가능한 시스템을 구축할 수 있음을 보여줍니다. 특히, TTS와 같이 스트리밍 특성이 중요한 애플리케이션에서 사용자 경험을 크게 향상시킬 수 있으며, 'logmaxxing' 패턴을 통해 시스템의 단순성과 신뢰성을 동시에 확보할 수 있다는 점이 중요한 시사점입니다. 이는 로컬 AI 서비스뿐만 아니라 다양한 분산 시스템 설계에 적용될 수 있는 유용한 접근 방식입니다.
### 기술·메타
* **하드웨어:** NVIDIA Jetson Orin Nano Super Kit
* **AI 모델:** Kokoro-82M (Neural Text-to-Speech)
* **스트리밍 기술:** Durable Streams (S2-Lite 구현체)
* **프로그래밍 언어:** Python
* **핵심 개념:** Content-addressed ID, Fair Scheduling, At-least-once Delivery, Idempotent Output
### 향후 전망
본 프로젝트는 로컬 AI 서비스의 가능성을 보여주지만, 향후 몇 가지 변수에 따라 발전할 수 있습니다. 첫째, Jetson 하드웨어의 성능 향상 및 최신 AI 모델의 경량화 추세는 더 복잡하고 성능이 뛰어난 모델을 로컬에서 실행할 수 있게 할 것입니다. 둘째, S2-Lite와 같은 Durable Streams 구현체의 발전 및 커뮤니티 지원 확대는 이러한 아키텍처의 도입을 더욱 용이하게 할 것입니다. 셋째, 경쟁 제품으로는 클라우드 기반 AI 서비스들이 여전히 강력한 경쟁력을 유지할 것이며, 로컬 AI는 특정 사용 사례(개인 정보 보호, 오프라인 환경, 낮은 지연 시간 요구 사항)에 집중될 가능성이 높습니다. 본 글에서 제시된 아키텍처는 이러한 로컬 AI 서비스의 기반 기술로서, 향후 다양한 AI 애플리케이션으로 확장될 잠재력을 가지고 있습니다. 예를 들어, LLM 토큰을 Durable Stream으로 스트리밍하고 TTS 워커가 이를 실시간으로 음성으로 변환하는 'AI 라디오'와 같은 새로운 형태의 서비스도 가능할 것입니다.
📝 원문 및 참고
- Source: Lobsters
- 토론(Lobsters): [lobste.rs](https://lobste.rs/s/jiwsyd/serving_local_ai_on_my_jetson_through)
- 원문: [링크 열기](https://s2.dev/blog/local-ai)
---
출처: Lobsters · [원문 링크](https://s2.dev/blog/local-ai)
신고 · 불법·유해·아동 안전(CSAE) 관련 콘텐츠
댓글 0
아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.