본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 15. 05:31

Claude Agent SDK를 Railway에 배포하며 겪은 3가지 문제점

요약

Claude Agent SDK를 사용하여 Slack 봇을 Railway에 배포할 때 발생하는 세 가지 주요 기술적 문제와 해결 방법을 다룹니다. 루트 권한 제한, MCP 서버 연결 지연으로 인한 환각 현상, 내부 모델 동작 방식에 대해 설명합니다.

핵심 포인트

  • 루트 컨테이너 환경에서는 bypassPermissions 설정이 거부되어 프로세스가 종료됨
  • 표준 에러(stderr)를 캡처하지 않으면 자식 프로세스의 오류 원인 파악이 어려움
  • stdio MCP 서버의 연결 지연 시 모델이 도구 호출을 연기하며 환각을 일으킬 수 있음
  • API 로그에 나타나는 haiku 모델은 내부 작업을 위한 설계된 동작임

Claude Agent SDK로 구축한 Slack 봇 앱을 Railway에 배포했는데, 배포하자마자 SDK 자체와 관련된 일련의 지뢰들을 밟았습니다. 그중 모든 문제는 "로그가 무엇이 잘못되었는지 알려주지 않는" 종류였으며, 특히 두 번째 문제는 제 시간을 아주 많이 잡아먹었습니다. 다른 사람들도 같은 지점에서 막힐 가능성이 높기에, 이를 기록해 두려 합니다.

이 글은 Node.js에서 @anthropic-ai/claude-agent-sdk (query())를 사용하는 주니어~미들급 개발자를 대상으로 합니다.

요약 (TL;DR)

  • 문제점 1: 루트 컨테이너 (root container)에서는 bypassPermissions가 허용되지 않으며, 자식 프로세스가 code 1과 함께 종료됩니다. 더 나쁜 것은 stderr (표준 에러)가 삼켜져서 왜 그런지 확인할 수 없다는 점입니다.
  • 문제점 2: stdio MCP 서버는 기본적으로 연결을 기다리지 않으므로, 첫 번째 턴(turn 1)에서 도구 목록이 비어 있게 됩니다. 이로 인해 모델이 도구 호출을 "연기"하고 결과를 날조합니다.
  • 문제점 3: API 로그에 haiku가 나타나지만, 이는 모델 성능이 저하된 것이 아니라 설계된 방식입니다. 내부적인 작업을 위해 사용됩니다.

문제점 1: 루트 컨테이너에서는 bypassPermissions가 작동하지 않음

발생한 현상

로컬에서는 잘 작동하던 코드가 Railway에 배포하자마자 code 1과 함께 죽기 시작했습니다. 에이전트는 아무것도 하지 않고 그냥 종료되었습니다. 전체 에러 메시지는 본질적으로 다음과 같았습니다:

Error: Claude Code process exited with code 1

이것은 아무런 정보도 주지 않습니다. 유일한 스택 트레이스 (stack trace)는 제 앱의 것이었습니다. 자식 프로세스 (claude 바이너리)가 죽기 전에 실제로 내뱉은 말은 완전히 블랙박스 상태였습니다.

원인

query()는 내부적으로 claude 바이너리를 실행합니다. 이 바이너리는 루트 (root) 권한이나 sudo로 실행될 때 --dangerously-skip-permissions (SDK에서는 permissionMode: "bypassPermissions"라고 호출함)를 거부합니다. 이는 안전 조치입니다. 루트 권한으로 모든 권한 확인을 건너뛰는 것은 너무 위험하기 때문입니다.

많은 컨테이너 환경과 마찬가지로 Railway는 기본적으로 루트로 실행되므로, bypassPermissions를 설정했다면 항상 이 문제에 부딪히게 됩니다. 일반 사용자로 실행 중이라면 로컬에서는 이 문제를 잡아낼 수 없습니다.

로그가 없는 이유

이것이 정말 골치 아픈 부분입니다. options.stderr 콜백을 전달하지 않는 한, SDK는 자식 프로세스의 stderr를 `

도구가 존재하지 않음에도 "매출을 조회해달라"는 요청을 받으면, 모델은 충실하게 텍스트로서 도구 호출(tool call)을 "연기"하고 그럴싸해 보이는 결과를 스스로 작성해 버립니다. 그것이 환각(fabrication)의 원인이었습니다.

그 구조는 "로컬 프로세스 생성(spawning a local process)"과 "네트워크 API 호출(making a network API call)" 사이의 경주와 같습니다:

  • MCP 서버 = 로컬 프로세스 생성 (CPU 집약적)
  • 1차 턴 프롬프트(turn-1 prompt) 조립 = Anthropic API 호출

Railway와 같이 CPU가 제한된 환경에서는 로컬 프로세스 생성이 매번 패배하므로, 이 현상이 안정적으로 재현됩니다. 반대로, 제 로컬 머신에서는 의도적으로 CPU 부하를 높임으로써 이를 재현할 수 있었고, 이를 통해 근본 원인을 확인할 수 있었습니다.

확인 방법

init 이벤트에서 mcp_servers 상태를 확인하세요. 결과는 즉각적입니다:

  • connected → 도구가 존재함 → 정상
  • pending → 도구 목록이 비어 있음 → 환각이 발생할 것임

이것을 확인하는 것만으로 현재의 응답을 신뢰할 수 있는지 알 수 있습니다. 디버깅 시 로그를 남길 가치가 있습니다.

해결책: alwaysLoad: true

각 MCP 서버 설정에 alwaysLoad: true를 추가하세요. 이렇게 하면 연결이 완료될 때까지(최대 5초) 시작을 차단하여, 1차 턴(turn 1)에서 도구가 반드시 존재하도록 보장합니다.

const result = query({
  prompt: "...",
  options: {
...

에이전트(agent)의 사용 사례에서는 "말하기 전에 도구가 준비될 때까지 기다리는 것"이 "비차단(non-blocking) 및 빠른 속도"보다 훨씬 중요합니다. 숫자를 다루는 에이전트에게 환각은 치명적이므로, 이 경우에는 실행을 차단하더라도 확실성을 확보해야 합니다.

주의사항 3: API 로그의 haiku는 성능 저하가 아닙니다

발생한 현상

주의사항 2를 조사하던 중, API 로그를 살펴보니 메인 작업에 지정한 모델(sonnet)과는 별개로 haiku로 향하는 요청들이 섞여 있는 것을 발견했습니다. 그리고 그 요청들은 출력 토큰이 16개 정도로 매우 작았습니다.

"모델이 몰래 다운그레이드된 건가?" "이것이 환각의 원인인가?" 저는 잠시 두 가지 모두를 의심했지만, 이것은 전적으로 설계된 의도이며 정상적인 동작입니다.

원인

Agent SDK는 요약, 분류, 짧은 판단과 같은 **내부 작업 (internal chores)**을 위해 메인 응답 생성(sonnet)과는 별개로 작은 haiku 모델을 사용합니다. 이러한 아주 작은 요청들이 바로 그것입니다. 이는 비용과 속도 모두에 최적화된 정당한 설계입니다.

환각(fabrication)의 원인은 모델의 품질이 아니라 도구의 부재(Gotcha 2)였습니다.

교훈

"출력이 이상해 보인다 → 모델이 약하다 → Opus로 업그레이드하자"라고 추론하고 싶은 유혹이 들겠지만, 이 경우에는 모델을 업그레이드해도 환각 문제는 해결되지 않습니다 (근본 원인인 '도구 없음'은 동일하기 때문입니다).

Opus로 도망치기 전에, 도구가 실제로 전달되고 있는지부터 확인하세요.

이것이 가장 큰 깨달음이었습니다. 모델 등급을 올리는 것은 도구(tools), 프롬프트(prompt), 그리고 컨텍스트(context)가 올바르게 연결되었음을 확인한 후의 최후의 수단이어야 합니다.

마무리

세 가지 문제 모두 "로그에 찍힌 모습"이 당신을 속이는 버그였습니다.

증상실제 원인해결책
code 1과 함께 명확한 이유 없이 종료됨root가 bypassPermissions를 거부함stderr를 캡처하고 allowedTools로 전환
...

공통된 교훈은 다음과 같습니다: Agent SDK는 외부 요소들 — 자식 프로세스(child process)와 MCP — 의 시작 타이밍에 크게 의존합니다. 동작이 의심스러워 보일 때, 모델이나 프롬프트를 의심하기 전에 "자식 프로세스가 종료되기 전에 뭐라고 말했는가?"와 "도구가 실제로 전달되고 있는가?"를 먼저 확인하세요. 그것이 지름길입니다.

제가 허비한 시간을 누군가는 아낄 수 있기를 바랍니다.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0