프롬프트 17단계·50% 최적화·launchd 구조
상담봇의 출력은 대단계 7개, 하위 단계 최대 17개로 쪼개져 있습니다. 원래는 7단계로 한 번에 호출했지만, 품질·맥락·건너뛰기 유연성 때문에 세분화했습니다.
이 챕터는 그 설계 결정을 다룹니다.
한 대단계에 "장점 + 단점 + 공감 멘트" 를 모두 요구하면, Claude가 균형 맞추느라 각 부분이 얇아짐. 특히 공감 멘트가 형식적으로 나왔음.
장점 해석은 충분한데 공감 멘트만 더 길게 받고 싶을 때, 대단계 통째로 다시 돌려야 했음.
공감 멘트만 건너뛰고 싶은데 대단계 전체가 나와야 했음.
1-1 장점 해석에서 말한 내용을 1-2 단점 해석이 모르면, "앞서 말씀드린 장점이 뒤집히면..." 같은 연결 멘트가 안 나옵니다.
이전 하위 단계 응답의 마지막 2000자를 다음 프롬프트에 포함합니다.
왜 2000자냐: 경험적으로 2000자 이상은 맥락 유지에 큰 차이 없고, 프롬프트 크기만 커져서 비용·속도 악화.
단계 성격에 따라 3가지 포맷이 자동 배분됩니다:
| 포맷 | 길이 | 구조 | 할당 단계 |
|---|---|---|---|
| FMT_EXPLAIN (설명형) | 800~1200자 | 번호 + 굵은키워드 + 짧은문장 | 1-1, 1-2, 2-1, 2-2, 3-1, 3-2, 4-1, 4-2 |
| FMT_SCRIPT (멘트형) | 500~800자 | 교사 실전 대사, 큰따옴표 | 1-3, 2-3, 3-3, 4-3, 7-2 |
| FMT_ANALYSIS (분석형) | 800~1200자 | 데이터 항목별 분석 + 연결 | 3-1e, 5, 6, 7-1 |
각 하위 단계 답변에 [다음 ▶] / [⏭️ 건너뛰기] 버튼:
| 측면 | 이전 (7 호출) | 현재 (17 호출) |
|---|---|---|
| 호출 횟수 | 적음 | 약 2.4배 증가 |
| 총 시간 | 짧음 (3~4분) | 길어짐 (7~10분) |
| 응답 품질 | 보통 | 높음 ⭐ |
| 건너뛰기 유연성 | 낮음 | 높음 ⭐ |
| 맥락 일관성 | 자동 | sub_responses로 수동 관리 |
| 프롬프트 복잡도 | 낮음 | 높음 |
→ 품질·유연성을 우선하는 결정이었음
다음 챕터: Stage 3 프롬프트 50% 최적화 (203KB → 101KB)
상담봇의 도형 해석 단계(Stage 3)는 가장 무거운 프롬프트였습니다. 전체 57개 도형 조합 전략 + 공통 해석 자료를 매번 함께 넣어서 203KB 까지 부풀었습니다.
이걸 101KB(50% 감소) 로 줄인 최적화 케이스입니다.
섭외자의 에니어그램 번호에 해당하는 조합만 프롬프트에 포함.
57개 조합 중 모든 조합에 공통적으로 포함되는 대형 자료 3건(각 ~12KB)이 있었음. 매 조합마다 반복되니 프롬프트가 폭발.
해결: 공통 자료 3건을 프롬프트에서 제외하고, 필요 시 knowledge DB 조회로 별도 주입.
각 조합마다 "이 조합은 도형과 에니어의 관계를 설명합니다..." 같은 메타 도입부가 있었음. Claude에겐 불필요한 서술 → 모두 제거.
| 항목 | 이전 | 현재 | 감소율 |
|---|---|---|---|
| 프롬프트 크기 | 203KB | 101KB | -50% |
| 포함 조합 수 | 57개 (고정) | 6~8개 (동적) | 동적 |
| 공통자료 중복 | 57회 | 0회 (DB 별도) | -100% |
| 평균 응답 시간 | 45~60초 | 20~30초 | -50% |
같은 시기에 knowledge DB의 도형 해석 항목도 중복 정리했습니다.
knowledge DB 전체 변화: 186건 → 151건
du 로 전체 크기 보고서야 감지"모든 사용자에게 같은 대형 프롬프트" 는 거의 항상 비효율입니다. 확인할 것:
다음 챕터: launchd · TCC · claude CLI 구조 — 맥에서 봇 24시간 돌리기
봇을 24시간 자동 가동하려면 운영체제 수준의 구성이 필요합니다. 맥에서 겪은 3가지 이슈와 해결 방법을 정리합니다.
~/Documents/ 경로에서 launchd로 실행하면 macOS가 파일 접근을 차단. TCC(Transparency, Consent, and Control) 정책 때문.
코드를 TCC 제외 경로로 복사 후 그곳에서 실행:
# 코드 동기화
for f in bot.py db.py handlers.py ...; do
cp "$SRC/$f" "$DEST/$f"
done
# 데이터 rsync
rsync -au "$DATA_SRC/" "$DATA_DEST/"
# 봇 재시작
launchctl unload "$PLIST"
launchctl load -w "$PLIST"
launchd로 실행된 프로세스는 셸 rc 파일(.zshrc)을 읽지 않음 → PATH가 최소한만 설정됨 → claude 같은 CLI 못 찾음.
Errno 2 No such file or directory: 'claude'
shell에서는 claude 되는데, launchd 봇은 못 찾음.
방법 A — plist에 PATH 명시
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
</dict>
방법 B — 코드에서 절대경로 사용 (더 안전)
import shutil
_NPM_CLAUDE = "/Users/.../.npm-global/bin/claude"
_CMUX_CLAUDE = "/Applications/cmux.app/.../claude"
if os.path.exists(_NPM_CLAUDE):
CLAUDE_BIN = _NPM_CLAUDE
elif (_w := shutil.which("claude")) and _w != _CMUX_CLAUDE:
CLAUDE_BIN = _w
else:
CLAUDE_BIN = _CMUX_CLAUDE
권장: B (절대경로). A는 claude 설치 위치 바뀌면 또 고장.
봇이 Claude Code 환경 안에서 개발·테스트되는 경우, 환경변수 CLAUDECODE=1 이 상속됨. 이 상태에서 봇이 claude -p 를 호출하면:
Error: nested Claude Code session detected
subprocess 호출 전에 환경변수 제거:
env = os.environ.copy()
env.pop("CLAUDECODE", None) # 다른 CLAUDE* 변수는 유지
proc = await asyncio.create_subprocess_exec(
CLAUDE_BIN, "-p",
env=env,
...
)
CLAUDECODE 만 제거, CLAUDE_CONFIG_DIR 등 다른 CLAUDE* 변수는 유지해야 계정 인증 상태가 유지됨.
<key>Label</key>
<string>com.consulting-bot</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>/Users/.../consulting-bot-run/run_bot.sh</string>
</array>
<!-- 자동 재시작 (크래시 시) -->
<key>KeepAlive</key><true/>
<!-- 재시작 간격 (연속 크래시 방지) -->
<key>ThrottleInterval</key><integer>10</integer>
<!-- 로그인 시 자동 시작 -->
<key>RunAtLoad</key><true/>
<!-- 로그 -->
<key>StandardOutPath</key>
<string>/Users/.../logs/bot.log</string>
<key>StandardErrorPath</key>
<string>/Users/.../logs/bot.log</string>
launchd 재시작 타이밍에 이전 프로세스가 완전히 죽기 전 새 프로세스가 올라오면, 두 봇이 동시에 텔레그램 폴링 → 409 Conflict.
| 명령 | 역할 | |
|---|---|---|
launchctl load -w |
등록 + 활성화 (⚠️ 항상 -w) | |
launchctl unload |
중지 + 등록 해제 | |
| `launchctl list \ | grep name` | 상태 확인 (PID, exit code) |
launchctl kickstart -k |
재시작 |
주의: load 할 때 -w 없으면 "Disabled" 상태로 남아 다음 부팅 시 안 뜰 수 있음.
~/Documents/ 피해서 ~/consulting-bot-run/ 에서 실행CLAUDE_BIN 절대경로로 해결세 챕터에서 다룬 것들:
이 패턴들은 다른 Claude 기반 봇에도 재사용 가능합니다. 상담봇은 기획부 업무봇, 교육 Q&A 봇 등 다른 봇들과 같은 구조를 공유합니다.
목차로 돌아가기