Skip to content
게으른 엔지니어의 기술 블로그
Go back

Claude Code한테도 메모리를 붙여주려다가 4편 — 틀리는 게 아니라 지어내고 있었다, 그래서 답변 모델만 되돌렸다

3편에서 Claude Code에도 Honcho를 붙일지 판단하려고 실험을 설계하다가 장애부터 발견했었다. 그 조사와 감시 장치는 그날(07-13) 만들었는데, 정작 Claude Code에 실제로 붙는 훅 (대화 시작 시 관련 기억을 불러오는 것, 대화 끝날 때 새 내용을 저장하는 것) 자체는 그다음 날 아침(07-14)에야 만들어졌다 — 파일 생성 시각을 나중에 다시 확인해보고서야 알았다. 그때부터 오늘(07-17)까지, 사흘째 여러 프로젝트를 오가며 실사용 중이다.

미리 밝혀두자면 이번 글은 순전히 개인적인 실사용 경험이다. 지금 쓰는 모델은 gemini-3.1-flash-lite고(2편에서 “정확도는 비슷한데 7배 빠르다”는 이유로 전 구간을 이 모델로 통일했다), 다른 모델이나 reasoning level 조합으로 쓰면 결과가 달라질 수 있다 — 일반적인 결론이라기보다는, 사흘 동안 실제로 겪은 사례 모음에 가깝다.

지난 글에서 설계된 실험으로 확인한 건 “약한 모델(low)은 가끔 비슷한 이름 두 개를 헷갈린다”는, 확률적이지만 그래도 이해할 만한 실패 패턴이었다. 근데 사흘 동안 실전에서 써보니, 그것보다 훨씬 다루기 까다로운 패턴이 계속 나왔다.

버전 번호를 지어냈다

플러그인 패치 버전을 올리려는데, 마침 hook이 먼저 끼어들어서 “현재 최신 버전은 0.89.5”라고 알려줬다. 확인해보니 실제 manifest.json엔 0.89.7이 적혀 있었다. 틀린 정도가 아니라 — 지어낸 숫자였다. 실제 버전을 검증하지 않고 진행했다면, 이미 존재하는 버전 번호로 다시 릴리스를 시도했을 거다.

PR 리뷰 이메일 내용을 통째로 지어냈다

오픈소스 PR에 리뷰 답장이 왔다는 걸 알려달라고 했더니, hook이 이런 요약을 내놨다 — “AstroPaper 프로젝트에 낸 PR인데, 기여에 감사하다는 인사와 함께 머지 전에 몇 가지 추가 확인이 필요하다는 내용”이었다.

실제 메일을 직접 열어보니 완전히 달랐다. AstroPaper가 아니라 전혀 다른 리포 (hermes-agent)에 낸 PR이었고, 내용도 감사 인사가 아니라 자동 리뷰 봇이 “이 경고 메시지가 안내하는 YAML 문법이 실제로는 잘못됐다”고 구체적인 코드 라인까지 짚어가며 지적한, 훨씬 기술적이고 정확한 리뷰였다. 프로젝트 이름부터 리뷰 성격까지, 겹치는 게 하나도 없었다.

”이미 고쳤다”고 세 번 우겼다

블로그 초안 문장 하나를 고쳐달라고 요청할 때마다, hook이 매번 “요청하신 대로 수정했습니다”라며 구체적인 before/after 문구까지 붙여서 알려줬다. 근데 실제 파일을 열어보면 세 번 다 그대로였다 — 아무것도 안 바뀌어 있었다. 심지어 hook이 제시한 “수정 후” 문구조차 실제로 요청한 것과 미묘하게 달랐다.

이게 앞의 두 사례보다 더 신경 쓰였다. 사실이 틀린 것과, “작업을 완료했다”고 확신에 찬 어조로 보고하는 건 다른 문제다. 만약 실제 파일을 매번 다시 열어서 확인하지 않았다면, 안 고쳐진 글을 고쳐졌다고 믿고 그대로 넘어갔을 거다.

완전히 다른 맥락을 계속 섞어 넣었다

이번 세션엔 최근 마무리한 작업(웹 클리퍼 중복 클리핑 문제)이 하나 있었는데, hook은 그 뒤로도 계속 이 주제를 다른 대화에 끼워 넣었다 — 플러그인 프롬프트 설계를 논의하는 중에도, 디버그 모드 얘기를 하는 중에도, 심지어 무관한 이메일 확인 요청에도 “Web Clipper 중복 문제와 관련이 있어 보인다”는 식으로 등장했다. 다섯 번 넘게 반복됐다. 이미 끝난 이야기 하나에 꽂혀서, 새로운 맥락을 그 틀에 억지로 끼워 맞추는 것처럼 보였다.

정리 자체를 지어냈다

가장 인상 깊었던 사례는 이거였다 — 코드 변경 이유를 문서로 잘 정리해달라고 했더니, hook이 “이미 문서화가 완료됐다”며 그럴듯한 근거 목록(개인정보 보호, 보안 우려, 로그 혼선 방지 등)을 스스로 만들어서 제시했다. 문제는 그 근거들이 실제로 논의된 적이 전혀 없는 내용이었다는 거다. 실제 이유(카탈로그가 이미 같은 정보를 실시간으로 더 풍부하게 제공하고 있어서 중복이었다는 것)와는 방향 자체가 달랐다.

사실을 잘못 아는 것과, 그럴듯한 문서를 통째로 새로 지어내는 건 완전히 다른 급의 문제다.

패턴을 정리해보면

지난 글에서 본 실패(비슷한 이름 헷갈림)는 저장은 정확한데 답변 합성 단계에서 흔들리는, 그래도 원인을 짐작할 수 있는 종류였다. 이번에 실전에서 본 실패들은 성격이 달랐다 —

전부 다 “모른다”고 인정하는 대신 그럴듯한 답을 지어내는 방향으로 실패했다. 그리고 자신감 있는 어조는 실제 정확도와 전혀 상관없었다 — 틀린 답도 맞는 답만큼 확신에 차 있었다.

매번 hook이 주는 정보를 검증 없이 그대로 쓰지 않고, 사실 확인이 필요한 부분은 항상 직접 파일을 읽거나 명령어를 돌려서 재확인하는 식으로 대응했다. 버전 번호는 manifest.json을 직접 읽고, 이메일 내용은 실제로 열어서 확인하고, “이미 고쳤다”는 말은 무시하고 매번 grep으로 재확인했다. 근데 매번 재검증해야 한다면, 애초에 기억을 불러오는 비용을 들일 이유가 약해진다. 검증 습관만으로 넘어갈 문제가 아니라는 판단이 들어서, 같은 날(07-17) 설정을 하나 바꿨다.

왜 저장 쪽은 그대로 뒀나

Honcho는 크게 두 단계로 나뉜다 — 대화를 읽고 기억을 추출해서 저장하는 deriver, 그리고 질문에 답할 때 저장된 기억을 검색해서 답을 합성하는 dialectic. 위에서 나온 문제들(버전 번호, 이메일 내용, 완료 보고, 문서 근거)은 전부 dialectic 쪽 — “질문에 답하는” 순간에 지어낸 것들이었다.

deriver 쪽을 의심할 이유는 지금까지 없었다. 시리즈 초반과 3편에서 저장된 원본 데이터 (observation)를 직접 까봤을 때 항상 정확했고, 이번 3일 동안도 저장 실패나 큐 정체는 없었다. 만약 deriver까지 의심된다면 문제가 훨씬 커진다 — 지금까지 쌓인 기억 자체를 못 믿게 되고, 최악의 경우 전부 지우고 다시 쌓아야 한다는 뜻이다. 다행히 그 정도는 아니라고 판단했다. 그래서 저장은 그대로 두고, 답변을 합성하는 dialectic 쪽만 손대기로 했다.

왜 낯선 모델이 아니라 이미 검증된 모델로

dialectic의 5단계(minimal/low/medium/high/max)는 전부 gemini-3.1-flash-lite로 통일돼 있었다 — 3편에서 “정확도는 비슷한데 7배 빠르고 가격은 절반”이라는 이유로 바꾼 설정이다. 이번엔 그걸 gemini-3-flash-preview로 되돌렸다.

새 모델을 시도해볼 수도 있었지만, 그러지 않았다. gemini-3-flash-preview는 3편에서 7개 질문으로 이미 정확도를 검증해본 모델이다. 지금 필요한 건 “더 똑똑한 모델을 찾는 실험”이 아니라, “이미 정확하다고 확인된 조합으로 일단 되돌리는 것”이었다. 검증 안 된 새 모델을 넣으면, 나중에 문제가 또 생겼을 때 “모델을 바꿔서 그런가, 아니면 원래 있던 문제인가”를 구분할 수 없게 된다.

# 5개 레벨 전부 동일하게 변경
[dialectic.levels.low.model_config]
transport = "gemini"
- model = "gemini-3.1-flash-lite"
+ model = "gemini-3-flash-preview"

deriver, summary, dream, embedding 설정은 손대지 않았다.

파일만 고쳐서는 안 됐다

설정 파일을 고치고 나서 바로 끝난 줄 알았는데, config.toml이 호스트에 마운트되는 게 아니라 Docker 이미지 빌드 시점에 이미지 안으로 복사되는 방식이었다.

COPY --chown=app:app config.toml* /app/

그래서 파일만 바꾼 상태로는 컨테이너 안의 실제 설정이 그대로였다. apideriver가 같은 Dockerfile을 쓰고 있어서, 재빌드하면 두 컨테이너가 같이 재생성됐다.

docker compose up -d --build api deriver

재시작했다고 바로 믿지 않았다

3편에서 배운 게 있어서, 재시작만 하고 넘어가지 않았다. 컨테이너 안에 실제로 새 설정이 들어갔는지 직접 확인했다.

docker exec honcho-api-1 grep "model = " /app/config.toml
# dialectic 5개 레벨 전부 gemini-3-flash-preview, deriver/summary/dream은 그대로

그리고 재시작 과정에서 혹시 representation 큐가 또 조용히 멈추지 않았는지도 확인했다.

docker exec honcho-database-1 psql -U honcho -d honcho -t -c "
  SELECT COALESCE(EXTRACT(EPOCH FROM (now() - min(created_at)))::int, 0)
  FROM queue WHERE processed = false AND task_type = 'representation';
"
# 0

밀린 게 없었다. 설정도 정확히 반영됐고, 저장 파이프라인도 멀쩡했다.

지금 상태

새 관찰 구간의 시작점

컨테이너가 새 설정으로 실제 기동한 시각은 **2026-07-17 03:44:09 (KST)**다. 이 시점 이전에 나온 답변(위에 모아둔 사례들 포함)은 전부 gemini-3.1-flash-lite 기준이고, 이 시점 이후부터가 gemini-3-flash-preview로 답한 결과다. 나중에 “그래서 바뀐 다음엔 어땠나”를 판단할 때 헷갈리지 않으려고 정확한 기준점을 남겨둔다.

지금은 결론을 낼 수 없다 — 방금 바꾼 참이라 비교할 데이터가 없다. 며칠 더 이 설정으로 실사용하면서, 위에서 나왔던 지어내기 패턴(버전 번호, 이메일 내용, “이미 고쳤다” 같은 확인 가능한 사실)이 이 기준점 이후로 줄어드는지 지켜본 다음 다시 판단하기로 했다. 결과는 다음 편에 계속.


Share this post:

Previous Part
Claude Code한테도 메모리를 붙여주려다가 3편 — 판단 기준을 만들다가 장애부터 찾았다
Next Part
Claude Code한테도 메모리를 붙여주려다가 5편 — 틀린 이유가 다 같지 않았다