claude-daily-review 플러그인 개발기 - Claude Code를 회고에 이용하기
일단 플러그인 링크부터 투척 ㅎ
https://github.com/giwonn/claude-daily-review
만든 계기
회고를 쓰려고 하면 항상 같은 문제가 생긴다.
프로젝트의 시작과 끝은 기억나는데, 중간 과정이 떠오르지 않는다.
"그 때 왜 그렇게 결정했더라?", "그거 해결했지?" 같은 것들이 흐릿해진다.
결국 회고는 매번 비슷한 패턴이 된다. 시작은 이랬고, 결과는 이렇다. 중간은 대충 넘어간다.
그런데 생각해보니, 나는 일할 때 Claude를 항상 달고 산다.
코드를 짜면서 하는 고민이나, 삽질하는 과정, 의사결정까지 전부 대화에 남아있다.
그러면 이 대화 내역 자체가 회고 자료가 될 수 있지 않을까?
세션이 사라지면 대화 내역이 휘발되지 않도록, 자동으로 수집하고 정리하는 플러그인을 만들었다.
만들면서 겪은 것들
대화 내용을 어디에 저장하지?
처음 설계할 때부터 저장소를 어디에 둘지 고민이 있었다. 대화 내용에는 뭐가 들어있을지 모른다.
회사 코드, 내부 시스템 구조, 심하면 API 키까지.
그래서 두 가지 저장 방식을 지원하기로 했다.
- 로컬 저장 (Obsidian vault 등) — 내 기기에만 남으니까 안전
- GitHub 원격 저장 — 여러 기기에서 쓸 수 있되, 반드시 private repo로
StorageAdapter라는 인터페이스를 만들어서 둘 다 같은 방식으로 동작하게 추상화했다.
회고 생성은 수동으로
처음에는 세션이 끝날 때마다 AI가 자동으로 요약을 생성하게 만들었다.
SessionEnd라는 훅에 agent를 붙여서, 대화가 끝나면 바로 회고 마크다운을 뽑아주는 구조였다.
근데 실제로 써보니 사용성이 좋지 않았다.
세션을 종료시킬 때, SessionEnd 훅을 발동하리라는 보장이 있을까?
(당장 나만 해도 세션을 끌 때, /exit 커맨드를 사용하지 않고 터미널을 직접 종료한다...)
사용자가 세션을 어떻게 종료할지 통제할 수 없다면, 대화이력을 적재하는것에만 집중하기로 했다.
(어차피 대화이력만 있다면, 언제든지 회고를 뽑아낼 수 있다.)
회고 자동 생성을 걷어내고, 사용자가 원할 때 /generate로 생성하는 방식으로 바꿨다.
raw 로그만 차곡차곡 쌓아두고, 명령어를 치면 이렇게 계단식으로 요약을 만든다.
daily → weekly → monthly → quarterly → yearly
자동화가 항상 좋은 건 아니라는 걸 직접 써보고 나서야 알았다.
디렉토리 구조를 뒤집다
처음 설계할 때는 동시에 여러 터미널에서 Claude 세션을 돌리니까, 세션 단위로 폴더를 만들고 그 안에 날짜별로 로그를 저장하려 했다.
.raw/{세션ID}/{날짜}.jsonl ← 처음 설계
근데 실제로 회고를 생성하다 보니, 날짜별로 로그를 모아볼 일이 훨씬 많았다.
오늘 뭐 했지?를 보려면 세션 폴더를 하나하나 뒤져야 하는 구조는 불편했다.
raw/{날짜}/{세션ID}.jsonl ← 결국 이렇게 바꿨다
기존 사용자를 위한 마이그레이션 명령어까지 만들어야 했다.
별 생각없이 구조를 잡았다가 좀 후회했다...
API Key 같은 걸 입력하면 어쩌지?
보안 쪽에서 가장 고민이 많았던 건 시크릿 마스킹이다. 대화에 API 키나 토큰이 포함될 수 있으니까,
혹여나 API Key 같은게 입력될까봐 로컬로 관리할 수 있게 했다지만, 애초에 저장할 수 없도록 하는게 중요하다.
그래서 주로 알려진 패턴들을 4단계로 탐지하게 만들었다.
| 단계 | 탐지 대상 | 예시 |
|---|---|---|
| 1 | 알려진 서비스 키 패턴 | sk-proj-..., ghp_..., AKIA... |
| 2 | 구조적 시크릿 | PEM 키, DB 연결 문자열, JWT |
| 3 | key=value 형태 | API_KEY=xxx, .env 블록 |
| 4 | 고엔트로피 문자열 | 의미 없는 긴 랜덤 문자열 |
위 예시에 해당하는 문자열을 탐지하면, 해당 부분은 마스킹 처리하여 로그로 저장하도록 했다.
물론 그래도 한계는 있다.
"우리 DB 비번은 xxx야"라고 자연어로 말하면 잡을 수 없다.
코드 블록 안에 하드코딩된 값도 패턴에 안 걸리면 통과한다.
일단은 README에 가능하면 로컬로 사용하되, 원격 저장소에 연결할거라면 절대 노출되지 않도록 PRIVATE으로 사용하는 것을 권장하도록 하였다.
마스킹이 다 해결해주길 바라는 것보다, 저장소 자체를 안전하게 유지하는 게 더 현실적이다.
이 부분은 어떻게 하면 더 안전하게 할 수 있을지 고민중이다...
마무리
3월 28일에 설계를 시작해서 바이브코딩으로 하루만에 MVP를 만들고, 계속해서 사용중이다.
그 뒤로 일주일 정도 더 다듬어서 어쩌다가 v0.5.1까지 왔다. (버전 너무 많이 올렸나 ㅎ)
업무에서는 코드 작성은 AI에게 맡기지만, 플랜이나 코드리뷰에는 사람이 개입하도록 하는 편이다.
(TDD를 적용하면 완성도가 꽤 좋아지지만 그래도 여전히 좀 미묘하더라)
이번에는 플랜과 코드리뷰조차 완전히 AI에게 위임해봤다.
(개발 중간에 고민포인트가 있다면, 내가 답변해주는 대신 AI가 스스로 고민하고 결정하도록...)
어차피 혼자 하는 사이드 프로젝트니까, 명세를 구체화하는 것에만 온전히 집중했다.
"일단 돌아가는 걸 빠르게 만들어보자"라는 목적에는 꽤 잘 맞는 방식이었다.
원래 목표였던 회고의 중간 과정을 메우자는 어느 정도 달성한 것 같다.
실제로 이 글도 raw 로그를 기반으로 초안을 작성하였다.
이 프로젝트를 진행하면서도 그 때 왜 그런 결정을 했는지가 대화에 다 남아있어서 수월했다.
매일 기록하지 않아도, 기억에 의존하지 않아도 되는 회고
그게 이 플러그인을 만든 이유였고, 지금은 직접 쓰면서 계속 다듬어가는 중이다.