Hostname은 기기 식별자가 아니다
macOS에서 hostname이 네트워크 상황에 따라 바뀌며 Claude Code 토큰 사용량이 중복 집계된 사례와, 더 안정적인 기기 식별자로 hw.model을 선택한 이유를 정리합니다.
내가 토큰을 이만큼이나 썼다고?
Claude Code statusline을 평소처럼 쳐다보다가 숫자가 이상한 걸 발견했다.
Last 30 Days $4038.03 · 5.1B tokens이틀 전까지 2.5B였다. 그 사이에 3B를 더 썼을 리 없다. 두 배가 됐다는 건 어디선가 중복이 일어나고 있다는 뜻이다.
집계 구조
내 ~/.claude는 맥북과 맥미니 두 기기에서 Syncthing으로 sync된다. 토큰 사용량 합산은 그 위에 단순한 구조로 얹었다. 각 기기가 자기 hostname을 이름으로 쓰는 JSON 파일에만 쓰고, statusline은 디렉토리 내 모든 JSON을 *.json glob으로 긁어 합산한다.
USAGE_DIR="$HOME/.claude/usage-summary"
HOSTNAME_SHORT="$(hostname -s | tr -d '\n\r' | tr -c 'a-zA-Z0-9.-' '_')"
CACHE_FILE="$USAGE_DIR/$HOSTNAME_SHORT.json"각 기기는 자기 영역만 쓰고, 합산은 디렉토리 수준에서. 단순한 설계 같았다.
디렉토리를 열어봤다.
Mac.json
mini.json
Sanghuns-MacbookPro-M4Max.json세 개. 기기는 두 대뿐인데.
데이터로 잡아낸 중복
가장 먼저 물은 것은 "이 세 파일 중 둘이 같은 기기에서 나온 거 아닌가". ccusage는 실행 기기의 로컬 ~/.claude/projects/**/*.jsonl 세션 로그를 읽어 집계하므로, 같은 기기에서 나온 두 파일은 같은 history의 다른 시점 스냅샷일 수밖에 없다.
확인 포인트는 두 가지.
첫째, 30일 합계의 규모.
| 파일 | last30 tokens |
|---|---|
Mac.json |
2,531,953,934 |
Sanghuns-MacbookPro-M4Max.json |
2,532,361,686 |
mini.json |
65,207,390 |
Mac.json과 Sanghuns-MacbookPro-M4Max.json이 둘 다 2.5B 근처. mini.json은 65M. 맥미니가 갑자기 40배 더 써서 2.5B를 찍었을 리는 없다. 규모로 보면 두 파일은 같은 맥북에서 나왔다고 보는 게 맞다.
둘째, 일별 값의 완전 일치. Mac.json의 today (2026-04-20)와 Sanghuns-MacbookPro-M4Max.json의 yesterday (같은 2026-04-20) 값이 토큰 수, 비용, 모델별 breakdown까지 전부 동일했다. 두 기기가 우연히 똑같은 값을 뱉을 수 없다. 같은 projects 디렉토리에서 뽑은 데이터다.
즉 맥북 하나가 파일 두 개를 쓰고 있었다. 이유는 뻔했다. 파일명이 hostname 기반인데 hostname이 두 값을 오가는 것.
1차 조치의 실패
stale 판정한 Mac.json을 지웠다. 그날 저녁에 다시 쳐다봤더니 도로 5.1B였다. ls를 해보니 Mac.json이 또 생겨있었다.
$ hostname -s
Mac몇 시간 전엔 Sanghuns-MacbookPro-M4Max를 반환하던 명령이 지금은 Mac을 뱉는다. 내가 기기를 바꾼 적도, 네트워크를 특별히 만진 적도 없다.
hostname이 오락가락한다는 게 직관과 어긋나서 한참 다시 확인했다. 맥미니는 수십 번을 찍어도 항상 mini를 반환한다. 왜 맥북만 오가는가.
macOS의 세 가지 이름
macOS에는 이름이 셋 있다.
ComputerName: GUI에 표시되는 사람용 이름. "Sanghun's MacbookPro M4Max" 같은 공백 섞인 문자열.LocalHostName: Bonjour가 쓰는 이름.ComputerName을 ASCII화한 "Sanghuns-MacbookPro-M4Max".HostName: RFC 1178 unix hostname. 명시 설정해야 존재. 없으면 비어있다.
$ scutil --get ComputerName
Sanghun's MacbookPro M4Max
$ scutil --get LocalHostName
Sanghuns-MacbookPro-M4Max
$ scutil --get HostName
HostName: not sethostname 명령이 반환하는 값은 HostName이 설정돼 있으면 그걸 쓰고, 없으면 상황에 따라 폴백한다. 폴백 경로는 LocalHostName에서 유도하거나, DHCP가 주는 hostname이거나, 아니면 그 외 네트워크 스택의 디폴트. 내 맥북의 Mac은 그 디폴트 폴백이었다. 네트워크에 따라 DHCP 쪽이 잡히면 Mac, LocalHostName 쪽이 잡히면 Sanghuns-MacbookPro-M4Max. 왔다갔다.
반면 맥미니는 HostName이 mini로 명시 설정돼 있다. 그래서 폴백이 필요 없고 안 바뀐다.
한마디로 hostname -s는 "어떤 기기에서 돌고 있는지"를 식별하는 용도로는 설정 상태에 따라 신뢰할 수 없는 명령이다. 내가 설정해둔 기기에서는 잘 돌지만 그렇지 않은 기기에서는 오락가락한다.
대안 비교
근본 해결에 두 방향이 있다. 하나는 hostname을 안정시키는 것. 다른 하나는 hostname을 버리고 더 안정적인 기기 식별자를 쓰는 것.
| 옵션 | 장점 | 단점 |
|---|---|---|
sudo scutil --set HostName ... |
근본 원인 고침. 시스템 전체가 혜택 | sudo 1회. 일부 IT 도구가 덮어쓸 위험 |
sysctl -n hw.model |
커널 sysctl, 절대 안 바뀜. 스크립트 2줄 | 파일명 가독성↓ (Mac16,5.json) |
ioreg의 IOPlatformUUID |
완벽히 유니크 | 파일명 UUID로 추해짐 |
| 환경변수 오버라이드 | 사용자 명명 가능 | 기기마다 수동 설정 |
| 기기별 매핑 테이블 | 예쁜 이름 | 기기 늘면 테이블 유지 필요 |
나는 sysctl -n hw.model을 택했다. 이유는 두 개. 첫째로 수정 범위가 ccusage-cache.sh 한 파일의 세 줄이다. 둘째로 sudo 같은 시스템 변경 없이 스크립트만으로 해결된다. hw.model 충돌이 나려면 "완전히 동일한 모델의 맥 두 대를 소유하고 둘 다 Claude Code를 돌린다"는 시나리오가 필요한데, 지금은 해당 없고 앞으로도 드물 것이다.
수정
~/.claude/ccusage-cache.sh
# Before
HOSTNAME_SHORT="$(hostname -s 2>/dev/null | tr -d '\n\r' | tr -c 'a-zA-Z0-9.-' '_')"
[ -z "$HOSTNAME_SHORT" ] && HOSTNAME_SHORT="unknown"
CACHE_FILE="$USAGE_DIR/$HOSTNAME_SHORT.json"
# After
HOST_ID="$(sysctl -n hw.model 2>/dev/null | tr -d '\n\r')"
[ -z "$HOST_ID" ] && HOST_ID="unknown"
CACHE_FILE="$USAGE_DIR/$HOST_ID.json"statusline-command.sh는 손댈 필요 없다. 합산 로직이 디렉토리의 *.json을 그대로 긁기 때문에 파일명 규칙이 바뀌어도 그대로 동작한다.
기존 stale 파일을 지우고, 스크립트를 한 번 돌려 새 파일을 만든다. ~/.claude는 Syncthing으로 sync되기 때문에 스크립트 수정은 자동으로 맥미니에도 반영됐다. 맥미니에서는 예전 mini.json을 지우고 스크립트를 한 번 돌려주기만 하면 됐다.
최종 상태.
Mac16,5.json # 맥북 (last30 = 2.54B)
Mac16,11.json # 맥미니 (last30 = 66M)합계 2.6B. 원래 있어야 할 숫자다.
여담: Apple이 M4부터 네이밍을 갈아엎었다
Mac16,11을 처음 봤을 때 이게 맥미니가 맞나 긴가민가했다. Macmini로 시작하는 식별자에 익숙했기 때문이다. 확인해보니 Apple이 M4 세대부터 model identifier에서 제품군 접두어를 다 뺐다. 예전에는 Macmini9,1, MacBookPro18,3 같은 식으로 읽기만 해도 어떤 제품인지 짐작이 됐는데, 이제는 전부 MacN,X다.
Mac16,5= MacBook Pro 14" M4 MaxMac16,11= Mac mini M4 Pro
파일명만 봐서는 어느 쪽이 맥북인지 구분이 안 된다. 가독성은 내려갔지만, hw.model이 "절대 안 바뀐다"는 식별자로서의 신뢰성은 오히려 올라갔다. 제품군 접두어는 카테고리를 상상하게 만들어 사람이 이해하기 쉽게 만드는 장치였는데, Apple이 그걸 포기한 건 아마 세대 내 제품 경계가 점점 흐려지고 있다는 신호이기도 할 것이다. Mac Studio가 Mac Pro와 겹치고, Mac mini가 Mac Studio와 겹친다.
정리
hostname -s는 기기 고유 식별자로 쓰면 안 된다. HostName이 설정 안 된 기기에선 DHCP/LocalHostName 사이를 오간다.
대안으로 sysctl -n hw.model이 제일 가볍다. sudo 없고, 스크립트 몇 줄이면 끝난다. 파일명 가독성을 포기하는 게 유일한 비용이다.