18화 2026-06-09

매번 10초씩 멈추는 에이전트.

지난 편에서 게시판을 에이전트한테 연결하는 데 성공했어요. 그런데 쓸 때마다 묘하게 거슬리는 게 있었어요. 뭘 시키든 답하기 전에 꼭 몇 초씩 멈추고, 화면엔 늘 이 안내가 떴어요.

This response is taking longer than expected.

처음엔 “통역사(mcp-remote) 부르느라 그런가 보다” 하고 넘겼어요. 근데 게시판이랑 상관없는 걸 물어봐도 똑같이 멈추더라고요. 그러면 통역사 탓이 아니죠. 뭔가 다른 게 매번 시간을 잡아먹고 있다는 뜻이에요. 오늘은 그 정체를 끝까지 쫓아간 기록이에요.


로그를 보면 답이 있다

이런 건 머리로 추측해봤자 답이 안 나와요. 에이전트가 일하는 과정을 기록해둔 로그를 봐야 해요. OpenClaw는 작업 기록을 파일로 남겨두거든요. 방금 게시판을 불렀던 그 시각대(밤 9시 45분쯤)의 기록을 펼쳐봤어요.

grep '21:4[3-9]' /tmp/openclaw/openclaw-2026-06-09.log | tail -40

💡 grep '21:4[3-9]'는 “21시 43분~49분 사이 줄만 뽑아줘”라는 뜻이에요. [3-9]가 “3부터 9까지 아무 숫자”를 의미해요. 시간으로 범위를 자른 거죠.

쏟아진 기록 중에 이상한 단어가 눈에 박혔어요.

cli exec: provider=claude-cli model=opus ...
claude live session start: provider=claude-cli model=claude-opus-4-7

claude-cli? opus?

이게 왜 여기 있죠. 제 에이전트는 분명히 로컬 모델(qwen)로 돌아가는데, 로그엔 클라우드의 Claude(Opus)를 부르고 있다고 적혀 있었어요. 그리고 바로 아랫줄.

claude live session close: ... reason=abort
claude live session turn failed: ... durationMs=10001 error=FailoverError

claude-cli를 부른 게 **딱 10초 만에(durationMs=10001) 실패(FailoverError)**했어요. 그런데 화면엔 게시판 글이 멀쩡히 떴잖아요. 어떻게 된 걸까.

그 다음 줄에 답이 있었어요.

[trace:embedded-run] ... bundle-tools:5826ms ...

claude-cli가 죽은 직후, embedded(임베디드, 로컬) 실행이 일을 받아서 끝낸 거예요. 즉 흐름이 이랬어요.

  1. 에이전트한테 일을 시킴
  2. 먼저 claude-cli(클라우드 Claude)를 부름
  3. 그런데 제 컴퓨터엔 Claude 인증이 없으니, 10초 기다리다 실패
  4. 실패하자 로컬 모델(qwen)로 넘김(failover)
  5. 그제야 로컬 모델이 일을 끝냄

화면의 “This response is taking longer than expected” 그 멈춤이, 바로 3번의 10초였어요. 매번 안 되는 클라우드를 먼저 두드려보고, 10초 헛걸음한 뒤에야 로컬로 넘어가고 있었던 거예요.


그런데 claude-cli를 설정한 적이 없는데

여기서 의문이 생겼어요. 저는 claude-cli를 쓰겠다고 한 적이 없어요. 제 에이전트 설정엔 분명히 로컬 모델만 박아뒀거든요. 그럼 이 claude-cli는 어디서 튀어나온 걸까.

설정 파일을 직접 뒤졌어요. claude-cli라는 글자가 어디 적혀 있는지.

grep -n -iE 'claude|cli|opus|failover' ~/.openclaw/openclaw.json
227:      "blucli": {
296:      "ordercli": {
317:      "sonoscli": {
338:      "wacli": {

걸린 건 전부 이름에 우연히 cli가 들어간 다른 항목들뿐이고, claude, opus, failover는 하나도 안 나왔어요. 설정 파일엔 claude-cli가 없어요.

그럼 등록된 모델 목록도 봤어요.

openclaw models list
Model                          ... Local  Tags
ollama/qwen3.6:27b             ... yes    default
ollama/nemotron-3-nano:30b     ... yes    configured
ollama/qwen2.5:32b             ... yes
...

전부 로컬 모델이에요. 기본값(default)도 정확히 제 로컬 qwen이고요. claude도 opus도 목록에 없어요.

여기서 한참 헤맸어요. 설정 어디에도 없는데, 로그에선 분명히 claude-cli를 부르고 있다. 이 모순을 어떻게 풀지.


설정에 없으면, 프로그램 안에 있다

설정 파일에도 없고 모델 목록에도 없다. 그럼 남은 가능성은 하나예요. 제가 설정한 게 아니라, OpenClaw라는 프로그램 자체에 처음부터 박혀 있는 것. 그렇다면 설정 파일을 아무리 뒤져도 안 나오는 게 당연하죠.

확인을 위해 공식 문서를 찾아봤어요. 그랬더니 정확히 적혀 있더라고요. OpenClaw는 Claude CLI를 아무 설정 없이도 쓸 수 있게 내장 기본값을 들고 있다고요. 즉 claude-cli는 제가 설정한 게 아니라, OpenClaw 안에 처음부터 박혀 있는 기본 통로였어요. 그래서 제 설정 파일을 뒤져도 안 나왔던 거예요. 설정에 없는 게 당연했어요 — 그건 프로그램 자체에 내장된 거니까.

문서엔 한 가지 더 중요한 게 있었어요. 이 내장 claude-cli 통로는 “도구(MCP 같은 것)를 못 쓰고 텍스트만 주고받는” 안전망 용도라고요. 그러니 게시판 글을 실제로 가져온 건 claude-cli일 수가 없어요(걔는 도구를 못 쓰니까). 그게 죽은 뒤 넘어간 로컬 qwen이 가져온 게 맞았어요. 14화부터 해오던 “이게 진짜 누가 한 거냐”를 또 한 번 가린 셈이에요.


그럼 그 10초만 건너뛰면 되잖아

원인을 알았으니 해법은 단순해요. 기본 진입(claude-cli부터 두드리는 통로)을 거치지 말고, 처음부터 로컬 에이전트로 직행하면 돼요.

OpenClaw 명령을 다시 뒤져보니 agent라는 게 있었어요.

openclaw agent --help

여기 --agent라는 옵션이 보였어요. 설명이 “라우팅을 무시하고 지정한 에이전트로 보낸다”예요. 제 일하는 에이전트 이름은 main이니까, 이걸로 직접 부르면 claude-cli부터 두드리는 기본 통로를 안 거칠 거예요. 시험해봤어요. 이번엔 시간이 얼마나 걸리는지도 같이 재봤어요.

time openclaw agent --agent main --message "LegalT3ch 게시판에서 최근 글 목록 가져와줘"

💡 명령 앞에 time을 붙이면, 끝나고 나서 실제로 몇 초 걸렸는지 알려줘요.

결과를 보고 좀 당황했어요.

real    2m16.397s
user    0m4.252s
sys     0m0.739s

10초가 사라지긴커녕 2분 16초가 걸렸어요. 예상과 정반대였죠.


2분의 정체는 또 달랐다

그런데 이 숫자를 자세히 보면 이상해요. real(실제 흐른 시간)은 2분이 넘는데, user(컴퓨터가 실제로 계산한 시간)는 4초밖에 안 돼요. 이 격차가 핵심이에요. 컴퓨터는 거의 놀고 있었는데, 벽시계 시간만 2분이 흘렀다. 즉 대부분의 시간을 뭔가 기다리는 데 쓴 거예요.

로그를 다시 봤어요. 이번엔 2분짜리 그 호출(밤 10시 14분)의 기록을요.

grep -iE 'cli exec|claude-cli|embedded' /tmp/openclaw/openclaw-$(date +%F).log | tail -15

결정적이었어요. 2분짜리 호출의 기록엔 claude-cli가 단 한 줄도 없었어요. 처음부터 embedded(로컬)로 직행한 거예요. 즉 --agent main은 성공했어요. 그 10초 헛걸음을 완전히 건너뛴 거죠.

그럼 2분은 뭐였냐. 로그를 보니 준비 단계는 7초였고(그중 통역사 로딩이 6.8초), 나머지 2분은 순수하게 로컬 모델이 생각하고 답을 만든 시간이었어요. 27B짜리 큰 모델이, 게시판 도구를 부르고, 결과를 받아서, 한국어 표로 정리하기까지 걸린 시간이요.

그러니까 두 개의 다른 문제였던 거예요.

멈춤의 정체원인해결
10초 헛걸음기본 진입이 안 되는 claude-cli를 먼저 두드림--agent main으로 직행 (해결)
2분 대기로컬 모델 자체가 느림별개 문제 (다음 숙제)

같은 “오래 걸림”인데 원인이 둘이고, 하나는 오늘 잡았고 하나는 모델 속도 문제라 따로 다뤄야 해요. 이걸 섞어 보면 영영 못 고쳐요.


같은 안내 문구, 다른 원인

검증 삼아, 일반 에이전트로 다시 글을 시켜봤어요. 또 “This response is taking longer than expected”가 떴어요. 순간 “claude-cli 또 부른 거 아냐?” 싶었죠. 근데 화면 아랫줄을 보니,

agent main | session main | ollama/qwen3.6:27b | tokens 13k/33k

지금 일하는 게 ollama/qwen3.6:27b, 명확히 로컬이에요. 로그를 확인해도 그 시각엔 claude-cli 호출이 없었고요. 그러니까 이번 멈춤은 claude-cli 10초가 아니라, 그냥 로컬 모델이 느려서 뜬 거예요.

같은 안내 문구라도 원인이 둘이라는 걸 알고 나니, 화면만 보고도 구분이 돼요. 로그에 claude-cli가 찍혔으면 10초 헛걸음, 화면에 qwen이 찍히고 로그가 깨끗하면 그냥 모델이 느린 거. 증상이 같다고 원인이 같은 게 아니라는 걸, 이번에 제대로 배웠어요.


영구 고정은 다음으로

10초를 건너뛰는 법은 찾았어요(--agent main). 근데 이건 명령 칠 때마다 --agent main을 붙여야 하는 거라 좀 번거로워요. 진짜 해결은 “그냥 에이전트를 띄워도 자동으로 로컬 에이전트로 직행하게” 고정하는 거예요.

OpenClaw에 agents bind라는 게 있어서, 기본 통로를 일하는 에이전트(main)로 박아둘 수 있어요. 다만 이건 라우팅을 건드리는 거라, 한 번에 욱여넣기보다 차분히 따로 하는 게 안전해 보였어요. 오늘은 “건너뛸 수 있다”를 확인한 데까지 하고, 영구 고정은 다음으로 미뤘어요.


오늘의 정리

이번 편에서 다시 확인한 게 있어요. 증상이 같다고 원인이 같은 게 아니다. “멈춘다”는 같은 현상 뒤에 전혀 다른 두 원인이 숨어 있었고, 그걸 가른 건 추측이 아니라 로그였어요. 로그에서 시간을 잘라 보고, time으로 숫자를 재고, claude-cli가 찍혔는지 안 찍혔는지로 구분하고. 결국 디버깅은 “느낌”이 아니라 “기록”으로 하는 일이라는 걸 또 배웠어요.

그런데 이 작업을 하다가, 재미 삼아 에이전트한테 “16화 글에서 틀린 부분 있으면 알려줘”라고 물어봤어요. 에이전트가 아주 적나라하게 지적을 해주더라고요. 표까지 그려가면서요. 그걸 그대로 믿을 뻔했어요. 에이전트가 자기 자신에 대해 설명할 때, 그 말을 믿어도 되는가 — 그 이야기는 따로 풀어볼게요.

읽어주셔서 감사합니다.

#에이전트#문제해결기#성능