본문으로 건너뛰기

"도구" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

모든 태그 보기

pg_shmemviz 공유 메모리

· 약 6분

일주일 전에 pg_walviz로 WAL segment 내부를 들여다봤는데, 같은 저자가 이번엔 공유 메모리를 열었어요. Bertrand Drouvot(베르트랑 드루보)이 2026년 8월 20일 pg_shmemviz v0.1.0-beta.1을 공개했습니다.

두 도구의 성격이 닮았습니다. 이미 있는 뷰로도 요약은 볼 수 있는데, 정작 "그게 메모리 어디에 어떤 모양으로 놓여 있나"는 안 보인다는 문제를 같은 방식으로 풉니다. 스냅샷을 떠서 브라우저에서 바이트 단위로 걸어 다니게 하는 방식입니다.

pg_shmem_allocations는 어디까지 보여 주나

먼저 기존 뷰의 한계를 실측으로 확인했습니다. PostgreSQL 18 컨테이너를 기본 설정으로 띄우고 pg_shmem_allocations를 조회했습니다.

$ docker run -d --name shmemtest -e POSTGRES_PASSWORD=pw postgres:18
$ docker exec shmemtest psql -U postgres -Atc "show shared_buffers"
128MB
select name, off, size, allocated_size
from pg_shmem_allocations
order by size desc limit 8;
name | off | size | allocated_size
----------------------+-----------+-----------+----------------
Buffer Blocks | 6785664 | 134221824 | 134221824
<anonymous> | | 4747776 | 4747776
XLOG Ctl | 60928 | 4208200 | 4208256
AioHandleIOV | 150482816 | 2850816 | 2850816
| 154760064 | 2280576 | 2280576
AioHandle | 148879232 | 1603584 | 1603584
AioHandleData | 153333632 | 1425408 | 1425408
Buffer Descriptors | 5737088 | 1048576 | 1048576

전체는 75개 항목, 합계 150MB였습니다. 여기서 볼 수 있는 것과 볼 수 없는 것이 꽤 선명하게 갈립니다.

보이는 것은 이름, 시작 오프셋, 요청 크기, 실제 할당 크기입니다. XLOG Ctl이 4,208,200바이트를 요청했는데 4,208,256바이트가 할당된 것을 보면 56바이트가 정렬 때문에 붙었다는 사실까지는 읽힙니다. PostgreSQL 18에서 비동기 I/O가 들어오면서 AioHandle, AioHandleIOV, AioHandleData 세 항목이 합쳐 5.8MB를 차지하는 것도 확인됩니다. 비동기 I/O 글에서 다룬 io_uring 구조가 메모리에서 이 정도 자리를 쓴다는 뜻입니다.

안 보이는 것이 문제입니다. 위 출력에서 이름 칸이 빈 행이 하나 있는데, 이건 아직 아무에게도 배정되지 않은 여유 공간입니다. <anonymous>는 이름 없이 잡힌 익명 할당이라 오프셋조차 안 나옵니다. 그리고 XLOG Ctl 안에 XLogCtlData 구조체의 어떤 필드가 몇 번째 바이트에 앉아 있는지, 필드 사이에 컴파일러가 끼워 넣은 padding이 몇 바이트인지는 이 뷰의 관심사가 아닙니다.

정리하면 이렇습니다.

알고 싶은 것pg_shmem_allocationspg_shmemviz
할당 이름과 크기지원지원
요청 크기 대 실제 크기 차이지원지원
할당 사이 빈 구간의 물리적 위치부분 (이름 없는 행)지원
C 구조체의 필드별 오프셋과 값지원
필드 사이 컴파일러 padding지원
포인터가 가리키는 대상 영역지원
페이지의 NUMA 노드 배치pg_shmem_allocations_numa지원 (시각화)
두 시점 사이 차이 비교수동지원

실행 중인 서버에 붙지 않고 구조체를 읽는 방법

여기가 이 도구에서 가장 흥미로운 부분입니다. 공유 메모리의 바이트 배열을 읽는 것 자체는 어렵지 않습니다. 어려운 건 그 바이트가 무슨 구조체의 어느 필드인지 알아내는 일입니다. 그 정보는 소스 코드에만 있고 실행 중인 서버의 메모리에는 없습니다.

pg_shmemviz는 이 문제를 postgres 실행 파일의 DWARF 디버그 정보로 해결합니다. 컴파일된 바이너리에는 각 구조체의 필드 이름, 타입, 오프셋이 DWARF 형식으로 들어 있습니다. macOS에서는 LLDB, 그 외 환경에서는 GDB를 써서 이 메타데이터를 읽습니다. 중요한 건 디버거를 실행 중인 서버에 attach하지 않는다는 점입니다. 실행 파일의 메타데이터만 읽습니다.

복사 단계에는 lock을 걸지 않습니다. 덕분에 서버를 멈추지 않지만, 대가가 있습니다. 스냅샷 안의 필드들이 서로 다른 순간의 값일 수 있습니다. 저자도 이 점을 문서에 명시했습니다. 그러니 "이 두 카운터의 차이가 정확히 몇인가"를 따지는 용도로는 맞지 않고, 구조와 배치를 파악하는 용도입니다.

설치와 사용

extension과 CLI 두 부분으로 되어 있습니다.

cd ~/pg_shmemviz
make PG_CONFIG=/path/to/postgres-install/bin/pg_config
make PG_CONFIG=/path/to/postgres-install/bin/pg_config install

psql -d postgres -c 'CREATE EXTENSION pg_shmemviz'

스냅샷을 뜨는 명령입니다.

~/pg_shmemviz/bin/pg_shmemviz capture \
--pg-config /path/to/postgres-install/bin/pg_config \
--dbname postgres \
/path/to/new-snapshot

뜬 스냅샷을 브라우저로 봅니다. 기본값은 127.0.0.1:8765이고 로컬 브라우저가 열립니다.

~/pg_shmemviz/bin/pg_shmemviz serve /path/to/new-snapshot

원격 서버에서 뜬 스냅샷을 SSH 포트 포워딩으로 볼 때는 브라우저 자동 실행을 끕니다.

~/pg_shmemviz/bin/pg_shmemviz serve --no-open --port 8765 /path/to/new-snapshot

화면이 보여 주는 것

뷰가 여러 개인데 서로 연동됩니다. 한쪽에서 할당을 고르면 다른 쪽이 같은 지점을 따라갑니다.

공유 메모리 맵은 main segment와 DSM, DSA 영역을 통틀어 이름 있는 할당, padding, 미사용 구간을 늘어놓습니다. 위 실측에서 이름 칸이 비어 있던 2.2MB가 어디에 어떤 이웃과 붙어 있는지가 여기서 드러납니다.

Structure Fields 패널이 이 도구의 핵심입니다. 중첩된 C 구조체를 펼쳐 필드별 오프셋과 값, 컴파일러가 끼운 padding, 배열의 stride padding을 보여 줍니다. 경계를 알 수 있는 포인터는 가리키는 영역을 참조 구간으로 표시합니다. 통계, WAL, 프로세스 배열, SLRU, dynahash, DSM registry 같은 PostgreSQL 특유의 구조에는 전용 해석이 들어가 있습니다.

Physical Bytes 뷰는 주소, 오프셋, 값, 어느 구조체 필드에 속하는지, 어느 NUMA 노드에 놓였는지를 함께 보여 주는 바이트 창입니다. Buffer Cache 뷰는 선택 사항인데, buffer별 식별자와 database, relation, fork, block 번호, 그리고 그 buffer를 pin하고 있는 backend까지 나옵니다. pg_buffercache로 보던 내용을 물리적 배치 위에 겹쳐 놓은 셈입니다.

NUMA 노드가 여러 개인 장비에서는 페이지 배치를 그림으로 봅니다. pg_shmem_allocations_numa 뷰가 숫자로 알려 주던 것을 눈으로 확인하는 용도입니다.

스냅샷 두 개를 비교한다

이 기능이 실무 관점에서 가장 쓸모 있어 보입니다. 서로 다른 시점의 스냅샷 두 개를 나란히 열어 할당 단위, 필드 단위, 바이트 단위로 차이를 봅니다.

~/pg_shmemviz/bin/pg_shmemviz serve \
/path/to/before-snapshot \
/path/to/after-snapshot

설정 하나를 바꿨을 때 공유 메모리가 실제로 어떻게 달라지는지 확인하는 데 쓸 수 있습니다. 위 실측에서 PostgreSQL 18의 AIO 관련 세 할당이 5.8MB를 차지했는데, io_method를 바꾸기 전후로 스냅샷을 떠서 비교하면 그 5.8MB의 내부 구성이 어떻게 변하는지가 필드 단위로 보일 것입니다.

운영 인스턴스에서는 쓰지 않는다

저자가 문서 앞쪽에 강하게 못 박은 부분이라 그대로 옮깁니다.

Do not run pg_shmemviz on a production PostgreSQL instance.

이유가 몇 겹입니다. 스냅샷은 공유 메모리 전체를 복사한 파일이라 크고, 그 안에 실제 데이터가 그대로 들어갑니다. buffer에 올라온 테이블 내용이 파일로 떠지는 셈이니 민감 정보가 그대로 흘러나갑니다. viewer에는 인증도, 권한 검사도, TLS도 없습니다. loopback 밖으로 내보내면 안 됩니다.

구조체 해석에는 캡처한 서버가 쓰던 것과 정확히 같은 postgres 실행 파일이 필요합니다. 빌드가 다르면 필드 오프셋이 어긋나 엉뚱한 값을 읽습니다. 검증은 PostgreSQL 20devel 기준으로 되어 있고, 어느 버전까지 되는지는 저장소 README를 봐야 합니다. 제가 위에서 실측한 PostgreSQL 18 컨테이너 이미지에는 디버그 정보가 없으니, 실제로 붙여 보려면 디버그 심볼을 켜서 직접 빌드한 인스턴스가 필요합니다.

어디에 쓰면 좋을까

용도가 좁습니다. 운영 진단 도구가 아니고, extension이나 코어 패치를 개발하면서 "내가 잡은 공유 메모리 구조가 실제로 어떻게 배치됐나"를 확인하는 도구입니다. 그리고 학습 자료로서의 가치가 따로 있습니다. XLogCtlDataPGPROC 배열이 메모리에서 어떤 모양인지 소스만 읽어서 상상하던 것을 눈으로 확인하는 경험은 소스 독해 속도를 꽤 올려 줍니다.

PostgreSQL 내부를 3D 도시로 걸어 본 글에서 시각화 도구가 학습에 어떤 도움이 되는지 이야기했는데, pg_shmemviz는 그보다 훨씬 실무 쪽에 가깝습니다. 비유가 아니라 실제 주소와 실제 바이트를 보여 주니까요.

pg_walviz와 pg_shmemviz가 한 주 간격으로 나왔습니다. 저는 이 흐름이 반갑습니다. PostgreSQL 내부는 소스를 읽을 수 있는 사람에게만 열려 있었는데, 그 문턱을 낮추는 도구가 늘고 있어요.

참고

pg_walviz WAL 시각화

· 약 3분

WAL을 공부할 때 제일 답답한 건 실체가 안 보인다는 점이었어요. record가 페이지 경계에서 쪼개진다, 세그먼트 첫 페이지에는 long header가 붙는다, 이런 문장을 문서로는 읽는데 실제 바이트가 어떻게 놓이는지는 상상에 맡겨야 했거든요.

Bertrand Drouvot(베르트랑 드루보)가 8월 13일 공개한 pg_walviz가 정확히 그 지점을 채웁니다. WAL 세그먼트 파일 하나를 읽어 브라우저에서 시각화하는 읽기 전용 도구입니다. 현재 버전은 v0.1.0-beta.1이고 저장소는 GitHub에 있습니다.

무엇을 보여주나

화면은 서로 동기화되는 네 개의 뷰로 구성됩니다.

내용
세그먼트 개요히트맵. resource manager별로 record가 세그먼트 어디에 몰려 있는지
record 조각 목록선택한 페이지에 걸친 record들, 페이지 경계에서 쪼개진 조각 포함
record 검사기선택한 record의 헤더, 물리 배치, full-page image 정보
물리 바이트색으로 구분된 원본 바이트열

히트맵에서 눈에 띄는 영역을 클릭하면 그 페이지의 record 목록이 뜨고, record를 고르면 헤더 필드와 실제 바이트가 같이 하이라이트됩니다. 페이지 번호, record 번호, 파일 오프셋, LSN을 직접 입력해서 이동할 수도 있습니다.

pg_waldump와 겹치는 도구가 아니냐는 생각이 들 수 있는데, 역할이 다릅니다. pg_waldump는 record의 논리적 내용을 사람이 읽을 텍스트로 풀어 줍니다. 어떤 rmgr가 어떤 연산을 기록했는지 보기에 좋습니다. pg_walviz는 record가 세그먼트 안에 물리적으로 어떻게 저장되는지를 보여줍니다. 페이지 헤더, record 조각, continuation record, 정렬 padding, 블록 참조가 바이트 위에 그대로 표시됩니다. 실제로 pg_walviz는 내부적으로 pg_waldump를 사용하므로 두 도구는 상하 관계에 가깝습니다.

실행 방법

PostgreSQL 서버도, 데이터 디렉터리도 필요 없습니다. 세그먼트 파일 하나와 그 파일을 만든 서버 버전에 맞는 pg_waldump 바이너리만 있으면 됩니다.

~/pg_walviz/bin/pg_walviz \
--pg-waldump /usr/pgsql-18/bin/pg_waldump \
/archive/000000010000000000000042

실행하면 로컬 웹서버가 뜨고 브라우저가 열립니다. 원격 서버에서 실행할 때는 브라우저 자동 실행을 끄고 포트를 지정합니다.

~/pg_walviz/bin/pg_walviz --no-open --port 8765 \
--pg-waldump /usr/pgsql-18/bin/pg_waldump \
/archive/000000010000000000000042

주의사항이 둘 있습니다. 현재 쓰기가 진행 중인 세그먼트는 열지 말라는 것, 그리고 WAL에는 실데이터가 들어 있으므로 로컬 밖으로 노출하지 말라는 것입니다. 특히 두 번째는 archive에서 세그먼트를 복사해 분석용 장비에서 여는 습관과 묶어 기억해 둘 만합니다. WAL은 INSERT된 행의 내용을 그대로 담고 있어서, 세그먼트 파일 하나가 곧 데이터 유출 경로가 됩니다.

어디에 쓸 만한가

첫째는 학습입니다. WAL record 헤더의 xl_prev가 무엇인지, full-page image가 왜 checkpoint 직후에 몰리는지 같은 주제는 글로 읽는 것보다 히트맵에서 직접 확인하는 쪽이 빠릅니다. checkpoint 직후 세그먼트를 열어 보면 FPI가 차지하는 공간이 시각적으로 드러나고, full_page_writes가 WAL 볼륨에 미치는 영향이 감으로 잡힙니다.

둘째는 장애 분석의 보조 도구입니다. 예전에 standby가 record with incorrect prev-link를 반복하며 멈춘 사건을 분석할 때는 pg_waldump 출력과 오프셋 계산을 손으로 맞춰 가며 recycled 세그먼트의 잔재를 추론했습니다. 그때 이 도구가 있었다면 문제 지점의 바이트를 바로 눈으로 확인했을 겁니다. 세그먼트 경계의 long page header(40바이트)와 첫 record의 위치 같은 것들이 화면에 그대로 보이니까요.

PostgreSQL 내부를 3D 도시로 만든 PGSimCity가 buffer와 프로세스를 보여주는 조감도였다면, pg_walviz는 WAL이라는 한 지점을 현미경으로 파는 도구입니다. 아직 beta라 큰 세그먼트에서 로딩이 느리고 단일 파일 검사가 권장되는 수준이지만, 방향이 좋습니다.

archive에 쌓여 있는 세그먼트 하나 골라서 열어 보세요. 문서 열 페이지보다 히트맵 한 화면이 WAL 구조를 빨리 가르쳐 줄 거예요.

참고 자료

Claude Code Switcher

· 약 15분

왜 "스위처"가 필요해졌나

Claude Code가 2024년 말 등장한 직후만 해도 사용량 캡은 거의 의식되지 않았어요. 그게 바뀐 건 2025-08-28이에요. Anthropic이 Pro / Max 플랜에 5시간 롤링 윈도우 + 7일 weekly cap 이중 제한을 도입한 날이에요. Max 5x ($100/mo)와 Max 20x ($200/mo)도 weekly 캡에서 자유롭지 않습니다.

cap에 걸리면 두 가지 길이 있습니다.

  1. 그 주가 끝날 때까지 기다립니다
  2. 다른 프로바이더로 옮깁니다. Z.AI의 GLM Coding Plan, Moonshot의 Kimi, OpenRouter의 300개 모델 중 하나, 또는 로컬 Ollama를 선택합니다

옮기는 일 자체는 어렵지 않습니다. Claude Code가 환경변수 두 개(ANTHROPIC_BASE_URLANTHROPIC_AUTH_TOKEN)만 보고 동작하기 때문입니다. 예를 들어 GLM으로 옮기는 방법은 Z.AI 공식 가이드 기준으로 두 줄이면 됩니다.

export ANTHROPIC_BASE_URL="https://api.z.ai/api/anthropic"
export ANTHROPIC_AUTH_TOKEN="..."

다른 프로바이더(Kimi, DeepSeek 등)도 같은 패턴이지만 정확한 Anthropic-호환 엔드포인트 URL은 각 프로바이더 공식 문서에서 직접 확인해야 합니다. 같은 회사라도 OpenAI-호환 엔드포인트(/v1)와 Anthropic-호환 엔드포인트가 다르고, 후자가 잘못 표기된 글이 인터넷에 흔합니다.

문제는 하루에 셋넷씩 갈아타게 되는 순간입니다. 회사 계정, 개인 계정, GLM, 로컬 모델, 임시 OpenRouter를 오가며 매번 셸 변수를 바꾸다 보면, 헷갈려서 회사 계정으로 사이드 프로젝트를 돌리기도 하고 캡이 어디서 깎이는지도 까먹습니다. 이 지점에서 등장한 도구가 **CCS (Claude Code Switcher)**입니다.

CCS 한 줄 요약

@kaitranntt/ccs는 Kai Tran(카이 트란)이 만든 Claude Code용 멀티 프로바이더/멀티 계정 프로필 매니저입니다. MIT 라이선스의 npm 패키지이며, GitHub ★2.2k, 2026-04-29 기준 v7.75.0입니다. 721개 릴리즈와 3,687개 커밋이 쌓일 만큼 개발이 매우 활발합니다.

홈페이지: https://ccs.kaitran.ca/ 저장소: https://github.com/kaitranntt/ccs

자기 소개는 한 문장입니다.

The multi-provider profile and runtime manager for Claude Code and compatible CLIs. — config 파일 갈아엎지 말고, 활성 세션 깨지 않으면서, 몇 초 안에 프로바이더를 옮겨라.

무엇을 지원하나

설치는 한 줄이면 됩니다.

npm install -g @kaitranntt/ccs
# 또는
bun add -g @kaitranntt/ccs

ccs config 한 번 돌려 초기 설정 후, 프로필 단위로 사용합니다.

명령라우팅
ccs기본값: Claude Sonnet 4.6
ccs glmZ.AI GLM-5.1 (API 또는 Coding Plan)
ccs kimiMoonshot Kimi (1M context)
ccs geminiGemini 3 Pro/Flash (OAuth)
ccs codexGPT-5.4 / Codex (OAuth)
ccs ollama로컬 Ollama 모델
ccs work / ccs personal같은 Claude 라도 계정 격리
ccs --target droid glmruntime 자체를 Factory Droid로 바꾸고 모델은 GLM

지원 프로바이더는 점점 늘어 현재 다음을 포함합니다.

  • Claude (Sonnet 4.6, Opus 4.6): 공식
  • GLM-5.1, GLM-5-Turbo, GLM-4.7: Z.AI
  • Kimi K2.5: Moonshot
  • Gemini 3 Pro/Flash: Google (OAuth)
  • GPT-5.4 / Codex: OpenAI (OAuth)
  • Antigravity Pro/Turbo: ccs agy (OAuth)
  • OpenRouter: 300+ 모델 한 번에
  • Ollama, llama.cpp, Novita, Alibaba Coding Plan 등 로컬/OpenAI-호환 모두

어떻게 동작하나

CCS의 핵심은 두 가지 컴포넌트입니다.

첫 번째는 로컬 Anthropic-호환 프록시입니다. GLM/Kimi처럼 이미 Anthropic-호환 엔드포인트를 제공하는 프로바이더는 단순 패스스루로 지나가고, 그렇지 않은 OpenAI-호환 프로바이더(OpenRouter, DeepSeek 등)는 로컬 프록시가 요청과 응답을 변환해 Claude Code가 자기 형식대로 받게 만듭니다.

두 번째는 CLIProxyAPI라는 OAuth 프록시 백엔드입니다. Gemini, Codex, Antigravity처럼 공식 API 키가 없는 OAuth 기반 프로바이더는 이 별도 컴포넌트가 처리하고, 라운드로빈이나 fill-first 같은 토큰 관리 정책도 여기서 돕습니다. 커뮤니티 fork(CLIProxyAPIPlus)도 옵트인으로 쓸 수 있습니다.

활성화는 eval "$(ccs proxy activate)" 같이 셸에 평가시켜 ANTHROPIC_BASE_URL, ANTHROPIC_AUTH_TOKEN을 그 세션 한정으로 주입하는 방식입니다. 다음 셸이나 다음 디렉토리에서는 다시 깨끗해집니다.

# CCS가 한 번에 처리하는 것
$ ccs glm "이 PR 리뷰해줘"
# 내부적으로:
# 1. ~/.ccs/profiles/glm.settings.json 읽기
# 2. ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic 주입
# 3. ANTHROPIC_AUTH_TOKEN=$GLM_KEY 주입
# 4. claude code 호출

겉으로는 한 줄이지만 안쪽에서 하는 일은 수동 env 셋과 다르지 않고, 그걸 프로필이라는 단위로 캡슐화했을 뿐입니다.

장점은 어디서 나오나

가장 눈에 띄는 건 명령 하나가 프로파일 하나에 대응한다는 점입니다. 회사 Claude, 개인 Claude, GLM, Kimi, 로컬까지 다섯 개를 셸 변수 갈아끼우지 않고 명령 하나로 분리합니다. 여기서 한 발 더 들어가면 멀티 계정 격리가 있습니다. ccs workccs personal이 같은 머신에서 동시에 다른 Claude 세션을 돌릴 수 있고 weekly cap도 따로 깎이므로, 회사 계정으로 사이드 프로젝트를 돌리다 cap을 축내는 사고가 구조적으로 사라집니다.

비용 이야기도 빼놓기 어렵습니다. 공식 페이지는 "Save $500–1000/month with strategic delegation"이라 적는데, 검증은 본인 워크로드에 따라 다릅니다. 다만 무거운 보일러플레이트는 GLM($10–30/mo)으로 돌리고 설계만 Claude Max로 가는 패턴은 실제로 cap 부담을 크게 줄여줍니다.

나머지 장점은 결이 비슷합니다. Z.AI처럼 API 키를 발급해 쓰는 곳, Gemini처럼 OAuth로 가는 곳, 로컬 Ollama까지 같은 명령 표면 위로 올라오고, proxy.routing 설정으로 "긴 컨텍스트는 Kimi, 추론은 Claude, 백그라운드는 GLM" 식의 자동 라우팅도 짤 수 있습니다. config 파일을 손으로 만지지 않고 비주얼 대시보드로 프로필을 추가/수정할 수 있어, 한국에서 GLM Coding Plan처럼 결제/키 발급이 번거로운 프로바이더를 쓸 때 편합니다. 721 릴리즈에 거의 매일 업데이트될 만큼 개발이 활발해 새 프로바이더가 나오면 빠르게 흡수되는 것도 덤입니다.

단점과 주의사항

가장 실질적인 부담은 추상화가 두껍다는 점입니다. 프록시가 두 단계(로컬 + CLIProxyAPI)로 끼어들고 프로바이더마다 라우팅 룰이 따로 사는 탓에, "내 요청이 어디로 갔지?"가 헷갈리는 순간이 생깁니다. 로그(~/.ccs/logs/)를 켜둘 가치가 여기 있습니다. 핵심 기능 일부가 CLIProxyAPI라는 별도 프로젝트에 묶여 있다는 점도 같은 맥락인데, 그쪽 이슈가 CCS 동작에 그대로 옮겨붙을 수 있습니다. 버전 업이 매우 빠른 것(v7.75.0, 721 릴리즈)도 새 프로바이더 흡수에는 좋지만 "내 환경에서 안정적인 v7.x"를 고수하려는 보수적 운영에는 부담이라, lockfile로 고정하는 편이 낫습니다.

쓸모의 경계도 분명합니다. 다른 프로바이더를 안 쓰고 회사/개인 두 계정만 격리하는 경우라면 direnv.envrc 같은 더 가벼운 도구로 충분하고, CCS는 옮겨 다닐 곳이 셋 이상일 때부터 의미가 생깁니다. 그리고 Codex, Antigravity 같은 비공개 OAuth 프로바이더를 우회로 쓰는 것은 각 서비스 이용약관 위반 소지가 있으니, 회사 환경에서는 한 번 확인하는 편이 안전합니다.

한국에서 쓸 때 걸리는 현실적 지점도 둘 있습니다. Z.AI Coding Plan은 분기 결제(분기당 $30–80), Moonshot Kimi는 위안화 결제라 CCS가 결제까지 해결해주지는 않습니다. 또 이 도구가 weekly cap 회피 수단으로 광고되지만, Anthropic 입장에서 "한 사람이 멀티 계정으로 cap을 돌파"하는 패턴이 쌓이면 정책이 다시 조여질 수 있습니다. 도구의 책임은 아니어도 시장 동학은 의식해 둘 만합니다.

한국 커뮤니티 반응

CCS 자체에 대한 긱뉴스(news.hada.io) 단일 글은 (작성 시점 기준) 아직 없지만, CCS 같은 도구가 왜 등장했는지를 보여주는 신호는 긱뉴스에 풍부합니다.

스레드(Threads) 쪽에서는 한국어 사용자들이 비슷한 도구를 다양하게 시도 중이라는 점이 눈에 띕니다. vibe proxy로 Claude Code에 AntiGravity와 GLM을 라이드 매핑하거나, oh-my-opencode(★9K)가 Kimi K2.5와 GLM 5를 메인 오케스트레이터로 튜닝하거나, free-claude-code가 NVIDIA NIM 무료 API로 Claude Code를 무료 운영하는 식입니다. 한국 개발자들이 프록시와 멀티 프로바이더라는 패턴 자체에 적극적으로 베팅하고 있다는 의미이고, CCS는 그 흐름에서 가장 잘 정리된 도구 중 하나입니다.

대안 비교

CCS만 있는 게 아닙니다. 같은 영역에 여러 도구가 경쟁 중입니다.

도구강점약점
CCS (kaitranntt)★2.2kOAuth 프록시 + GUI 대시보드 + 활발한 업데이트추상화 두꺼움, 의존성 복잡
claude-code-router (musistudio)★33.2k시나리오 라우팅(background/think/longContext), 토큰 임계값 자동 전환, JS 플러그인OAuth 미지원
cc-switch (farion1231)(데스크톱)데스크톱 GUI, Claude Code/Codex/OpenCode/Gemini 통합CLI 친화도 낮음
claude-code-switch (foreveryh)(소규모)미니멀, 한 명령으로 Anthropic 모델만 전환Anthropic 외 미지원
OpenCode (opencode.ai)(별도 트리)75+ 프로바이더, 완전 오픈, Claude Code 호환 인터페이스자체 CLI 라 Claude Code 그대로는 아님
DIY (.zshrc 두 줄)의존성 없음, 가장 투명함프로필 3개 넘어가면 관리 불가

API 키 기반 프로바이더가 2개 이내이고 라우팅이 필요하다면 claude-code-router가 어울립니다. 별 수도 가장 많고 시나리오 라우팅이 가장 강합니다. OAuth 프로바이더를 포함한 멀티 계정이라면 이 영역에서 거의 유일한 CCS가 맞습니다. 데스크톱 친화성과 멀티 툴 통합 GUI를 원한다면 cc-switch, Anthropic만 쓰면서 단순함을 우선한다면 DIY 또는 claude-code-switch를 고르면 됩니다.

시나리오: 회사 Team + Enterprise 두 계정만 쓴다면

CCS가 풀려는 문제가 프로바이더 다양화와 OAuth 우회라면, Anthropic만 쓰면서 회사 계정 두 개(Team + Enterprise)만 격리하는 시나리오에는 정확히 그 두 가치가 빠져 있습니다. 이때는 도구 선택이 달라집니다.

이 시나리오의 본질은 두 ANTHROPIC 계정 사이를 빠르고 정확하게 전환하는 한 가지로 줄어듭니다. 다른 프로바이더도, 시나리오 라우팅도, 로컬 모델도 무관합니다.

이 경우라면 direnv가 첫 손에 꼽힙니다. .envrcexport ANTHROPIC_API_KEY=... 한 줄을 두 회사 디렉토리에 각각 두면 cd만으로 키가 자동 로드됩니다. 이 시나리오에서 가장 큰 리스크는 한 회사 코드에 다른 회사 키가 실수로 흘러가는 사고인데, 디렉토리 경계로 그걸 막아주는 게 direnv의 장점입니다.

더 단순하게 가려면 ~/.zshrc에 alias 두 줄이면 됩니다.

alias cct='ANTHROPIC_AUTH_TOKEN=$TEAM_TOKEN claude'
alias cce='ANTHROPIC_AUTH_TOKEN=$ENT_TOKEN claude'

디렉토리에 묶이지 않아 빠른 대신, 지금 어느 회사 컨텍스트인지는 사람이 기억해야 합니다. Anthropic 전용 미니멀 스위처인 claude-code-switch도 CCS보다 가볍고 이 시나리오에 정확히 맞습니다. CCS를 굳이 쓴다면 멀티 계정 모드만(ccs auth create team / ccs auth create ent) 떼어 쓰는 것도 동작은 하지만, 프로바이더 다양화, 프록시, OAuth 같은 95% 기능을 놀리면서 의존성과 복잡도는 그대로 짊어지게 됩니다. 나중에 GLM 같은 외부 프로바이더로 확장할 가능성이 있을 때만 미리 깔아두는 의미가 있습니다.

Enterprise가 SSO를 강제하면 단순 API 키 토글로는 안 되고 OAuth 로그인 사이클이 필요합니다. 이때는 direnv만으로 부족해 CCS의 OAuth 프로필 분리나 Anthropic Console의 organization 스위처를 써야 하는데, SSO 강제에 잦은 전환까지 겹친 경우가 사실상 CCS를 정당화하는 거의 유일한 회사 시나리오입니다. 정리하면 API 키 기반 두 계정에는 direnv로 충분하고, SSO 강제에 잦은 전환이 겹칠 때만 CCS가 값을 하며, 그 밖에는 대체로 과한 도구입니다.

설정/대화는 공유하면서 계정만 분리하고 싶다면

같은 시나리오의 변종입니다. 두 회사 계정을 전환은 하되 슬래시 커맨드, MCP, hooks, CLAUDE.md/대화 히스토리는 한 군데에서 공유하고 싶은 경우인데, 이때는 정답이 다릅니다.

먼저 Claude Code가 무엇을 어디 두는지 알면 답이 나옵니다.

위치무엇계정 종속?
~/.claude/settings.json사용자 설정 (theme, env, hooks 트리거 등)무관
~/.claude/commands/, agents/, skills/커스텀 슬래시 커맨드, 에이전트, 스킬무관
~/.claude/CLAUDE.md글로벌 메모리무관
~/.claude/projects/<path-hash>/*.jsonl대화 히스토리 (프로젝트 경로 기준)무관
OS 키체인 / ANTHROPIC_AUTH_TOKEN인증 토큰종속

핵심은 계정 종속이 토큰 한 가지뿐이라는 점입니다. 토큰만 갈아끼우면 나머지는 자동으로 공유되므로, 답은 direnv로 토큰만 스위칭하는 것입니다. .envrcexport ANTHROPIC_AUTH_TOKEN=... 한 줄만 두고 ~/.claude/는 건드리지 않으면, 슬래시 커맨드, hooks, MCP, 대화가 전부 자동으로 공유됩니다. 반대로 ccs auth create work 같은 CCS의 isolated profile 모드는 정확히 이 공유를 분리하는 기능이라 피해야 합니다. CCS 자체는 써도 되지만 isolation 옵션은 끄고 토큰만 바꾸는 모드로만 씁니다. 여러 머신 사이에서도 공유하고 싶으면 ~/.claude/를 git으로 관리하는 dotfiles가 답인데, settings.json에 토큰이 평문으로 들어가지 않도록 .gitignoresettings.local.json을 등록해 두는 정도만 주의하면 됩니다.

다만 Enterprise 데이터 격리는 짚어둘 필요가 있습니다. Enterprise 플랜 약관에 대화 데이터를 다른 organization 환경과 섞지 못하게 하는 조항이 있을 수 있어서, PII, 고객 데이터, 비공개 코드를 다루는 프로젝트라면 ~/.claude/projects/를 공유하는 것이 회사 보안 정책 위반이 될 수 있습니다. 사내 보안팀에 한 번 확인하는 게 안전하고, 우려가 있으면 프로젝트 디렉토리 자체를 회사별로 분리해 자연히 다른 <path-hash>로 떨어뜨리는 패턴(예: ~/work/team/, ~/work/ent/ 두 루트)이 가장 깔끔합니다.

SSO 강제 환경, 한국 회사 현실에 더 가까운 케이스

위 두 서브섹션은 API 키를 사용자가 직접 발급받을 수 있다는 전제 위에 있습니다. 그런데 국내 대기업, 금융권, 보안 민감 조직 대부분은 그 전제 자체가 깨져 있습니다. Team/Enterprise 플랜에서 SSO를 강제하면 사용자 API 키 발급이 비활성화되고, 인증은 OAuth + IdP MFA 사이클로만 가능합니다. 이 환경에서는 도구 선택이 다시 한 번 달라집니다.

먼저 구조를 짚으면 다음과 같습니다.

  1. claude login → 브라우저 → 회사 IdP 로그인 (SSO + MFA) → Anthropic Console → 토큰 발급
  2. 토큰은 OS 키체인 또는 ~/.claude/.credentials.json에 저장
  3. 토큰은 보통 시간 제한이 있고 (몇 시간~며칠), 만료되면 다시 SSO 사이클
  4. 한 머신의 한 OS 유저는 동시에 한 organization의 세션만 보유 가능

즉 SSO 강제 환경에서 두 회사 organization 사이를 전환하려면 결국 logout, 다른 org로 login, 다시 작업 사이클을 돌아야 합니다. IdP가 매번 MFA를 요구하니 도구가 우회할 수 있는 영역이 아닙니다.

실제로 동작하는 패턴은 현실적 운영 순으로 정리할 수 있습니다. 가장 흔한 사례이자 가장 깔끔한 결론은 organization 하나만 쓰는 것입니다. 회사가 Enterprise 하나를 표준화했고 Team이 레거시/POC였다면 둘 다 유지할 이유가 없으니 회사 IT에 정리를 요청하는 편이 낫습니다. 두 organization이 같은 Anthropic Workspace 안의 서로 다른 workspace라면, admin이 workspace를 분리해 두는 것만으로 organization 전환 없이 claude /switch-workspace 식의 in-session 전환이 가능합니다. 이게 되는지부터 회사 IT에 확인하면 가장 매끄럽습니다.

두 organization이 진짜 별개라면 방법이 무거워집니다. 같은 노트북에 OS 계정 두 개를 만들어 각각 SSO 로그인 상태를 독립으로 두면 키체인과 ~/.claude/가 자연히 분리되지만, 설정/대화 공유가 깨져서 dotfiles를 두 OS 유저 사이에 공유하는 추가 작업이 필요합니다. CCS의 OAuth 프로필 분리(ccs auth create work-team / ccs auth create work-ent)는 이론상 이 시나리오에 정확히 맞지만, 회사 IdP가 OAuth 흐름에 거는 추가 검증(IP 화이트리스트, 디바이스 트러스트, MFA 빈도)에 따라 CCS의 토큰 캐시 방식이 IdP 정책과 충돌할 수 있어 시도 전에는 알기 어렵습니다. 사내 보안팀과 사전 협의를 권합니다. 가장 보수적인 선택은 두 회사용 Dev Container나 VM을 따로 띄워 각각 한 organization으로 로그인하는 것인데, 무겁고 호스트 키체인을 못 쓴다는 대가가 따릅니다.

반대로 SSO 환경에서 동작하지 않는 패턴은 다음과 같습니다.

  • direnv + ANTHROPIC_AUTH_TOKEN 토글: 사용자 API 키 자체가 없으니 토글할 대상이 없습니다.
  • 셸 alias로 토큰 swap: 같은 이유로 동작하지 않습니다.
  • "session 토큰을 추출해서 재사용": 만료가 짧고 IdP가 디바이스 핑거프린팅으로 거부할 가능성이 있습니다. ToS의 회색지대이기도 합니다.
  • 두 organization의 ~/.claude/.credentials.json을 수동으로 백업/복구: 동작은 할 수 있지만 MFA 빈도 정책을 우회하는 모양새가 되어 정책 위반 우려가 있습니다.

한국 회사 현실에 맞는 결론은, SSO 강제면 organization 전환 자체가 비용이 크다는 사실을 인정하고 두 organization을 동시에 자주 오가지 않는 워크플로우를 설계하는 쪽입니다. 오전엔 Team org에서 한 덩어리, 오후엔 Enterprise org에서 다른 덩어리를 처리하는 식의 시간 분할이, 전환을 도구로 매끄럽게 만드는 것보다 운영 부담이 훨씬 적습니다. 도구는 그 다음 문제입니다.

실전 팁

블로그, GitHub 이슈, 도구 README의 패턴을 종합해 한국 환경에서 바로 쓸 만한 것만 모았습니다.

가장 큰 가치는 라우팅 자동화보다 자기 워크플로우에 맞는 모델 분리에서 나옵니다. 설계/아키텍처는 ccs(Claude Sonnet), 보일러플레이트/테스트 정리는 ccs glm, 1M 컨텍스트가 필요한 대규모 리뷰는 ccs kimi, 민감 코드는 로컬 ccs ollama 정도가 무난한 시작점입니다. Claude Sonnet 4.6도 1M 컨텍스트를 지원하지만 토큰 값이 비싸서, 큰 monorepo 전체 리뷰는 ccs kimi 한 번이 훨씬 싸게 먹힙니다. 새 prompt가 안정적인지 확인하는 단계라면 첫 5~10번은 무료인 ccs ollama로 돌려보다 만족스러우면 Claude로 옮기면 됩니다.

회사/개인 계정은 무조건 격리하는 편이 좋습니다(ccs auth create work / ccs auth create personal). weekly cap이 섞이지 않아 둘 다 마음 편히 쓸 수 있습니다. 여기에 더해 Claude Max의 weekly cap이 60% 이상 깎였으면 남은 작업의 70% 정도는 GLM으로 돌리는 룰을 정해두면, cap이 갑자기 끊기는 사고가 사라집니다.

라우팅은 단순하게 시작하는 편이 낫습니다. proxy.routing 시나리오 라우팅을 처음부터 복잡하게 짜면 요청이 어디로 갔는지 못 따라가니, 모델을 직접 지정해 일주일 운용하고 패턴이 보이면 그때 룰을 추가합니다. 기본 CLIProxyAPI가 새 프로바이더를 못 잡으면 옵트인 fork(CLIProxyAPIPlus) 활성화부터 시도해 볼 만합니다.

매번 eval 치기 싫으면 ~/.zshrc에 한 줄을 넣어 영구화합니다.

[[ -s "$HOME/.ccs/init.zsh" ]] && source "$HOME/.ccs/init.zsh"

멀티 계정 사고를 디버깅할 때는 CCS_LOG=debug ccs glm "..." 식으로 한 번 돌려보면 어느 base URL로 갔는지, 어느 토큰을 썼는지 정확히 보이니 로그를 켜두는 게 필수입니다.

한 줄로

CCS는 Claude Code가 환경변수 두 개로 정의되는 도구라는 사실을 그대로 받아들인 도구입니다. 그 두 변수를 프로파일이라는 단위로 정리하고, OAuth 우회와 다중 계정까지 한 명령 표면 위로 올려놓았습니다. weekly cap 시대에 한 프로바이더에만 의지하는 게 부담스러워진 사용자에게 기본기에 가까운 도구가 됐고, 같은 영역에 claude-code-router 같은 더 큰 별 수의 경쟁자도 있습니다. 자기 워크플로우가 옮겨 다닐 곳이 셋 이상인지부터 보고, 그다음에 도구를 고르는 순서가 맞아요.


→ 다음 편: Claude Code Switcher (CCS) 2편: 디렉토리, 설정, 라우팅의 실제 — 사용자 머신의 ~/.ccs/를 직접 들여다보며 instance / shared 격리 모델, config.yaml의 9개 영역, 로컬 프록시의 5단계 변환을 풀어 봅니다.

참고