본문으로 건너뛰기
effidevFlutter · Cloudflare 엣지 · 클라우드 비용 최적화

Claude Code 세션을 우리 서버에서 돌린다: self-hosted 환경 실전 가이드

effidev

Claude Code self-hosted 환경 러너 아키텍처

2026년 8월 6일, Anthropic이 Claude Code의 self-hosted 환경을 퍼블릭 베타로 공개했다. CLI 지원은 다음 날 2.1.224에 실렸다(npm 배포 시각 2026-08-07 01:36 UTC).

한 줄로 말하면 이렇다. claude.ai·모바일·데스크톱에서 시작한 Claude Code 세션이 Anthropic 서버가 아니라 우리 네트워크 안에서 돈다. 사내 DB에 붙고, 내부 레지스트리에서 이미지를 당기고, 체크아웃한 코드가 회사 밖으로 나가지 않는다.

보안 심사 때문에 클라우드 세션을 못 쓰던 팀에게는 이게 잠금 해제다. 다만 공식 문서가 “대부분의 팀에게는 Anthropic 호스팅을 권한다”고 먼저 못 박아 둘 만큼 운영 부담이 따라온다. 이 글은 그 부담이 정확히 무엇인지를 정리한다.

먼저: 이건 터미널 Claude Code 얘기가 아니다

헷갈리기 쉬운 지점이라 먼저 잘라 두자.

실행 위치 무엇
개발자 노트북 터미널·IDE에서 쓰는 평범한 Claude Code. 원래부터 로컬이라 여기서 할 게 없다
Anthropic 인프라 클라우드 세션 — claude.ai, 모바일·데스크톱 앱, claude --cloud, 예약 routine
우리 인프라 ← 이번 건 위 클라우드 세션을 우리 네트워크 안에서 실행

문서의 표현 그대로다.

If your team doesn’t use cloud sessions, there’s nothing here to configure: sessions in a terminal or IDE always run on the developer’s own machine.

내 always-on 머신에서 돌리고 다른 기기로 조종하고 싶은 거라면 이게 아니라 Remote Control 이다. 그건 Pro·Max 플랜에서도 된다.

구조는 셋뿐이다

self-hosted CI 러너를 써 봤다면 그림이 거의 같다.

용어 무엇
Environment 세션을 보낼 수 있는 이름 붙은 목적지. claude.ai 관리자 설정에서 만든다. 러너들의 묶음
Runner 우리 네트워크 안 호스트에서 도는 프로그램. 실제로 세션을 실행한다
Session 개발자가 시작한 Claude Code 작업 하나

흐름은 이렇다.

  1. 개발자가 세션을 시작하면 환경 선택기가 뜬다. Anthropic 호스팅 환경들과 우리가 만든 환경이 나란히 보인다
  2. 우리 환경을 고르면 Anthropic 컨트롤 플레인이 그 환경의 에 세션을 올린다
  3. 여유 있는 러너가 세션을 claim 하고 리스를 잡는다
  4. 러너가 저장소를 클론하고 자식 Claude Code 프로세스를 띄운다
  5. 자식이 HTTPS로 이벤트를 스트리밍하는 동안 러너는 계속 폴링한다. 이 폴링이 곧 하트비트
  6. 러너가 약 60초 폴링을 멈추면 서버가 세션을 다른 러너로 재큐잉한다

API 필드와 토큰 클레임, 메트릭 이름에서는 environment가 pool, 환경 ID가 pool_id로 나온다. 문서와 실제 플래그 이름이 달라 보이는 건 이 때문이다.

네트워크: 전부 아웃바운드다

방화벽 담당자를 설득할 때 쓸 문장은 이것 하나다.

Anthropic never connects into your network.

인바운드 연결이 전혀 필요 없다. 우리 쪽에서 나가는 것만 있다.

경로 무엇
컨트롤 플레인 러너 → api.anthropic.com 폴링(HTTPS). 폴링이 하트비트를 겸한다
Git 러너 → 우리 git 호스트 (HTTPS 또는 SSH). 내부 호스트면 내부에서 붙는다
세션 자식 자식 프로세스 → api.anthropic.com 이벤트 스트림 + 모델 추론
SCM 커넥터 오케스트레이터의 선택 기능. 유일한 WebSocket 연결

사내 프록시도 지원한다. 러너와 오케스트레이터가 HTTPS_PROXY·NO_PROXY 같은 환경변수를 따른다. 다만 조건이 하나 붙는다 — 세션 스트리밍이 SSE(서버 전송 이벤트)라 경로 중간의 프록시가 응답을 버퍼링하면 안 된다. 사내 프록시가 응답을 모아서 내보내는 설정이면 여기서 막힌다.

무엇이 남고 무엇이 나가나 — 여기서 오해가 갈린다

self-hosted 라는 말 때문에 “이제 대화도 우리 안에서 도는구나”로 읽기 쉬운데, 아니다.

우리 인프라에 남는 것 Anthropic 으로 가는 것
저장소 체크아웃 대화 자체 — 프롬프트, 응답, 도구 실행 결과
빌드 산출물 세션 트랜스크립트 (다른 기기에서 이어가기 위해 저장됨)
시크릿 세션 오케스트레이션·큐잉
세션이 만들거나 고친 파일 claude.ai 인터페이스

문서가 직접 이렇게 정리한다.

a self-hosted environment moves session execution into your network, not the control plane.

실행 위치가 옮겨지는 것이지 데이터 경계가 통째로 옮겨지는 게 아니다. 소스코드가 회사 밖으로 나가면 안 되는 요건에는 맞지만, “모델에 보내는 내용까지 외부로 안 나가야 한다”는 요건이라면 이걸로는 해결되지 않는다.

러너 1대 = 사용자 1명. 이게 대수 산정을 지배한다

문서에서 가장 중요한데 가장 놓치기 쉬운 문장이다.

A runner serves one user at a time.

러너는 처음 집어 든 세션의 사용자 계정에 잠긴다. 그 뒤로는 그 계정의 세션만 --capacity 만큼 동시에 처리한다. 체크아웃한 코드가 사용자 간에 섞이지 않게 하려는 설계다.

여기서 바로 따라오는 결론이 있다.

The minimum fleet size is therefore the number of users you expect to be active at once.

동시에 활동할 개발자 수만큼 러너가 필요하다. 개발자 20명이 동시에 세션을 돌리는 조직이면 러너 20대가 최소치다. “한 대 크게 띄우고 여럿이 나눠 쓰기”가 안 된다. CI 러너 감각으로 대수를 잡으면 큐가 밀린다.

부하가 들쭉날쭉하면 오토스케일링 오케스트레이터를 쓰면 된다. 우리가 호스팅하는 두 번째 프로세스로, 세션이 큐에 쌓이면 러너를 띄우고 각 러너는 일이 끝나면 알아서 종료된다.

종료 처리 — 스팟 인스턴스를 쓴다면 여기를 봐야 한다

일이 끝난 러너가 어떻게 되는지는 --drain-grace-sec 가 정한다.

동작
0 (기본) 활성 세션이 끝나는 즉시 종료. 더 폴링하지 않는다. 쿠버네티스 같은 오케스트레이터가 디스크가 깨끗한 새 러너로 재시작해 아무 계정이나 받을 수 있게 하는 전제
양수 잠긴 계정의 큐를 그 초 수만큼 더 폴링한 뒤 종료

기본값이 0인 게 핵심이다. 사용자 간 디스크 상태를 지우지 않고도 격리가 되는 이유가 여기 있다 — 지우는 대신 러너를 버린다.

문제는 호스트가 신호 없이 사라지는 경우다. 스팟 인스턴스 회수나 샌드박스 수명 상한이 그렇다. SIGTERM이 오면 알아서 드레인하지만, 신호 없이 죽으면 컨트롤 플레인은 이걸 크래시로 기록하고 세션은 다른 러너로 재큐잉된다.

그래서 회수 시각을 아는 환경이라면 --retire-at <epoch-seconds> 를 그 몇 분 전으로 준다. 그 시각이 되면 러너는:

  1. 새 작업을 받지 않고
  2. 활성 세션을 release 한다 — 사용자가 다음 메시지를 보내면 새 러너에서 이어진다. 턴 중간이면 그 턴이 끝나는 즉시, 백그라운드 작업이 남았으면 최대 60초 유예 후 놓아준다
  3. 전부 놓아준 뒤 0으로 종료한다

킬 시각을 넘긴 턴은 어쨌든 유실된다. 마진을 얼마나 둘지는 세션의 평균 턴 길이를 보고 잡아야 한다.

못 하는 것들 — 도입 판단은 여기서 갈린다

기대하고 접근했다가 막히는 지점들이다.

도입 전 체크리스트

마무리

Anthropic 스스로 “대부분의 기업에는 호스팅 버전을 권한다”고 적어 뒀다. 러너 이미지를 만들고, 플릿을 운영하고, 네트워크를 통제하는 일이 통째로 우리 몫이 되기 때문이다.

그래도 이게 열린 의미는 작지 않다. 지금까지 “코드가 외부 서버에서 체크아웃된다”는 한 줄 때문에 클라우드 세션 도입이 막히던 조직들이 있었다. 그 조직들이 이제 사내 DB와 내부 레지스트리에 붙는 에이전트 세션을 돌릴 수 있다.

판단 기준은 결국 하나다. 막고 싶은 게 소스코드의 이동인가, 대화 내용의 이동인가. 전자면 지금 검토할 만하고, 후자면 아직 기다려야 한다.