1편에서 GPU 없이 로컬 LLM을 띄웠고, 2편에서 한국어엔 Qwen2.5-3B가 낫다는 걸 실측으로 확인했습니다. 이제 마지막 단계 — 이 로컬 LLM을 실제 자동화에 연결합니다. llama.cpp를 OpenAI 호환 API 서버로 띄우고, n8n 워크플로우에 붙여서 일을 시켜 봤습니다. 결론부터: n8n이 로컬 LLM을 호출해 nginx 에러 로그를 “ERROR”로 정확히 분류하는 데까지 성공했습니다. API 요금 0원, 전부 홈랩 안에서.
1. llama-server로 OpenAI 호환 API 띄우기
llama.cpp에는 llama-server라는 실행 파일이 함께 빌드됩니다(1편 참고). 이걸 띄우면 OpenAI의 /v1/chat/completions와 똑같은 형식의 API가 생깁니다.
./build/bin/llama-server \
-m /root/models/Qwen2.5-3B-Instruct-Q4_K_M.gguf \
-c 4096 -t 4 \
--host 0.0.0.0 --port 8080
여기서 OpenAI 호환이라는 점이 핵심입니다. 세상의 수많은 도구·라이브러리·자동화 노드가 이미 “OpenAI API 형식”을 표준으로 지원하니까, URL만 내 홈랩 서버로 바꾸면 그대로 붙습니다. 외부에 돈 내고 부르던 걸 로컬로 갈아끼우는 셈이죠. --host 0.0.0.0은 같은 네트워크의 다른 기기(n8n 등)에서 접근하게 열어 주는 옵션입니다.
2. API가 진짜 되는지 먼저 확인
워크플로우에 붙이기 전에 curl로 직접 찔러 봤습니다.
curl http://127.0.0.1:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen2.5-3b",
"messages": [{"role":"user","content":"홈랩 자동화에 로컬 LLM을 쓰면 좋은 점 한 문장."}],
"temperature": 0.3
}'
실제 응답(발췌)입니다.
"content": "로컬 LLM은 ... 홈랩 로그의 특징을 정확하게 분류하는 데 유용할 수 있습니다.",
"usage": { "prompt_tokens": 60, "completion_tokens": 50, "total_tokens": 110 }
토큰 사용량까지 OpenAI와 똑같은 스키마로 돌아옵니다. 이제 이걸 자동화 도구에 물릴 차례입니다.
3. n8n 설치 — 여기서 함정을 밟았다
자동화 도구로는 오픈소스 워크플로우 툴 n8n을 골랐습니다. 그런데 설치가 한 번에 되지 않았습니다. 최신 Debian(13)에서 npm install -g n8n이 네이티브 모듈(isolated-vm) 빌드 단계에서 죽더군요.
ModuleNotFoundError: No module named 'distutils'
gyp ERR! configure error
npm ERR! ... isolated-vm ... not ok (exit 127)
원인은 Python 3.12에서 distutils가 표준 라이브러리에서 제거됐기 때문입니다. 기본 저장소의 구버전 Node/node-gyp가 이걸 아직 참조해서 빌드가 깨진 거죠. 해결은 최신 Node로 교체하는 것이었습니다.
# NodeSource로 Node 22 설치 (npm 10 / 최신 node-gyp 포함)
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
apt-get install -y nodejs
npm install -g n8n
Node 22로 바꾸니 네이티브 모듈이 정상 빌드되고 n8n(2.35)이 깔렸습니다. 스펙표엔 안 나오는, 직접 깔아 봐야 아는 함정이라 그대로 남겨 둡니다 — 같은 에러를 만날 분이 분명 있을 테니까요.
4. n8n 워크플로우 구성 — 로그 분류기
실용적인 예로 “로그 한 줄을 INFO / WARN / ERROR로 분류”하는 워크플로우를 만들었습니다. 구조는 단순합니다.
- Manual Trigger — 실행 시작
- HTTP Request — 로컬 LLM 호출
HTTP Request 노드 설정이 전부입니다.
| 필드 | 값 |
|---|---|
| Method | POST |
| URL | http://<llama-server-IP>:8080/v1/chat/completions |
| Body | JSON (아래) |
{
"model": "qwen2.5-3b",
"messages": [
{ "role": "system", "content": "너는 로그 분류기다. 입력 로그를 INFO/WARN/ERROR 중 하나로만 답하라." },
{ "role": "user", "content": "nginx: upstream timed out (110: Connection timed out) while reading response header" }
],
"temperature": 0
}
n8n과 llama-server가 같은 호스트면 127.0.0.1, 다른 기기면 서버의 홈랩 IP를 넣으면 됩니다. system 메시지로 “분류기” 역할을 못 박고 temperature: 0으로 답을 고정한 게 포인트입니다.
5. 실행 결과 — 로컬 LLM이 정확히 판단했다
워크플로우를 실행했습니다. n8n의 실제 실행 결과(요약)입니다.
status: "success"
Local LLM 노드 → message.content: "ERROR"
timings: prompt 46 tok/s, generation 13.65 tok/s (노드 실행 1.4초)
nginx의 upstream 타임아웃 로그를 로컬 LLM이 정확히 “ERROR”로 분류했습니다. GPU도, 외부 API도, 요금도 없이 내 홈랩 안에서 자동화 파이프라인의 부품으로 로컬 LLM이 동작한 순간입니다. 이제 이 노드 앞뒤에 트리거·알림만 붙이면 실제 운영 자동화가 됩니다.
6. 이걸로 뭘 할 수 있나
- 로그·알림 분류: 서버 로그를 등급으로 분류해 ERROR만 텔레그램으로 즉시 알림
- 요약: 긴 문서·메일·뉴스를 로컬에서 요약(데이터가 외부로 안 나감)
- 정형화: 자유 텍스트를 JSON·태그로 구조화
핵심 이점은 비용과 프라이버시입니다. 외부 LLM API는 호출마다 돈이 들고 데이터가 밖으로 나가지만, 로컬 LLM은 몇 번을 부르든 0원이고 데이터가 홈랩을 벗어나지 않습니다. 실시간 초고성능이 필요한 게 아니라 배치·자동화 용도라면, GPU 없는 홈랩 CPU로도 충분히 실전에서 굴릴 수 있습니다.
시리즈를 마치며
1편 설치 → 2편 모델 선택 → 3편 자동화 연동까지, GPU 없는 i5 미니 PC 한 대로 로컬 LLM을 실전에 투입하는 전 과정을 직접 해봤습니다. “로컬 AI는 그래픽카드 있어야 한다”는 편견은, 적어도 3B급 자동화 용도에선 사실이 아닙니다. 여러분의 홈랩에도 하나 올려 보시길 권합니다.