Mac에서 로컬 LLM 실행
anchor alias
Mac에서 로컬 LLM 실행
이 가이드는 OpenAI 호환 API를 사용하여 macOS에서 로컬 LLM 서버를 실행하는 과정을 안내합니다. Apple Silicon에서는 완벽한 개인 정보 보호, API 비용 없음, 놀랍도록 우수한 성능을 누릴 수 있습니다.
우리는 두 가지 백엔드를 다룹니다.
| 백엔드 | 설치 | 최고 | 형식 |
|---|---|---|---|
| 라마.cpp | brew install llama.cpp | 가장 빠른 최초 토큰 획득 시간, 낮은 메모리를 위한 양자화된 KV 캐시 | GGUF |
| omlx | omlx.ai | 가장 빠른 토큰 생성, 기본 Metal 최적화 | MLX(세이프텐서) |
둘 다 OpenAI 호환 /v1/chat/completions 엔드포인트를 노출합니다. Hermes는 둘 중 하나와 작동합니다. http://localhost:8080 또는 http://localhost:8000을 가리키기만 하면 됩니다.
이 가이드는 Apple Silicon(M1 이상)이 탑재된 Mac을 대상으로 합니다. Intel Mac은 llama.cpp와 함께 작동하지만 GPU 가속 없이는 작동하므로 성능이 상당히 느려질 것으로 예상됩니다.
모델 선택
시작하려면 **Qwen3.5-**를 권장합니다. 이는 양자화 기능을 갖춘 이상의 통합 메모리에 편안하게 맞는 강력한 추론 모델입니다.
| 변형 | 디스크 크기 | 필요한 RAM( 컨텍스트) | 백엔드 |
|---|---|---|---|
| Qwen3.5--Q4_K_M(GGUF) | 5.3 GB | 양자화된 KV 캐시 포함 최대 | 라마.cpp |
| Qwen3.5--mlx-lm-mxfp4(MLX) | ~5 GB | ~12 GB | ㅋㅋㅋ |
메모리 법칙: 모델 크기 + KV 캐시. Q4 모델은 ~입니다. Q4 양자화를 사용하는 컨텍스트의 KV 캐시는 4를 추가합니다. 기본(f16) KV 캐시를 사용하면 최대 까지 늘어납니다. llama.cpp의 양자화된 KV 캐시 플래그는 메모리가 제한된 시스템을 위한 핵심 트릭입니다.
대형 모델(, )의 경우 이상의 통합 메모리가 필요합니다. 는 8~ 시스템에 가장 적합합니다.
옵션 A: llama.cpp
llama.cpp는 가장 이식성이 뛰어난 로컬 LLM 런타임입니다. macOS에서는 즉시 GPU 가속을 위해 Metal을 사용합니다.
설치
brew install llama.cpp
그러면 전역적으로 llama-server 명령이 제공됩니다.
모델 다운로드
GGUF 형식 모델이 필요합니다. 가장 쉬운 소스는 huggingface-cli을 통한 Hugging Face입니다.
brew install huggingface-cli
그런 다음 다운로드:
huggingface-cli download unsloth/Qwen3.5--GGUF Qwen3.5--Q4_K_M.gguf --local-dir ~/models
Hugging Face의 일부 모델은 인증이 필요합니다. 401 또는 404 오류가 발생하면 먼저 huggingface-cli login을 실행하세요.
서버 시작
llama-server -m ~/models/Qwen3.5--Q4_K_M.gguf \
-ngl 99 \
-c 131072 \
-np 1 \
-fa on \
--cache-type-k q4_0 \
--cache-type-v q4_0 \
--host 0.0.0.0
각 플래그의 기능은 다음과 같습니다.
| 깃발 | 목적 |
|---|---|
-ngl 99 | 모든 레이어를 GPU(Metal)로 오프로드합니다. CPU에 아무것도 남지 않도록 하려면 높은 숫자를 사용하세요. |
-c 131072 | 컨텍스트 창 크기( 토큰) 메모리가 부족하면 이 값을 줄이세요. |
-np 1 | 병렬 슬롯 수. 단일 사용자 사용의 경우 1로 유지하세요. 더 많은 슬롯이 메모리 예산을 분할합니다. |
-fa on | 플래시주의. 메모리 사용량을 줄이고 긴 컨텍스트 추론 속도를 높입니다. |
--cache-type-k q4_0 | 키 캐시를 4비트로 양자화합니다. 이것은 큰 메모리 절약 기능입니다. |
--cache-type-v q4_0 | 값 캐시를 4비트로 양자화합니다. 위와 함께 KV 캐시 메모리를 f16에 비해 ~75% 줄입니다. |
--host 0.0.0.0 | 모든 인터페이스에서 청취하세요. 네트워크 액세스가 필요하지 않은 경우 127.0.0.1을 사용하세요. |
다음이 표시되면 서버가 준비된 것입니다.
main: server is listening on http://0.0.0.0:8080
srv update_slots: all slots are idle
제한된 시스템을 위한 메모리 최적화
--cache-type-k q4_0 --cache-type-v q4_0 플래그는 메모리가 제한된 시스템에 가장 중요한 최적화입니다. 컨텍스트에서의 영향은 다음과 같습니다.
| KV 캐시 유형 | KV 캐시 메모리( ctx, 모델) |
|---|---|
| f16(기본값) | ~16 GB |
| q8_0 | ~8 GB |
| q4_0 | ~4 GB |
Mac에서는 q4_0 KV 캐시를 사용하고 context를 -c 32768()로 줄입니다. 에서는 컨텍스트를 편안하게 수행할 수 있습니다. 이상에서는 더 큰 모델이나 여러 병렬 슬롯을 실행할 수 있습니다.
여전히 메모리가 부족하면 먼저 컨텍스트 크기를 줄인 다음(-c) 더 작은 양자화(Q4_K_M 대신 Q3_K_M)를 시도하세요.
테스트해 보세요
curl -s http://localhost:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen3.5--Q4_K_M.gguf",
"messages": [{"role": "user", "content": "Hello!"}],
"max_tokens": 50
}' | jq.choices[0].message.content
모델명 알아내기
모델 이름을 잊어버린 경우 모델 엔드포인트를 쿼리하세요.
curl -s http://localhost:8080/v1/models | jq '.data.id'
옵션 B: omlx를 통한 MLX
omlx는 MLX 모델을 관리하고 제공하는 macOS 기반 앱입니다. MLX는 Apple Silicon의 통합 메모리 아키텍처에 맞게 특별히 최적화된 Apple 자체 기계 학습 프레임워크입니다.
설치
omlx.ai에서 다운로드하여 설치하세요. 모델 관리를 위한 GUI와 내장 서버를 제공합니다.
모델 다운로드
omlx 앱을 사용하여 모델을 검색하고 다운로드하세요. Qwen3.5--mlx-lm-mxfp4을 검색하여 다운로드하세요. 모델은 로컬에 저장됩니다(일반적으로 ~/.omlx/models/).
서버 시작
omlx는 기본적으로 http://127.0.0.1:8000의 모델을 제공합니다. 앱 UI에서 제공을 시작하거나 가능한 경우 CLI를 사용하세요.
테스트해 보세요
curl -s http://127.0.0.1:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen3.5--mlx-lm-mxfp4",
"messages": [{"role": "user", "content": "Hello!"}],
"max_tokens": 50
}' | jq.choices[0].message.content
사용 가능한 모델 나열
omlx는 여러 모델을 동시에 제공할 수 있습니다.
curl -s http://127.0.0.1:8000/v1/models | jq '.data.id'
벤치마크: llama.cpp 대 MLX
두 백엔드 모두 비슷한 양자화 수준(GGUF의 경우 Q4_K_M, MLX의 경우 mxfp4)에서 동일한 모델(Qwen3.5-)을 실행하는 동일한 시스템(Apple M5 Max, 통합 메모리)에서 테스트되었습니다. 5개의 다양한 프롬프트(각각 3회 실행), 리소스 경합을 피하기 위해 백엔드를 순차적으로 테스트했습니다.
결과
| 미터법 | 라마.cpp (Q4_K_M) | MLX(mxfp4) | 우승자 |
|---|---|---|---|
| TTFT(평균) | 67 ms | 289 ms | llama.cpp(4.3배 빠름) |
| TTFT(50페이지) | 66 ms | 286 ms | llama.cpp(4.3배 빠름) |
| 세대(평균) | 70톡/초 | 96톡/초 | MLX(37% 더 빠름) |
| 세대(p50) | 70톡/초 | 96톡/초 | MLX(37% 더 빠름) |
| 총 시간(토큰 512개) | 7.3s | 5.5s | MLX(25% 더 빠름) |
이것이 의미하는 바
-
llama.cpp는 신속한 처리에 탁월합니다. 플래시 어텐션 + 양자화된 KV 캐시 파이프라인을 통해 최대 66ms 만에 첫 번째 토큰을 얻을 수 있습니다. 인식된 응답성이 중요한 대화형 애플리케이션(챗봇, 자동 완성)을 구축하는 경우 이는 의미 있는 이점입니다.
-
MLX는 일단 실행되면 최대 37% 더 빠르게 토큰을 생성합니다. 일괄 워크로드, 긴 형식 생성 또는 총 완료 시간이 초기 대기 시간보다 더 중요한 작업의 경우 MLX는 더 빨리 완료됩니다.
-
두 백엔드 모두 매우 일관적입니다. 실행 간 차이는 무시할 수 있을 정도였습니다. 이 숫자를 믿을 수 있습니다.
어느 것을 선택해야합니까?
| 사용 사례 | 추천 |
|---|---|
| 대화형 채팅, 지연 시간이 짧은 도구 | 라마.cpp |
| 긴 형식 생성, 대량 처리 | MLX(omlx) |
| 메모리 제한(8~) | llama.cpp(양자화된 KV 캐시가 일치하지 않음) |
| 여러 모델을 동시에 제공 | omlx(내장 다중 모델 지원) |
| 최대 호환성(Linux도 마찬가지) | 라마.cpp |
헤르메스에 연결
로컬 서버가 실행되면 다음을 수행하세요.
hermes model
사용자 정의 엔드포인트를 선택하고 프롬프트를 따릅니다. 기본 URL과 모델 이름을 묻는 메시지가 표시됩니다. 위에서 설정한 백엔드의 값을 사용하세요.
시간 초과
Hermes는 로컬 엔드포인트(localhost, LAN IP)를 자동으로 감지하고 스트리밍 시간 초과를 완화합니다. 대부분의 설정에는 구성이 필요하지 않습니다.
여전히 시간 초과 오류가 발생하는 경우(예: 느린 하드웨어에서 매우 큰 컨텍스트) 스트리밍 읽기 시간 초과를 재정의할 수 있습니다.
# In your.env — raise from the 120s default to 30 minutes
HERMES_STREAM_READ_TIMEOUT=1800
| 시간 초과 | 기본값 | 로컬 자동 조정 | 환경 변수 재정의 |
|---|---|---|---|
| 스트림 읽기(소켓 수준) | 120s | 1800년대로 올려짐 | HERMES_STREAM_READ_TIMEOUT |
| 오래된 스트림 감지 | 180s | 완전히 비활성화됨 | HERMES_STREAM_STALE_TIMEOUT |
| API 호출(비스트리밍) | 1800s | 변경이 필요하지 않습니다 | HERMES_API_TIMEOUT |
스트림 읽기 시간 초과는 문제를 일으킬 가능성이 가장 높은 것입니다. 이는 다음 데이터 청크를 수신하기 위한 소켓 수준 기한입니다. 대규모 컨텍스트를 미리 채우는 동안 로컬 모델은 프롬프트를 처리하는 동안 몇 분 동안 출력을 생성하지 않을 수 있습니다. 자동 감지는 이를 투명하게 처리합니다.