우당탕탕 클로드 코드 사용기
우당탕탕 클로드 코드 사용기 전체 목차. 56편을 읽는 순서대로 정리했다.
이 시리즈 읽기 전에
1인 개발자가 Claude Code와 함께 사이드 프로젝트를 만들면서 남기는 작업 로그다. 자랑보다 막힌 자리, 장애, 되돌린 결정이 대부분이다. 한 편이 하루나 이틀치 작업이고, 하려던 것 → 어떻게 시켰나 → 어디서 막혔나 → 어떻게 풀었나 → 배운 점 순서로 같은 틀을 쓴다.
서비스와 상주 데몬은 집에 있는 맥미니에서 돈다. 모델은 처음에 같은 집의 DGX Spark에 직접 띄워 세 프로젝트가 나눠 썼는데, 가동률 3%를 확인하고 36화에서 자체 서빙을 걷어내고 Claude 구독 호출로 갈아탔다. 그 뒤로 제약은 돈이 아니라 쿼터다. 스파크는 지금 다른 용도를 시험하는 중이다.
등장하는 것들
- 공시 요약 서비스
- 상장사 공시를 LLM이 요약해 주는 서비스. 이 시리즈의 첫 프로젝트이고 지금도 하루 400건 규모로 돈다.
- 의정활동 트래커
- 국회의원 의정활동을 찾아보는 서비스. 트래픽이 안 늘어서 접을지 말지를 숫자로 판정하는 중이다.
- AI 뉴스 다이제스트
- 뉴스를 모아 추려 주는 막내 서비스.
- 자동매매 봇
- 규칙과 LLM을 나란히 돌려 비교하는 매매 시스템. 아직 모의계좌 단계다.
- 온콜 봇
- 에러 알림을 받아 텔레그램에서 수정 PR까지 만드는 봇.
- LLM 모델 서버
- DGX Spark 위에 직접 띄웠던 자체 서빙. 36화에서 걷어냈다.
용어
- 규칙 방식 · Claude 방식
- 자동매매에서 전략을 내는 두 경로. 룰 코드가 내는 쪽과 LLM이 내는 쪽을 나란히 돌려 성적으로 비교한다. 15화에 처음 나온다
- 모의계좌 · 실전계좌
- 증권사 모의투자 계좌와 실제 돈이 든 계좌. 아직 앞쪽만 쓴다. 15화에 처음 나온다
- 장부
- 계좌 없이 DB에 가상 체결만 기록하는 쪽. 계좌가 없는 방식의 성적은 여기서 나온다. 15화에 처음 나온다
- 가드레일 · 안전장치
- 주문이 나가기 전 마지막으로 막는 하드 리밋. 전략이 룰에서 왔든 LLM에서 왔든 여기를 통과해야 주문이 된다. 15화에 처음 나온다
- 실전 전환 관문
- 모의계좌에서 실전으로 넘어가려면 먼저 만족해야 하는 조건들. 여섯 개다. 15화에 처음 나온다
- 존속 판단 게이트
- 서비스를 계속할지 접을지 미리 못 박아 둔 숫자와 날짜. 해석 여지를 남기지 않는 게 요점이다. 42화에 처음 나온다
- 채점표
- 눈으로 보는 판단을 점수로 환산하는 기준표. 20화에 처음 나온다
- 채점기
- 모델 출력이 맞았는지 자동으로 채점하는 코드. 이게 틀리면 모델 평가가 통째로 틀린다. 32화에 처음 나온다
- 상류 · 복제 잡
- 데이터를 받아 오는 원본 데이터베이스와, 그걸 우리 DB로 옮겨 오는 주기 작업. 50화에 처음 나온다
- 컷오버
- 돌아가는 서비스를 한 인프라에서 다른 인프라로 옮겨 붙이는 전환 작업. 50화에 처음 나온다
- 백필
- 과거 데이터를 뒤늦게 대량으로 채워 넣는 일. 라이브 트래픽 뒤에 세워야 한다. 40화에 처음 나온다
- 쿼터
- 구독제에서 쓸 수 있는 총량 상한. 호출 한 번의 값이 아니라 이게 제약이다. 36화에 처음 나온다
- 공유 큐
- 그 쿼터를 여러 프로젝트가 나눠 쓰도록 앞에 세운 대기열. 36화에 처음 나온다
- 헤드리스
- 대화창이 아니라 명령 한 줄로 Claude Code를 실행하는 방식. 스케줄러가 이걸 부른다. 21화에 처음 나온다
- 프리필 · 디코드
- LLM 추론의 두 단계. 입력을 한꺼번에 읽는 쪽과 답을 한 토큰씩 내놓는 쪽. 속도 이야기는 대부분 이 구분에서 나온다. 27화에 처음 나온다
- 페르소나 토론
- 역할을 나눠 붙인 AI 여럿을 라운드로 토론시키는 방식. 1화의 AI 이사회가 이거다. 1화에 처음 나온다
- ADR
- 왜 그렇게 정했는지 남기는 짧은 결정 기록. 뒤집은 결정일수록 남긴다. 14화에 처음 나온다
- 에스컬레이션
- 시스템이 스스로 못 정하고 사람에게 올리는 결정 요청. 50화에 처음 나온다
처음이라면 이 순서로
- 1화 · 아이디어가 없어서, 아이디어를 심사하는 AI 이사회부터 만들었다 아이디어가 없어서 심사하는 AI부터 만든 편. 시리즈의 시작이다.
- 15화 · 원칙을 한 층 내려 다시 세우다 자동매매의 용어와 원칙이 정해진 편. 뒤쪽 편들이 이 단어들을 그대로 쓴다.
- 36화 · 제약이 돈에서 쿼터로 바뀌자 큐가 필요해졌다 집 GPU 서빙을 접고 구독으로 갈아탄 편. 제약이 돈에서 쿼터로 바뀐다.
- 42화 · 존속 판단 게이트를 다시 정했다 서비스를 접을지 정하는 기준을 다시 세운 편.
- 1화 아이디어가 없어서, 아이디어를 심사하는 AI 이사회부터 만들었다 아이디어가 없어서 아이디어 평가 시스템부터 만들었다. 페르소나 토론 세팅법과 삽질의 기록
- 2화 이름 짓고, 도메인 사고, 첫 커밋까지 — 아이디어에서 개발 시작까지 이틀 이름 붙이는 것도 토론으로 시켰다. 새벽의 도메인 결제, 원격 개발 셋업 삽질, 그리고 첫날 커밋 22개
- 3화 프로젝트마다 모델을 띄우다가, LLM 서버를 하나로 합쳤다 DGX Spark 한 대에 vLLM 서버를 세우고, 프로젝트마다 모델을 띄우는 대신 하나로 분리해 첫날 모니터링까지 붙인 기록
- 4화 두 AI가 서로를 탓했다 — 프로젝트마다 에이전트를 붙였을 때 생기는 일 프로젝트마다 붙인 에이전트가 각자 자기 로그만 보고 결백을 주장해서, 양쪽 로그를 겹쳐 놓고 결론을 낸 기록
- 5화 AI가 다시 써준다면 스택을 갈아타도 될까 — 12일 동안 세 번 갈아탄 기록 12일 동안 백엔드를 Spring Boot에서 Go로, 모바일을 세 번 갈아타며 전환 비용이 정말 0인지 확인한 기록
- 6화 도커 볼륨을 통째로 날렸다 — AI는 경고했고, 지운 건 나였다 Docker.raw를 지워 로컬 postgres가 전멸한 뒤, 복구 대신 공용 인프라를 새로 세운 기록
- 7화 컨테이너 메모리 제한을 걸어놨는데 장비가 통째로 멈췄다 DGX Spark에서 도커 메모리 제한이 통하지 않아 26B LoRA 학습이 장비를 통째로 멈춘 15시간짜리 사고와 두 겹 방어 기록
- 8화 파인튜닝 5일이 프롬프트 108자에 졌다 Gemma 4 26B-A4B에 LoRA로 5일을 썼는데 튜닝 안 한 것과 별로 다르지 않았다. 같은 과제를 프롬프트 압축으로 다시 붙여본 결과
- 9화 프롬프트를 줄여 55% 빨라졌는데, 정작 중요한 게 사라졌다 −55%를 만든 압축이 정작 도메인의 핵심을 버리고 있었다. 안 재던 지표가 무너진 이야기
- 10화 서버 앞에 뭘 하나 더 만들려다 제지당했다 범용 엔드포인트를 신설하려는 걸 끊었다. 그리고 그 김에 프로젝트 하나를 접기로 했다
- 11화 에러 알림에서 폰으로 고치는 PR까지 — 온콜 봇 하루 만들기 자작 텔레그램 봇을 만들고 같은 날 폐기했다. 인바운드 포트를 하나도 열지 않고 폰에서 서버 에러를 고치는 구조
- 13화 launchd 위의 Claude Code, 그리고 13일 묵은 401 항상 켜진 맥미니에 Claude Code remote-control을 launchd 상주로 세팅하다 만료 토큰 401, TUI 로그 폭탄, 검증 스크립트 레이스를 차례로 만난 40분.
- 14화 구현 금지 킥오프와 12문항 인터뷰 자동매매 봇 설계를 시작하며 구현 코드 작성을 금지하고 인터뷰부터 시킨 킥오프 프롬프트 사용기.
- 15화 원칙을 한 층 내려 다시 세우다 AI의 정직한 수익률 답변이 자동매매 봇의 1번 원칙과 충돌했고, 폐기하는 대신 한 층 아래로 내려 재정의한 기록.
- 16화 "승인 5, 거부 없음"이라는 거짓말 첫 무인 매매에서 주문 5건이 소수점 하나로 전량 거부됐는데, 알림은 성공이라고 보고한 날의 사고 분석.
- 17화 AI에게 브라우저를 쥐여줬더니 자기 차단을 풀고 왔다 대시보드에서 안 풀리던 봇 차단 토글, Claude가 직접 브라우저를 조작해 마스터 룰 구조를 밝혀내고 재구성한 기록
- 18화 질문 한 줄이 프로젝트로 독립하기까지 자동매매 세션의 곁가지 질문이 하루 만에 별도 프로젝트로 분리되고, 첫 채점에서 해로운 기능의 발주자가 나였음이 드러났다
- 19화 제헌절에 매매를 시도한 봇 휴장일 캘린더 누락 사고를 계기로 수제 캘린더 위에 증권사 API 검증 계층을 얹은 이틀간의 기록.
- 20화 밴드 대신 채점표 화면 절반을 덮은 예측 밴드를 실데이터 시안 다섯 개 끝에 버리고, 오늘 뷰와 정확도 뷰로 갈라 220일 소급 채점과 함께 배포한 이야기.
- 21화 제안하는 Claude, 심문하는 Claude 자동매매 봇의 하루에 헤드리스 Claude를 역할별로 박아 넣은 기록 — 뉴스 수집, 조간회의, 반대 심문, 저녁 자가 감사, 그리고 역할마다 다른 실패의 기본값.
- 22화 데몬은 살아있는데 로그인만 죽는다 한 달마다 풀리는 OAuth에 조용히 죽는 상주 데몬들 — 토큰 삽질 끝에 헬스체크와 텔레그램 봇으로 안전망을 깔았다.
- 23화 재개 장치부터 만들고 자러 갔다 토큰 한도에 걸려도 스스로 다시 일어나는 밤샘 리서치 위임과, 4월 아이디어 점수의 사후 감사
- 24화 "6주"를 0.06으로 읽은 로컬 LLM 자동매매 봇의 데일리 LLM 역할을 자가호스팅 모델로 옮기다 만난 오독 버그를 DB 원문 재현과 A/B 실측으로 잡은 기록
- 25화 죽으면 누가 아픈가 — 구조를 다시 짠 한 주 자동매매 봇의 trader/desk 프로세스 분리, 코드 0줄 재작성 프로젝트의 커밋 전 문서 위생, 그리고 49일 된 launchd 상주 체제의 전면 철거
- 26화 돌아온 첫 시간에 로그 2.5개월치를 날렸다 두 달 만에 연 DGX Spark 세션에서 "로그 확인해줘"가 컨테이너 재생성으로 이어져 334MB가 사라졌다. 살아남은 건 다른 시스템이 우연히 보고 있던 14일치
- 27화 나눗셈 한 번으로 모델 후보 절반을 걸렀다 DGX Spark의 메모리 대역폭을 실측하니 231GB/s. 활성 파라미터로 나누면 디코드 상한이 나오고, dense 모델은 계산만으로 전부 탈락했다
- 28화 혼자면 나쁘고 둘이면 좋은 설정 chunked prefill만 줄이면 꼬리 지연이 오히려 나빠지고, priority 스케줄링과 함께 쓰면 최악 TTFT가 51.8초에서 2.0초로 내려갔다. 커뮤니티 권고 네 가지를 실측으로 기각한 밤
- 29화 커뮤니티 말을 믿고 디코드를 절반으로 깎았다 "투기 디코딩과 멀티모달은 양립 불가"를 믿고 MTP를 껐더니 42.8t/s가 19.4t/s로 떨어졌다. 소스를 읽으니 경고만 하고 진행하는 코드였고, 그 사이 다른 함정이 하나 더 켜져 있었다
- 30화 장비를 처음부터 다시 재기로 했다 sm_121이라는 고아 번호, 6:0으로 이기던 SGLang이 투기 디코딩을 켜자 뒤집힌 표, 공개 벤치 1등이 자체 라벨 데이터에서 진 결과. DGX Spark를 칩·엔진·모델 세 층에서 다시 잰 하루
- 31화 게이트웨이를 지우고 배선을 고쳤다 이틀 전에 세운 게이트웨이가 요리 질문에까지 증시 개장일을 붙이고 있었다. 4월에 제지당한 패턴을 그대로 반복했고, 지우고 나니 채팅 품질 문제의 대부분은 모델이 아니라 조용히 무시되는 설정이었다
- 32화 채점기가 모델보다 자주 틀렸다 자는 동안 800회 넘게 검증을 돌리고 아침에 실패 목록을 보니 8건 이상이 측정 도구 결함이었다. 도구를 고치고 나서 남은 진짜 결함으로 설정 실험 1,000회. 넘은 것 셋, 벽 넷
- 33화 따로 잰 건 같이 잰 게 아니다, 그리고 가동률 3% 띵킹을 오프라인 세트로 재고 효과 없음이라 결론 냈다가 다단계 세트에서 역전. 그 사이 측정한 적 없는 조합이 프로덕션에 들어갔다. max_tokens 상한은 예산이 아니라 차단기였고, 넉 달 튜닝한 장비의 가동률은 3%였다
- 34화 337MB 세션 로그로 넉 달 워크플로우 결산하기 연재를 마치며 — 넉 달치 Claude Code 세션 기록을 Claude에게 통째로 분석시켜 확인한 내 워크플로우의 실체, 그리고 그 기록이 기본 설정으로는 30일이면 사라진다는 사실.
- 35화 원문 대신 정형 데이터를 먹였다 정기보고서 원문의 15%만 읽히고 있었고, LLM 입력의 55%를 먹으면서 결과는 표지 재진술이었다. 원문 대신 공시 API의 확정 수치 6계정을 넣으니 입력이 1/40로 줄고 요약에 숫자가 생겼다
- 36화 제약이 돈에서 쿼터로 바뀌자 큐가 필요해졌다 자체 GPU 서빙을 접고 구독 CLI로 갈아탔다. 4월에 "만들지 마라"고 못 박았던 공용 계층을, 이번에는 만들었다.
- 37화 thinking을 껐다 요약 잡 출력 토큰의 85.8%가 thinking이었다. 환경변수 하나로 끄니 출력 −85%, 처리 시간 4.5배, 스키마 10/10, 요약엔 오히려 숫자가 늘었다. 그리고 끄는 코드 한 줄이 세 프로젝트 인증을 동시에 죽일 수 있었던 이유
- 38화 데스크톱 화면을 나흘간 다섯 번 갈아엎었다 모바일 전용으로 넉 달을 버틴 서비스의 검색 유입 96%가 데스크톱이었다. 죽은 여백을 재고, 레일을 붙이고, 카드 2단은 6시간 만에 버리고, 디자인 핸드오프로 전부 다시 짠 기록
- 39화 dev 환경의 조용한 함정 둘 하루에 네 번 "수정이 안 먹는다"로 코드를 다시 읽었다. 범인은 코드가 아니라 dev와 build가 공유하는 .next 디렉터리, 그리고 로컬 DB를 고쳐도 옛 응답을 주는 두 겹 캐시였다. 사용자 눈에는 한 번도 안 보인 함정
- 40화 64만 건 백필을 라이브 뒤에 세우는 장치 셋 2020~2025 공시 아카이브를 채우려면 외부 API 일일 한도와 LLM 처리량 안에서 몇 달을 돌려야 한다. 수집과 분석을 떼고, 아카이브를 신규 공시 뒤에 세우고, 한도 오류에 전 워커를 멈추는 장치를 만들었다. 완료 예상은 닷새 사이 네 번 바뀌었다
- 41화 폭주를 잡 단위로 판정하지 않기로 했다 호출 1회 비용 상한을 만들고, 올리고, 알림으로 바꾸고, 결국 없앴다. 나흘 동안 같은 장치를 네 번 고친 끝에 남은 건 총량 게이트와 타임아웃뿐이다. "알림만 주라고 했지 않아?"
- 42화 존속 판단 게이트를 다시 정했다 넉 달 동안 구글 색인만 고쳤는데 유입은 네이버였고, 네이버 색인 4,300건에 클릭은 27이었다. 측정 불가가 세 번 연속 나온 옛 게이트를 버리고, GA4 비직접 세션 기준선 54로 11월 15일과 1월 10일 두 판정일을 박았다
- 43화 빠르게 하려고 Cloudflare로 가려다 Cloudflare에서 나왔다 백엔드 전체를 Cloudflare로 옮길까 물었다. 옮기기 전에 재보니 백엔드를 한 번도 안 부르는 페이지와 정적 PNG가 똑같이 0.47초였다. 무료 플랜이 요청 5건 중 1건을 죽이고 있었고, 결론은 정반대 방향이었다
- 44화 effort를 열어줬더니 effort가 비어 있었다 공유 큐에 잡별 모델·effort 선택을 붙였다. 자체 리뷰를 시키자 에이전트가 스크래치 세션 9개로 실측해 닷새 전에 끈 thinking이 effort를 무력화하고 있음을 찾았다. 요청값과 실제값을 컬럼 둘로 나눈 이유, 그리고 배포 뒤 문서와 프로덕션이 다섯 군데 어긋나 있던 것
- 45화 LLM 없이 150건을 39건으로 줄이는 전처리부터 만들었다 새로 만든 AI 뉴스 다이제스트의 수집기가 사흘치 248건을 쏟았다. "LLM을 무한정 쓸 수 없잖아"에서 시작한 규칙 전처리, 임베딩 기각, 그리고 한글 제목을 전부 중복으로 버리던 정규식 한 글자
- 46화 로컬에서 재현이 안 된 건 버그가 없다는 뜻이 아니었다 Railway로 옮긴 뒤 의정보기 웹의 메모리가 26시간 동안 226MB에서 833MB로 곧게 올랐다. 렌더 부하도 아니고 같은 스택의 옆 서비스는 멀쩡했다. 맥에서 3,000건을 때려도 재현이 안 돼 "요청량으로는 재현 불가"라고 적었는데, 컨테이너 안에서 다시 재니 요청당 388KB였다. 플랫폼이 신호를 가리고 있었다
- 47화 파라미터를 하나씩 조이다 두 번 뚫리고, 조이기를 그만뒀다 형제 경로에 모양 검사가 없는 걸 고치러 갔다가 그게 핵심이 아니라는 걸 봤다. 캐시 키가 RequestURI 전체라 같은 응답을 가리키는 표기가 여럿이면 항목도 여럿이었다. 적중률을 포기하고 총량 상한 64MB를 걸었고, 그 뒤 리뷰가 상한 자체의 구멍을 셋 더 찾았다
- 48화 AI가 온 게 아니라 ChatGPT만 왔다 메모리와 트래픽이 뛰었는데 분석 도구에는 아무것도 안 잡혔다. 서버 로그를 User-Agent로 세니 세 시간 15,001건 중 11,321건이 백링크 도구 봇 하나였다. 봇 일곱을 막고 나서 분석 도구를 다시 봤더니, "AI 어시스턴트 53세션"의 정체는 ChatGPT 한 곳이었다
- 49화 색인 가치가 없다고 막은 경로가 유입 1위였다 옆 서비스에서 크롤러를 막은 김에 같은 작업을 했다. JSON이라 색인 가치가 없다며 /api/ 를 막았는데, 네이버에 제출한 RSS 주소가 그 아래였고 네이버가 비-direct 유입 1위였다. 홈 본문도 거기서 온다. 42분 뒤에 철회했다
- 50화 복제 잡이 "상류 없음"을 성공으로 적고 있었다 두 달치 데이터를 정리하자고 했다가 가격 이력이 8월 24일에 멈춰 있는 걸 봤다. 상류가 비밀번호를 거부한 게 시작이었고, 컷오버 때 환경변수 하나가 목록에서 빠지면서 시끄럽던 실패가 조용한 성공으로 바뀌었다. 그리고 안전장치는 두 달 동안 518번 통과했다
- 51화 네 모델을 200건으로 재고 나서, 내가 재지 않은 것이 결론을 뒤집었다 수치 충실도로는 후보가 이겼다. 그런데 한국어 띄어쓰기가 200건 전부 깨져 있었다
- 52화 프롬프트로는 안 됐고, 단계를 나누니 됐다 요약이 얇은 걸 프롬프트로 고치려다 더 나빠졌다. 수치 추출과 문장 작성을 분리하니 재현율 18%p, 실재율 2.6%p가 같이 올랐다
- 53화 입력을 3분의 1로 줄여보니, 고쳤다고 믿었던 게 둘로 갈렸다 2단 처리가 수치 정확도와 누락을 같이 고쳤다. 짧은 입력으로 다시 재보니 하나는 길이 문제였고 하나는 구조 문제였다
- 54화 자동 게재를 켜자 사흘 동안 넷이 드러났다 사람이 손으로 내보낼 때는 안 보이던 것들이다. 재실행이 옛 응답을 새 목록에 붙이고, 슬러그가 다시 만들어져 링크가 어긋나고, 스키마만 채운 껍데기가 지면에 오르고, 한 곳이 후보 25칸 중 9칸을 먹었다
- 55화 빈 배열 하나가 한도 도달을 일반 실패로 만들었다 새벽 두 시간 동안 프로젝트를 가리지 않고 잡이 전부 실패했다. 남은 문구는 한 줄이고 원인 자리가 비어 있었다. 그리고 그걸 고치자 공시 본문의 "429억원"이 전역 정지를 부를 수 있게 됐다
- 56화 누락 0건을 전수로 검증한 PR이, 주석 한 줄로 분석을 세 시간 멈췄다 26만 건 소급 재생성을 위해 락·롤링 배포·누락 행까지 따진 PR이었다. 마지막에 넣은 정렬 변경의 주석 안 치환 자리 하나가 SQL을 깨뜨렸고, 테스트 네 개는 전부 통과했다
- 57화 서치 콘솔이 공시 페이지를 모른다고 해서 확인한 것들 네이버 서치어드바이저의 "robots.txt에 의해 차단" 18건에서 시작해, 구글 서치 콘솔의 표본 조회와 페이지 두께 실측까지 이어진 이틀