맥에서 로컬 LLM을 돌려본 사람이라면 한 번쯤 이 질문에 부딪혔을 것이다. MLX를 써야 할까, llama.cpp를 써야 할까. 두 런타임 모두 Apple Silicon에서 잘 돌아가고, 커뮤니티도 활발하며, 지원 모델도 점점 겹쳐가고 있다. 그런데 실제로 써보면 상황에 따라 체감 속도 차이가 꽤 크게 날 때가 있다. 단순히 “MLX가 애플 공식이니까 더 빠르다”는 식의 설명은 절반만 맞다.
MLX가 강한 구간
MLX가 진가를 발휘하는 조건은 꽤 구체적이다. 첫째로, mlx-community 허브에 올라온 전용 변환 모델을 사용할 때다. Hugging Face의 mlx-community 조직은 주요 모델을 MLX에 최적화된 safetensors 포맷으로 미리 변환해 올려두고 있다. 이 모델들은 단순 변환이 아니라 MLX의 레이어 구조와 메모리 레이아웃에 맞게 조정된 상태다. 이 경우 llama.cpp의 GGUF 모델과 직접 비교하면 토큰 생성 속도에서 MLX 쪽이 우세한 경우가 많다.
둘째로, 배치 처리나 긴 프롬프트 처리에서 MLX의 이점이 두드러진다. MLX는 Apple Silicon의 통합 메모리(Unified Memory) 구조를 직접 활용하도록 설계되어, GPU와 CPU가 같은 메모리 풀을 공유한다는 특성을 십분 살린다. 긴 컨텍스트를 처리할 때 데이터를 GPU 메모리로 복사하는 오버헤드가 없기 때문에, 프롬프트 길이가 길어질수록 MLX의 상대적 이점이 커지는 경향이 있다. 배치로 여러 요청을 동시에 처리하는 서버 용도라면 이 차이가 더 선명하게 나타난다.
셋째, MLX는 Apple의 Metal 셰이더(shader)를 직접 활용하는 커널을 사용한다. attention 연산이나 행렬 곱셈 같은 핵심 연산이 Metal Performance Shaders(MPS)와 커스텀 Metal 커널로 구현되어 있어, 동일 하드웨어에서 일반적인 CPU 경로보다 훨씬 높은 처리량을 낼 수 있다. M-시리즈 칩의 GPU 코어 수가 많을수록, 즉 M2 Max나 M4 Pro처럼 GPU 코어가 40개 이상인 경우 이 이점이 더욱 극대화된다.
llama.cpp가 오히려 앞서는 경우
그렇다고 MLX가 항상 빠른 것은 아니다. llama.cpp가 우세한 조건도 분명히 존재한다.
가장 현실적인 이유는 모델 지원 속도다. 새 모델이 나왔을 때 llama.cpp 커뮤니티가 GGUF 변환본을 먼저 올리는 경우가 많다. MLX 변환은 mlx_lm.convert 도구로 직접 할 수도 있지만, 모델 아키텍처가 MLX에 아직 통합되지 않았다면 변환 자체가 실패하거나 추론 결과가 불안정할 수 있다. 반면 llama.cpp는 GGUF 포맷의 유연성 덕분에 새 아키텍처를 비교적 빠르게 흡수한다. 신규 모델을 당장 써보고 싶다면 llama.cpp 쪽이 선택지가 더 넓다.
또한 GGUF의 양자화 옵션 다양성은 llama.cpp만의 강점이다. Q4_K_M, Q5_K_S, Q6_K, IQ3_XXS처럼 세밀하게 조정된 양자화 방식이 존재하고, 품질과 속도 사이의 트레이드오프를 사용자가 직접 선택할 수 있다. MLX도 4비트, 8비트 양자화를 지원하지만 옵션의 세분화 면에서는 아직 GGUF에 미치지 못한다. 메모리가 넉넉하지 않은 환경에서 최대한 압축된 모델을 써야 할 때 llama.cpp 쪽 선택지가 더 풍부하다.
CPU와 GPU 혼합(offloading) 처리가 필요한 경우도 llama.cpp가 유리하다. 모델이 GPU 메모리 용량을 초과할 때 llama.cpp는 레이어 일부를 CPU로 넘기는 -ngl 옵션이 잘 동작한다. MLX는 통합 메모리 덕분에 이 문제가 덜 발생하지만, 극단적으로 큰 모델을 저사양 맥에서 억지로 돌릴 때는 llama.cpp의 혼합 처리 방식이 더 안정적이다.
이미지 출처: Unsplash
포맷 변환 오버헤드도 고려해야 한다
모델 포맷 이야기를 빼놓을 수 없다. llama.cpp는 GGUF 포맷을 사용하고, MLX는 safetensors 기반의 자체 포맷을 쓴다. mlx-community에 원하는 모델이 없을 때는 mlx_lm.convert로 직접 변환해야 하는데, 이 과정이 의외로 시간이 걸린다. 70억 파라미터 규모의 모델 기준으로 로컬에서 변환하면 수 분에서 십수 분까지 소요될 수 있다. 당장 한두 번 테스트해볼 목적이라면 이미 GGUF가 준비된 llama.cpp 쪽이 진입 장벽이 낮다.
반대로, 한 모델을 지속적으로 사용할 계획이라면 MLX 변환 비용은 일회성이다. 변환 후 반복 사용한다면 MLX 특유의 Metal 최적화 이점을 온전히 누릴 수 있다. 따라서 “탐색 단계”인지 “정착 단계”인지에 따라 선택이 달라진다.
시나리오별로 정리하면
정리하자면, 이미 mlx-community에 변환본이 올라와 있고 컨텍스트가 긴 작업을 반복적으로 처리한다면 MLX가 더 나은 선택이다. 서버 형태로 여러 요청을 배치 처리하거나, Apple Silicon의 GPU 코어를 최대한 활용하고 싶은 경우도 마찬가지다. 반면 막 출시된 모델을 빠르게 테스트해보거나, 메모리 한계를 넘어서는 모델을 돌리거나, 양자화 옵션을 세밀하게 조정하고 싶다면 llama.cpp가 더 실용적이다.
결국 두 런타임은 서로를 대체하는 관계가 아니라 상호 보완적인 관계에 가깝다. LM Studio나 Jan처럼 두 런타임을 모두 백엔드로 지원하는 프런트엔드 도구들이 점점 늘어나는 것도 이런 이유에서다. MLX는 Apple이 직접 키우는 프레임워크인 만큼 앞으로도 Metal 최적화와 모델 지원 속도 면에서 지속적으로 개선될 것이다. llama.cpp 역시 크로스플랫폼 특성과 풍부한 양자화 생태계라는 강점이 쉽게 무너지지 않는다. 어느 쪽이 “더 좋다”는 질문보다 지금 하려는 작업의 조건을 먼저 따져보는 것이 훨씬 유용한 접근이다.
출처