본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 24. 22:16

AI 홈랩 구축하기

요약

로컬 환경에서 LLM을 배포하고 테스트하기 위한 개인용 홈랩 구축 과정을 소개합니다. Mac Mini M4 Pro를 기반으로 Tailscale, Traefik, llamactl 등을 활용한 네트워크 및 추론 인프라 구성 방법을 다룹니다.

핵심 포인트

  • Mac Mini M4 Pro를 활용한 고효율 로컬 추론 환경 구축
  • Tailscale과 Traefik을 이용한 클라우드-로컬 간 안전한 네트워크 연결
  • llamactl과 MLX를 활용한 멀티 모델 인스턴스 관리
  • Mikoshi를 통한 사용자 상호작용 엔트리포인트 구현

지난 1년 동안 업무의 일환으로 다양한 하드웨어 설정에서 LLM (Large Language Models)을 로컬에 배포하고 평가해 왔습니다. 자연스럽게 사용 가능한 오픈 소스 (open source) 도구와 모델, 그리고 다양한 하드웨어 옵션에 대해 잘 알게 되었습니다. 그래서 로컬 추론 (inference)을 위한 저만의 홈랩 (homelab)을 구축하기로 결정했습니다.

제 목표는 다양한 모델, 도구, 그리고 에이전트 프레임워크 (agent frameworks)를 시험해 볼 수 있는 놀이터를 갖는 것이었습니다. 사용 가능한 하드웨어 옵션 중에서, 저는 성능과 전력 효율성의 균형을 고려하여 Mac Mini M4 Pro를 선택했습니다. 또한 TV 아래에 배치하기 좋고 미디어 센터 (media center)로도 활용할 수 있습니다.

모든 설정 파일은 저의 homelab repo에서 확인할 수 있습니다.

참고: 이 기사는 원래 2026년 2월에 저의 개인 웹사이트에 게시되었으며, 2026년 6월에 업데이트되었습니다.

홈랩 개요

제 홈랩 설정에 대한 상위 수준의 개요는 다음과 같습니다. 각 구성 요소에 대한 자세한 내용은 나중에 설명하겠습니다.

Homelab network architecture diagram showing Traefik and Authelia connected via a Tailnet to an Nginx reverse proxy serving various internal services including Llamactl, Mikoshi, monitoring, and audio tools.

홈랩은 Tailscale을 통해 저의 cloud VPS에 연결되어 있습니다. 클라우드 VPS에서는 Traefik이 리버스 프록시 (reverse proxy) 역할을 하여 Tailscale 네트워크를 통해 Mac Mini로 요청을 전달합니다. Mac Mini에서는 Nginx가 로컬에서 실행되는 다양한 서비스로 요청을 프록시합니다. 또한, 서비스에 인증이 필요한 경우 VPS의 Authelia에서 auth_request를 사용하여 이를 처리합니다.

추론 백본 (inference backbone)은 llama-server와 MLX를 사용하여 여러 모델 인스턴스를 관리하는 llamactl이 담당합니다. 사용자 상호작용을 위한 엔트리포인트 (entrypoint)는 이전에 AgentKit이라고 불렸던 Mikoshi입니다. 또한 MLX 모델을 사용하는 ASR (Automatic Speech Recognition) 및 TTS (Text-to-Speech)를 위한 오디오 서비스와 기본적인 시스템 모니터링을 위한 Glances도 있습니다.

어떻게 진화했는가

제 홈랩의 첫 번째 반복(iteration)은 Ollama와 OpenWebUI를 사용하는 것으로 시작되었습니다. 하지만 저는 곧 Ollama의 한계에 부딪혔고, 이는 제가 Llamactl 기사에서 자세히 다룬 llamactl을 개발하게 된 계기가 되었습니다. 또한 Ollama는 적절한 인정(acknowledgment) 없이 llama.cpp를 기반으로 구축되었기 때문에 훌륭한 오픈 소스 시민(open source citizen)이라고 보기도 어렵습니다. 더 최근에는 그들만의 엔진을 구현했는데, 이 역시 출처 표기 없이 llama.cpp를 심하게 복제하고 있습니다 (심지어 버그까지도).

OpenWebUI는 괜찮은 인터페이스를 제공했지만, 상당히 독단적(opinionated)이고 불투명하게 느껴졌습니다. 예를 들어, 그들은 모델 컨텍스트 프로토콜 (MCP, Model Context Protocol) 서버를 지원하지 않았고, 사용자들이 그들만의 MCP 프록시인 MCPo를 사용하도록 강제했습니다. 그들의 함수(functions) 및 밸브(valves) 시스템은 흥미롭고 강력할 수 있지만, 불투명합니다. 설정은 관리자용과 사용자용으로 중복되어 흩어져 있어, 저와 같은 단일 사용자 인스턴스에서는 혼란을 줍니다. 그들의 커스텀 라이선스는 제 개인적인 사용 사례에는 차이가 없을지라도, 저에게는 결정적인 거부 사유(final nail in the coffin)가 되었습니다.

하지만 궁극적으로 저의 주요 동기는 화려한 UI 뒤에 숨겨지지 않은 LLM 클라이언트, 도구(tools), 그리고 에이전트(agents)를 직접 경험해 보는 것이었습니다.

Smolagents 실험

에이전트가 어떻게 작동하는지 이해하기 위해, 저는 smolagents 프레임워크로 시작했습니다. 이 프레임워크는 코드를 파헤쳐 보면 상당히 단순하고 이해하기 쉽습니다. 저는 간단한 ToolCallingAgent를 생성하고 이를 기본적인 채팅 루프(chat loop)로 감싸는 것부터 시작했습니다. 도구 호출(tool calls)과 더 복잡한 로직을 통해 루프를 확장해 나가면서, 제가 기본적으로 smolagents의 핵심 로직을 재구현하고 있다는 사실을 깨달았습니다. 현재로서는 smolagents 통합을 그대로 유지한 채 MCP를 추가하는 단계로 넘어갔습니다.

Mikoshi

smolagents를 기반으로 구축한 기본적인 채팅 루프(chat loop)는 Mikoshi라는 이름의 독자적인 프로젝트로 성장했습니다 (원래 이름은 AgentKit이었으나 Mikoshi로 변경되었습니다. 이름의 유래를 알고 계신다면 가산점을 드립니다). 시간이 흐르면서 유연한 AI 제공자(AI providers), 대화 메모리(conversation memory), 도구 관리(tool management), 그리고 플러그인(plugins)과 같은 더 많은 기능들을 추가했습니다. MCP를 통합하기 시작했을 때, smolagents가 이를 관리하는 방식과 충돌이 발생하는 것을 발견했습니다. 핵심 에이전트 로직의 대부분을 이미 직접 구축한 상태였기에, smolagents 의존성을 완전히 제거하고 저만의 간단한 에이전트 프레임워크를 완성하기로 결정했습니다.

Dark-themed Mikoshi chat interface showing a conversation history where 'Uplink' (user) prompts are answered by 'Daemon' (assistant), with 'Data Shard' entries representing tool call results.

MCPs

모델 컨텍스트 프로토콜 (Model Context Protocol, MCP)은 LLM이 외부 도구 및 소스와 데이터를 통합하고 공유할 수 있도록 하는 개방형 표준입니다. 이것이 사실상의 표준(de facto standard)이 되어가는 것 같아, 공식 Python SDK를 사용하여 제 설정에 MCP 지원을 추가하고 싶었습니다. 모든 가이드가 서버를 작성하는 데 집중되어 있는데, 이는 GitHub에 '바이브 코딩(vibe coded)'된 채 방치된 수천 개의 MCP 서버들이 존재하는 이유를 설명해 줍니다.

클라이언트를 작성하는 것에 대한 문서는 상대적으로 부족합니다. 권장되는 방식은 메시지당 하나의 MCP 클라이언트와 세션을 초기화하는 것으로 보이는데, 이는 상당히 무거운 작업처럼 느껴집니다. 몇 차례의 실험 끝에, 저는 각 MCP 서버에 대해 전역 세션(global session)을 열어두고 이를 여러 메시지에 재사용하는 방식을 선택했습니다.

Audio Services

오디오 기능을 추가하기 위해, mlx-audio 라이브러리를 사용하여 Whisper ASR 및 TTS 서비스를 설정했습니다. 전사(transcription) 및 텍스트 음성 변환(text-to-speech synthesis)을 위해 OpenAI 호환 엔드포인트를 노출하는 간단한 FastAPI 앱을 만들었습니다. 이 앱은 llamactl과 동일한 방식으로 메모리를 절약하기 위해 필요할 때 모델을 로드하고, 타임아웃 후에 모델을 언로드(unload)합니다.

Monitoring

모니터링을 위해, CPU, 메모리, 디스크 및 네트워크 사용량과 같은 시스템 리소스를 모니터링할 수 있는 웹 인터페이스를 제공하는 Glances를 설정했습니다. 이는 가볍고 설정하기 쉽습니다.

도구 예시 (Tool Examples)

다음은 제가 Mikoshi에 통합한 몇 가지 도구 예시입니다:

  • Task Tool: CalDAV를 사용하여 작업(task)과 할 일(todo)을 관리합니다.
  • Notes Tool: Gitea MCP를 사용하여 마크다운(markdown) 노트를 관리하기 위해 git 리포지토리(repository)와 통합합니다.
  • Anki Tool: Anki에 플래시카드(flashcards)를 생성합니다.
  • Dictionary Tool: 사전에서 단어 정의를 찾아봅니다.

macOS 관련 참고 사항

Linux 배경을 가진 입장에서 macOS에 홈랩(homelab)을 구축하는 것은 흥미로운 경험이었습니다. 몇 가지 참고 사항은 다음과 같습니다:

  • Homebrew는 패키지 관리(package management)에 훌륭하지만, apt나 pacman만큼 포괄적이지는 않습니다.
  • Launchd는 서비스를 관리하는 데 유용하지만, systemd에 비해 기능이 상당히 제한적입니다. 예를 들어, 리소스 제한(resource limits)이나 서비스 간의 의존성(dependencies)을 설정하는 쉬운 방법이 없습니다. 서비스를 시작하고 중지하는 것도 더 번거롭습니다.
  • macOS가 Unix 시스템이라는 점을 고려할 때, Docker가 Linux VM 내부에서 실행되어야 한다는 사실을 알고 놀랐습니다. 이로 인해 컨테이너화된 워크로드(containerized workloads)에 대해 GPU 가속(GPU acceleration)을 사용할 수 없습니다.

다음 단계

현재로서는 주로 Mikoshi에 더 많은 플러그인(plugins)과 도구들을 추가하고 기존의 것들을 개선하는 데 집중하고 있습니다. 로컬 LLM(Large Language Models)을 최대한 활용하고 싶으며, 특정 도구와 에이전트(agents)가 그 방법이 될 것으로 보입니다. 또한 모니터링을 확장하고 추적(tracing), 프롬프트 관리(prompt management), 그리고 메모리(memory) 기능을 추가하고 싶습니다.

또한 저는 소형 오픈 소스 로봇인 Reachy Mini를 가지고 있습니다. 이는 음성 비서(voice assistant)를 구축하기 위한 완벽한 플랫폼으로 보이며, 최근에 통합 작업을 시작했습니다.

리소스 (Resources)

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0