마지막 수정
M4 Mac mini 16GB에서 Bonsai 27B 실험: oMLX·LM Studio·llama.cpp 비교
M4 Mac mini 16GB에서 Ternary Bonsai 27B를 세 엔진으로 직접 실행했습니다. 속도와 메모리뿐 아니라 최종 출력과 도구 호출까지 비교합니다.

결론 먼저
M4 Mac mini 16GB에서 Ternary Bonsai 27B를 에이전트로 쓸 때 가장 안정적이었던 경로는 llama.cpp Metal과 Q2_0 GGUF였습니다. oMLX는 메모리 가드 조정이 필요했고, LM Studio는 이번 설정에서 최종 답변을 만들지 못했습니다.
- 실험 환경
- Apple M4 Mac mini 16GB, Ternary Bonsai 27B, oMLX MLX 서버, LM Studio 0.4.19+2 MLX 엔진, llama.cpp Metal Q2_0 GGUF, context 8K·parallel 1 동일 요청 비교
- 누구에게 유용한가
- 16GB Apple Silicon Mac에서 27B급 로컬 모델을 에이전트나 번역 작업에 연결하려는 사람, MLX와 GGUF 중 실제 운영 경로를 고르는 사람
확인한 자료와 한계
- Daejin Lab M4 Mac mini 16GB 로컬 실행 기록
- PrismML Bonsai Demo
- Ternary-Bonsai-27B 공식 모델 카드
세 엔진의 thinking과 memory guard를 완전히 같은 구현으로 맞추지 못했습니다. 한 개의 짧은 영문 요청과 기능별 호출을 중심으로 확인했으며, 장문 한국어 품질과 장시간 안정성은 별도 측정이 필요합니다.
이 글에서 다루는 핵심 3가지
첫 측정값만 보면 결론은 간단했습니다. oMLX는 1 tok/s도 나오지 않았고, llama.cpp는 8 tok/s를 넘었습니다. 그대로 적었다면 틀린 비교가 될 뻔했습니다.
oMLX에는 모델 로드 시간과 thinking 비용, 메모리 가드가 함께 섞여 있었습니다. 조건을 다시 맞추자 약 5.1 tok/s까지 올라왔습니다. llama.cpp는 같은 재실험에서 7.42 tok/s였습니다.
속도 차이는 줄었지만 최종 선택은 바뀌지 않았습니다. llama.cpp에서는 답변이 끝까지 나왔고, API 응답과 기본 도구 호출도 완료됐습니다. 16GB 메모리에서 번역 모델과 번갈아 운영하는 방법도 가장 예측하기 쉬웠습니다.
Bonsai 27B 발표 자료를 확인한 글에 이어, 이번 글에서는 Ternary Bonsai 27B를 oMLX, LM Studio, llama.cpp로 직접 실행한 결과를 정리합니다. 모델 로드 여부보다 최종 답변, 메모리 조건, API와 도구 호출을 우선해서 봤습니다.
결론 먼저
| 하려는 일 | 이번 실험의 선택 | 이유 |
|---|---|---|
| 로컬 에이전트·도구 호출 | llama.cpp Metal + Q2_0 GGUF | 7.42 tok/s, 최종 답변과 기본 도구 호출 완료 |
| 웹 번역 | oMLX + 4B급 번역 모델 | 번역 전용 모델을 따로 운영하기 쉬움 |
| GUI 채팅·모델 관리 | LM Studio MLX | 조작은 편하지만 Bonsai의 thinking 설정은 재검증 필요 |
16GB에서는 번역 모델과 27B 모델을 동시에 상시 로드하지 않았습니다. 필요한 모델만 하나씩 띄우는 방식이 가장 안정적이었습니다.
실험에서 확인하려던 것
이번 비교의 질문은 “어느 엔진이 가장 빠른가”보다 조금 길었습니다.
모델이 실제로 로드되는가
첫 응답이 시작되는가
최종 content가 끝까지 나오는가
thinking 비용을 통제할 수 있는가
도구 호출 형식이 깨지지 않는가
다른 로컬 모델과 메모리가 충돌하지 않는가
로컬 에이전트는 짧은 채팅 한 번과 다릅니다. 답변이 빨라도 최종 content가 비어 있거나 tool call이 반복되면 작업에 붙이기 어렵습니다. 모델 파일이 메모리에 들어가도 번역 모델과 함께 띄웠을 때 서버가 종료된다면 운영 방식부터 바꿔야 합니다.
테스트 환경
| 항목 | 조건 |
|---|---|
| 장비 | Apple M4 Mac mini |
| 통합 메모리 | 16GB |
| 모델 계열 | Ternary Bonsai 27B |
| oMLX | Ternary-Bonsai-27B-mlx-2bit |
| LM Studio | Ternary-Bonsai-27B-mlx-2bit, MLX 엔진 |
| llama.cpp | Ternary-Bonsai-27B-Q2_0.gguf, Metal |
| 공통 context | 8K 요청 조건 |
| parallel | 1 |
| temperature | 0.2 |
| 최대 출력 | 64 tokens |
공통 요청은 아래 한 문장이었습니다.
Write exactly one English paragraph of about 60 words. Output only the paragraph.
짧고 단순한 요청을 사용한 이유는 모델의 지식보다 엔진의 출력 완료와 thinking 처리 차이를 먼저 보기 위해서였습니다. 모든 실험은 다른 모델을 내린 뒤 순서대로 진행했습니다.
결과 한눈에 보기
| 엔진 | 모델 로드 | 최종 답변 | 관찰한 생성 속도 | 현재 판단 |
|---|---|---|---|---|
| oMLX MLX | 가드 완화 후 성공 | 성공 | 약 5.1 tok/s | 설정을 조정하면 가능 |
| LM Studio MLX | 성공 | 실패 | 직접 비교 보류 | GUI 실험용 |
| llama.cpp Metal | 성공 | 성공 | 7.42 tok/s | 에이전트 운영 우선 |
이 표만 보고 GGUF가 MLX보다 본질적으로 빠르다고 결론 내리면 안 됩니다. oMLX와 LM Studio는 각자의 memory guard와 chat template, thinking 처리가 들어갑니다. 이번 결과는 현재 설치한 엔진과 설정을 합친 실제 운영 경로의 비교입니다.
oMLX: 처음에는 1 tok/s도 안 나왔다
초기 비통제 측정에서 oMLX의 Ternary Bonsai는 약 0.5–0.9 tok/s로 보였습니다. 같은 시점의 llama.cpp가 약 8.2–8.7 tok/s였기 때문에 차이가 너무 컸습니다.
다시 확인해보니 oMLX 기본 aggressive 메모리 가드는 당시 사용 가능한 상한을 약 7.97GB로 계산했습니다. 불러오려던 Bonsai 모델은 약 8.30GB였습니다. 기본 상태에서는 로드 단계부터 막히는 조건이었습니다.
실험 동안 메모리 한도를 15GB로 조정하고 prefill guard와 thinking 조건을 통제했습니다. 결과는 다음과 같습니다.
completion tokens: 57
서버 기록 시간: 13.53초
전체 wall time: 18.23초
모델 로드: 약 4.17초 포함
최종 content: 정상 완료
생성 구간은 약 5.1 tok/s로 확인됐습니다. 초기 0.5–0.9 tok/s는 모델 로드, thinking, 출력 길이와 메모리 조건이 섞인 값이었습니다.
oMLX가 실행되지 않는다는 결론은 틀렸습니다. 다만 16GB 장비에서 메모리 가드를 완화하면 운영체제와 다른 앱이 쓸 여유도 같이 줄어듭니다. 번역 모델과 Bonsai를 한 서버에 계속 올려두는 구성은 제 환경과 맞지 않았습니다.
LM Studio: 로드는 됐지만 최종 content가 비었다
LM Studio에서는 약 8.52GB의 MLX 모델을 GPU max, context 8192, parallel 1로 로드했습니다. 모델 로드에는 약 18.29초가 걸렸습니다.
문제는 thinking이었습니다. 요청에 reasoning을 끄는 값을 전달했지만 현재 모델 메타데이터와 API 조합에서는 적용되지 않았습니다.
reasoning tokens: 63
최종 content: 비어 있음
wall time: 16.31초
API가 오류로 끝난 것은 아닙니다. 모델도 로드됐습니다. 하지만 “한 문단만 출력하라”는 요청이 최종 문단까지 도달하지 못했습니다. 이 상태에서 tok/s를 oMLX나 llama.cpp와 나란히 놓으면 reasoning 생성과 최종 답변 생성을 섞어 비교하게 됩니다.
따라서 이번 Bonsai 모델·설정·API 조합은 실패로 기록했습니다. LM Studio 전체가 Bonsai를 지원하지 않는다는 뜻은 아닙니다. 모델별 설정에서 thinking을 확실히 끈 뒤 다시 측정해야 합니다. GUI에서 모델을 살펴보고 관리하는 용도로는 편했지만, 현재 설정 그대로 에이전트 API의 기본 경로로 두지는 않았습니다.
llama.cpp Metal: 7.42 tok/s와 최종 출력 완료
llama.cpp에서는 삼진 가중치의 Q2_0 GGUF를 Metal 서버로 실행했습니다. 서버 기본 context는 64K로 두되, 동일 비교 요청은 8K 조건으로 보냈습니다. 슬롯은 하나, KV cache는 Q4, reasoning은 껐습니다.
결과는 아래와 같습니다.
completion tokens: 47
wall time: 8.31초
prompt 처리: 15.09 tok/s
generation: 7.42 tok/s
최종 content: 정상 완료
속도 차이보다 더 중요했던 것은 후속 확인이었습니다. 이 경로에서 OpenAI 계열 응답 형식, Claude Messages 형식, chat tool calling을 실제 요청으로 확인했습니다. 로컬 에이전트 프로필에서도 터미널과 파일 도구의 기본 호출이 완료됐습니다.
Codex 연결은 제한적이었습니다. Codex의 기본 지시문은 크고, 일부 Responses 전용 도구는 로컬 서버가 그대로 처리하지 못했습니다. 간단한 응답은 가능했지만 일반 Codex 작업의 주력 경로로 권하기는 어려웠습니다. Claude 계열 클라이언트와 단순한 오픈소스 에이전트가 현재 구성에는 더 잘 맞았습니다.
16GB에서는 두 모델을 동시에 띄우지 않았다
이번 운영에서 가장 확실하게 남은 규칙은 속도보다 메모리였습니다.
웹 번역에는 4B급 번역 모델을 사용했습니다. 에이전트 작업에는 Ternary Bonsai 27B를 사용했습니다. 두 모델을 동시에 상시 로드하자 메모리 압박으로 Bonsai 서버가 종료되는 상황을 확인했습니다.
그래서 역할을 이렇게 나눴습니다.
| 작업 | 모델·엔진 | 판정 근거 |
|---|---|---|
| X·Threads·Reddit 번역 | oMLX와 4B급 번역 모델 | 번역 작업에 필요한 모델만 가볍게 유지 |
| 로컬 에이전트·도구 호출 | llama.cpp Metal과 Ternary Bonsai 27B GGUF | 최종 답변과 기본 도구 호출 완료 |
| GUI 채팅·모델 관리 | LM Studio MLX | 조작은 편하지만 thinking 설정 재검증 필요 |
번역할 때는 27B 서버를 내립니다. 에이전트 작업을 시작할 때는 번역 모델을 내립니다. 번거로워 보이지만 16GB에서 두 모델이 서로 밀어내는 것보다 예측하기 쉬웠습니다.
현재 운영값
에이전트 서버의 기준값은 다음처럼 정리했습니다.
context: 64K
parallel slots: 1
KV cache: Q4
prompt cache: 512MiB
reasoning: off
vision: off
vision을 끈 이유는 메모리와 도구 호출 경로를 먼저 안정화하기 위해서입니다. 이미지 입력용 파일을 추가하면 메모리 요구량과 처리 조건이 달라집니다. 이번 글에서는 텍스트 에이전트만 다룹니다.
64K context를 설정했다고 항상 64K를 채워 쓰는 것도 아닙니다. 긴 context는 KV cache와 prompt 처리 시간을 늘립니다. 실제 요청은 필요한 범위로 제한하고, 긴 문서를 넣기 전 메모리 사용량을 따로 확인해야 합니다.
실패 로그가 바꾼 결론
처음 숫자만 봤을 때는 “MLX는 느리고 GGUF가 빠르다”라고 적기 쉬웠습니다. 재실험 뒤에는 그렇게 쓰지 않기로 했습니다.
초기 관찰
oMLX 0.5–0.9 tok/s
llama.cpp 8.2–8.7 tok/s
조건 통제 후
oMLX 약 5.1 tok/s
llama.cpp 7.42 tok/s
메모리 가드와 thinking을 통제하자 격차가 크게 줄었습니다. LM Studio는 thinking을 끄지 못해 최종 답변 비교에서 빠졌습니다.
이번 결론은 엔진의 이론적 성능 순위가 아닙니다. 현재 버전과 설정에서 에이전트 출력이 끝까지 완료되고 도구 호출까지 이어진 경로가 llama.cpp였다는 운영 기록입니다.
같은 비교를 할 때 남길 항목
- 다른 모델을 모두 메모리에서 내립니다.
- 모델 파일 크기와 memory guard 상태를 기록합니다.
- prompt, temperature, max tokens, context, parallel을 맞춥니다.
- 첫 요청과 warm 요청을 분리합니다.
- 모델 로드 시간과 생성 시간을 따로 기록합니다.
- reasoning tokens와 final content tokens를 나눕니다.
- text generation 뒤에 tool call과 finish reason을 확인합니다.
- 실험이 끝나면 완화한 메모리 설정을 원래 값으로 돌립니다.
tok/s 하나만 남기면 모델 로드와 thinking 비용이 섞일 수 있습니다. 최종 content가 비어 있는지도 놓치기 쉽습니다. 로컬 에이전트 비교에서는 “몇 토큰을 만들었나”와 “작업이 완료됐나”를 함께 기록해야 했습니다.
현재 결론
M4 Mac mini 16GB에서도 Ternary Bonsai 27B는 실제 텍스트 에이전트 후보가 됐습니다. llama.cpp Metal과 Q2_0 GGUF 조합에서 약 7.42 tok/s를 확인했고, 최종 답변과 기본 도구 호출도 완료했습니다.
oMLX도 메모리 가드와 thinking을 조정하면 약 5.1 tok/s로 정상 생성됐습니다. 기본 가드를 풀어야 한다는 점 때문에 번역 전용 서버로 남겼습니다. LM Studio는 로드와 API 응답은 가능했지만 이번 설정에서 최종 content 생성에 실패해 재실험이 필요합니다.
16GB에서 가장 효과가 컸던 선택은 모델을 하나 더 최적화하는 일이 아니라 번역과 에이전트 모델을 동시에 상시 로드하지 않는 것이었습니다. 작업에 따라 하나씩 전환하니 속도와 메모리 문제를 구분하기 쉬워졌습니다.
같이 읽을 글
- Bonsai 27B가 3.9GB라고? 발표에서 먼저 확인할 것
- Gemma 4 12B를 M4 Mac mini 16GB에서 먼저 돌려본 기록
- Ollama와 LM Studio를 실제로 나눠 본 기준
- 로컬 AI와 클라우드 AI 사이에서 초보자가 정해야 할 기준
참고 자료
기준일은 2026년 7월 17일입니다. 엔진 버전과 low-bit kernel 지원은 바뀔 수 있으므로 설치 전 공식 모델 카드와 실행 문서를 다시 확인해야 합니다.