📌 AI 사용량 위젯 제작기 2편입니다. 1편에서 "토큰 0으로 한도 보는 창"을 만들었다면, 이번엔 그걸 아이폰에서 보고, 한도가 차면 알림을 받고, 맥미니를 켜면 저절로 뜨게 키운 이야기예요. 중간중간 삽질도 있습니다. 결론만 궁금하시면 맨 아래 최종 요약으로 가셔도 돼요.
1편 「토큰 0으로 AI 사용량 보는 위젯 만들기」에서 만든 건 맥미니 화면에 떠 있는 창 하나였어요. 저는 맥미니에 모니터를 따로 안 달고 아이패드를 화면으로 쓰거든요(사이드카). Claude Code·Codex 한도, 지금 일하는 중인지, 어떤 모델로 얼마나 썼는지를 AI 모델을 한 번도 부르지 않고 보여 주는 창이죠. 그런데 며칠 써 보니 아쉬운 게 세 가지 생기더라고요.
📎 궁금하신 분들은 지난 「아이패드만으로 맥미니 주모니터 사용하기|사이드카 연결부터 HDMI 더미플러그까지」 포스팅을 참고하세요 → 글 보러 가기

- 아이패드 화면에서만 보인다: 소파에서 아이폰으로 Claude 일을 시켜 놓으면, 한도 보려고 아이패드를 다시 켜서 맥미니 화면을 띄워야 했어요.
- 내가 봐야만 안다: 한도가 95%가 돼도 창을 안 보고 있으면 모르고 지나가요.
- 맥미니를 다시 켜면 꺼져 있다: 재부팅할 때마다 서버를 손으로 다시 켜야 했어요.
이 세 개를 하나씩 풀고, 마지막에 로컬 LLM 사용량까지 같이 세게 만든 순서로 적어 볼게요.
1. 아이폰·아이패드에서 보기: 인터넷엔 안 열고
위젯 화면은 원래 맥미니 안에서 도는 작은 웹 서버가 그려 줘요. 그러니 아이폰 브라우저로 그 주소에 들어가기만 하면 되는데, 문제는 이걸 인터넷에 공개하고 싶지는 않다는 거였어요. 제 AI 사용 기록이 담긴 화면이니까요.
그래서 Tailscale을 썼어요. 제 기기들끼리만 묶인 개인 네트워크(tailnet)를 만들어 주는 서비스인데, 여기에 들어온 제 아이폰·아이패드에서만 위젯 주소가 열리고 바깥 인터넷에서는 안 보여요. 외부 공개 기능(funnel)은 켜지 않았고요.
💡 tailnet: 내 기기끼리만 쓰는 사설 네트워크라고 보시면 돼요. 회사에서도 집 맥미니에 붙을 수 있지만, 로그인한 내 기기가 아니면 주소를 알아도 못 들어와요.
그다음엔 사파리 "홈 화면에 추가"로 앱처럼 띄울 수 있게, 앱 이름·아이콘이 든 설정 파일(manifest)을 붙였어요. 주소창 없이 꽉 찬 화면으로 열려서 진짜 앱 같더라고요. 다른 앱 갔다가 돌아오면 끊긴 실시간 연결을 다시 잇는 코드도 넣었고요.
삽질: 스크롤만 하면 화면이 멈춘다
아이폰에서 써 보니 이상한 일이 생겼어요. 표를 손가락으로 쓱 스크롤하고 나면 숫자가 더 이상 안 바뀌는 거예요. 연결 표시는 초록불 그대로인데요.
원인은 터치 이벤트였어요. 위젯은 "사용자가 누르고 있는 동안엔 화면을 다시 그리지 않는다"는 규칙이 있는데, 아이폰에서 스크롤하면 손을 뗄 때 "뗐다(pointerup)" 신호 대신 "취소됐다(pointercancel)" 신호가 오더라고요. 그래서 위젯은 계속 누르고 있는 줄 알고 갱신을 멈춘 거였어요. 취소 신호에서도 "뗐다"로 처리하게 한 줄 고치니 해결됐어요. 표를 옆으로 밀어 둔 위치가 갱신 때마다 처음으로 튀던 것도 같이 고쳤고요.
참고로 아이폰 홈 화면 위젯(앱 아이콘 옆 작은 카드)도 생각했는데, 그건 실시간으로 바뀌지 않아서 보류했어요.
2. 맥미니 켜면 저절로 뜨게: launchd
맥에는 로그인할 때 프로그램을 띄워 주고, 죽으면 다시 살려 주는 launchd라는 관리자가 있어요. 여기에 위젯 서버와 창을 등록하는 명령을 만들었어요.
💡 launchd: 윈도우의 "시작 프로그램 + 서비스 자동 재시작"을 합친 맥의 기본 관리자예요. 설정 파일(plist) 하나로 "로그인 때 켜기", "비정상 종료면 다시 켜기"를 정할 수 있어요.
서버는 비정상으로 꺼지면 30초 뒤에 다시 켜지고, 창은 로그인 때 한 번만 떠요. 정말 그렇게 도는지 직접 확인했어요.
| 해 본 것 | 결과 |
|---|---|
| 일부러 끄기(stop) | 40초 동안 꺼진 채 유지(내가 끈 건 안 살림) |
| 강제 종료(kill -9) | launchd가 다시 띄움 |
| 설치 후 데이터 수집 | 모든 수집 항목 정상, 아이폰 접속도 정상 |
삽질: 테스트가 진짜 서버를 꺼 버렸다
등록하고 나서 테스트를 돌렸더니 위젯이 꺼졌어요. 알고 보니 "켜기·끄기" 기능을 검사하는 테스트가 임시 서버가 아니라 방금 등록한 진짜 자동 시작 항목을 내려 버린 거였어요.

그래서 "자동 시작으로 설치돼 있다"는 판정을, 테스트용 포트·경로 설정이 없을 때만 참이 되게 바꿨어요. 이 사고가 다시 안 나도록 그 경우를 검사하는 테스트도 하나 더 붙였고요.
로그인 항목에 "python"이 두 개?
맥 설정의 로그인 항목을 열어 보니 이름이 "python"인 게 두 개 떠 있었어요. 뭐가 뭔지 모르겠더라고요. 그래서 "Agent Status"라는 이름과 아이콘을 가진 작은 앱 껍데기를 만들어 연결했어요. 이제 로그인 항목과 Dock에 "Agent Status"로 보이고, Spotlight에서 이름으로 찾아 열 수도 있어요.
3. 한도 차면 알림: 맥미니 + 아이폰(워치는 따라오는지 미확인)
이제 "안 보고 있어도 알게" 할 차례예요. 규칙은 이렇게 정했어요.
- 언제: Claude·Codex의 5시간·주간 한도가 80%, 95%를 넘을 때. 같은 창에서 기준값마다 딱 한 번.
- 리셋되면: 기준을 넘었던 창이 리셋되면 한 번 더 "리셋됐어요".
- 오래된 값으론 안 보냄: 1편에서 말한 "모르면 0%라고 하지 않기"와 같은 이유예요. 낡은 숫자로 알림이 오면 믿을 수가 없으니까요.
- 내용: 숫자와 시각만. 대화 내용은 들어가지 않아요.
알림 제목은 한눈에 알아보게 "⚠️ 한도 95% 넘음 · Claude 5시간", "✅ 한도 리셋 · Claude 5시간"처럼 붙였어요. 맥미니(아이패드 화면)는 알림 센터로, 아이폰은 홈 화면 앱의 "알림 받기" 버튼을 눌러 등록하는 웹 푸시(iOS 16.4부터 지원)로 보내요. 워치는 아이폰 알림이 넘어가는 대로 따라가고요.

아이폰 알림이 오는 건 확인했어요. 워치에 넘어오는지는 그때 따로 확인하지 않았어요.
"읽기만 한다" 원칙에 붙인 예외 네 개
1편의 원칙은 "모델을 부르지 않는다"였지만, 위젯은 원래 맥미니 안의 기록을 읽어서 화면에 보여 주기만 하는 프로그램이었어요(밖으로 나가는 건 1편에서 말한 한도 조회와 짧은 핑 정도). 알림을 보내려면 그걸 조금 깨야 해서, 무엇을 깨는지 하나하나 적고 제가 승인했어요.
| 예외 | 이유와 제한 |
|---|---|
| 알림 등록·해제 요청 2개 | 그 밖엔 여전히 읽기 전용. 애플 푸시 주소만, 2KB 이하, 최대 10개 |
| 암호화 라이브러리 설치 | 웹 푸시는 내용을 암호화하고 서명해야 보낼 수 있어서 |
| 애플 푸시 서버로 전송 | 알림 내용을 처음으로 바깥(애플 푸시 서버)에 보내는 곳. 실패하면 최대 20번까지만 재시도 |
| Claude 설정 파일 수정 | 아래 설정 패널에서 제가 버튼을 누를 때만 |
이 기능은 구현 담당 서브에이전트(implementer) 세 개를 동시에 띄워 나눠서 동시에 만들게 했고(푸시 암호화 / 알림 규칙 / 설정 바꾸기), 계획 단계와 구현 단계에서 한 번씩 Codex 리뷰를 받아 지적을 반영했어요. 리뷰를 다른 회사 AI에게 맡기는 방식은 예전에 따로 정리한 적이 있어요.
📎 궁금하신 분들은 지난 「Claude Code에 Codex 리뷰어 붙이기」 포스팅을 참고하세요 → 글 보러 가기
맥미니 위젯 창의 설정 패널: 서브에이전트 모델·노력도까지
맥미니에 뜨는 위젯 창에는 ⚙ 버튼으로 여는 설정 패널도 넣었어요. 설정 파일을 직접 열어 고치던 걸 위젯에서 바로 바꾸는 거예요. 바꿀 수 있는 건 이렇습니다.

설정 패널의 팀원 이름이 서브에이전트 글이랑 다른 건 1편에서 말한 대로 그 사이 팀을 다시 짜서예요(7명 → 지금 8명, 로컬 LLM 담당 text-drafter는 정리). 이 이야기는 따로 정리해서 올릴게요.
- Claude 기본 모델: 새 대화를 시작할 때 쓰는 기본 모델을 고릅니다(Claude Code 설정 파일의
model값 하나). - 서브에이전트별 모델: 코드 찾는 애, 리뷰하는 애처럼 팀원마다 쓸 모델을 따로 정해요(각 팀원 파일의
model:줄). - 서브에이전트별 노력도: 얼마나 깊게 생각하게 할지예요.
low·medium·high·xhigh·max중에 고르고, "기본값"을 고르면 그 줄을 지워서 대화 쪽 설정을 따르게 해요. 모델이 지원하지 않는 단계를 고르면 그 아래 지원 단계로 내려가요. - 데스크톱 앱용 짧은 핑: 1편에서 말한 예외 기능을 켜고 끄고, 주기를 1~60분(기본 2분)으로 바꿔요. 범위 밖 숫자는 저장하지 않고 안내만 해요.
- 알림 기준값: 몇 %에서 알릴지 정해요(바로 위 알림 기능의 기준값).
- 자동 시작 켜기·끄기: 다음 로그인부터 적용돼요. 지금 떠 있는 위젯은 끄지 않고요.
설정 파일을 건드리는 거라 안전장치를 꼼꼼히 걸었어요. 바꾸기 전에 뭐가 바뀌는지 보여 주고, 백업을 남기고, 그 값 하나만 바꾸고, 그 값만 되돌릴 수 있게요. 그사이 누가 같은 값을 바꿨으면 되돌리기 전에 알려 주고요. 아이폰 화면에는 이 패널을 넣지 않았어요.
4. 로컬 LLM 사용량도 같이 세기
저는 가벼운 글쓰기 일은 맥미니에 깔린 로컬 LLM(Ollama)에 맡겨요. Claude 토큰을 아끼려고요.
📎 궁금하신 분들은 지난 「로컬 LLM(Ollama gemma4:12b)으로 Claude 토큰 아끼기」 포스팅을 참고하세요 → 글 보러 가기
그런데 위젯 표에는 그 일을 맡은 서브에이전트(그때 이름은 text-drafter, 지금은 정리돼서 없어요)가 "haiku로 일했다"고만 나왔어요. 실제로 글을 쓴 건 로컬 모델인데 말이죠. 서브에이전트가 로컬 모델에 일을 넘기는 중계 역할이라 생긴 일이었어요.
그래서 Claude 작업 기록에서 로컬 LLM을 부른 기록과 결과 끝에 붙는 통계 한 줄(모델 이름, 토큰 수, 초당 속도)만 골라 읽게 했어요. 본문은 저장하지 않아요. 이제 표에 "(로컬 LLM)" 행이 따로 생겨서 어떤 모델이 몇 번, 토큰을 얼마나 썼는지 보여요. 일을 맡겨 놓고 서브에이전트가 로컬 모델을 안 부르고 끝내 버리면 "로컬 LLM 미호출 N"이라고 따로 표시해요.
하나 고민한 게 있었어요. 처음엔 "Claude 한도와는 상관없으니까" 로컬 토큰을 비율·합계에서 뺐는데, 다시 생각해 보니 제가 알고 싶은 건 "어떤 에이전트가 어떤 모델로 토큰을 얼마나 쓰나"였어요. Claude든 GPT든 로컬이든요. 그래서 합계에 넣었어요. 하드웨어 카드에는 Ollama 상태 줄도 붙여서 지금 어떤 모델이 메모리에 올라와 있는지, 몇 분 뒤 내려가는지도 보이게 했어요.
⚠️ 한계: Ollama는 "지금 생성 중"인지 알려 주지 않아요. 그리고 처음엔 스크립트가 Ollama를 직접 부르면 Claude 기록에 안 남아 표에 안 잡혔어요. 나중에 Ollama 자체 로그를 읽게 바꿔서, 짝이 없는 호출은 "직접 호출 (로컬 LLM)"으로 따로 세요.
주의사항
- 공개 범위: 사용 기록이 담긴 화면은 인터넷에 열지 말고 내 기기끼리만 보게 하세요. 저는 Tailscale tailnet 안에서만 열었어요.
- 테스트와 실제 환경 분리: 자동 시작을 등록한 뒤엔 테스트가 진짜 항목을 건드리지 않는지 꼭 확인하세요. 저는 한 번 당했어요.
- 원칙의 예외는 적어 두기: "토큰 0", "읽기 전용" 같은 원칙을 깰 땐 무엇을 왜 깨는지 문서에 적고 직접 승인하세요. 나중에 헷갈리지 않아요.
마치며
아이패드 화면에서만 보던 창이 이제 아이폰에서도 보이고, 한도가 차면 먼저 알려 주고, 맥미니를 켜면 알아서 떠요. 만드는 데 며칠이 걸렸지만 제일 크게 바뀐 건 한도를 확인하러 가지 않아도 된다는 점이에요. 알림이 올 때만 보면 되거든요.
이 위젯은 그 뒤로 AI들이 올린 결정할 일(결재함)과 진행 상황(현황판)까지 한 화면에 모은 "본부" 앱으로 커졌어요. 그 이야기는 회사처럼 굴리게 된 이야기와 같이 따로 써 볼게요.
최종 요약
✅ 결론만 보고 싶은 분
1. 아이폰·아이패드: Tailscale tailnet 안에서만 열고, 홈 화면 앱으로. 스크롤하면 멈추던 버그는 pointercancel 처리로 해결.
2. 자동 시작: launchd에 서버(죽으면 30초 뒤 재시작)와 창 등록, "Agent Status" 앱 껍데기로 이름·아이콘 정리.
3. 알림: 80%·95% 넘을 때와 리셋 때 한 번씩, 맥미니 알림 센터 + 아이폰 웹 푸시. 오래된 값으론 안 보냄.
4. "읽기만" 원칙의 예외 네 개(등록 요청 2개·암호화 라이브러리·애플 푸시 전송·설정 수정)는 적어 두고 직접 승인.
5. 로컬 LLM: 호출 기록과 통계 한 줄만 읽어 "(로컬 LLM)" 행으로, 합계에도 포함.
· · ·
도움이 됐다면 공유 부탁드립니다! AI 한도 알림, 어떤 방식으로 받고 계신지 댓글로 알려 주세요.
#클로드코드 #ClaudeCode #위젯 #Tailscale #맥미니
'만들기' 카테고리의 다른 글
| 토큰 0으로 AI 사용량 보는 위젯 만들기|스테이터스 위젯 제작기 1편 (0) | 2026.10.24 |
|---|