21회차 에이전트와 22회차 평가·서빙까지 만들었다면 '한 번 돌리면 잘 되는' 시스템은 완성입니다. 하지만 실제 서비스의 진짜 난관은 그다음입니다. 사람이 안 보는 동안 매일, 몇 주씩 돌아가야 하니까요. 그사이 API는 한 번쯤 죽고, 모델은 가끔 이상한 답을 내고, 네트워크는 끊깁니다. 이 '데모와 제품의 간극'을 메우는 네 가지 설계를 이번 회차에서 다룹니다. 바로 메모리, 비결정성, 복구, 비용입니다.
🧠 메모리 설계 — 세션이 끝나도 이어지는 비서
LLM은 대화가 끝나면 전부 잊습니다. '어제 하던 일을 이어서' 하려면 기억을 모델 밖에 저장해야 해요. 기억은 세 층으로 나눕니다.
- 단기 기억 — 지금 대화가 담긴 컨텍스트 창입니다. 길어지면 요약해서(컴팩션) 핵심만 남깁니다. 21회차 하네스의 컨텍스트 관리가 바로 이것이었죠.
- 장기 기억 — 세션이 끝나도 남겨야 할 것들입니다. 사용자 취향, 진행 상황, 작업 이력을 파일이나 DB에 저장해 두고, 다음 실행 때 다시 읽어 옵니다.
- 검색형 기억 — 기록이 많이 쌓이면 전부 넣을 수 없습니다. 그래서 벡터 검색으로 '지금 필요한 기억만' 골라 옵니다. 사실 20회차 RAG가 바로 이 장기 기억입니다.
# 장기 기억의 최소 구현 — 거창한 DB 없이 파일부터
memory/
├── profile.md # 사용자 취향·반복 지시 ('요약은 3줄로', '~는 제외')
├── state.json # 진행 상황 (마지막 수집 날짜, 처리한 항목 ID 목록)
└── history/ # 실행별 결과 기록 (중복 방지·회고용)
# 실행 시작 때 읽고 → 끝날 때 갱신. 이것만으로 '이어서 일하는' 비서가 된다.
🎲 비결정성 제어 — 같은 입력, 다른 출력 길들이기
LLM은 같은 질문에도 매번 조금씩 다른 답을 냅니다. 데모에선 애교지만 매일 도는 시스템에선 사고입니다. 어제는 JSON을 주다가 오늘은 사과문을 주면 파이프라인 전체가 멈추니까요. 대책은 하나로 요약됩니다. '출력을 믿지 말고 검증하기'입니다.
- 스키마 검증 + 재시도 — 19회차 구조화 출력의 실전판입니다. 출력이 틀에 안 맞으면 에러 메시지를 붙여 1~2회 다시 요청하고, 그래도 실패하면 안전하게 중단합니다.
- 출력 계약 — '반드시 이 필드, 이 형식'을 프롬프트와 코드 양쪽에 못 박습니다. 그러면 코드가 계약 위반을 즉시 잡아냅니다.
- 검증 게이트 — 결과가 다음 단계로 넘어가기 전에 규칙을 검사합니다. 개수·형식·금지어 같은 것이죠. 22회차의 judge를 이 게이트로 세워도 됩니다.
- 안전한 기본값 — 끝내 실패하면 이전 성공 결과를 그대로 유지하고 알립니다. 틀린 결과로 덮어쓰는 것보다 백배 낫습니다.
# 검증-재시도 루프 (의사코드) — '믿지 말고 검증'의 뼈대
for attempt in range(3):
raw = ask(prompt)
ok, errors = validate(raw) # 스키마·개수·금지어 검사
if ok:
return parse(raw)
prompt += f'\n형식 오류: {errors}. 스키마에 맞춰 다시.'
return last_good_result # 끝내 실패 → 이전 성공본 유지 + 알림
🔁 긴 워크플로 복구 — 3단계에서 죽으면 1단계부터?
수집→정리→검증→반영처럼 여러 단계가 이어진 작업을 생각해 봅시다. 3단계가 실패했다고 처음부터 다시 돌리면 시간과 비용이 두 배로 듭니다. 해법은 단계마다 결과를 저장해 두는 것입니다. 이걸 체크포인트라고 해요. 재시작하면 실패한 단계부터 이어서 돌립니다.
- 체크포인트 — 각 단계의 출력을 파일이나 DB에 저장합니다. 재시작하면 이미 끝난 단계는 건너뜁니다.
- 멱등성 — 같은 단계를 두 번 실행해도 결과가 망가지지 않게 만드는 것입니다. 덮어쓰기 전에 확인하고, 중복 ID를 체크합니다.
- 부분 실패 — 항목 100개 중 3개가 실패했다고 전부 멈추지 않습니다. 성공한 97개는 진행하고, 실패한 3개만 기록해 뒀다가 다음 실행 때 다시 시도합니다.
- 타임아웃·서킷브레이커 — 응답 없는 도구는 기다리지 말고 끊습니다. 연속으로 실패하는 도구는 잠시 쉬게 합니다. 21회차 실패 처리를 확장한 개념이에요.
⚡ 지연·비용 최적화 — 빠르고 싸게
품질이 같다면 빠르고 싼 쪽이 이깁니다. 최적화에는 대전제가 하나 있어요. 먼저 22회차 트레이싱으로 '어디서 시간과 돈이 새는지'를 숫자로 본 다음에 손을 대는 것입니다.
- 모델 티어링 — 분류·라우팅·간단한 요약은 작고 싼 모델에 맡기고, 어려운 추론만 큰 모델에 맡깁니다. 이것만으로 비용이 몇 분의 1로 줄어요.
- 캐싱 — 같은 입력에는 저장해 둔 답을 재사용합니다(22회차). 프롬프트의 공통된 앞부분을 할인해 주는 '프롬프트 캐싱'도 프로바이더마다 지원합니다.
- 스트리밍 — 전체 응답을 기다리지 않고 첫 글자부터 바로 흘려보냅니다. 그러면 '체감 지연'이 줄어듭니다.
- 프롬프트 다이어트 — 습관적으로 넣던 불필요한 문서나 이력을 걷어냅니다. 토큰이 곧 돈이고 지연이니까요.
🔧 만들 것 — 자료 수집 에이전트를 '무인 운영' 등급으로
21회차 에이전트를 이 회차의 네 가지 설계로 무장시킵니다. 새 기능이 아니라 '안 죽는 힘'을 붙이는 업그레이드예요.
- ① 메모리 — 처리한 항목 ID·마지막 실행 시각을 state.json에 저장, 재실행 시 중복 수집 방지
- ② 검증 게이트 — 수집 결과에 스키마 검증+재시도를 달고, 끝내 실패하면 이전 결과 유지+알림
- ③ 체크포인트 — 수집·정리·초안 단계별로 저장, 중간에 죽여도 이어서 재개되는지 확인
- ④ 스케줄 실행 — cron 등으로 매일 자동 실행하고 성공/실패를 로그·알림으로 남기기
- ⑤ 비용 리포트 — 실행당 토큰·비용을 기록하고, 쉬운 단계를 작은 모델로 바꿔 전/후 비용 비교
✅ 완료 기준 (숫자로 닫기)
- 손대지 않고 3일 연속 자동 실행이 성공한다(로그로 증명).
- 실패 주입 테스트 통과 — 네트워크 차단·빈 응답·깨진 JSON을 일부러 넣어도 스스로 복구하거나 안전하게 멈춘다.
- 재시작해도 중복·유실이 없고(멱등성), 티어링 적용 전/후 실행당 비용을 숫자로 답할 수 있다.
📌 23회차 핵심
- 데모와 제품의 차이 = 신뢰성. 'AI는 틀리고 도구는 실패한다'를 전제로 설계한다.
- 기억은 모델 밖에 — 단기(컨텍스트 요약)·장기(파일·DB)·검색형(RAG)의 3층 구조.
- 출력은 믿지 말고 검증 — 스키마 검증·재시도·검증 게이트·안전한 기본값.
- 긴 작업은 체크포인트로 이어 달리고, 비용은 트레이싱으로 본 뒤 티어링·캐싱으로 줄인다.
이제 시스템은 사람이 안 봐도 매일 돌아갑니다. 남은 마지막 한 걸음은 그 시스템의 심장, 즉 모델 자체를 우리 데이터로 만드는 일입니다. 다음 24회차가 이 트랙의 마지막 봉우리입니다.