Claude Haiku 대신 Ollama gemma4:e4b — 웹서치와 파일 탐색을 로컬 LLM으로

웹 검색 결과를 정리하거나, 코드베이스에서 관련 파일을 추려내는 작업에 클로드 하이쿠 API를 쓰다 보면 어느 순간 “이 정도 작업을 꼭 클라우드 API로 보내야 하나?”라는 의문이 든다. 민감할 수 있는 파일 내용이나 내부 코드가 외부 서버를 거친다는 점도 마음에 걸린다.

터미널 화면에 코드가 실행되는 모습

이미지 출처: Unsplash

마침 올라마(Ollama)에서 gemma4:e4b를 로컬에서 돌려본 뒤로 생각이 달라졌다. 반복성 높은 경량 작업에서는 하이쿠와 체감 차이가 거의 없으면서, API 비용은 0원이다. 이 글은 그 경험을 정리한 것이다.

gemma4:e4b가 뭔지부터

gemma4는 구글 딥마인드가 2025년에 공개한 Gemma 4 시리즈 모델이다. e4b는 “early 4-bit quantized” 모델로, 약 4GB 메모리 안에서 구동이 가능하다. 양자화(quantization)를 거쳤기 때문에 풀 정밀도 모델보다 품질이 약간 낮지만, 로컬에서 돌리기에는 충분한 균형점을 찾은 버전이다. M 시리즈 맥북이라면 GPU 없이 통합 메모리(unified memory)에서 바로 추론이 돌아간다. 내가 쓰는 환경은 M5 Pro, 48GB 통합 메모리인데, 이 스펙에서는 모델 로딩 자체가 몇 초 안에 끝나고 짧은 응답은 1초 안팎으로 나온다. 4GB 남짓 차지하는 모델이 48GB에 올라가니 메모리 압박도 전혀 없다.

설치 방법

올라마 자체는 공식 사이트에서 인스톨러를 내려받거나 macOS라면 터미널 한 줄로 끝난다.

brew install ollama

설치 후 모델을 가져오는 것도 단순하다.

ollama pull gemma4:e4b

약 4~5GB 다운로드가 진행되며, 이후로는 네트워크 없이 로컬에서만 구동된다. 서버 실행은 ollama serve로 하거나, 앱을 실행하면 백그라운드에서 자동 기동된다. API는 기본적으로 localhost:11434에서 REST로 노출된다. OpenAI 호환 엔드포인트도 지원해서, /v1/chat/completions 경로를 그대로 쓸 수 있다.

파이썬에서 호출할 때는 이렇게 된다. OpenAI 호환 엔드포인트를 쓰면 기존 코드 변경이 거의 없다.

from openai import OpenAI

client = OpenAI(base_url="http://localhost:11434/v1", api_key="ollama")

response = client.chat.completions.create(
    model="gemma4:e4b",
    messages=[{"role": "user", "content": "..."}],
)
print(response.choices[0].message.content)

웹서치 결과 처리

가장 먼저 붙여본 작업은 웹 검색 결과를 파이프라인으로 넘겨서 관련성을 걸러내는 용도였다. 예를 들어 특정 기술 키워드로 검색한 결과 10~20개를 한꺼번에 넘기고, “내가 찾는 주제와 실제로 연관된 링크만 남겨줘”라고 지시하는 식이다.

직접 써본 시나리오는 이렇다. DuckDuckGo나 Brave Search의 API로 검색 결과 JSON을 받아온 뒤, 제목과 snippet을 묶어서 gemma4:e4b에게 “다음 중 XXX 라이브러리의 실제 사용 예제가 담긴 링크를 골라줘”라고 넘겼다. 결과는 쓸 만했다. 문서 공식 사이트, 릴리즈 노트, 실제 예제 코드가 있는 링크를 꽤 정확하게 분리해냈다.

흥미로운 건 속도다. 검색 결과 20개를 한 번에 넘겨도 M5 Pro 기준 2초 안팎에 응답이 온다. 클라우드 API를 쓰면 네트워크 왕복에 토큰 비용까지 붙는데, 로컬이라 그런 고민이 없다. 같은 쿼리를 100번 돌려도 부담이 없으니 자동화 스크립트에 그냥 박아두게 된다.

한 가지 주의할 점은 프롬프트를 명확하게 구조화해야 한다는 것이다. “관련 있는 거 골라줘” 정도의 느슨한 지시보다는, 기준을 구체적으로 써줄수록 결과 품질이 올라간다. JSON으로 결과를 받고 싶다면 예시 포맷을 프롬프트에 직접 넣어주는 편이 낫다.

Claude Haiku 대신 Ollama gemma4:e4b — 웹서치와 파일 탐색을 로컬 LLM으로

이미지 출처: Unsplash

파일 탐색과 코드 검색

두 번째로 많이 쓰는 용도는 파일 시스템 탐색이다. 낯선 레포지토리에 처음 들어갔을 때, 어떤 파일이 어떤 역할을 하는지 빠르게 파악하고 싶을 때 쓴다.

구체적으로는 find 또는 tree 명령으로 디렉토리 구조를 뽑아 gemma4:e4b에 넘기고, “설정 파일이 어디 있을 것 같냐”, “라우팅 로직은 어느 디렉토리에 있을 것 같냐”를 물어본다. 그러면 파일명 패턴과 디렉토리 이름만 보고도 꽤 합리적인 추측을 내놓는다. 이어서 해당 파일의 일부를 읽어 넘기면 “이 파일은 미들웨어 설정이고, 인증 로직은 여기서 체인으로 연결되는 것 같다”는 식의 요약을 해준다.

grep 결과를 넘기는 것도 효과적이다. 심볼이나 함수명으로 검색한 결과가 20~30줄 나왔을 때, 어느 것이 실제 정의이고 어느 것이 호출부인지 맥락 없이 눈으로 훑기가 귀찮다. gemma4:e4b에 grep 출력 전체를 붙여넣고 “정의 위치만 찾아줘”라고 하면 파일 경로와 줄 번호를 정확하게 추려준다. 모델이 틀리는 경우도 있지만, 수십 줄을 직접 읽는 것보다 훨씬 빠르게 첫 번째 후보를 좁혀준다.

개인적으로 가장 유용했던 케이스는 로그 파일 분석이다. 수백 줄짜리 스택 트레이스를 잘라서 넘기고 “에러 원인과 가장 관련 깊은 라인만 요약해줘”라고 했을 때, 하이쿠와 비교해도 손색없는 수준으로 핵심 라인을 짚어냈다.

Claude Code 스킬로 위임 자동화하기

로컬 Ollama 호출을 매번 파이썬 스크립트로 짜는 건 번거롭다. 실제로는 Claude Code의 스킬(skill) 시스템을 활용해서, “이런 류의 작업이면 Ollama로 넘겨”라는 트리거 규칙을 한 번만 정의해두고 재사용하고 있다.

스킬은 ~/.claude/skills/<스킬이름>/SKILL.md 형태로 저장되는 마크다운 파일이다. 파일 상단에 YAML 프론트매터로 이름과 트리거 설명을 적어두면, Claude Code가 대화 중에 조건이 맞는다고 판단할 때 자동으로 해당 스킬을 읽고 따른다.

내가 만들어 쓰는 ollama-local-delegate 스킬의 구조를 보면 이런 식이다.

---
name: ollama-local-delegate
description: Use when facing repetitive file scanning, bulk text processing,
  pattern extraction tasks, or web research where preserving Claude's context
  window matters. Delegates grunt work to local Ollama LLM (gemma4:e4b) via API.
---

# Ollama Local Delegate

## When to Use

- 파일 수십 개 이상 반복 스캔 (패턴 추출, 분류)
- 대량 텍스트 요약/변환
- 단순 반복 판단 ("이 파일이 X 조건에 해당하는가?")
- 웹 검색 결과 필터링

## Core Pattern

python3 - /path/to/files/*.md <<'PYEOF'
import json, sys, urllib.request

for path in sys.argv[1:]:
    content = open(path).read()[:2000]
    payload = json.dumps({
        "model": "gemma4:e4b",
        "prompt": f"...",
        "stream": False
    }).encode()
    req = urllib.request.Request("http://localhost:11434/api/generate", data=payload)
    with urllib.request.urlopen(req) as r:
        print(f"{path}: {json.load(r)['response'].strip()}")
PYEOF

여기서 핵심은 description 필드다. “언제 이 스킬을 써야 하는가”를 구체적으로 써둘수록 Claude가 적절한 타이밍에 꺼내 쓴다. 트리거 문구를 느슨하게 쓰면 관련 없는 상황에서도 발동되고, 너무 좁게 쓰면 써야 할 때 놓친다. 몇 번 써보면서 description을 조금씩 다듬는 게 스킬 작성의 핵심 작업이 된다.

스킬 안에는 패턴뿐 아니라 주의사항도 적어두면 좋다. 예를 들어 파일 내용을 curl 명령 인라인에 직접 보간하면 JSON이 깨지는 문제가 있는데, 그런 “절대 하지 말 것” 항목을 스킬 파일 안에 명시해두면 같은 실수를 반복하지 않게 된다.

스킬 직접 만드는 법

만드는 과정 자체는 단순하다.

mkdir -p ~/.claude/skills/ollama-local-delegate
touch ~/.claude/skills/ollama-local-delegate/SKILL.md

파일 내용은 다음 구조를 따른다.

---
name: 스킬이름
description: 이 스킬을 언제 쓸지 — 구체적인 상황을 영어나 한국어로 서술
---

# 스킬 제목

## When to Use
(어떤 상황에 적용할지)

## 패턴 또는 지시사항
(Claude가 따라야 할 절차나 코드 템플릿)

저장하면 Claude Code를 재시작할 필요 없이 바로 인식된다. /skills 명령어나 대화 중 Skill 도구로 언제든 불러올 수 있다.

한 가지 실용적인 팁은 스킬을 처음부터 완벽하게 만들려 하지 말고, 실제 작업에서 “이 패턴을 다음에도 쓰겠다”는 순간에 바로 파일로 옮기는 것이다. 작업하다 나온 파이썬 스니펫을 복사해서 스킬로 등록하는 데 2~3분이면 충분하다. 그렇게 쌓인 스킬이 서너 개를 넘어서면, 반복 작업을 로컬 모델에 위임하는 흐름이 자연스러워진다.

어디서 멈추는가

솔직히 말하면 한계도 명확하다. 지시 준수(instruction following) 정밀도가 하이쿠보다 떨어진다. 복잡한 조건을 중첩해서 요청하거나, 여러 단계를 한 번에 처리하게 하면 중간에 흐름이 끊기는 경우가 생긴다. 또 컨텍스트 창이 넉넉하지 않아서 파일이 길어지면 뒷부분이 잘리거나 앞부분 내용을 잊어버리는 일도 있다.

그래서 운용 원칙은 단순하게 유지된다. 작업 하나에 입력 하나, 출력 하나. 복잡한 판단이 필요한 건 클라우드 모델로 넘기고, 반복적이고 경계가 뚜렷한 작업만 로컬에 맡긴다. 그렇게 역할을 나눠보니 API 비용이 실질적으로 줄었고, 내부 코드나 파일이 외부 서버를 거치지 않는다는 안도감도 생겼다. 완전한 대체제를 찾는다기보다, 용도에 맞는 도구를 하나 더 갖게 된 느낌이 맞는 표현일 것 같다.


출처

댓글 남기기