셀프호스팅 기억 엔진 대정비 - 9모델 전쟁, 좀비 크론, 그리고 '캡은 보험일 뿐' 철학
TL;DR
- 셀프호스팅 기억 엔진(Honcho)의 회상 회로(dialectic)를 3일간 총망아 교체했다: 9모델 실측 전쟁 → 좀비 크론 사고 → 설정 철학 전쟁
- 최종 아키텍처: 기록은 glm-5.3-flash(정액 무료), 일상 회상은 haiku-5.5(실측 $0.0135/회), 깊은 조사(max)만 glm-5.3+thinking MAX(무료, 실측 178초)
- 캡(턴수·출력 토큰)은 절약 도구가 아니라 발산 방지 보험이다 - 서버 허용 최대치로 통일하는 게 정답이었다
- 가장 큰 교훈: 소스 기본값에는 "레벨별로 다른 모델"이라는 숨은 가정이 있다. 그 가정을 깨는 순간 기본값은 독이 된다
배경: 벤치 승리로 끝이 아니었다
지난 글에서 셀프호스팅 Honcho의 회상 백엔드 6-way 실측으로 haiku-5.5가 승리했음을 적었다. 그런데 벤치 우승은 시작의 절반이었다. 운영 적용 → 사고 → 설정 원칙 정립까지 가야 끝나는 게 자기 서버 관리다. 이 글은 그 후반전 기록이다.
9모델 전쟁의 전체 성적표
동일 프로토콜(3-팩트 회상 × 10회)로 실제 dialectic 파이프라인을 돌린 결과:
| 실험 | 모델 | 결과 | 판정 |
|---|---|---|---|
| EXP3 | recursive/flint-v1.0:free | 정확도 71% | 무료의 대가 - 비추천 |
| EXP3b | mistral-nemo ($0.03/M) | 팩트 0% (합성 실패) | 미채용 |
| EXP3c | nemotron-3-ultra-550b (로컬 게이트웨이) | 120s 타임아웃 5/9 | 단일호출 안정성이 다중호출에서 증폭 붕괴 |
| EXP3d | qwen3.5-flash | "정보 없음" 정직 거절로 스크리닝 탈락 | → 컨텍스트 있으면 달라진다는 교훈으로 haiku 재검증 트리거 |
| EXP3e | haiku-5.5 | 20.9s · 팩트 30/30 · $0.0135/회 | 👑 우승 |
| EXP3f | haiku + Anthropic 네이티브 캐싱 | 캐싱 무효 | cache_control 마커가 system에만 붙어 본류 미커버 |
| EXP3g | gpt-6-luna | 13.7s 신기록, 비용 18% | 품질 미달 - 속도 왕은 의미 없음 |
| EXP3h | haiku + thinking off | 13.1s지만 정확도 100→62% | thinking이 합성 품질의 핵심임을 실증 |
개인적으로 가장 인상 깊었던 건 EXP3e의 메타 정직성이다. 회상 답변에서 "F1 0.92라는 수치는 Honcho 실험 프롬프트에 적힌 문구다"라고 출처를 스스로 식별하고 내 발언과 구분했다. 없는 걸 지어내지 않는 성향이, 16K 기억 컨텍스트가 실리는 환경에선 정확성으로 승화됐다.
그리고 실험 전체를 관통하는 교훈: 단발 스크리닝 ≠ 파이프라인 성능. 원샷 3.8s짜리 free 모델이 16K 컨텍스트 dialectic에선 평균 86s·타임아웃 20%였다. 모델 선정은 반드시 실제 부하로 e2e 10회를 돌려야 한다.
좀비 크론: 자동화가 자기 설정을 되돌리는 사건
벤치 내내 가장 소름 돋는 장면. 실험 감시용으로 만들어뒀던 n8n 게이트가 흐지부지 종료됐는데, 그 안의 5분 크론이 아직 살아 있어서 밤 9시 20분에 스스로 부활해 진행 중인 실험의 .env를 "복구"(=되돌리기)했다. 재현 중인 실험이 원래 없던 설정으로 Kill 당하는 것.
대응은 원천 차단이 정답이다:
- n8n 정지 + 좀비 실행 전수 삭제 (잔좀비 스캔 포함)
.env에chattr +i(immutable) - 파일 단위 방화벽- 벤치 인프라는 n8n → Windmill 이식 (Postgres durable 큐·스텝 단위 병렬)
교훈: 자동화의 감시자는 반드시 수명을 갖혀야 한다. 일회성 작업의 게이트가 무기한 크론으로 남으면, 언젠가 그게 주인을 문다.
적용 단계의 함정 2종
- API 키 경로:
MODEL_CONFIG__API_KEY_ENV는 조용히 무시된다. 반드시OVERRIDES__API_KEY_ENV. 증상은 401인데 원인은 설정 위치라 디버깅이 오래 걸렸다 - thinking 캡: haiku에서 thinking을 끄면 위 표대로 62% 붕괴. "기본값이 최적"이라는 걸 주석으로 못 박아둠
검증 도구의 함정
설정을 바꿨는데 진짜로 적용됐는지 확인하는 것도 함정 투성이었다.
docker exec -e VAR=x로 오버라이드 테스트가 안 통한다 - 앱이 기동 시load_dotenv(override=True)로 마운트된/app/.env를 항상 이긴다. 실효값 확인은 컨테이너 안에서 직접 settings를 introspect하는 수밖에 없다- env에
MAX_OUTPUT_TOKENS=null(전역 폴백 의도)을 쓰면env_parse_none_str미설정 탓에 검증 크래시로 서버가 안 뜬다. 동값 명시가 정답
소스 기본값의 숨은 가정: 턴 사다리 역전
Honcho dialectic 레벨(minimal~max)의 소스 기본 턴수는 1/5/2/4/10이다. low가 medium보다 2.5배 많은, 단조도 아닌 사다리. 최초 도입 커밋을 뒤져보니 답이 있었다:
# TODO: Fill in appropriate values for each reasoning level
개발자 본인도 손튜닝 임시값임을 남긴 코드. 그리고 이 값들의 전제는 레벨마다 다른 모델+thinking이다(원래 low=싸고 빠른 flash 모델이 검색을 5번 돌리는 티어). 나는 9모델 전쟁에서 모델을 통일했으니, 남는 건 턴수뿐 - 그 순간 사다리는 역전된 채로 굴러간다. "레벨을 올릴수록 좋아진다"는 기대가 설정값으로는 성립 안 되는 구조.
캡 철학: 보험은 모델 한계 근처에
여기서 내 원칙을 확정했다: 캡은 절약 도구가 아니라 발산 방지 보험이다.
- output 토큰 캡을 낮춰도 절감은 0이다. 과금은 실제 생성분만 청구되고, 잘리는 순간 input+thinking 비용은 물고 답변 0개로 끝난다 - OpenAI·Anthropic·Gemini 공식 문서가 전부 같은 경고를 한다. Gemini는 아예 "max_output_tokens 줄이지 말고 thinking 레벨을 낮춰라"라고 쓰여 있다
- haiku-5.5의 공식 max output은 128K. 다만 Honcho 설정 검증이
le=100000이라 100000이 서버 허용 최대치 → 전 레벨 100000 통일 (128000을 걸면 서버가 부팅을 거부한다) - 턴수도 같은 논리. 설정 검증 상한
le=50(툴 루프 하드캡 100)이니 전 레벨 50 통일. 요즘 모델은 adaptive하게 1~3턴에 스스로 종료하니 실제 지출은 그대로고, 50은 순수하게 최악성기 상한이다
출발점은 이 믿음이다: 요즘 모델은 적당한 추론과 적당한 턴수를 스스로 잘 고른다. 그렇다면 캡은 모델을 가르치는 도구가 아니라, 폭주할 때만 잡아주는 안전망이어야 한다.
effort 기본값은 명시돼 있다 (그런데)
"haiku는 thinking 기본이 최적"이라고만 알고 있었는데, 기본이 정확히 뭔지 조사했다. 공식 문서 답변: haiku-5.5(·opus 5.5)의 기본 effort는 medium - 그 외 모델은 high. thinking은 항상 켜져 있다(adaptive).
재미있는 건 다음 실측 모순이다. 공식은 "기본값을 명시하는 것과 생략은 완전히 동일하다"는데, dialectic 실측에서 effort medium 명시 96.8s vs 생략 20.9s - 4.5배 차이가 났다. adaptive의 본질은 "생각할지 말지부터 모델이 자판"하는 건데, effort를 명시하는 순간 그 자판이 고정되는 것으로 추정한다. 어느 쪽이든 미지정 유지가 정답이라는 결론은 더 단단해졌다.
최종 아키텍처와 비용
| 역할 | 모델 | 비용 | 실측 |
|---|---|---|---|
| 기록 (deriver/summary/dream) | glm-5.3-flash + thinking max | 정액플랜 무료 | 상시 |
| 일상 회상 (low) | haiku-5.5 (thinking 미지정) | $0.0135/회 | 15~21s |
| 깊은 조사 (max) | glm-5.3 + thinking MAX | 무료(정액) | 178s |
| 검색 임베딩 | qwen3-embedding:4b | 로컬 Ollama 무료 | - |
daily 회상은 저렴하고 빠르게, "진짜 파고들어라" 요청은 무료 슬로우 티어로 보내는 구조. 턴수 50·출력 100000은 전 구간 공통 보험이다.
남은 것
- 턴별 자동 주입(perTurn) OFF 2주 실험 - 11/13쯤 재평가
- Honcho v3.0.3 → v3.0.9 (145커밋) 업그레이드 - 빌드·마이그레이션 이슈로 계속 보류 중
총정리: 남에게도 통하는 교훈
- 모델 벤치는 실제 파이프라인 부하로 e2e 10회. 단발 스크리닝은 오답을 낳는다
- 자동화 파이프라인엔 수명을 걸어라. 살아남은 크론은 언젠가 설정을 되돌린다
- 소스 기본값엔 가정이 숨어 있다. 그 가정을 깨는 배포(예: 모델 통일)를 하면 기본값을 다시 심사한다
- 캡은 보험이다. 보험료(필요량)를 계산해서 모델 한계 근처에 걸어라, 아슬아슬하게가 아니라
- 설정 검증은 앱의 실효값으로. env 변수 오버라이드는 dotenv override=True 앞에서 무력화된다


