TRENDSHIFT #17 딥다이브 · 2026-06-02

StemDeck 딥다이브
— 노래 한 곡을 보컬·드럼·베이스로 쪼개주는 내 컴퓨터 속 오디오 작업실

좋아하는 노래에서 보컬만 빼고 싶거나, 드럼만 듣고 싶었던 적 있으신가요? StemDeck은 MP3·WAV·FLAC 파일을 끌어다 놓거나 유튜브 주소만 붙여넣으면, 인공지능이 노래를 최대 6개의 트랙(보컬·드럼·베이스·기타·피아노·기타등등)으로 분리해 줍니다. 그리고 그 트랙들을 DAW(전문 음악 편집 프로그램)처럼 생긴 멀티트랙 믹서에 펼쳐, 음소거·솔로·구간 반복·파형 확대를 하며 가지고 놀 수 있죠. 핵심은 모든 처리가 내 컴퓨터 안에서만 일어난다는 것 — 회원가입도, 업로드도, 구독료도 없습니다. (저장소: stemdeckapp/stemdeck · Apache-2.0 · ⭐454 · alpha 단계 · TrendShift 17위)
목차
  1. 프로젝트 한줄 요약
  2. 왜 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석
  5. 디렉토리 구조 해부
  6. 학습 포인트 (기술별)
  7. 하드웨어/시스템 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한줄 요약

한 문장으로: "노래를 넣으면 보컬·드럼·베이스 같은 악기별 트랙으로 쪼개주고, 그 트랙들을 음악 작업실처럼 섞어 들을 수 있게 해주는 '내 컴퓨터 전용' 무료 오픈소스 프로그램."

음악을 만지는 사람들에게 "스템 분리(stem separation)"는 오래된 꿈입니다. 완성된 노래 한 곡은 보컬·드럼·베이스 같은 여러 소리가 이미 한 덩어리로 합쳐진 상태인데, 이걸 다시 악기별로 떼어내는 작업이죠. 노래방 반주를 만들거나, 베이스 라인을 귀로 따려고(채보) 하거나, 리믹스를 할 때 꼭 필요합니다. 그동안은 Moises나 LALAL.AI 같은 클라우드 유료 서비스에 파일을 올려야 했는데, StemDeck은 그 일을 내 노트북 안에서 공짜로 해냅니다.

핵심 용어
스템(Stem) / 스템 분리(Stem Separation)
스템은 원래 음악 제작에서 "악기별로 따로 녹음·보관한 개별 트랙"을 뜻합니다(보컬 스템, 드럼 스템…). 스템 분리는 이미 합쳐진 완성곡에서 인공지능으로 그 개별 트랙을 되살려내는 일이고요. 비유하자면, 잘 섞인 미숫가루 한 잔에서 콩가루·보릿가루·찹쌀가루를 다시 골라내는 마법 같은 작업입니다.
영웅 비유

"내 책상 위에 놓인, 인터넷 없이 도는 1인용 녹음 스튜디오"

당신이 좋아하는 노래 MP3를 책상 위 작은 기계에 넣습니다. 잠시 윙― 돌아가더니, 한 곡이었던 소리가 보컬 칸, 드럼 칸, 베이스 칸… 이렇게 여러 줄(레인)로 나뉘어 모니터에 펼쳐집니다. 각 칸에는 볼륨 손잡이와 음소거 버튼이 달려 있어서, 드럼만 끄고 들어 보거나 보컬만 솔로로 들어 볼 수 있죠. 마음에 드는 조합이 나오면 그 믹스를 WAV 파일로 뽑아 갑니다. 중요한 건 이 스튜디오가 인터넷에 연결돼 있지 않다는 점 — 당신의 노래는 이 방을 절대 떠나지 않습니다.

기술적으로 풀면, StemDeck은 웹 기술로 만든 데스크톱 앱입니다. 안에는 작은 웹 서버(FastAPI)가 돌고, 실제 분리는 Meta(페이스북)가 공개한 인공지능 모델 Demucs가 담당합니다. 화면(파형·믹서)은 브라우저 기술로 그리고, 그 브라우저를 통째로 감싸 진짜 프로그램처럼 만들어주는 껍데기가 Tauri입니다. 이 세 조각의 조합이 이 프로젝트의 전부이자 가장 배울 점이 많은 부분입니다.

2왜 주목받는가

"클라우드 유료 서비스가 하던 일을, 프라이버시를 지키며 공짜로, 내 기계에서" — 셀프호스팅 흐름과 정확히 맞물렸다

StemDeck이 TrendShift 상위권에 오른 이유는 단순히 "또 하나의 AI 도구"여서가 아닙니다. 요즘 개발자·창작자 사이에서 커지는 두 흐름에 정확히 올라탔기 때문입니다: ① 내 데이터를 남의 서버에 올리기 싫다는 프라이버시·로컬 우선(local-first) 욕구, ② 구독료 대신 한 번 받아 평생 쓰는 셀프호스팅(self-hosted) 선호.

핵심 용어
로컬 우선(Local-first) · 셀프호스팅(Self-hosted)
로컬 우선은 "데이터와 처리를 클라우드가 아니라 내 기기에서 먼저 한다"는 설계 철학입니다. 셀프호스팅은 남이 운영하는 서비스 대신 "내가 내 컴퓨터/서버에 직접 깔아 돌린다"는 뜻이고요. 비유하면, 매번 빨래방에 맡기는(클라우드 구독) 대신 집에 세탁기를 들여놓는(셀프호스팅) 것입니다. 초기 설치는 번거로워도 그 뒤로는 공짜·비공개입니다.

경쟁자인 클라우드 서비스와의 차이를 저장소가 아주 정직하게 표로 정리해 둔 점도 인상적입니다. "우리가 더 좋다"가 아니라 "우리는 여기까지만 잘하고, 나머지는 유료 서비스가 낫다"고 먼저 인정하죠. 핵심 비교를 추려 보면:

항목StemDeckMoises · LALAL.AI (클라우드 유료)
가격완전 무료, 영구무료체험 후 크레딧·구독 필요
처리 위치내 컴퓨터 안에서만파일을 그들의 서버로 업로드
계정필요 없음필수
프라이버시오디오가 기기를 떠나지 않음업로드 후 제3자 서버에서 처리
분리 모델Demucs htdemucs_6s (오픈소스)비공개 자체 모델 (대체로 더 고품질)
스템 수6개최대 10개 (플랜별)
속도내 하드웨어에 좌우 (GPU면 빠름)하드웨어 무관 빠름 (서버가 처리)
소스 공개오픈소스, 포크·셀프호스팅 가능비공개
배울 점
"정직한 비교표"라는 마케팅 전략

오픈소스 프로젝트가 상용 제품과 경쟁할 때, 단점을 숨기지 않고 "속도·품질·모바일 앱이 필요하면 유료가 낫다"고 먼저 말하면 오히려 신뢰를 얻습니다. 사용자가 "써 보고 나서 빈틈을 발견"하는 대신 "처음부터 알고 선택"하게 만드는 것 — README가 직접 밝힌 의도입니다.

또 하나 주목할 점은 "다운로더가 아니라 분리 도구"라는 선 긋기입니다. 유튜브 URL을 받긴 하지만, 저장소는 "본래 용도는 당신이 이미 가진 오디오 파일을 처리하는 것"이라고 못 박고, 다운로드한 콘텐츠를 저장·캐시·재배포하지 않는다고 명시합니다. 법적 리스크가 큰 영역에서 의도와 책임 소재를 분명히 하는 방식도 오픈소스 운영의 교과서적 사례입니다.

3기술 스택 전체 지도

백엔드(파이썬 서버 + AI) · 프론트엔드(순수 자바스크립트) · 데스크톱 껍데기(러스트) — 세 층이 또렷이 나뉜다

StemDeck은 한 가지 언어로 된 단일 프로그램이 아니라, 역할이 다른 세 개의 층이 맞물린 구조입니다. 깃허브 언어 통계(JavaScript 30% · CSS 27% · Python 18% · Rust 11% · HTML 7% · Shell 4%)가 이 다층 구조를 그대로 보여줍니다. 하나씩 뜯어봅시다.

백엔드 — 파이썬 + FastAPI + AI 라이브러리들

실제 "무거운 일"을 하는 층입니다. 작은 웹 서버를 띄워 두고, 프론트엔드가 보낸 요청(이 노래를 분리해 줘)을 받아 인공지능 파이프라인을 돌립니다.

도구역할한 줄 풀이
Python 3.10+백엔드 언어AI·오디오 라이브러리가 가장 풍부한 언어
FastAPI웹 서버 프레임워크요청을 받고 응답하는 "접수 창구"
Uvicorn서버 실행기(ASGI)FastAPI 앱을 실제로 켜 두는 엔진
Demucs (htdemucs_6s)스템 분리 AI노래를 6트랙으로 쪼개는 Meta의 신경망
PyTorch / torchaudioAI 실행 엔진Demucs가 올라타 도는 딥러닝 토대
yt-dlp유튜브 오디오 받기URL에서 음원만 떼어 오는 도구
FFmpeg오디오 변환·믹싱포맷 변환과 트랙 합치기 만능 칼
librosa음악 분석BPM(빠르기)·키(조성) 자동 추출
pyloudnorm음량 측정방송 표준(BS.1770)으로 체감 음량 계산
uv패키지 관리자파이썬 라이브러리를 빠르게 설치·고정
핵심 용어
FastAPI · SSE(Server-Sent Events)
FastAPI는 파이썬으로 웹 API(프로그램끼리 대화하는 창구)를 빠르게 만드는 도구입니다. StemDeck은 여기에 SSE를 곁들이는데, 이건 "서버가 브라우저에 한 방향으로 계속 소식을 흘려보내는" 기술입니다. 분리 작업이 "다운로드 중 → 분석 중 → 분리 중 30%…"처럼 시시각각 진행되는데, 그 진행률을 실시간으로 밀어 보내는 통로가 SSE죠. 라디오 생중계처럼 한쪽이 계속 말하고 다른 쪽은 듣기만 합니다.

프론트엔드 — 프레임워크 없는 "맨손" 자바스크립트

요즘 웹 앱이 거의 다 React·Vue 같은 프레임워크를 쓰는 것과 정반대로, StemDeck의 화면은 순수 바닐라 JavaScript + Web Audio API로만 짜였습니다. 빌드 단계(컴파일)조차 없어서, static/ 폴더의 .js 파일이 곧 브라우저가 실행하는 코드 그 자체입니다.

비유

"빌드 단계가 없다"는 건, 가구를 살 때 조립이 필요한 이케아 가구(빌드 필요)가 아니라 완성된 채로 배송 오는 가구(빌드 없음)와 같습니다. 코드를 고치면 변환·번들링 과정 없이 새로고침만으로 바로 화면에 반영되죠. 배우기엔 더없이 투명하지만, 규모가 커지면 관리가 힘들어지는 트레이드오프가 있습니다.

도구역할한 줄 풀이
Vanilla JS화면 로직프레임워크 없이 순수 자바스크립트로 직접 제어
Web Audio API브라우저 내 오디오 처리볼륨·음소거·VU 미터를 브라우저가 직접 계산
Canvas파형 그리기min/max 샘플 렌더링으로 파형을 그림판처럼 직접 그림
multitrack.js (vendor)멀티트랙 표시여러 트랙을 가지런히 정렬해 보여주는 보조 라이브러리

데스크톱 껍데기 — Tauri v2 (Rust)

위의 웹 서버 + 웹 화면을 그냥 브라우저로 열어도 동작하지만(localhost:8000), 일반 사용자에게는 "진짜 설치되는 앱"이 필요합니다. 그 껍데기를 만드는 게 Tauri입니다. macOS·Windows용 .dmg/.exe를 만들어, 사용자는 파이썬이나 명령어를 전혀 몰라도 더블클릭만으로 쓸 수 있죠.

핵심 용어
Tauri · WebView
Tauri는 웹 기술(HTML·CSS·JS)로 만든 화면을 러스트(Rust) 껍데기로 감싸 가벼운 데스크톱 앱으로 만들어주는 도구입니다. 비슷한 도구인 Electron이 크롬 브라우저를 통째로 끼워 앱이 수백 MB로 무거워지는 반면, Tauri는 운영체제에 이미 깔린 WebView(macOS는 WKWebView, Windows는 WebView2)를 빌려 써서 훨씬 가볍습니다. WebView란 "주소창·탭이 없는 알맹이 브라우저"라고 보면 됩니다. StemDeck의 desktop/src-tauri/src/main.rs가 바로 이 껍데기 + 내장 파이썬 서버를 띄우고 관리하는 러스트 코드입니다.

인프라·운영 — Docker · Woodpecker CI

서버로 띄우고 싶은 사람을 위해 Docker 구성(build/Dockerfile, docker-compose.yml)이 준비돼 있고, 코드가 바뀔 때마다 자동으로 테스트·빌드하는 CI(지속적 통합)는 흔한 GitHub Actions가 아니라 Woodpecker CI를 씁니다 — 이것 자체가 셀프호스팅이 가능한 오픈소스 CI라, 프로젝트의 "셀프호스팅 철학"과 일관됩니다.

4아키텍처 심화 분석

한 곡이 들어와 6트랙으로 나뉘기까지 — "잡(Job) 파이프라인"이라는 컨베이어 벨트를 따라가 보자

StemDeck의 심장은 app/pipeline/ 폴더에 있는 잡 파이프라인(job pipeline)입니다. 사용자가 노래를 넣으면 하나의 "잡(작업 건)"이 만들어지고, 이 잡이 정해진 5단계 컨베이어 벨트를 순서대로 지나갑니다. 전체 흐름을 그림으로 보면:

사용자 (브라우저 / 데스크톱 앱) │ ① "이 노래 분리해줘" (URL 또는 파일 업로드) ▼ ┌──────────────────────────────────────────────┐ │ FastAPI 서버 (app/main.py) │ │ POST /api/jobs → 잡 생성, job_id 발급 │ └───────────────┬──────────────────────────────┘ │ 백그라운드 작업으로 넘김 ▼ ┌──────────────────────────────────────────────┐ │ 파이프라인 (app/pipeline/runner.py) │ │ ※ 세마포어(1) — 무거운 잡은 "한 번에 하나만" │ │ │ │ download → analyze → separate │ │ (yt-dlp) (librosa) (Demucs 서브프로세스) │ │ │ │ │ collect ←──────┘ │ │ (FFmpeg: 트랙 모으기) │ │ │ │ │ ▼ │ │ mix (FFmpeg amix: 선택 믹스 만들기) │ └───────────────┬──────────────────────────────┘ │ ② 진행률을 SSE로 실시간 전송 ▼ GET /api/jobs/{id}/events (브라우저가 듣고 있음) │ ③ 완료되면 스템 WAV 스트리밍 ▼ GET /api/jobs/{id}/stems/vocals.wav … (구간 요청 지원)

설계 패턴 1 — 세마포어로 "한 번에 하나만" 강제

Demucs는 GPU·CPU를 통째로 잡아먹는 무거운 작업입니다. 두 곡을 동시에 돌리면 둘 다 느려지거나 메모리가 터지죠. 그래서 runner.py세마포어(Semaphore)를 1로 걸어 둡니다 — "이 문은 한 번에 한 사람만 통과"라는 신호등입니다. 여러 요청이 와도 무거운 분리 작업은 줄을 서서 차례로 처리됩니다(대기 잡이 3개를 넘으면 503으로 거절).

핵심 용어
세마포어(Semaphore)
동시에 자원을 쓰는 사람 수를 제한하는 교통 신호등입니다. 값이 1이면 "한 명만", 3이면 "세 명까지" 통과시키고 나머지는 대기시킵니다. 식당 화장실 열쇠가 하나뿐이라 다음 사람이 기다려야 하는 상황을 떠올리면 됩니다. StemDeck은 비싼 AI 연산이 서로 충돌하지 않게 이 열쇠를 하나만 둡니다.

설계 패턴 2 — 서브프로세스 + 워치독으로 안전하게 AI 돌리기

분리 단계(separate.py)는 Demucs를 같은 프로세스 안에서 부르지 않고, 별도 프로그램(서브프로세스)으로 띄웁니다. 이렇게 하면 두 가지 이득이 있습니다: ① 사용자가 "취소"를 누르면 그 프로세스만 즉시 죽일 수 있고(메인 서버는 멀쩡), ② AI가 멈춰 버려도(GPU 데드락 등) 서버 전체가 같이 죽지 않습니다.

여기에 워치독(watchdog, 감시견) 스레드를 붙인 게 인상적입니다. Demucs는 진행 상황을 stderr(오류 출력 통로)에 23%처럼 찍는데, 코드는 이걸 한 글자씩 읽으며 \r(같은 줄 다시 그리기) 문자를 기준으로 잘라 진행률을 뽑아냅니다. 그리고 감시견은 "30초마다 깨어나, 마지막 출력 이후 너무 오래(설정값) 조용하면 잡이 멈춘 것으로 보고 프로세스를 종료"합니다.

배울 점
취소를 EOF로 번역하는 우아한 처리

POST /cancel이 호출되면 코드는 Demucs 프로세스에 terminate()를 보냅니다. 그러면 출력 통로가 끊겨(EOF) 읽기 루프가 자연스럽게 끝나고, proc.wait()가 0이 아닌 종료코드를 돌려줍니다. 코드는 이 상황을 "에러"가 아니라 "사용자 취소(JobCancelled)"로 먼저 해석해, 부분 결과 폴더를 지우고 깔끔히 "취소됨" 상태로 돌아갑니다. 실패와 취소를 구분하는 이런 디테일이 견고한 서버 코드의 핵심입니다.

설계 패턴 3 — 업로드 파일을 먼저 "표준 규격"으로 변환

runner.py_prepare_local_source()는 작지만 중요한 함정을 막습니다. 사용자가 24비트·32비트 실수·고샘플레이트·다채널 WAV를 올리면 Demucs가 조용히 무음(silence)을 뱉는 버그가 있는데, 이를 피하려고 모든 업로드를 먼저 FFmpeg로 16비트·44.1kHz·스테레오 WAV라는 단일 규격으로 변환한 뒤 AI에 넘깁니다. "들어오는 데이터를 일단 표준화하고 일을 시작한다"는 방어적 설계의 모범입니다.

설계 패턴 4 — "원본(Original)" 보조 트랙과 선택 믹스

사용자가 6개 중 일부 스템만 고르면(예: 보컬·드럼만), collect.py고르지 않은 나머지를 모두 합친 7번째 트랙 "Original"을 만들어 줍니다. 이건 A/B 비교(내가 고른 것 vs 나머지 전부)를 노래를 두 번 트는 것 없이 가능하게 하는 영리한 장치입니다. 또 선택한 스템만 FFmpeg의 amix로 합쳐 mix.wav 한 파일로 내려받게 해 줍니다.

설계 패턴 5 — 상태는 메모리에, 결과는 디스크에

잡의 진행 상태(어디까지 처리됐나)는 서버 메모리에 두고, 실제 결과물(스템 WAV)은 jobs/<job_id>/ 디스크에 저장합니다. 서버를 재시작하면 잡 목록은 초기화되지만 파일은 남고, 오래된 폴더는 백그라운드 청소 루프가 24시간 뒤(설정 가능) 자동으로 쓸어 담습니다(sweep_old_jobs). 메모리는 가볍게, 디스크는 정리되게 — 서버 자원을 오래 깨끗이 유지하는 패턴입니다.

5디렉토리 구조 해부

폴더 이름만 봐도 "세 개의 층"이 그대로 보인다 — app(백엔드) · static(프론트) · desktop(껍데기)

저장소를 처음 열면 폴더가 많아 막막할 수 있지만, 역할별로 묶어 보면 의외로 단순합니다. 핵심만 추려 트리로 보면:

stemdeck/ ├── app/ ← 🐍 백엔드 (파이썬 웹 서버 + AI 파이프라인) │ ├── main.py · FastAPI 앱 본체 (서버 시작·헬스체크·청소 루프) │ ├── api/ · 요청 창구(엔드포인트) │ │ ├── jobs.py · 잡 생성/조회/취소 (가장 큰 파일, ~12KB) │ │ ├── stems.py · 스템 WAV 스트리밍 (구간 요청 지원) │ │ └── events.py · SSE 진행률 스트림 │ ├── core/ · 공용 토대 │ │ ├── config.py · 환경변수·경로·디바이스 설정 │ │ ├── models.py · Job 데이터 구조 정의 │ │ └── registry.py · 잡 등록부(메모리 상태 보관·복원) │ └── pipeline/ · ⭐ 분리 파이프라인의 핵심 │ ├── runner.py · 전체 단계 오케스트레이션 │ ├── download.py · yt-dlp로 유튜브 음원 받기 │ ├── analyze.py · librosa로 BPM·키 분석 │ ├── separate.py · Demucs 서브프로세스 실행 │ └── collect.py · FFmpeg로 트랙 모으고 믹스 만들기 │ ├── static/ ← 🌐 프론트엔드 (빌드 단계 없는 순수 웹) │ ├── index.html · 단일 페이지 (44KB) │ ├── js/ · 바닐라 JS 모듈들 │ │ ├── player.js · DAW 플레이어 본체 (가장 큰 JS, ~48KB) │ │ ├── catalog.js · 라이브러리·트랙 목록 (~67KB) │ │ ├── mixer.js · 믹서(볼륨·솔로·음소거) │ │ ├── transport.js · 재생·정지·루프 컨트롤 │ │ └── audioEngine.js· Web Audio 그래프 관리 │ ├── css/ · 화면 스타일 (daw.css가 69KB로 최대) │ └── vendor/multitrack.js · 외부 멀티트랙 보조 라이브러리 │ ├── desktop/ ← 🦀 데스크톱 껍데기 (Tauri v2 / Rust) │ ├── src-tauri/ │ │ ├── src/main.rs · 러스트 껍데기 + 내장 파이썬 서버 관리 (81KB!) │ │ └── tauri.conf.json │ └── ui/setup.js · 첫 실행 시 런타임·모델 내려받는 설치 화면 │ ├── build/ ← 🐳 Docker 구성 (Dockerfile, compose) ├── scripts/ ← 🔧 macOS·Windows 빌드 자동화 스크립트 ├── packaging/ ← 📦 배포용 안내문·DMG 배경 등 ├── tests/ ← ✅ pytest 테스트 (10개 파일) ├── pyproject.toml · 파이썬 의존성·설정 └── run.sh · setup/start/stop 제어 스크립트
비유

이 구조를 식당에 빗대면, app/주방(실제 요리=AI 처리), static/손님이 보는 홀과 메뉴판(화면), desktop/식당 건물 외관과 간판(설치 가능한 앱 껍데기)입니다. 주방에서 일하는 사람(파이썬)과 손님 응대(자바스크립트), 건물 관리(러스트)가 각자 다른 전문가인 셈이죠. 이렇게 층이 또렷이 갈려 있으면, 한 층만 공부해도 다른 층을 망칠 걱정 없이 손댈 수 있습니다.

흥미로운 디테일 하나: desktop/src-tauri/src/main.rs가 무려 81KB로 저장소에서 가장 큰 소스 파일입니다. 단순한 껍데기가 아니라, 내장 파이썬 서버를 띄우고·포트를 잡고·부모 프로세스가 죽으면 백엔드도 같이 정리하는 등 "앱 생명주기 관리"의 복잡함이 전부 여기 들어 있다는 뜻입니다.

6학습 포인트 (기술별)

이 레포 한 채에서 "오디오 AI · 비동기 서버 · Web Audio · 데스크톱 패키징 · 의존성 관리"를 한꺼번에 맛본다

StemDeck이 공부 자료로 훌륭한 이유는, 한 가지 기술만 깊게 파는 게 아니라 실전 제품을 이루는 여러 조각을 작고 읽기 좋은 크기로 보여주기 때문입니다. 기술별로 "무엇을 배울 수 있고, 무엇을 직접 해 보면 좋은지" 정리합니다.

학습 포인트 ① — 오디오 AI (Demucs)

합쳐진 소리를 다시 가르는 신경망

배울 것: Demucs의 htdemucs_6s가 어떻게 한 파형을 6개로 가르는지, "소스 분리(source separation)"라는 문제 자체가 무엇인지. 모델을 직접 학습시킬 필요 없이 python -m demucs ... 한 줄로 불러 쓰는 추론(inference) 사용법.

실습 아이디어: 같은 노래를 htdemucs(4스템)와 htdemucs_6s(6스템)로 각각 돌려, 기타·피아노 분리 품질이 어떻게 다른지 귀로 비교해 보기.

학습 포인트 ② — 비동기 웹 서버 (FastAPI + 백그라운드 잡)

"오래 걸리는 일"을 우아하게 처리하는 법

배울 것: 응답을 곧장 못 주는 무거운 작업을, 잡으로 만들어 백그라운드로 넘기고 → SSE로 진행률을 흘려보내고 → 세마포어로 동시성을 막는 전형적 패턴. asyncio.to_thread로 블로킹 작업을 스레드에 떠넘기는 기법도.

실습 아이디어: app/main.py/api/health를 흉내 내, 내 FastAPI 앱에 "현재 디바이스가 CUDA인지 CPU인지" 반환하는 엔드포인트를 직접 추가해 보기.

학습 포인트 ③ — Web Audio API & Canvas

브라우저만으로 만드는 미니 DAW

배울 것: 여러 오디오 트랙을 동기화해 재생하고, 트랙별 볼륨·음소거·솔로를 거는 오디오 그래프 구성. VU 미터(음량 막대)를 분석기(analyser) 노드의 RMS로 그리는 법. 파형을 Canvas에 min/max 샘플로 직접 그리는 시각화.

실습 아이디어: 두 개의 오디오 파일을 동시에 재생하면서 한쪽 볼륨만 슬라이더로 조절하는 30줄짜리 Web Audio 데모 페이지를 만들어 보기.

학습 포인트 ④ — 음악 정보 검색 (MIR)

BPM·키를 코드로 알아내기

배울 것: librosa의 비트 추적으로 빠르기(BPM)를, 크로마(chroma) 분석 + Albrecht-Shanahan 키 프로파일로 조성(key)을 추정하는 알고리즘. analyze.py는 단순히 라이브러리를 부르는 데 그치지 않고, 팝/록은 자연단음계를 쓴다는 점을 반영해 "장조 대신 단조를 살짝 우대"하는 보정까지 손수 구현해 둔, 보기 드문 교육용 코드입니다.

실습 아이디어: 내가 키를 아는 노래 5곡을 넣어, analyze.py가 맞히는 정확도를 표로 정리해 보기.

학습 포인트 ⑤ — 데스크톱 패키징 (Tauri)

웹 앱을 진짜 설치 파일로 굽기

배울 것: 웹 서버 + 화면을 .dmg/.exe로 묶는 과정, "첫 실행 시 런타임·모델을 내려받는" 설치 마법사 설계(desktop/ui/setup.js), 부모 앱이 종료되면 내장 서버도 함께 정리하는 워치독 패턴(main.py_desktop_parent_watchdog).

실습 아이디어: Tauri 공식 튜토리얼로 "Hello World" 데스크톱 앱을 빌드해, Electron 대비 결과물 용량이 얼마나 작은지 확인해 보기.

학습 포인트 ⑥ — 의존성 지옥과의 싸움 (pyproject.toml)

주석으로 남은 "왜 이 버전인가"의 기록

배울 것: pyproject.toml의 의존성 핀(pin)마다 달린 긴 주석은 그 자체로 한 편의 교과서입니다 — "torchaudio 2.7이 내장 오디오 라이터를 없애서 Demucs가 깨지므로 2.6에 고정", "인텔 맥은 휠이 없어 torch 2.2로", "보안 취약점(CVE) 때문에 urllib3 하한선 상향" 등. 실무에서 라이브러리 버전을 왜·어떻게 고정하는지 살아 있는 사례.

실습 아이디어: 주석들을 읽고 "이 핀이 없으면 어떤 증상이 나는가"를 한 줄씩 내 말로 풀어 적어 보기.

7하드웨어/시스템 요구사항

GPU가 있으면 빠르고, 없으면 느리지만 동작은 한다 — "내 기계 성능 = 처리 속도"

StemDeck은 클라우드가 아니라 내 컴퓨터에서 AI를 돌리므로, 속도가 전적으로 내 하드웨어에 달려 있습니다. 코드는 켜질 때 가장 빠른 연산 장치를 자동으로 골라잡습니다(config.py의 디바이스 자동 감지).

구분요구·권장
운영체제macOS · Windows · Linux (데스크톱 앱은 macOS·Windows 빌드 제공)
연산 장치NVIDIA GPU(CUDA) ≫ Apple Silicon(MPS) ≫ CPU 폴백 순으로 빠름
디스크Demucs 모델 ~170MB + 데스크톱 런타임(파이썬 ~500MB 등). Windows NVIDIA 빌드는 ~1.6GB
인터넷유튜브 다운로드 + 첫 모델 내려받기에만 필요. 그 뒤로는 오프라인 가능
입력 길이 제한기본 1200초(20분) 초과 오디오는 거절 (STEMDECK_MAX_DURATION_SEC로 조정)
핵심 용어
CUDA · MPS · CPU 폴백(fallback)
CUDA는 NVIDIA 그래픽카드로 AI 계산을 돌리는 기술, MPS는 애플 실리콘(M1 이상) 칩으로 같은 일을 하는 기술입니다. 둘 다 없으면 일반 CPU로 떨어지는데(=폴백), 동작은 하지만 몇 배 느립니다. 비유하면 같은 짐을 트럭(GPU)으로 나르느냐 손수레(CPU)로 나르느냐의 차이입니다. STEMDECK_DEMUCS_DEVICE 환경변수로 강제 지정도 가능합니다.

주요 설정값(환경변수)을 알아 두면 셀프호스팅 시 유용합니다: STEMDECK_MAX_PENDING_JOBS(대기 잡 한도, 기본 3) · STEMDECK_JOB_TTL_SECONDS(결과 보관 시간, 기본 24시간) · STEMDECK_JOBS_DIR(결과 저장 위치) 등이 있습니다.

8직접 해볼 수 있는 실습 과제

설치만 하고 끝내지 말고, 난이도별로 손을 더럽혀 보자 — 읽기만 한 코드는 금방 잊힌다
난이도 ★ — 입문

웹 서버 모드로 띄워 첫 분리 돌려 보기

데스크톱 앱 대신 소스에서 직접 띄워 봅니다. git cloneuv syncuv run uvicorn app.main:app --reloadlocalhost:8000 접속. 짧은 노래 한 곡을 넣어 "다운로드 → 분석 → 분리" 단계가 화면에 어떻게 흘러가는지 관찰합니다. (FFmpeg가 PATH에 있어야 함.)

난이도 ★ — 입문

API를 직접 호출해 보기

화면 없이 터미널에서 curlPOST /api/jobs에 유튜브 URL을 보내 job_id를 받고, GET /api/jobs/{id}로 상태를 폴링해 봅니다. SSE 스트림(/events)도 curl로 받아 보며 "서버가 한 방향으로 진행률을 밀어 보낸다"를 체감합니다.

난이도 ★★ — 중급

환경변수로 동작 바꿔 보기

STEMDECK_DEMUCS_DEVICE=cpu로 강제하고 처리 시간을 재 본 뒤, GPU/MPS와 비교합니다. STEMDECK_MAX_DURATION_SEC를 짧게 줄여 "긴 파일 거절" 동작을, STEMDECK_MAX_PENDING_JOBS=1로 줄여 "대기 한도 초과 시 503"을 직접 재현해 봅니다.

난이도 ★★★ — 중상급

분석 결과에 새 지표 추가하기

app/pipeline/analyze.py를 읽고, 기존 BPM·키·LUFS 외에 "곡 길이를 분:초로 표기" 같은 새 메타데이터를 계산해 metadata.json에 추가해 봅니다. 파이프라인의 어디에 끼워 넣어야 하는지(runner.py_write_metadata) 흐름을 따라가는 게 핵심.

난이도 ★★★★ — 고급

Docker로 셀프호스팅 후 다른 기기에서 접속

docker compose -f build/docker-compose.yml up --build로 컨테이너를 띄우고, 모델 가중치가 명명 볼륨에 캐시돼 재빌드 때 다시 안 받는지 확인합니다. 그다음 같은 네트워크의 다른 기기(휴대폰 등)에서 접속해, "내 PC를 작은 스템 분리 서버로" 바꿔 봅니다. (GPU 패스스루는 OS별 제약 확인.)

9관련 기술 심화 학습 로드맵

StemDeck을 출발점 삼아 "오디오 AI 풀스택"으로 뻗어 나가는 6주 코스

이 레포가 건드리는 기술을 체계적으로 익히고 싶다면, 아래 순서를 권합니다. 각 주차는 StemDeck의 특정 폴더·파일과 연결돼 있어, 배운 걸 곧바로 실물 코드에서 확인할 수 있습니다.

주차주제 · 목표StemDeck 연결고리
1주차파이썬 비동기·FastAPI 기초 — 라우터, 의존성 주입, 백그라운드 작업app/api/, app/main.py
2주차오디오 기본기 — 샘플레이트·비트심도·채널, FFmpeg로 변환·믹싱collect.py, _prepare_local_source
3주차딥러닝 추론 — PyTorch로 사전학습 모델 불러 쓰기, Demucs 소스 분리separate.py
4주차음악 정보 검색(MIR) — librosa로 BPM·키·크로마, LUFS 음량 측정analyze.py, pyloudnorm
5주차Web Audio & Canvas — 오디오 그래프, 멀티트랙 동기 재생, 파형 시각화static/js/player.js, mixer.js
6주차데스크톱 패키징 — Tauri로 웹 앱을 설치 파일로, CI로 자동 빌드desktop/, .woodpecker/
비유

이 로드맵은 요리를 거꾸로 배우는 것과 같습니다. 완성된 요리(StemDeck)를 먼저 맛본 뒤, "이 소스는 어떻게 만들었지?"(FFmpeg) → "이 고기는 어떻게 익혔지?"(Demucs) → "간은 어떻게 맞췄지?"(LUFS) 식으로 하나씩 거슬러 올라갑니다. 전체 그림을 먼저 본 다음 부품을 파고드는 방식이라, 길을 잃지 않습니다.

10핵심 키워드 사전

이 문서와 저장소에 등장한 용어를 한 곳에 모았다 — 헷갈릴 때 돌아와 찾아보세요
용어풀이 (+ 비유)
스템 (Stem)악기별로 분리된 개별 오디오 트랙. 미숫가루에서 다시 골라낸 콩가루 한 봉지.
스템 분리 (Source Separation)합쳐진 완성곡을 AI로 다시 악기별로 가르는 작업.
Demucs / htdemucs_6sMeta가 공개한 오픈소스 스템 분리 신경망. 6스템 버전이 보컬·드럼·베이스·기타·피아노·기타등등을 나눔.
DAWDigital Audio Workstation. 음악을 녹음·편집·믹싱하는 전문 프로그램. StemDeck의 화면이 이걸 흉내 냄.
FastAPI파이썬으로 웹 API를 빠르게 만드는 프레임워크. 요청을 받는 "접수 창구".
SSE (Server-Sent Events)서버가 브라우저로 한 방향 실시간 소식을 흘려보내는 기술. 라디오 생중계.
세마포어 (Semaphore)동시 사용 인원을 제한하는 신호등. StemDeck은 무거운 잡을 "한 번에 하나만" 통과시킴.
서브프로세스 (Subprocess)메인 프로그램이 띄우는 별도 프로그램. 취소·충돌 시 그것만 따로 죽일 수 있음.
워치독 (Watchdog)"너무 오래 조용하면 멈춘 것"으로 보고 작업을 정리하는 감시견 스레드.
Tauri웹 화면을 러스트 껍데기로 감싸 가벼운 데스크톱 앱으로 만드는 도구. Electron보다 가벼움.
WebView주소창·탭이 없는 "알맹이 브라우저". OS에 이미 깔린 걸 빌려 씀.
Web Audio API브라우저가 직접 오디오를 처리·분석하는 기술. 볼륨·VU 미터·믹싱을 담당.
VU 미터소리 크기를 실시간 막대로 보여주는 계기. 분석기 노드의 RMS로 계산.
BPMBeats Per Minute. 1분당 박자 수 = 곡의 빠르기. librosa가 자동 추정.
LUFSLoudness Units Full Scale. 사람이 느끼는 체감 음량의 방송 표준(BS.1770) 단위.
uv러스트로 만든 초고속 파이썬 패키지 관리자. pip·가상환경을 대체.
yt-dlp유튜브 등에서 음원·영상을 받아 오는 커맨드라인 도구.
FFmpeg오디오·영상 포맷 변환과 믹싱의 만능 도구. amix로 여러 트랙을 한 파일로 합침.
CUDA / MPS각각 NVIDIA GPU·애플 실리콘으로 AI 연산을 가속하는 기술. 없으면 CPU로 폴백(느림).
로컬 우선 (Local-first)클라우드 대신 내 기기에서 데이터·처리를 먼저 한다는 설계 철학.
CI (Woodpecker)코드가 바뀔 때마다 자동으로 테스트·빌드하는 시스템. Woodpecker는 셀프호스팅 가능한 오픈소스 CI.

11참고 링크

원본 저장소와, 이 프로젝트를 떠받치는 핵심 오픈소스들