실행 프로그램과 확장
Crane이란? Rust로 LLM·OCR·음성을 로컬 API로 실행하기
대화 모델은 한 Python 환경, OCR은 다른 라이브러리, 음성 인식은 또 별도 설치로 관리하다 보면 기능보다 환경 정리에 시간을 씁니다. Crane은 Hugging Face Candle 기반의 Rust 추론 프로젝트로, 텍스트 모델과 OCR·ASR·TTS 예제를 한 저장소에 두고 crane-serve를 통해 로컬 API로 연결합니다. 먼저 작은 Qwen3.5 모델로 채팅 경로를 확인한 뒤 필요한 모델을 더하는 식으로 시작할 수 있습니다. 아래에서는 저장소를 고정 버전으로 빌드하고, 서버를 내 컴퓨터에만 열고, 앱에서 같은 API를 호출하는 순서를 따라갑니다.
핵심 내용
- 01
- Crane은 Candle 기반 Rust 프로젝트이며 텍스트·이미지·음성 기능을 애플리케이션과 HTTP API에 연결합니다.
- 02
- 공식 Qwen/Qwen3.5-0.8B 파일로 먼저 채팅 서버를 확인하고, API 주소 http://127.0.0.1:8080/v1과 모델 이름 crane-local을 클라이언트에 넣습니다.
- 03
- Bonsai 2의 Prism GGUF 경로는 CPU·NVIDIA CUDA 지원으로 안내되어 있습니다. 프로젝트의 Metal 지원과 모델별 실행 지원은 나눠서 봅니다.
기능마다 다른 Python 환경을 관리하는 대신
대화 서버는 기존 가상환경에서 잘 도는데 OCR 패키지를 추가하자 의존성이 꼬이고, 음성 인식 데모는 다른 Python 버전을 요구하는 상황을 떠올려 보세요. 이때 불편한 지점은 모델 자체보다 기능별로 갈라진 실행 환경입니다. Crane은 Rust와 Candle을 중심으로 텍스트 추론, 이미지 입력, OCR과 음성 처리 코드를 한 프로젝트에서 관리하려는 접근입니다.
Rust는 컴파일 단계에서 여러 오류를 찾아내고, 결과물을 실행 파일로 묶어 배포하기 좋습니다. Candle은 Rust로 텐서 연산과 모델 구성 요소를 제공하므로, Crane은 이를 이용해 앱 코드와 추론 엔진을 같은 언어 생태계에 둘 수 있습니다. 이것은 운영·개발 구조의 이점이지, 어떤 모델이든 자동으로 빨라진다는 약속은 아닙니다.

Crane, Ollama, MLX는 쓰임이 다릅니다
Ollama는 모델을 받아 로컬에서 실행하고 API로 쓰는 흐름을 간단히 제공합니다. MLX는 Apple Silicon에서 머신러닝 연산을 수행하는 프레임워크이고, oMLX 같은 앱이 이를 이용합니다. Crane은 Candle의 Rust 모델 구현과 여러 실행 장치 경로를 묶습니다. Rust 앱 안에 추론을 넣거나, 같은 서버 프로그램을 모델에 맞춰 실행하고 싶을 때 살펴볼 만합니다. 기본 실행은 프로세스 하나에 모델 하나입니다. 채팅과 음성을 함께 쓰려면 필요한 서버를 서로 다른 포트로 따로 띄우는 식으로 구성합니다.
사용자는 Crane의 crane-serve에 모델을 연결하고, 기존 프로그램에서 OpenAI 형식의 채팅 요청을 보낼 수 있습니다. 데스크톱 앱의 편의 기능을 바꾸려는 선택이라기보다, 앱과 모델 사이에 내가 다룰 수 있는 서버 계층을 두는 선택입니다. Mac에서 Metal을 쓸 수 있다는 프로젝트 설명도 모델별 실행 지원과 같지는 않습니다. 아래의 Bonsai 2처럼 특정 체크포인트는 지원 장치가 따로 안내됩니다.
저장소 버전을 고정하고 실행 파일 만들기
아래 예시는 2026년 9월 23일 검토한 Crane 커밋에 맞춘 절차입니다. 저장소를 내려받고 해당 커밋으로 이동하면 이후 main 변경 때문에 명령이나 지원 모델이 달라지는 일을 줄일 수 있습니다. Rust 도구체인을 준비하고 macOS에서는 Xcode Command Line Tools, NVIDIA CUDA를 컴파일할 Linux 장치에서는 호환되는 CUDA toolkit을 설치합니다.
아래 세 가지 빌드 명령 중 내 장비에 맞는 하나만 실행하세요. Mac은 Metal·Accelerate, NVIDIA GPU를 쓰는 Linux는 CUDA, GPU 없이 시험한다면 CPU 구성을 고릅니다. 모델 파일은 빌드에 포함되지 않으며 다음 단계에서 따로 받습니다. 공식 install.sh도 같은 선택을 돕지만, 여기서는 어떤 기능을 켰는지 알 수 있도록 Cargo 명령을 직접 사용합니다.
git clone https://github.com/lucasjinreal/Crane.git
cd Crane
git checkout --detach 99a60887bdca16b4852b7bc953ca03c1df374e88cargo build --release -p crane-serve --features "metal,accelerate"cargo build --release -p crane-serve --features cudacargo build --release -p crane-serve
작은 모델로 먼저 채팅 경로 확인하기
첫 실행에는 공식 Hugging Face 저장소 Qwen/Qwen3.5-0.8B를 사용합니다. Crane README는 Qwen 3.5 0.8B를 지원 모델로 명시하고, 모델 카드는 같은 ID의 safetensors 저장소와 라이선스 정보를 제공합니다. 이 모델은 비전 인코더가 포함된 체크포인트이므로, 텍스트 대화만 시험할 때는 crane-serve의 --text-only 옵션으로 비전 부분을 제외합니다.
모델 파일은 Hugging Face CLI의 hf download 명령으로 저장합니다. uv가 이미 있다면 아래처럼 uvx hf를 쓰면 됩니다. 다운로드 도구가 쓸 격리 환경은 uv가 관리하므로 가상환경을 직접 만들 필요가 없습니다. uv가 없다면 아래 CLI 설치 안내에서 자신의 환경에 맞는 방법을 고르세요. 다운로드가 끝나면 모델 폴더에 설정·토크나이저·가중치 파일이 함께 있는지 확인합니다.
uvx hf download Qwen/Qwen3.5-0.8B --local-dir models/Qwen3.5-0.8B서버를 127.0.0.1에서만 열기
모델 파일을 받은 뒤 crane-serve를 실행합니다. --model-name crane-local은 API 요청에서 사용할 이름이고, --context 4096은 이 시험의 문맥 한도를 정합니다. --host 127.0.0.1을 적어야 서버가 같은 컴퓨터의 클라이언트만 받습니다. Crane의 기본 host 값은 0.0.0.0이므로 이 옵션을 빼지 않습니다.
서버가 시작되면 터미널 로그의 주소를 확인하고, 내장 화면이 열리지 않으면 브라우저에서 http://127.0.0.1:8080/에 접속합니다. --ui는 Crane의 내장 브라우저 화면을 제공합니다. 텍스트만 로드한 이 실행에서는 우선 짧은 질문을 넣어 응답이 끝까지 오는지 살펴보세요.
./target/release/crane-serve --model-path models/Qwen3.5-0.8B --model-type qwen3_5_vl --text-only --model-name crane-local --host 127.0.0.1 --port 8080 --context 4096 --uiAPI 클라이언트에서 같은 서버 부르기
직접 HTTP 요청을 보내면 서버와 앱 사이의 연결을 분리해서 볼 수 있습니다. curl -N은 스트리밍 응답을 버퍼링하지 않고 표시하며, 요청의 model 값은 실행 명령에서 정한 crane-local과 일치해야 합니다. chat_template_kwargs의 enable_thinking 값은 지원되는 Qwen 템플릿에서 생각 모드를 끄는 옵션입니다.
앱의 OpenAI 호환 설정에는 base URL http://127.0.0.1:8080/v1과 모델 이름 crane-local을 넣습니다. 위 명령은 API 인증을 켜지 않은 로컬 전용 예제입니다. 앱이 API key 칸을 필수로 요구하면 local 같은 임시 문자열을 쓸 수 있습니다. 이 값은 서버를 보호하는 비밀번호가 아닙니다. 연결이 되면 평소 쓰는 한국어 질문이나 짧은 코드 설명을 보내 결과를 살펴보세요.
curl -N http://127.0.0.1:8080/v1/chat/completions -H 'Content-Type: application/json' -d '{"model":"crane-local","messages":[{"role":"user","content":"Say hello in one short sentence."}],"stream":true,"max_tokens":256,"temperature":0,"chat_template_kwargs":{"enable_thinking":false}}'채팅 다음에 OCR·ASR·TTS 붙이기
채팅이 되면 목적에 맞는 모델 유형으로 서버를 바꿔 실행해 봅니다. Crane 저장소는 PaddleOCR 계열, Qwen3-ASR, Qwen3-TTS 등을 지원 목록에 두고 있고 crane-serve 문서에는 오디오 전사·음성 생성 경로가 있습니다. 음성 서버는 모델 유형과 입력 자료가 채팅과 다르므로, README의 해당 항목에서 옵션과 API 요청 형식을 그대로 가져와 샘플 하나로 연결하세요.
실제 파일이나 업무 내용을 보내기 전에는 짧고 민감하지 않은 입력으로 원하는 결과를 살펴보세요. OCR이라면 사진 속 글자를 옮기는지, ASR은 한국어 음성에서 단어를 놓치지 않는지, TTS는 필요한 언어로 소리를 내는지 확인하면 됩니다. 기능별로 필요한 모델이 다를 때도 같은 서버 형식으로 앱 연결을 재사용할 수 있습니다.
Bonsai 2로 바꿀 때 달라지는 모델 파일과 장치
Bonsai 2의 Prism 배포본은 PTQ1_0 또는 PQ2_0 삼진 가중치를 담은 GGUF 파일입니다. Crane은 GGUF 안의 전용 타입을 알아보고 해당 가중치에 TernaryLinear 실행 경로를 적용하도록 추가됐습니다. 따라서 파일을 받을 때 일반 Q4 GGUF가 아니라 Bonsai 2의 지정된 Prism 파일을 선택해야 합니다.
공식 지원 기록은 이 모델에 CPU와 NVIDIA CUDA 실행을 명시합니다. 이는 Qwen3.5의 Metal 경로와 다른 조건이므로, Mac에서 Crane을 빌드했다고 Bonsai 2도 같은 GPU 가속을 받는다고 기대하면 안 됩니다. 27B 파라미터라는 규모만 보고 메모리를 계산하지 말고, 선택한 Prism 파일 크기와 문맥 4096 설정에서 실제 메모리 여유를 확인하세요.
./target/release/crane-serve \
--model-path /absolute/path/Ternary-Bonsai-2-27B-PTQ1_0.gguf \
--model-name bonsai-local --host 127.0.0.1 --port 8080 \
--context 4096 --ui기존 런타임과 공정하게 비교하기
Crane의 성능은 이 글에서 직접 측정하지 않았습니다. 내 장비에서 비교할 때는 모델을 불러오는 첫 실행과 준비 실행을 따로 빼고, 같은 요청을 세 번 측정해 중앙값을 기록하세요. 첫 토큰 대기 시간, 이후 생성 속도, 전체 완료 시간을 나누면 문서를 읽는 단계와 답을 쓰는 단계 중 어디가 달라졌는지 알 수 있습니다.
같은 질문을 줬더라도 한쪽만 생각 모드가 켜져 있거나 출력 제한이 다르면 공정한 비교가 아닙니다. 모델·양자화·문맥 길이·출력 제한을 맞추고, 캐시가 없는 새 요청과 이어지는 대화를 나눠 보세요. MLX와 GGUF처럼 파일 형식이 다르면 그 차이도 기록합니다. 빨라졌지만 중요한 문장을 빠뜨렸다면 속도만으로 교체할 이유는 없습니다. 환경 관리가 줄고 매일 하는 일을 제대로 끝내는지가 마지막 판단 기준입니다.
