Mac에서 로컬 LLM 최적화하기 / EP07
8GB iMac에서 시작한 개인 AI 실험 — QwenPaw에서 Hermes로
8GB iMac에서 작은 Qwen과 OpenCode Go·Codex를 연결했다. 통제된 A/B/C 시험, 도구 호출과 원격 세션의 시행착오를 거쳐 Hermes를 메인 에이전트로 생각하게 된 기록.
이 글의 내용
8GB iMac에서 이런 실험을 시작한 이유
Mac Studio를 주문하기 전, 8GB iMac에서 먼저 해보고 싶은 게 있었다. 작은 로컬 모델로 일을 시작하고, 못 끝내면 클라우드에 넘기는 구조다. 꼭 큰 모델부터 있어야 가능한 일일까?
당시 쓰던 건 M1 iMac, 메모리 8GB에 SSD 256GB였다. 여러 앱을 개발하다 보면 메모리도 저장 공간도 빠듯했다. EP00에 적었던 그 환경에서 거대한 모델을 계속 켜두기는 어려웠다. 대신 작은 모델과 이미 쓰던 코딩 도구를 연결해보기로 했다.
2026년 9월 23일, Ollama의 Qwen2.5 1.5B Instruct Q4_K_S를 출발점으로 삼았다. 1.5B가 모든 일을 잘할 거라는 기대보다, 작게 시작해서 부족한 부분을 넘기는 경로가 실제로 이어지는지 궁금했다.
| 당시 구성 | 사용한 것 |
|---|---|
| 로컬 추론 | Ollama 0.20.0 · Qwen2.5 1.5B Instruct Q4_K_S |
| 클라우드 작업 | OpenCode 1.4.3의 Go 모델 · Codex CLI 0.156.0 |
| 대화·명령 진입점 | QwenPaw 2.2.1 |
| iPhone 원격 접속 | Paseo CLI 0.9.1 |
핵심 파이프라인은 Python 표준 라이브러리로 만들었다. Docker나 데이터베이스를 더 얹지 않고, 공급자는 순서대로 호출하고 작업 기록은 JSONL로 남겼다. Ollama에는 요청이 끝나면 모델을 내려달라고 했다. 연결 시험을 끝냈다고 8GB에서 장시간 안정적으로 운영할 수 있다는 뜻은 아니었다.
Local → Cloud 에스컬레이션 설계
흐름은 단순했다. 로컬 모델에 일을 맡기고, 결과를 검사한다. 통과하면 반환하고, 실패하면 허용된 다음 계층으로 넘긴다. OpenCode Go의 결과도 다시 검사하고, 필요하면 Codex CLI까지 간다.
여기서 라우터와 Judge는 다른 일을 한다. 라우터는 어디에 보낼지, Judge는 나온 결과가 조건을 만족하는지 맡는다. 처음 Judge는 별도 언어 모델이 아니었다. 글머리 개수와 필수 단어, JSON의 정확한 순서, 파일 존재 여부와 내용을 코드로 검사하고 그 결과를 PASS나 ESCALATE로 바꿨다. 설정에서 mock이라고 부르지만 공급자 답변을 가짜로 넣었다는 뜻은 아니다.
클라우드 호출에는 allow_cloud 승인이 필요했다. 로컬에서 실패했다고 개인 자료를 자동으로 외부에 보내는 구조로 만들지는 않았다. 당시 시험도 비민감 텍스트와 생성한 시험 디렉터리로 제한했다.
A/B/C, 실제로 어디까지 갔을까?
세 시험은 각각 다른 경로에서 끝나도록 조건을 잡았다. 특히 B와 C는 실패를 의도적으로 유도했다. 어려운 일을 알아서 분류하는 능력을 시험한 게 아니라, 실패 다음에 실제 호출이 이어지는지 보는 시험이었다.
A · B · C, 어디서 끝났을까?
Case A · 작은 텍스트 요약
작은 요약 작업을 로컬에 보냈다.
- 1Ollama · Qwen 1.5BDeterministic JudgePASS검사 통과 → 결과 반환
로컬 결과가 결정적 검사를 통과해 반환됐다.
Case B · JSON 검사 실패 후 승격
로컬 출력 토큰을 제한해 JSON 검사 실패를 유도했다.
- 1Ollama · Qwen 1.5BDeterministic JudgeESCALATE검사 미통과 → 허용된 다음 계층
- 2OpenCode GoDeterministic JudgePASS검사 통과 → 결과 반환
실제 OpenCode Go 호출 결과가 검사를 통과했다.
Case C · 파일 생성은 Codex까지
정확한 파일 생성을 요구하고 OpenCode를 읽기 전용 plan 에이전트로 설정했다.
- 1Ollama · Qwen 1.5BDeterministic JudgeESCALATE검사 미통과 → 허용된 다음 계층
- 2OpenCode GoDeterministic JudgeESCALATE검사 미통과 → 허용된 다음 계층
- 3Codex CLIDeterministic JudgePASS검사 통과 → 결과 반환
직접 호출한 Codex CLI가 파일을 만들고 검사를 통과했다. ACP 위임은 아니다.
세 작업의 전체 소요 시간
Case A · 작은 텍스트 요약3.82 s
Case B · JSON 검사 실패 후 승격6.15 s
Case C · 파일 생성은 Codex까지18.72 s
A는 짧은 텍스트를 요약하는 작업이었다. 로컬 답변의 글머리 개수와 필수 단어가 맞아서 그 자리에서 끝났다. 이 검사는 정해둔 형식을 확인했을 뿐, 요약의 모든 의미가 정확하다는 보증은 아니다.
B는 로컬 출력 토큰을 8개로 제한했다. JSON이 끝까지 나오기 어려운 조건을 만들어 검사 실패를 유도했고, 실제 OpenCode Go 호출 결과가 정확한 순서 검사를 통과했다.
C는 정해진 내용의 파일을 만들라는 요구였다. 로컬은 파일을 만들지 못했고, OpenCode도 읽기 전용 plan 에이전트라 파일 생성 조건을 만족하지 못했다. 마지막에 직접 호출한 Codex CLI가 파일을 만들고 내용 검사까지 통과했다. 이것을 OpenCode 모델이 코딩을 못한다는 결과로 읽으면 안 된다. 이 시험에서는 파일을 쓸 권한부터 달랐다.
세 경로가 이어진 건 확인했다. 하지만 이제부터가 더 어렵겠다는 생각도 들었다. 형식이 틀린 건 코드가 잡아준다. 형식은 맞는데 내용이 틀리면 무엇으로 걸러야 할까?
QwenPaw에서는 명령과 도구 호출이 달랐다
QwenPaw Console에서 /poc_route 명령 플러그인으로 파이프라인을 부르는 것은 성공했다. 명령이 같은 CLI를 실행하도록 연결했기 때문에 공급자 선택 로직을 다시 만들 필요도 없었다.
그런데 채팅 모델이 Skill을 보고 도구를 골라 호출하는 경로는 달랐다. 1.5B 모델로 두 번 시도했지만 실제 호출 대신 텍스트만 내놓았다. 8K 컨텍스트에서도 연결되지 않아 해당 Skill은 비활성화했다. “실행하겠다”는 답과 실제 실행은 별개였다.
네이티브 ACP 서버도 초기화와 새 세션 생성까지는 됐지만, 설치한 /poc_route 명령을 로드하지 않았다. 요청이 약한 채팅 모델로 넘어가 파이프라인을 실행하지 못했다. 명령 플러그인이 되는 것과 ACP 경로에서 같은 명령을 사용할 수 있는 것은 같지 않았다.
이 경험만으로 QwenPaw 자체에 구조적 결함이 있다고 말하기는 어렵다. 작은 모델의 도구 호출 능력, 서버와 플러그인 연결 방식, 내가 만든 PoC의 범위가 함께 걸려 있었다. 어느 층이 실패했는지 나눠 봐야 했다.
iPhone에서 실행해봤다
원격 진입점은 Paseo로 붙였다. QwenPaw의 네이티브 ACP 서버를 그대로 쓰는 대신, 작은 ACP 어댑터가 localhost Console API에 검증된 명령을 전달하도록 했다. Paseo는 요청과 결과를 옮기고, 모델을 고르는 일은 파이프라인에 남겼다.
처음에는 iPhone에서 기존 세션을 다시 열 때 오류가 났다. 어댑터에 ACP session/load를 추가하고 재개 시험을 통과한 뒤, iPhone에서 보낸 Case A 요청이 로컬 Ollama와 Judge를 거쳐 돌아오는 것을 확인했다. 원격으로 같은 경로를 부를 수 있다는 점은 반가웠지만, 그 시점에는 휴대폰의 B/C 승격까지 확인한 것은 아니었다.
후속 v0.2 기록에서는 범위가 더 넓어졌다. iPhone에서 보냈다고 보고한 자연어 JSON·코드 작업의 Task ID가 Paseo 진입 로그와 일치했고, 로컬 재시도와 OpenCode를 거쳐 Codex에서 정확성 검사·테스트를 통과했다. 다만 모바일에서 OpenCode까지만 가서 끝나는 경로는 여전히 별도 확인이 필요했다.
ACP도 따로 진전이 있었다. QwenPaw의 ACP 클라이언트 서비스에서 Codex 어댑터로 합성 코드 작업과 같은 세션의 후속 테스트를 위임한 기록이 남아 있다. 앞서 실패한 네이티브 ACP 서버의 명령 로딩과는 다른 시험이다. 기본 파이프라인의 최종 계층은 계속 직접 CLI였고, Hermes와 연결한 결과도 아니었다.
그런데 내가 원하는 건 단순한 라우터가 아니었다
경로는 연결했는데 사용 방식은 아직 시험 도구에 가까웠다. 정해진 명령을 보내고, 검사 조건을 넣고, 작업 ID로 로그를 확인해야 했다. 평소에 Cookly 오류를 고칠 때도 이렇게 요청을 포장하고 싶은 건 아니었다.
내가 원하는 쪽은 “Cookly 오류 분석하고 수정해줘”라고 말하면 프로젝트를 찾고, 이전 결정을 기억하고, 조사·수정·테스트를 나눠 진행하는 시스템이다. 실패한 부분만 다른 워커에게 넘기고, 마지막에는 무엇을 확인했는지 모아서 알려줬으면 했다. ChatGPT Dots 같은 개인 AI에서 기대하는 하나의 대화창도 이런 느낌이다.
로컬 → 클라우드 연결은 그 안의 한 기능이었다. 누군가는 현재 목표와 진행 상황을 붙잡고 있어야 한다. 앞선 시도가 왜 실패했는지, 이미 바뀐 파일은 무엇인지, 어느 프로젝트의 권한으로 작업하는지도 이어받아야 한다. 모델 이름만 바꾸는 라우터로는 이 부분이 채워지지 않았다.
후속 시험의 의미 Judge도 그 차이를 보여줬다. 1.5B 모델의 판단은 합성 평가 30건 중 13건만 맞았고 잘못된 PASS가 13건 있었다. 그래서 의미 판단만 통과한 답은 VERIFIED 대신 UNVERIFIED_DRAFT로 돌려주도록 했다. 이 작은 평가를 모든 모델의 성능으로 일반화할 수는 없지만, 내 설정에서는 자동 승인에 맡기기 어려웠다.
JevMLX도 별도로 격리 실행해봤다. 1.5B 구성은 같은 초기 합성 평가 24건 중 10건만 맞았고, 기본 파이프라인의 의미 판정은 계속 Ollama로 남겼다. 도구를 바꾸는 것만으로 판단의 신뢰도가 확보되지는 않았다. Mac Studio에서는 모델과 검사 조건을 다시 고르고 실제 작업으로 평가해야 한다.
QwenPaw에서 Hermes로 방향을 바꾼 이유
그래서 Mac Studio에서는 Hermes를 메인 에이전트로 두려 한다. 이미 Telegram으로 직접 쓰고 있는 도구라는 점도 크다. 새 모델을 하나 더 고르는 것보다, 계속 대화할 창구를 먼저 정하고 그 뒤에 검증한 경로를 붙이는 쪽이다.
Hermes 공식 문서에는 선별된 기억, 과거 세션 검색, 도구·Skill, 하위 에이전트 위임 같은 기반이 있다. 그렇다고 내 프로젝트별 작업 관리와 자동 승격, 메모리 상황에 맞춘 모델 교체까지 완성돼 있다는 뜻은 아니다. 그 연결은 내가 따로 확인해야 한다.
QwenPaw는 이 PoC의 시행착오를 설명하는 구성요소로 남긴다. 새 목표 구조에는 넣지 않는다. QwenPaw를 버리면 모든 문제가 풀린다는 판단보다, 사용자와 계속 대화하고 일을 취합할 메인 에이전트부터 정해야겠다는 선택에 가깝다.
Mac Studio에서 구현할 개인 AI 시스템
EP06에서는 앞으로 만들 구조를 먼저 정리했다. 이번 글의 8GB 시험은 그 구조를 고민하게 된 출발점이다. 그림도 같은 설계를 이어서 쓴다.
하나의 대화창 뒤에 둘 구조
Telegram · Paseo · Mac
의도·계획 · Task / Session 관리 · 장기 기억
도구·에이전트 위임 · 진행 추적 · 결과 취합
개인정보 · 클라우드 허용 · 작업 권한
작업 유형·난도 · 실행 대상 선택
General / Coding LLM 소형 판단 모델
허용된 클라우드 작업 모델·요금 정책 확인
복잡한 코딩 위임 CLI 확인 · ACP 통합 미확인
Vision · ComfyUI · STT / TTS · 문서 · 파일 · 코드
결정적 검사 → 의미 판단 → 품질 정책
재시도·승격은 Policy / Router로 되돌린다
결과 · 검증 상태 · 실행 경로 · 남은 문제
사용자는 Mac이나 Telegram, 가능하다면 Paseo·iPhone에서 Hermes에 요청한다. Hermes가 프로젝트와 세션을 확인해 일을 나누고, Policy/Router가 개인정보·난도·비용·메모리·지연을 보고 실행 대상을 제한한다. 로컬 결과를 검사한 뒤 충분하면 반환하고, 부족하면 허용된 클라우드 워커로 넘겨 다시 검사한다.
Weave Router는 모델 선택 계층의 후보, JevMLX는 MLX 모델로 제한된 선택지를 평가하는 경량 판단·의미 검증 후보로 보고 있다. JevMLX 자체를 독립된 Judge 모델로 부르지는 않는다. 둘의 Hermes 통합은 아직 확인하지 않았고, 의미 판단의 PASS가 실패한 컴파일이나 테스트를 덮어쓰게 만들 생각도 없다. Codex ACP도 목표 위임 경로이며, 앞의 별도 성공 시험과 Hermes 통합은 구분한다.
기본은 Local First지만 어려운 코딩은 처음부터 전문 에이전트로 보낼 수도 있다. LOCAL_ONLY면 로컬이 실패해도 클라우드로 넘기지 않는다. 이 정책은 워커뿐 아니라 메인 Hermes 모델, Judge와 외부 도구에도 적용해야 한다.
주문한 장비는 M5 Max, 128GB 통합메모리, SSD 1TB다. 큰 모델 하나를 계속 올려두기보다 자주 쓰는 중형 LLM과 작은 판단 모델을 두고, 무거운 모델은 필요할 때 부르려 한다.
자주 쓰는 모델과 필요할 때 쓰는 모델
- 중형 General LLM
- 작은 Judge / Router
- 필요한 STT 또는 임베딩
- 대형 Qwen / DeepSeek 후보
- Vision · 이미지 · 영상 · 음악
macOS · Xcode · Simulator · KV Cache · 런타임 버퍼
- 필요하면 덜 쓰는 모델의 작업 종료·해제
- 필요한 모델 로드 → 작업 → 결과 검증
- 작업 종료 후 기본 구성으로 복귀
STT·임베딩은 필요에 따라 상주 후보로, 대형 Qwen·DeepSeek와 Vision·이미지·영상·음악 모델은 필요할 때 로드할 후보로 나눈다. EP02에서 봤듯 가중치 외에 KV Cache와 실행 버퍼, 개발 도구 메모리도 남겨야 한다. 동시에 전부 올리는 것이 목표는 아니다.
기억도 사용자 선호, 프로젝트 결정, 현재 세션의 진행 상황, Obsidian·기술 문서로 나눠 찾으려 한다. 이 네 계층은 내 설계상의 구분이며 Hermes의 기본 저장소 네 개를 뜻하지 않는다. Cookly·KnitLens·Delsa·소복·소리여행을 오갈 때 필요한 맥락만 불러오는 쪽이다. 블로그 초안 자동화는 그중 한 가지 활용이다.
아직 검증해야 할 것들
다음 시험에서는 원격 요청부터 파일 변경·검증·결과 반환까지 Hermes 안에서 이어지는지 보려 한다. 작업별 권한과 클라우드 전송 승인을 확인하고, 실패하면 정해둔 횟수 안에서 재시도하거나 중단해야 한다. 로그에는 경로·판정·지연·사용량을 남기되 인증 정보와 원문을 무작정 쌓지 않으려 한다.
원본 초기 B/C 로그에는 실제 클라우드 호출과 맞지 않는 개인정보 정책 기본값이 남아 있었고, 후속 보고서가 이 충돌과 코드 수정을 따로 기록했다. 원본을 고쳐 성공처럼 보이게 만들지 않고, 앞으로는 승인 여부와 실제 호출 경로가 함께 맞는지도 검사하려 한다. 정책 이름 하나가 찍혔다고 안전하게 실행됐다고 읽을 수는 없다.
OpenCode Go와 Codex의 구독 사용량도 API 종량제 비용과 나눠 봐야 한다. 초기 B/C의 OpenCode 호출은 짧은 요구에도 약 3.8만 입력 토큰을 보고했다. 라우터가 보낸 문장이 짧아도 코딩 에이전트 내부 맥락은 클 수 있다. 당시 작업별 달러 비용은 로그에서 null이라 절약액으로 바꾸지 않았다.
메모리 피크·Swap, 모델 로드와 해제 시간, 동시 세션, 라우팅 지연과 전체 작업 시간은 Mac Studio가 도착하면 따로 측정할 예정이다. EP01의 토큰 속도, EP03의 가속, EP04의 스트리밍도 결국 이 작업 경로 안에서 쓸 만한지 봐야 한다. 장비 선택은 EP05의 고민으로 이어졌다.
8GB에서도 계층을 연결할 수는 있었다. 그다음에 어려웠던 건 언제 성공했다고 믿을지, 맡긴 일이 끝날 때까지 누가 맥락을 이어갈지였다. 이제는 더 큰 모델 하나보다, 하나의 대화창 뒤에서 여러 도구가 일을 끝내는 환경을 만들어보고 싶다.
기록과 출처
확인일: 2026-10-14. 9월 23일 v0.1·v0.2 보고서, ACP 시험 보고서, 파이프라인·공급자·원격 어댑터 코드와 원본 JSONL을 아카이브에서 확인했다. A/B/C 시간은 원본 시작·완료 시각의 차이다. iPhone 출발 여부는 당시 사용자 보고와 Paseo Task ID 대조에 기반한다. 이번 작성에서 PoC를 재실행하거나 Hermes 통합·Mac Studio 성능을 측정하지 않았다. 원본 로그와 인증·페어링 자료는 공개하지 않는다.
- Hermes: 기억과 세션 검색, 하위 에이전트 위임.
- 후보·연결: JevMLX, Weave Router, Paseo 제공자, Codex ACP 어댑터, OpenCode Go.
댓글과 좋아요
로그인 없이 닉네임으로 남길 수 있어. 닉네임과 댓글은 공개되고, 댓글은 확인 후 올라가.