본문으로 건너뛰기
5분 AI.
TRENDSHIFT MONTHLY #6 딥다이브 · 2026-10-23 분석

Strata 딥다이브
— 거대한 AI를 작은 그래픽카드에 나누어 담는 법

추론 엔진·앱

빠른 판단

무엇
MoE 가중치와 계산을 RAM·VRAM에 분담하고 로컬 API·데스크탑 앱으로 제공하는 추론 엔진
이럴 때
지원 모델을 소비자용 GPU에서 로컬 실행하며 메모리 계층·전문가 캐시·초안 검증 구성을 조정할 때
입력
지원 모델 파일·메모리 설정과 생성 요청
결과
로컬 API 또는 데스크탑 앱의 모델 응답
모델 전체를 VRAM에 올릴 수 없다면 계산과 데이터를 어떻게 나눌까요? Strata는 MoE 모델의 전문가를 CPU·RAM과 GPU·VRAM에 분산하고, 그 엔진을 Python API, React 화면, Tauri 앱으로 연결하는 로컬 추론 프로젝트입니다. 이 글은 설치 안내보다 메모리 계층, 프로세스 경계, 스트리밍, 성능 검증을 읽는 법에 초점을 맞춥니다. Niko1221/Strata · ⭐30,770 · 포크 3,282 · C++ · MIT · v0.2.2. 메타데이터는 2026-10-23 GitHub 기준, 구현 설명은 커밋 011c9e6 기준입니다.
목차
  1. 프로젝트 한줄 요약
  2. 왜 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석
  5. 디렉토리 구조 해부
  6. 학습 포인트 (기술별)
  7. 하드웨어 / 시스템 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한줄 요약

작은 챗봇 화면 뒤에 있는, 이기종 메모리와 계산의 분업

Strata는 Qwen3.8-Flash-Next 계열을 소비자용 하드웨어에서 실행하고, 로컬 API와 앱으로 제공하는 추론 엔진·제품 묶음입니다. README는 기본 모델을 1,250억 매개변수라고 소개합니다. 여기서 매개변수는 모델이 학습해 둔 숫자입니다. 숫자가 많을수록 저장 공간도 커지지만, MoE에서는 매 토큰마다 모든 전문가를 계산하지 않습니다.

Strata를 이해하는 핵심은 모델을 통째로 줄이는 것보다, 지금 필요한 가중치를 어디에 두고 어느 장치에서 계산할지 결정하는 데 있습니다. 양자화로 저장량을 줄이는 일과 CPU·GPU에 작업을 나누는 일은 서로 다른 최적화이며, 이 저장소는 둘을 함께 사용합니다.

용어부터
MoE — Mixture of Experts, 전문가 혼합 모델
여러 작은 계산 모듈인 전문가를 두고, 라우터가 입력마다 일부를 고르는 구조입니다. 기본 ModelGeometry에는 48개 층, 층마다 전문가 512개, 선택 수 10개가 적혀 있습니다. 따라서 (층, 전문가) 쌍은 총 24,576개지만, 한 토큰의 기본 경로에서는 층마다 10개씩 선택합니다. 이 값은 include/strata/core/geometry.hpp의 기본 형상이며, 가지치기된 Coder 등은 다릅니다.
전체를 이해하는 비유

거대한 주방의 조리법은 창고에, 자주 쓰는 재료는 조리대에 둡니다

SSD는 큰 창고, RAM은 주방의 선반, VRAM은 빠르지만 좁은 조리대입니다. GPU가 모든 조리법을 펼칠 수는 없습니다. 자주 선택되는 전문가를 조리대에 두고, 나머지는 CPU가 선반에서 계산하거나 필요한 부분을 GPU로 공급합니다.

손님이 메뉴를 바꾸면 자주 쓰는 재료도 달라집니다. 그래서 캐시는 대화의 사용 빈도를 따라 조정됩니다. 좋은 설계는 조리대만 크게 만드는 데서 끝나지 않고, 이동·계산·기다림을 함께 줄이는 것을 목표로 합니다.

사용자가 보는 세 가지 입구

입구실제 구성배울 수 있는 질문
데스크톱 앱apps/desktop의 Tauri + apps/host의 웹 UI·Node 호스트창을 닫을 때 엔진까지 어떻게 정리할까?
터미널strata.py, strata_cli/, strata_control/설치·시작·상태 조회를 어떻게 같은 제어 계층에 연결할까?
로컬 APIserve/server.py와 상주 C++ 엔진서로 다른 API 형식을 어떻게 하나의 생성 루프로 모을까?

API에는 /v1/chat/completions, /v1/messages, /v1/responses 처리 경로가 있습니다. 이는 요청·응답 형식의 호환성을 뜻합니다. OpenAI나 Anthropic의 원격 모델을 그대로 실행한다는 뜻은 아닙니다.

이미지 입력은 별도 인코더 strata-vision을 통해 임베딩으로 들어옵니다. 저장소에는 선택적인 이미지 생성 경로도 있지만, 이 글의 중심은 텍스트·이미지 입력을 받는 로컬 언어 모델 서빙입니다.

이 글을 읽고 얻을 것
모델 내부 수학을 전부 몰라도 시스템 경계부터 읽을 수 있습니다

먼저 HTTP 요청이 토큰 ID로 바뀌는 지점을 찾고, 다음으로 토큰 생성과 가중치 공급을 분리해 보세요. 마지막에 캐시와 GPU 커널을 읽으면, 복잡한 C++ 코드가 어느 문제를 풀고 있는지 훨씬 분명해집니다.

2왜 주목받는가

인기의 원인을 단정하지 않고, 관심을 끌 만한 설계를 근거와 함께 읽기

2-1. 큰 모델과 작은 VRAM 사이의 간격을 다룹니다

TrendShift Monthly #6 선정과 스타 30,770개는 이 글의 선정 근거입니다. 다만 스타 수만으로 사용률이나 성능을 증명할 수는 없습니다. 다음 세 가지는 README와 구현에서 읽어 낸 주목 요인에 대한 해석입니다.

  1. 메모리를 나누어 쓴다: 전문가를 전부 VRAM에 넣지 않고 RAM·CPU 계산과 결합합니다.
  2. 기존 도구에 연결한다: 여러 API 형식을 지원해 앱과 코딩 도구가 같은 로컬 엔진을 이용하게 합니다.
  3. 배포까지 묶었다: 엔진 외에도 하드웨어 감지, 모델 선택, 다운로드, 모니터링, 데스크톱 창을 제공합니다.

이 저장소의 차별점은 범용 모델 목록의 크기보다, 특정 모델 계열을 제한된 메모리에 맞추는 실행 경로와 배포 경험을 함께 설계했다는 점입니다.

2-2. 경쟁 도구와 비교할 때는 비교 축부터 고릅니다

아래 표는 성능 순위가 아닙니다. Strata에서 확인한 설계와 다른 선택지의 대표적인 용도를 나란히 놓은 표입니다. 실제 도입 시에는 각 제품의 공식 문서에서 필요한 모델과 기능의 지원 여부를 확인해야 합니다.

선택지비교할 관점Strata에서 확인한 장점·대가
llama.cpp범용 로컬 추론 엔진을 직접 조합하는 경우Strata는 특정 계열의 전문가 배치와 MTP·캐시 정책을 통합합니다. 대신 범용성보다 해당 모델의 형상에 강하게 결합합니다.
Ollama / LM Studio로컬 모델을 쉽게 관리·실행하려는 경우Strata는 자체 엔진과 하드웨어별 패키지를 제품으로 묶습니다. 기존 서버를 감지하는 코드도 있어 이들을 무조건 대체한다고 보기는 어렵습니다.
클라우드 API모델 계산을 외부 사업자에게 맡기는 경우Strata는 계산과 가중치를 로컬에 둘 수 있습니다. 대신 RAM, SSD, 드라이버, 엔진 운영을 사용자가 감당합니다.

소스 연결점도 있습니다. apps/host/server/inference.mjs의 detectBackend()는 Strata 작업자를 먼저 찾고, 다른 로컬 OpenAI 호환 서버도 식별합니다. C++ 엔진은 ggml의 CPU 백엔드와 일부 GPU 연산을 활용합니다. 독자 엔진과 외부 기술 재사용이 함께 존재합니다.

2-3. 빠르다는 주장은 조건과 함께 읽어야 합니다

README는 RTX 5070 12GB, Ryzen 5 7600, RAM 64GB에서 Q2_0 출력 약 94 tokens/s, 프롬프트 처리 약 2,650 tokens/s를 제시합니다. 이 수치는 README에 실린 프로젝트 측 측정값이며, 하드웨어·모델·설정에 따라 달라집니다.

표를 읽는 기준
프롬프트 처리량과 출력 속도는 다른 지표입니다
Prefill은 이미 주어진 많은 토큰을 읽는 단계, decode는 다음 토큰을 생성하는 단계입니다. 프롬프트 2,650 tokens/s와 출력 94 tokens/s를 같은 작업의 속도로 비교하면 안 됩니다. 첫 토큰까지의 시간에는 모델 적재와 대기 시간도 영향을 줍니다.

docs/DETAILS.md의 주요 성능 표에서 NVIDIA 수치는 엔진 0.1.26 측정이고, 별도 문단은 0.1.36 개선을 설명합니다. 현재 엔진 버전은 0.1.47이므로, 모든 표를 최신 바이너리의 보장값으로 읽으면 안 됩니다. bench/results/에는 하드웨어·버전별 결과가 있으니 비교 조건을 맞추는 연습에 적합합니다.

성능 비교의 비유

자동차 최고속도와 출퇴근 시간을 같은 숫자로 비교할 수 없듯, 토큰 처리량만으로 실제 대화 반응성을 판단할 수 없습니다. 모델 크기, 문맥 길이, 캐시 적중, 첫 실행 여부를 함께 적어야 비교가 성립합니다.

3기술 스택 전체 지도

선언된 버전, 잠금 파일의 버전, 실행에 필요한 도구를 구별하기

3-1. 백엔드: C++ 계산 엔진 + Python API + Node 제품 호스트

계층확인한 기술·버전근거와 역할
핵심 엔진C++20 · 엔진 0.1.47CMakeLists.txt: CMAKE_CXX_STANDARD 20, project(strata VERSION 0.1.47)
GPUCUDA / HIP / SYCL / MetalCUDA·HIP는 최상위 CMake 옵션, SYCL은 별도 하위 프로젝트, Metal은 metal/CMakeLists.txt
수치 연산 재사용llama.cpp / ggml 커밋 고정third_party/ggml/VERSION.txt와 CMake의 3cf03257f219afbe7334045ff7c6a06ac68c627d
API 서버Python 3.10+ · 표준 http.serverserve/server.py의 BaseHTTPRequestHandler, ThreadingHTTPServer; FastAPI를 쓰는 구조가 아닙니다.
프롬프트·이미지Jinja2 3.1.6 · Pillow 12.3.0requirements.txt; 템플릿 렌더링과 이미지 형식 변환
설치·상태 처리requests 2.34.2 · psutil 7.2.2requirements.txt; 다운로드와 시스템 상태 관련 의존성
제품 호스트Node.js ≥24.12.0 · ESMapps/host/package.json의 engines와 type: module; 앱 제어·API 중계
선택적 모니터Textual 8.2.8requirements-monitor.txt; 코어 서버와 분리된 터미널 화면

NumPy는 Python 버전에 따라 다르게 고정됩니다. requirements.txt는 Python 3.12 이상에 numpy==2.5.3, 3.11에 2.4.6, 그 미만에 2.2.6을 지정합니다. 같은 저장소라도 인터프리터 버전이 의존성 선택을 바꾼다는 사례입니다.

PyTorch는 일반 추론 경로의 필수 스택으로 쓰여 있지 않습니다. requirements-nvfp4-local.txt의 선택적 변환 도구에 torch==2.9.1 또는 Python 3.14 이상용 2.14.1, transformers==4.57.6, safetensors==0.7.0이 있습니다.

3-2. 프론트엔드와 데스크톱: 같은 웹 UI를 창으로 감쌉니다

기술의존성 선언잠금 파일에서 확인한 값
React / React DOM^19.1.0apps/host/package-lock.json: 둘 다 19.3.0
TypeScript^5.7.35.9.3
Vite^6.0.76.4.3
화면 보조KaTeX ^0.19.0, pdfjs-dist ^6.4.299, PrismJS 1.30.0이 행은 apps/host/package.json의 선언값입니다.
Tauri CLI2.12.3apps/desktop/package-lock.json도 2.12.3
Tauri Rust 크레이트tauri = "2"apps/desktop/src-tauri/Cargo.lock: 2.12.4
Rustedition 2021, rust-version 1.77apps/desktop/src-tauri/Cargo.toml의 최소 버전 선언입니다. 실제 빌드한 컴파일러 버전은 별도입니다.

의존성 파일의 허용 범위와 잠금 파일의 선택 결과를 구별하면, 문서의 버전 설명과 실제 빌드 환경 사이의 혼동을 줄일 수 있습니다. 예를 들어 React의 ^19.1.0을 보고 실제 설치 버전도 반드시 19.1.0이라고 단정하면 틀립니다.

apps/host/src/main.tsx는 createRoot()와 StrictMode로 앱을 시작합니다. apps/host/src/app/App.tsx의 AppShell()은 Chat·Setup·Serving·Monitor 등의 화면과 초기 설정 상태를 엮습니다. UI 소스는 apps/host/src/에 있습니다.

3-3. 인프라·빌드: 개발 환경과 배포 환경의 차이를 코드로 드러냅니다

.github/workflows/terminal-minimal-server.yml은 Python 3.11에서 런타임 의존성만 설치하고 가짜 엔진 점검과 serve/test_*.py 모음을 실행하도록 정의합니다. .github/workflows/terminal-portable-monitor.yml은 Windows·Linux와 Python 3.10·3.11 조합을 사용합니다.

.github/workflows/scripts-test.yml의 Node 22는 GitHub 보조 스크립트 테스트용입니다. 이것을 앱의 Node 요구 버전으로 읽으면 안 됩니다. .github/workflows/docker-images.yml은 수동 실행이며 push 입력 기본값이 false입니다. 워크플로 정의를 읽었다는 사실과 해당 실행이 통과했다는 사실도 구별해야 합니다.

초보자를 위한 읽기 순서
앱 0.2.2와 엔진 0.1.47은 모순이 아닙니다

배포 제품과 계산 엔진이 각각 버전을 가집니다. 어떤 문제를 재현할 때는 앱 버전, 엔진 버전, 모델 파일, GPU 백엔드를 함께 기록하세요. 이 네 항목이 다르면 같은 이름의 Strata라도 같은 실행 환경이 아닐 수 있습니다.

4아키텍처 심화 분석

요청을 받는 쪽, 계산하는 쪽, 가중치를 공급하는 쪽을 따로 보기

아래는 설치형 앱의 주요 경로를 단순화한 구조입니다. CLI로 직접 서버를 시작하면 Tauri와 Node 호스트를 거치지 않는 경로도 있습니다. 포트는 실행 방식과 설정에 따라 달라지므로 서버·앱·API 중계의 주소를 구별해야 합니다.

[사용자] | v [Tauri 창: apps/desktop/src-tauri/src/main.rs] | host_command() / start_host() (Windows·macOS) v [React 화면] <-- HTTP --> [Node 호스트: apps/host/server/index.mjs] | +---------+--------------------+ | 제어 | API v | [createControl() / runCli()] | | | v | [strata_control/runtime.py] | | 서버 시작·종료 | nativeGateway(): HTTP +---------+--------------------+ v [외부 API 클라이언트] --> [serve/server.py] | 요청 정규화 / 토큰화 / 대기·취소 | stdin: GEN ... / GENI ... | stdout: T ... / DONE ... v [상주 C++ 엔진] | 라우팅 / 사전 채움 / 생성 / 검증 +----------+----------+ v v [GPU + VRAM] [CPU + RAM] 공통 계산·캐시 전문가 계산·호스트 데이터 \ / +------ [SSD] ------+ 모델 / n-gram / 부족한 전문가

4-1. 패턴 ① 어댑터와 프로세스 분리: API 형식과 계산을 분리합니다

serve/frontend.py의 openai_to_messages()와 anthropic_to_messages()는 서로 다른 요청을 메시지·도구·템플릿 인자로 정규화합니다. 예를 들어 OpenAI의 developer 역할은 system으로 바뀌고, Anthropic의 tool_use 블록은 내부 도구 호출 표현으로 변환됩니다.

이후 Service.encode_prompt()가 템플릿과 토크나이저를 이용해 토큰 ID를 만듭니다. Engine 프로토콜은 계산 장치 대신 generate()라는 동작을 약속합니다. 아래는 실제 인터페이스의 핵심 부분입니다.

# serve/server.py — API 계층이 엔진에 요구하는 계약
class Engine(Protocol):
    max_context: int
    def generate(self, ids: list[int], max_new: int,
                 sampling: dict, cancel: threading.Event) -> Iterator[int]: ...

StrataEngine은 C++ 실행 파일을 --serve로 한 번 시작한 뒤 표준 입출력 파이프로 재사용합니다. 매 질문마다 수십 GB의 가중치를 다시 적재하지 않는 구조입니다. MockEngine은 같은 계약으로 미리 정한 토큰을 돌려줘 API 동작을 GPU 없이 검사할 수 있게 합니다.

# 단일 요청용 파이프 프로토콜의 개념도 — 숫자는 설명용입니다
Python -> C++ : GEN 16 101 202 303
C++    -> Python : T 404
C++    -> Python : T 505
C++    -> Python : DONE ...
# 실제 요청에는 샘플링 키, 이미지 임베딩, 배치용 확장이 더 붙을 수 있습니다.

이 분리는 엔진 장애를 API 계층이 감지·복구할 여지를 주지만, 파이프 응답 대기, 비정상 종료, 취소, 자식 프로세스 정리가 새 책임으로 생깁니다. serve/lifeline.py의 popen()은 부모 종료 뒤 자식이 남는 문제를 다룹니다.

데스크톱에서도 같은 원리가 반복됩니다. Rust의 host_command()는 Node 실행 파일과 apps/host/server/index.mjs를 연결하고 STRATA_BIND=127.0.0.1을 지정합니다. 화면과 호스트의 수명, 호스트와 Python 작업자의 수명, 작업자와 C++ 엔진의 수명을 각각 관리합니다.

4-2. 패턴 ② 계층형 캐시: 저장 공간과 교체 정책을 분리합니다

ExpertCache는 전문가 데이터를 담는 VRAM 슬롯과 (layer, expert)를 슬롯으로 바꾸는 상주 표를 관리합니다. slot_of()는 범위를 검사해 슬롯 번호 또는 kNotResident를 반환합니다.

// src/core/expert_cache.cpp — admit()의 마지막 부분 발췌
if (next_free_ >= slots_) return kNotResident;
residency_[at] = (int32_t) next_free_;
return (int32_t) next_free_++;

여기에는 LRU 퇴출 코드가 없습니다. 빈자리가 없으면 등록을 거절합니다. set_per_layer_admission()을 켠 경우에는 층마다 슬롯 범위를 나눠, 앞쪽 층이 전역 슬롯을 먼저 독점하는 문제를 줄입니다. 이 역시 교체 정책과는 별개입니다.

src/core/expert_source.cpp의 expert_hit_run()은 선택된 전문가가 상주하면 GPU 작업으로 넣습니다. 상주하지 않더라도 빈 슬롯이 있으면 admit()과 fill_slot()로 공급합니다. 복사와 커널을 같은 스트림에 넣어 복사 완료 뒤 계산하도록 순서를 정합니다.

반면 대화에 맞춰 전문가를 바꾸는 일은 src/program/generate.cpp의 상위 적응 로직이 담당합니다. 코드의 기본 설정은 adapt_every=4, adapt_decay=0.7, adapt_min_gain=1.5입니다. 실행 옵션과 백엔드에 따라 적용 경로는 달라질 수 있습니다.

단일 생성 경로의 adapt 람다는 사용 빈도가 높은 비상주 전문가와 낮은 상주 전문가를 짝짓습니다. apply_pending 람다는 복사 완료 이벤트를 확인한 뒤 상주 표를 갱신합니다. 복사를 요청한 순간과 새 데이터를 사용할 수 있는 순간은 다릅니다.

[라우터가 고른 전문가] | +-- VRAM 상주 --------> GPU 계산 | +-- 비상주 + 빈 슬롯 -> 복사 후 GPU 계산 | +-- 비상주 + 슬롯 없음 | +-- CPU 계산 / 설정에 따른 PCIe·보조 GPU 경로 [사용 빈도 관찰] -> [교체 후보 선정] -> [비동기 복사] | [완료 확인 후 상주 표 공개]
왜 역할을 나눌까요?

책장의 칸 번호를 관리하는 일과 어떤 책을 꺼낼지 고르는 일은 다릅니다. ExpertCache는 책장과 위치표에 가깝고, 상위 적응 로직이 사서에 가깝습니다. 그래서 “캐시가 적응한다”는 설명을 읽고 admit()에서 LRU만 찾으면 구현을 오해하게 됩니다.

docs/DETAILS.md는 RAM에 전문가를 두는 대표 구성을 설명하지만, 소스의 FileExpertSource와 저메모리 경로는 부족분을 파일에서 읽는 경우도 다룹니다. “모든 전문가가 언제나 RAM에 고정된다”는 문장으로 일반화하면 안 됩니다.

4-3. 패턴 ③ 추측 실행과 검증: 초안은 제안하고 본 모델이 확정합니다

한 번에 한 토큰만 계산하면 같은 가중치를 여러 번 읽게 됩니다. MTP 초안이나 이전 문맥에서 찾은 후속 토큰을 묶어 제안하고, 본 모델로 검증하면 한 번의 검증에서 여러 토큰을 확정할 기회가 생깁니다.

include/strata/spec/draft_policy.hpp와 src/spec/draft_policy.cpp의 DraftPolicy::choose()는 예상 확정 토큰 수 ÷ 실행 비용을 비교합니다. 기본 여유율 margin=0.03을 두어 lookup의 기대 효율이 MTP보다 충분히 나을 때 선택합니다.

# DraftPolicy가 사용하는 lookup 기대량을 풀어 쓴 학습용 계산
q = 0.8          # 앞 토큰이 맞았다는 조건에서 다음 초안도 맞을 확률의 추정값
k = 3            # 초안 개수
expected = 1 + q + q**2 + q**3   # 2.952 토큰
rate = expected / 12            # 한 라운드 12ms라고 가정하면 0.246 토큰/ms

DraftPolicy::observe()는 실제 라운드 시간과 수락 결과를 반영합니다. 시간 추정의 EMA 가중치는 0.1, MTP 토큰 추정은 0.05, lookup 관측치 감쇠는 0.97입니다. 이 값들은 모델 품질 점수가 아니라 실행 전략의 통계입니다.

실제 src/program/generate.cpp의 생성 루프에는 policy.choose(), Verifier::run(), Verifier::commit(), policy.observe()가 이어집니다. 초안을 검증한 뒤 수락한 접두부를 확정합니다. 단지 제안이 길다는 이유로 그대로 출력하지 않습니다.

src/spec/controller.cpp에도 비슷한 비용 모델이 있지만, 위 생성 루프는 DraftPolicy를 사용합니다. 비슷한 역할의 클래스가 여럿 있다면 호출 위치로 실제 사용되는 정책을 구별해야 합니다.

4-4. 패턴 ④ 스트리밍 상태기계와 역압: 조각을 정확히 읽고 천천히 보낼 줄 압니다

네트워크 조각은 문장이나 태그의 끝에서 끊긴다는 보장이 없습니다. serve/frontend.py의 OutputParser.feed()는 일부만 도착한 제어 태그를 버퍼에 남기고, 추론 내용·일반 답변·도구 호출을 이벤트로 구분합니다.

# 문자열 분할의 예시: 첫 조각만으로 끝 태그라고 확정할 수 없습니다.
조각 1: 생각 중입니다.</thi
조각 2: nk>답변입니다.
# 파서는 완성된 </think>를 확인한 뒤 상태를 전환해야 합니다.

Node의 apps/host/server/native-gateway.mjs에 있는 nativeGateway()는 작업자 응답을 중계합니다. res.write(chunk)가 false면 once(res, 'drain')을 기다립니다. 느린 클라이언트 앞에서 출력 버퍼만 계속 늘리지 않도록 하는 역압입니다.

또한 연결이 끝나면 AbortController로 상류 요청을 취소합니다. 이 게이트웨이는 사용량을 관측하면서 원래 바이트 조각을 전달합니다. 모델 출력 의미를 해석하는 Python 파서와 HTTP 흐름을 조절하는 Node 중계기의 책임을 구별해 보세요.

빠른 추론 시스템은 계산만 최적화하는 것이 아니라, 복사 완료·요청 취소·출력 대기처럼 기다림이 생기는 모든 경계를 명시합니다.

직접 읽을 소스
네 패턴을 확인하는 고정 커밋 링크

API와 엔진 프로토콜 · 슬롯 관리 · 적응·생성 루프 · 초안 정책 · 스트리밍 중계

5디렉토리 구조 해부

저장소 루트부터 엔진·서버·앱의 역할을 따라가기

C++ 엔진 소스는 src/, 핵심 실행 코드는 src/core/, 공개 헤더는 include/strata/에 있습니다. 아래 트리와 본문의 파일 경로는 모두 저장소 루트 기준입니다.

Strata/ ├── CMakeLists.txt C++ 엔진과 백엔드 옵션 ├── requirements*.txt Python 런타임·빌드·선택 기능 ├── strata.py 터미널 명령 진입점 ├── strata_cli/ 명령 해석과 사용자 상호작용 ├── strata_control/ 하드웨어·모델·실행·업데이트 제어 ├── src/ │ ├── artifact/ GGUF 검사 도구 진입점·양자화 처리 │ ├── core/ 가중치·전문가·세션·GPU 실행 관리 │ ├── kernels/ CPU·CUDA 계산 커널과 비교 검사 │ ├── prefill/ 프롬프트 일괄 계산·행렬 연산 │ ├── program/generate.cpp 생성·서빙·적응 정책을 연결하는 코드 │ ├── spec/ 초안 후보·정책·suffix lookup │ ├── platform/ OS별 메모리·파일 처리 │ └── ngram/ PLE 테이블 읽기 ├── include/strata/ 엔진 계약·형상·헤더 구현 ├── metal/ Apple GPU 엔진 ├── sycl/ Intel GPU 포트와 도구 ├── serve/ Python HTTP API·파서·웹 페이지·테스트 ├── apps/ │ ├── host/src/ React 화면·상태·컴포넌트 │ ├── host/server/ Node API·중계·앱 제어 │ └── desktop/src-tauri/ Rust 데스크톱 셸 ├── tools/ 모델 준비·검사·비전 인코더 등 ├── packaging/ 엔진·앱·Terminal 패키징 ├── docker/ 배포 이미지·실행 진입점·Compose ├── tests/terminal/ CLI·Control 계층 테스트 ├── bench/results/ 장치·버전별 측정 기록 ├── docs/ 설치·동작 원리·제약·측정 설명 ├── third_party/ 외부 코드·고정 버전 정보 └── ref/ 참조 자료

5-1. 파일명과 실제 구현 위치가 다를 수 있습니다

src/artifact/gguf_reader.cpp는 주로 CLI 진입점이고, 리더의 실제 구현은 include/strata/artifact/gguf_reader.hpp에 있습니다. 앞 파일만 읽고 “GGUF 파서가 없다”고 결론 내리면 안 됩니다. 클래스 정의와 호출 위치를 함께 검색하는 습관을 들이세요.

반대로 src/program/generate.cpp는 16,697줄, serve/server.py는 8,486줄입니다. 파일이 크다는 사실만으로 품질을 단정할 수는 없지만, 초보자는 처음부터 완독하기보다 policy.choose, slot_of, encode_prompt처럼 호출을 기준으로 좁혀 읽는 편이 좋습니다.

5-2. 직접 센 코드 규모

확장자 묶음파일 수물리적 줄 수
C/C++·헤더696280,585
CUDA·CUDA 헤더9055,226
Metal·Objective-C++276,673
Python676177,151
TypeScript·TSX24117,796
JavaScript·MJS·CJS33141,397
Rust52,716
Shell·PowerShell·Batch603,955
CSS149,899
위 항목 합계2,140595,398

집계는 파일을 읽어 줄바꿈 바이트 \n를 센 결과입니다. .git, third_party, ref, node_modules 디렉토리는 제외했습니다. 주석·빈 줄·테스트·벤치마크·픽스처·백엔드별 중복·생성된 헤더는 포함하므로, 고유 구현량이나 실행 코드 줄 수와는 다릅니다.

C/C++ 묶음은 .cpp .cc .c .h .hpp .hxx .cxx, CUDA는 .cu .cuh 기준입니다. CMake·HTML·JSON·문서는 합계에 넣지 않았습니다. “전체 59.5만 줄”은 이 범위를 전제로 읽어야 합니다.

6학습 포인트 (기술별)

파일을 읽고 끝내지 않고, 설계 판단을 자기 말로 설명하기

6-1. C++: 형상 검증과 자원 수명

ModelGeometry는 임베딩 폭·층 수·전문가 수 같은 모델 형상을 표현합니다. 모델 파일을 읽는 것과 해당 커널로 안전하게 계산할 수 있는지는 별개입니다. GgufFile과 check_architecture()를 따라가며 파일 형식 검증과 아키텍처 검증을 구별해 보세요.

src/artifact/gguf_reader.cpp의 검사 모드는 텐서를 오프셋 순으로 정렬한 뒤, 계산한 바이트 수가 다음 텐서와의 간격 안에 들어오는지 확인합니다. 이때 오프셋은 데이터 시작점에 대한 상대값입니다. 오프셋 하나와 길이를 비교하는 실수가 왜 위험한지 작은 숫자로 확인할 수 있습니다.

# 파일을 실행하지 않는 손계산 예시
현재 텐서 오프셋 = 96
다음 텐서 오프셋 = 256
현재 텐서 데이터 = 144 바이트
사용 가능한 간격 = 256 - 96 = 160 바이트
패딩 = 160 - 144 = 16 바이트
# 데이터 길이와 비교할 대상은 256 자체가 아니라 간격 160입니다.

자원 수명은 src/program/generate.cpp의 PreLaunchOff 같은 지역 정리 객체에서도 볼 수 있습니다. 소멸자에서 훅을 해제하고 메모리를 반환합니다. 실습으로 함수가 중간에 실패하는 반환 경로를 골라, 어떤 자원이 자동 정리되는지 표로 정리해 보세요.

6-2. GPU·운영체제: 비동기 작업에서 “완료”의 의미

용어부터
고정 메모리, 스트림, 이벤트
고정 메모리는 GPU 전송 등에 쓰려고 호스트 페이지를 이동·회수하지 못하도록 잡아 두는 메모리입니다. 스트림은 GPU 작업 순서의 흐름이고, 이벤트는 특정 지점까지 끝났는지 확인하는 표식입니다. 고정 메모리는 GPU 전용 메모리와 다르며, 무제한으로 고정하면 시스템의 여유가 줄어듭니다.

expert_hit_run()의 같은 스트림 안에서는 복사와 계산의 순서를 이용합니다. 다른 스트림을 쓰는 적응 경로에서는 이벤트와 상주 표 공개 시점을 맞춰야 합니다. 실습으로 “복사 요청 → 완료 → 상주 표 갱신 → 계산” 네 사건을 종이에 놓고, 순서를 바꾸면 어떤 오래된 데이터를 읽을 수 있는지 설명해 보세요.

src/platform/memory.cpp의 Windows lock_resident()는 작업 집합을 조정한 뒤 VirtualLock()을 호출합니다. ExpertCache::shrink()·grow()의 세그먼트 방식은 CUDA 전용 조건을 갖습니다. 같은 인터페이스가 있다고 모든 백엔드가 같은 메모리 기능을 제공하는 것은 아닙니다.

6-3. Python: 외부 형식을 내부 계약으로 바꾸기

openai_to_messages()와 anthropic_to_messages()에 같은 의미의 요청을 하나씩 적어 보세요. 역할, 텍스트, 도구 이름, 도구 인자가 어떤 내부 값으로 모이는지 비교하면 어댑터 패턴이 보입니다. 이후 ChatTemplate.render()와 Service.encode_prompt()를 연결합니다.

serve/test_context_overflow.py는 문맥 초과를 실제 GPU 없이 검사하는 예입니다. 프롬프트 자체가 넘치면 400 오류를 내고, 기본 설정에서는 출력 상한만 남은 공간으로 줄입니다. 실습으로 “입력이 넘침”과 “입력은 맞지만 출력 예산이 큼”을 별도 사례로 적어 보세요.

6-4. TypeScript·React: 초기화, 상태, 화면을 분리하기

apps/host/src/app/App.tsx의 AppShell()은 useStore()로 준비·설정 상태를, useLocation()으로 화면 위치를 읽고 bootOnce()를 호출합니다. 키보드 이벤트 등록에는 정리 함수가 붙습니다. 상태 조건을 따라가며 첫 실행 화면이 언제 열리는지 읽는 연습에 좋습니다.

실습 산출물은 “준비 전 / 설정 미완료 / 설정 완료” 세 상태의 화면 표로 충분합니다. JSX를 모두 베끼기보다 어떤 상태가 어떤 화면을 결정하는지 설명해 보세요. StrictMode가 선언되어 있다는 사실만으로 초기화의 모든 중복 문제가 해결됐다고 결론 내리지는 마세요.

6-5. Node·Rust·배포: 프로세스도 제품의 일부입니다

nativeGateway()는 느린 클라이언트와 연결 종료를 다룹니다. Windows·macOS에서 Rust의 start_host()·stop_host()는 창과 호스트의 수명을 다룹니다. 실습으로 “사용자가 창을 닫음”부터 “GPU 메모리 반환”까지 필요한 종료 신호를 화살표로 그려 보세요.

strata_control/signing.py는 업데이트 피드·엔진 서명의 verify_bytes()와 Ed25519 검증을 담습니다. 학습할 것은 독자 암호 구현을 따라 만드는 일보다, 신뢰할 공개 키와 검사할 바이트를 어디서 얻는가라는 경계입니다. 데스크톱 설치 파일용 서명과 엔진 컴포넌트 서명도 구별합니다.

가장 좋은 학습 산출물은 파일 목록보다, 입력·출력·실패·정리 책임을 한 장에 연결한 계약 지도입니다.

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

문서상 시작 조건과, 실제로 여유 있게 돌리는 조건은 다릅니다

아래 요구사항은 커밋 011c9e6의 README와 장치별 문서 기준입니다. 모델·메모리·백엔드에 따라 달라지는 세부 제한도 함께 확인해야 합니다.

항목문서 기준해석할 때의 조건
메모리 시작점RAM + VRAM 합계 최소 32GB가장 작은 변형을 포함한 시작 기준입니다. 모든 모델·문맥 길이에 충분하다는 뜻은 아닙니다.
NVIDIARTX 20·30·40·50, README 권장 VRAM 12GB 이상CUDA 13 패키지는 드라이버 580 이상을 안내합니다. 더 오래된 카드·드라이버는 CUDA 12 경로를 확인합니다.
AMDRX 6800 이상, Radeon AI PRO R9700 등RDNA 세대별 엔진 패키지를 구별합니다. RX 6000 패키지는 빌드됐으나 해당 릴리스에서 실카드 미검증입니다.
IntelArc · Linux 실험 경로별도 SYCL 프로젝트입니다. Windows 네이티브 지원으로 일반화하면 안 됩니다.
MacApple Silicon M1 이상 · macOS 15 이상통합 메모리를 RAM과 VRAM으로 중복 합산하면 안 됩니다. 메모리 상주 한도가 별도로 작용합니다.
디스크README 약 80GB 여유 · SSD 권장모델에 따라 다운로드·준비 파일·전문가 사본이 더 필요합니다. Gyro-M 다운로드만 해도 92GB로 안내됩니다.
운영체제Windows 10/11 · Linux · macOS장치별 드라이버와 패키지 지원 범위까지 함께 확인해야 합니다.
CPU배포용 x86 엔진은 AVX2 기준STRATA_ISA_FLOOR의 AVX·SSE4.2 경로는 실험적 별도 빌드입니다. Apple Silicon은 별도 Metal 경로입니다.

7-1. 모델 선택표는 RAM 예산을 읽는 출발점입니다

모델·크기README의 메모리 수치알아둘 차이
Gyro-S27.6GB · 합계 32GB 등급다운로드는 58.5GB입니다. 사용 메모리와 파일 크기가 다릅니다.
Swift IQ2_XS39.2GB · 합계 40GB 등급시스템·문맥·이미지 버퍼 여유까지 따져야 합니다.
IQ3_XXS47.0GB · 합계 48GB 등급입력 길이와 GPU 캐시 배분에 따라 속도가 달라집니다.
IQ3_S54.8GB · 합계 64GB 등급문서의 “64GB면 모든 크기”라는 짧은 문구를 모든 고비트 변형까지 넓혀 읽지 마세요.
큰 Unsloth 변형UD-IQ4_XS 약 72GB RAM, Q8_0 약 136GBREADME는 96GB 이상 범주에서 소개하며, 부족하면 SSD 읽기로 느려질 수 있다고 설명합니다.

RAM과 VRAM을 더한 숫자는 모델 선택의 대략적인 출발점이며, 서로 다른 메모리의 속도와 예약 공간까지 더해 주는 보증서가 아닙니다. strata_control/gpu_fit.py도 DENSE_GB=5.0, SYSTEM_ROOM_GB=10.0, 추가 분할 카드 비용 2.0GB처럼 별도 여유를 계산합니다. 이는 추천용 근사치이며 엔진의 모든 실제 할당량과 같지는 않습니다.

7-2. Mac·이미지·여러 GPU는 별도로 계산합니다

docs/MAC.md는 Q2_0의 상주 실행 권장을 통합 메모리 64GB부터, IQ3_S는 96GB부터로 설명합니다. 더 작은 Mac은 SSD에서 전문가를 읽는 경로가 있으며, 문서상 32~48GB Mac의 기본 설정은 MTP 초안 계층을 생략합니다. 96GB 이상 Mac의 SSD 스트리밍 설정은 MTP를 유지하고 --spec 3을 사용합니다. PC용 합계 메모리 표를 Mac에 그대로 적용하지 않는 이유입니다.

이미지 입력 인코더도 메모리를 사용합니다. docs/DETAILS.md는 GPU 이미지 인코더에 약 1.4GB VRAM을 안내하고, NVIDIA·AMD에서는 VRAM 24GB 미만일 때 CPU 인코더가 기본이라고 설명합니다. 이는 장치·설정에 따른 문서 기준입니다.

여러 GPU는 같은 제조사 안에서 나누는 경로입니다. strata_control/gpu_fit.py의 BACKEND_VENDOR는 CUDA·HIP·SYCL·Metal을 제조사와 연결합니다. NVIDIA와 AMD의 VRAM을 하나의 모델에 자유롭게 합치는 구조로 설명하면 안 됩니다.

문구보다 세부 조건을 우선하세요
“어떤 소비자 하드웨어에서나”는 무조건 실행 보장이 아닙니다

커밋 011c9e6의 README는 RX 6000용 엔진이 빌드됐지만 실제 카드에서 검증되지 않았음을 명시합니다. Intel 문서에는 Linux·실험 지원 및 일부 이미지 경로의 제약이 있습니다. Mac 소스 빌드는 컴파일 도구가 필요하지만, 미리 빌드된 앱·Terminal 경로는 그 도구가 필요 없다고 구분합니다.

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

설치·모델 다운로드 없이도 할 수 있는 다섯 가지 소스 독해 과제

아래 과제는 설치나 모델 다운로드 없이 읽기·검색·줄 수 집계·손계산만으로 진행할 수 있습니다. src/ 등의 구현을 읽고 결과를 별도 학습 노트에 정리해 보세요.

과제 1 · 입문 · 30~45분

요청 하나가 토큰 ID가 되기까지 추적하기

목표: 아래 JSON의 messages가 엔진에 전달되기까지 거치는 함수를 찾습니다.

{
  "model": "학습용-모델-이름",
  "messages": [{"role": "user", "content": "캐시를 쉽게 설명해 줘"}],
  "max_tokens": 32,
  "stream": true
}

읽을 곳: make_handler()의 do_POST(), openai_to_messages(), Service.encode_prompt(), Service.run(), StrataEngine.generate()입니다. JSON은 호출 흐름을 읽기 위한 예시입니다.

완료 기준: 각 단계의 입력·출력 자료형을 적고, “어느 단계부터 API의 역할 이름 대신 토큰 ID를 다루는가?”에 파일·함수명으로 답합니다.

과제 2 · 중급 · 45~60분

작은 캐시를 손으로 시뮬레이션하기

목표: 슬롯 관리와 교체 정책의 차이를 직접 확인합니다. 전문가 수나 층 수는 실제 모델 대신 작은 장난감 값으로 둡니다.

# 표기: (층 번호, 전문가 번호), 전역 슬롯은 3개
요청: (0,0), (0,1), (0,2), (1,0), (1,0), (1,0)
# ExpertCache::admit()의 전역 경로: 빈 슬롯만 등록, 퇴출 없음
처음 3개: 슬롯을 채움
이후 3개: (1,0)은 계속 등록 거절
# “자주 요청했으니 자동 퇴출”은 이 함수의 규칙에 없습니다.

읽을 곳: slot_of(), admit(), layer_slot_range(), src/program/generate.cpp의 적응 람다입니다.

완료 기준: 요청별 적중·등록·거절 표를 만들고, 층별 할당을 켰을 때 결과를 한 번 더 계산합니다. “슬롯 할당을 바꾸는 것”과 “이미 찬 슬롯을 교체하는 것”을 따로 설명하면 완료입니다.

과제 3 · 중급 · 45~60분

스트리밍 태그가 끊어지는 모든 위치 생각하기

목표: </think>를 두 조각으로 나누는 위치를 모두 적고, 첫 조각에서 화면에 내보낼 문자와 보류할 문자를 구분합니다.

읽을 곳: OutputParser._hold(), feed(), finish()와 serve/test_parser_hold.py입니다. 이 테스트 파일은 겹치는 접두부, 실제 태그의 분할 위치, 임의 조각 크기를 다룹니다.

완료 기준: 정상 종료 태그, 일반 문장, 코드 블록 안 태그처럼 최소 세 종류의 예시를 만들고, 단순 문자열 치환만으로 잘못 처리할 수 있는 이유를 적습니다. 테스트 코드가 다루는 사례와 실제 테스트 실행 결과도 구별해 적습니다.

과제 4 · 고급 · 60~90분

더 긴 초안이 오히려 느린 조건 계산하기

목표: MTP가 평균 2.5토큰을 10ms에 확정한다고 가정합니다. lookup이 세 토큰을 제안할 때 수락률 q=0.8, 라운드 비용 12ms와 9ms를 각각 비교합니다.

힌트: lookup 기대량은 1 + q + q² + q³ = 2.952입니다. 비교 기준은 (2.5 / 10) × 1.03 = 0.2575 토큰/ms입니다. 12ms일 때 약 0.246, 9ms일 때 약 0.328이므로 같은 제안도 선택 결과가 달라집니다.

읽을 곳: DraftPolicy::choose(), cost_ms(), observe()입니다. 실제 정책은 관측 부족·오래된 비용 추정에 대한 탐색 분기도 갖습니다.

완료 기준: 수락률과 비용을 바꾼 비교 표 여섯 행을 만들고, 정책이 초안의 길이보다 기대 효율을 보는 이유를 설명합니다. 이 손계산 값은 실제 Strata 벤치마크 수치가 아닙니다.

과제 5 · 고급 · 60~90분

벤치마크 보고서의 비교 가능성 검토하기

목표: bench/results/의 보고서 두 개를 골라 비교 조건을 표로 만듭니다. 측정하지 않고 기존 기록의 조건만 읽습니다.

기록할 열: GPU·VRAM, CPU·RAM, 엔진 버전, 모델 양자화, 문맥·프롬프트 길이, 캐시 상태, MTP 여부, prefill·decode 구분, 반복 횟수입니다.

완료 기준: 직접 비교 가능한 항목과 조건이 달라 결론을 보류할 항목을 적습니다. 빠르다는 결론보다 “이 차이가 GPU 때문인지 모델·설정 때문인지 분리 가능한가?”를 먼저 판단합니다.

경로를 찾을 때 쓸 수 있는 읽기 전용 명령입니다. 저장소 루트에서 실행하는 예시이며, 이 명령은 엔진·설치 프로그램을 실행하지 않습니다.

rg -n 'openai_to_messages|encode_prompt|class StrataEngine' serve
rg -n 'slot_of|ExpertCache::admit|layer_slot_range' src/core/expert_cache.cpp
rg -n 'policy.choose|policy.observe|auto adapt' src/program/generate.cpp
wc -l serve/server.py src/program/generate.cpp

실습의 완료 기준을 “실행됐다”보다 “어느 코드가 어떤 약속을 지키는지 설명할 수 있다”로 잡으면, GPU 없이도 설계를 깊게 배울 수 있습니다.

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

주 4~6시간, 여섯 주 동안 하나의 요청을 끝까지 따라가기

이 로드맵은 Strata를 새로 구현하는 계획이 아니라, 시스템 프로그래밍의 기본 개념을 이 저장소의 실제 경계에 연결하는 읽기 계획입니다. 처음 두 주는 GPU 지식이 없어도 시작할 수 있습니다.

주차배울 개념·읽을 소스주별 산출물
1주차HTTP·JSON·역할·토큰. serve/frontend.py의 두 요청 어댑터와 ChatTemplate같은 대화를 두 API 형식으로 적고, 공통 표현으로 바뀌는 표
2주차프로세스·파이프·취소. Engine, StrataEngine, MockEngine, serve/lifeline.py정상·취소·비정상 종료 세 경우의 시퀀스 그림
3주차C++ 자원 수명·바이너리 형식·메모리 매핑. GgufFile, ModelGeometry, lock_resident()오프셋·길이·패딩 계산표와 자원 소유자 목록
4주차캐시·CPU/GPU 분업·스트림·이벤트. ExpertCache, ExpertSource, expert_hit_run()작은 캐시 손계산과 복사 완료 전후의 상주 표 상태
5주차추측 실행·기대값·EMA·검증. DraftPolicy, SuffixDrafter, Verifier수락률·실행 비용에 따른 선택 표와 그 한계
6주차제품 통합·역압·배포. nativeGateway(), Rust 호스트 수명, 두 Dockerfile, CI앱 종료 흐름·요청 흐름·데이터 보존 위치를 합친 한 장의 지도

배경 지식은 이 순서로 보충하세요

  1. 기초 자료형·파일: 배열, 바이트, 정수 폭, 오프셋을 익힙니다. 주소와 데이터가 다르다는 점이 출발점입니다.
  2. 운영체제: 프로세스, 스레드, 가상 메모리, 페이지 캐시를 익힙니다. RAM에 “있다”는 말의 여러 의미를 구별합니다.
  3. 동시성: 락, 취소 신호, 작업 완료 통지를 익힙니다. CPU가 요청을 보낸 시점과 GPU가 끝낸 시점을 구별합니다.
  4. 추론: 토큰, prefill·decode, 양자화, MoE, KV 캐시를 익힌 뒤 MTP·lookup을 읽습니다.
  5. 검증: 같은 입력·설정·환경으로 비교하는 법과, 처리량·지연·수치 차이를 따로 기록하는 법을 익힙니다.

전체 파일을 순서대로 완독하기보다, 매주 하나의 질문을 정하고 그 질문에 답하는 호출 경로를 끝까지 따라가세요. 예를 들어 “클라이언트가 끊기면 계산은 누가 멈추는가?” 하나만으로도 웹·Python·엔진의 경계를 함께 배울 수 있습니다.

공부가 막힐 때

도시 전체의 도로명을 외우기보다 집에서 도서관까지 한 번 걸어 보는 편이 빠릅니다. 첫 번째 요청의 길을 익히고, 두 번째에는 취소 경로, 세 번째에는 캐시 실패 경로로 돌아가 보세요. 같은 장소를 다른 질문으로 다시 읽을 때 구조가 기억에 남습니다.

10핵심 키워드 사전

이름이 비슷해도 보관하는 데이터와 책임은 다릅니다
용어쉬운 설명
추론학습된 가중치로 새 입력의 다음 토큰을 계산하는 과정입니다. 이 저장소의 중심은 모델 학습보다 실행과 서빙입니다.
토큰모델이 다루는 텍스트 조각의 단위입니다. 한국어 한 글자나 영어 한 단어와 항상 일치하지 않습니다.
가중치학습 결과로 정해진 숫자 배열입니다. 전문가 캐시가 보관하는 핵심 데이터입니다.
텐서숫자를 여러 축으로 정리한 배열입니다. 폭과 크기를 잘못 해석하면 다른 데이터를 읽게 됩니다.
MoE라우터가 입력에 따라 일부 전문가를 선택하는 구조입니다. 전체 전문가 수와 매번 계산할 수가 다릅니다.
라우터어느 전문가를 얼마나 반영할지 정하는 계산입니다. 웹 요청을 분기하는 HTTP 라우터와 구별합니다.
양자화가중치 등을 더 적은 비트의 표현으로 바꾸는 방법입니다. 파일·메모리를 줄이지만 정밀도와 커널 지원을 함께 따집니다.
GGUF모델 메타데이터와 텐서를 담는 파일 형식입니다. Strata에는 직접 읽고 형상을 검사하는 코드가 있습니다.
VRAMGPU의 작업용 메모리입니다. 공통 가중치·KV·버퍼·전문가 캐시가 공간을 나눠 씁니다.
통합 메모리CPU와 GPU가 같은 물리 메모리를 공유하는 구성입니다. 두 용량을 별개처럼 더하면 안 됩니다.
전문가 캐시선택될 가능성이 높은 전문가 가중치를 빠른 계층에 보관하는 공간입니다.
캐시 적중·실패필요한 전문가가 이미 빠른 계층에 있으면 적중, 없으면 실패입니다. 실패가 곧 요청 실패라는 뜻은 아닙니다.
KV 캐시이전 토큰의 attention용 key·value를 저장하는 공간입니다. 전문가 가중치를 보관하는 캐시와 다릅니다.
Prefill주어진 프롬프트를 읽고 생성에 필요한 상태를 만드는 단계입니다. 여러 토큰의 병렬 행렬 연산을 활용합니다.
Decode앞 문맥에 이어 새 토큰을 생성하는 단계입니다. 메모리 접근과 다음 토큰 의존성이 중요합니다.
MTPMulti-Token Prediction. 이 프로젝트에서는 모델의 초안 계층으로 여러 후보 토큰을 제안하는 데 사용합니다.
추측 디코딩먼저 후보를 싸게 제안하고 본 모델로 검증해 수락한 부분을 확정하는 방식입니다.
Prompt lookup앞 문맥의 반복을 찾아 그 뒤에 나왔던 토큰을 초안으로 쓰는 방법입니다. 새 지식을 검색하는 RAG와 다릅니다.
PLE / n-gram 테이블문맥의 토큰 조합으로 참조하는 모델의 별도 임베딩 테이블입니다. 여기서는 큰 파일의 필요한 행을 SSD에서 읽는 경로가 있습니다.
고정 메모리장치 전송 등에 쓰려고 호스트 페이지를 고정한 메모리입니다. VRAM과 같은 말은 아닙니다.
메모리 매핑파일의 내용을 가상 주소에 연결하는 방법입니다. 매핑했다고 모든 바이트가 즉시 RAM에 들어오는 것은 아닙니다.
스트림·이벤트GPU 작업의 실행 순서와 완료 상태를 표현하는 도구입니다. 복사한 새 데이터를 언제 사용할지 맞추는 데 씁니다.
EMA새 관측값을 조금씩 반영하는 지수 이동 평균입니다. 초안 정책이 라운드 시간과 성공률을 따라가는 데 쓰입니다.
SSEHTTP 응답을 이벤트 단위로 이어 보내는 형식입니다. 전송 조각 하나가 이벤트 하나와 같다는 보장은 없습니다.
역압받는 쪽이 느리면 보내는 쪽도 기다리도록 하는 흐름 제어입니다. 중계기의 버퍼가 계속 커지는 문제를 줄입니다.
어댑터다른 외부 형식을 공통 내부 계약에 맞추는 코드입니다. OpenAI·Anthropic 요청 변환이 예입니다.
RAIIC++ 객체의 수명에 자원 확보·정리를 연결하는 관례입니다. 중간 실패 때 정리를 빠뜨리지 않는 데 도움이 됩니다.
Parity / KL참조 계산과 결과를 비교하는 검사, 또는 출력 확률 분포의 차이를 보는 지표입니다. 속도와 별도로 수치 정확성을 살핍니다.
MCPAI 도구 연결용 프로토콜입니다. 저장소에는 외부 MCP 도구를 연결하는 코드와 Strata 관리 도구를 제공하는 경로가 있습니다.
잠금 파일허용 범위 안에서 실제로 선택한 의존성 버전을 기록합니다. package.json의 버전 범위와 구별합니다.

특히 전문가 캐시·KV 캐시·운영체제 페이지 캐시는 모두 “캐시”지만 담는 내용이 다릅니다. 로그를 읽을 때는 무엇을 저장한 캐시인지 먼저 표시하면 병목 해석이 쉬워집니다.

11참고 링크

분석한 커밋의 문서와 실제 호출 경로를 함께 열어 보세요

공식 저장소와 분석 근거

관련 기술의 공식 학습 자료

위 외부 기술 링크는 개념 학습을 위한 참고 주소입니다. 구현 설명은 커밋 011c9e6 기준이며, 지원 범위와 측정 조건은 해당 커밋의 장치별 문서에서 확인할 수 있습니다.

현재 상태 (2026-10-23 확인)

항목확인한 내용출처·범위
선정TrendShift Monthly #62026-10-23 TrendShift 기준
스타 / 포크30,770 / 3,2822026-10-23 GitHub 기준
생성일2026-09-242026-10-23 GitHub 기준
주 언어C++2026-10-23 GitHub 기준; 확장자별 줄 수와 GitHub 언어 비율은 별개
최신 릴리스v0.2.2 · 2026-10-212026-10-23 GitHub 기준; 앱 설정에도 0.2.2
엔진 버전0.1.47분석 커밋의 CMakeLists.txt
최근 push2026-10-212026-10-23 GitHub 기준
기준 커밋011c9e6 · 2026-10-21RX 6000용 별도 엔진 패키지·실카드 미검증 안내
전체 커밋 ID011c9e600a93bbc9fd451c563501b5831c32bbcaGit 커밋 식별자
코드 규모선정 확장자 2,140개 파일 · 595,398줄5절 기준으로 직접 집계; 테스트·주석 포함, 벤더·참조 제외
라이선스MIT루트 LICENSE 확인; 모델·외부 코드·자산은 각각의 조건 적용
구현 설명 범위커밋 011c9e6의 코드·설정·문서코드 구조와 프로젝트 측 측정 기록을 구분
쓰기 전에 알아둘 한계
정적 분석, 문서 주장, 실측 결과를 구별해야 합니다

지원·성능: README의 실행 가능성·속도·품질 수치는 프로젝트 측 설명입니다. RX 6000의 새 엔진, Linux 실험용 Intel 경로, 저메모리 Mac은 장치별 문서의 제약을 먼저 읽어야 합니다.

수치 정확성: 초안 검증은 틀린 제안을 무조건 출력하지 않기 위한 구조입니다. 그러나 양자화, 프롬프트 청크, CPU·GPU 계산 경로, 비동기 교체 시점이 달라지면 반올림 차이가 생길 수 있습니다. 모든 백엔드·옵션에서 출력이 바이트 단위로 같다고 보장하는 글은 아닙니다.

데이터·네트워크: 서버와 데스크톱 호스트는 기본으로 로컬 주소에 바인딩합니다. “항상 외부 통신이 없다”는 뜻은 아닙니다. 설치·업데이트, 외부 모델 서비스, 웹 검색, 이미지 URL, 터널을 선택하면 네트워크를 씁니다. README의 “텔레메트리 없음”은 프로젝트의 주장으로 읽고 필요한 경우 전체 경로를 별도 감사해야 합니다.

적용 범위: 구현 설명의 기준은 커밋 011c9e6입니다. API 호환은 원격 서비스의 모든 기능·동작과 동일하다는 뜻이 아니며, CI 정의와 실제 장치별 검사 결과도 구별해야 합니다.