| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | |||||
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| 31 |
- claude ai
- 다크테마UI
- typescript
- docs-first
- 퍼블릭도메인
- 무료호스팅
- Chatgpt활용
- React
- 사주프로그램
- GitHub Pages
- Netlify
- AI개발
- ai웹사이트
- 바이브코딩
- 타로카드
- AI협업개발
- meslolgs nf
- 무료웹사이트
- 천간지지오행
- 웹사이트만들기
- 카드애니메이션
- claude활용
- github
- Cloudflare Pages
- 사주앱개발
- 무료서버
- 타로앱개발
- 코딩독학
- 웹앱개발
- 일렉트론
- Today
- Total
dog paw / development
퇴근 후 클로드 코드와의 씨름, AI의 한계인가? 크롬 익스텐션 개발기 본문
오늘도 퇴근 후 경제적 자유를 얻기 위한 몸부림이 시작되었다.
피곤하지만 샤워를 마치고 바로 클로드 코드와의 씨름이 시작되었다. 그리고 오늘도 세 번째로 git reset --hard를 치는 순간, 그냥 웃음이 나왔다.
새벽 1시. 빌드는 멀쩡히 된다. 에러도 없다. 근데 버튼을 누르면 아무 일도 안 일어난다. 콘솔 열었더니 이거 하나.
Could not establish connection. Receiving end does not exist.
background script가 또 죽어있었다. 오늘만 세 번째다.
Claude가 자신있게 내놓은 코드
MV3 기반 크롬 익스텐션이었다. popup에서 버튼 누르면 background에 메시지 보내고, background가 외부 API 찔러서 결과 돌려주는 단순한 구조. 뼈대는 Claude Code한테 잡아달라고 했고, 거기에 기능을 붙여가면서 만들고 있었다.
Claude Code가 처음에 내놓은 background.js가 이랬다.
// background.js
let sessionCache = {};
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.type === 'FETCH_DATA') {
if (sessionCache[message.key]) {
sendResponse({ data: sessionCache[message.key] });
return;
}
fetch(API_URL)
.then(res => res.json())
.then(data => {
sessionCache[message.key] = data;
sendResponse({ data });
});
return true;
}
});
sessionCache를 메모리에 들고 있다. MV3 service worker는 idle 되면 브라우저가 그냥 죽인다. 재시작되면 sessionCache는 초기화된다. 거기다 service worker가 죽어있는 상태에서 popup이 메시지 보내면 receiving end 자체가 없어서 연결이 아예 실패한다.
왜 이러냐고 Claude한테 물어봤더니 정확하게 설명해줬다. MV3 생명주기, chrome.storage로 상태 영속화, chrome.runtime.onConnect 장기 연결 관리까지. 틀린 말이 하나도 없었다. 수정 코드도 줬다. 적용했다. 그 버그는 잡혔다.
대신 이번엔 content script 쪽이 터졌다.
그래서 또 물어봤다. 또 고쳐줬다. 또 다른 데가 깨졌다. 이걸 사흘 반복했다.
두 번째 시도, 그리고 또 실패
처음부터 다시 짜면서 이번엔 프롬프트 앞에 제약을 박았다.
"MV3 service worker 기반으로 짜고, 전역 상태는 chrome.storage로만 관리해. 메모리 캐시 절대 쓰지 마."
초반엔 괜찮았다. 근데 기능이 늘면서 대화가 길어졌다. 매번 같은 조건 복붙하는 게 귀찮아져서 어느 순간부터 그냥 "이 함수 추가해줘"만 치고 있었다.
나중에 파일들 합쳐보니 각자 다른 패턴으로 짜여있었다. 어떤 파일은 메시지 타입을 string으로 쓰고, 어떤 파일은 enum처럼 쓰고. 스토리지 접근 방식도 제각각. 타입 불일치, 이벤트 처리 충돌.
두 번째 git reset --hard.
솔직히 이쯤에서 좀 황당했다. AI가 이렇게까지 일관성이 없을 줄은 몰랐으니까.
AI가 멍청한 게 아니었다
퇴근하고 지쳐서 멍하니 앉아있다가 이게 왜 반복되는지 생각해봤다.
AI는 대화가 길어질수록 앞부분 영향력이 희석된다. 초반에 내가 설정한 아키텍처 원칙이 스크롤이 길어지면서 흐려지고, 나중엔 그 순간 학습 데이터에서 가장 많이 본 패턴을 뱉는다. MV2 코드가 MV3보다 압도적으로 많다 보니 명시적으로 막지 않으면 MV2 스타일이 슬그머니 끼어드는 거다.
크롬 익스텐션은 이게 특히 치명적이다. service worker, content script, popup이 메시지 패싱으로 서로 물려있어서, 각 레이어 통신 방식이 파일마다 다르면 나중에 고치는 게 처음부터 새로 짜는 것보다 오래 걸린다.
80% 문제라고들 한다. 빠르게 만들어지다가 마지막 20%에서 막힌다고. 근데 겪어보니 그건 AI 능력의 문제가 아니었다. 80%쯤 됐을 때 이미 코드베이스가 제멋대로 섞여있는 거다. AI한테 지도 없이 집 지어달라고 한 셈이다. 방은 있는데 복도가 없는 집.
세 번째 시도에서 바꾼 것
코드 먼저 짜지 않기로 했다.
이 프로젝트에서 service worker가 뭘 하고 뭘 안 하는지, 메시지 타입은 어떻게 정의하는지, 스토리지 키는 어디서 관리하는지 — 이걸 먼저 문서로 정리하고 AI 요청마다 같이 태웠다. 프롬프트에 조건 복붙하는 게 아니라 참조할 컨텍스트 파일을 프로젝트 안에 아예 두는 방식으로.
ADR(Architecture Decision Record)도 써봤다. "왜 content script에서 직접 API 호출 안 하기로 했는가", "왜 chrome.storage.session으로 갔는가" 같은 결정의 이유들. 이게 있으면 AI가 나중에 비슷한 맥락에서 다른 선택을 하려 할 때 제동이 걸린다.
자주 쓰는 chrome API 패턴은 검증된 형태로 따로 묶어뒀다. AI가 매번 새로 생성하는 대신 이 패턴을 가져다 쓰게.
세 번 갈아엎고 나서야 겨우 방향이 잡혔다.
이게 반복되면서 하나의 흐름이 만들어졌다. 프로젝트 시작할 때 AI한테 단계적으로 질문하면서 ADR, 불변식, hooks, MCP 구성을 먼저 세팅하고 — 코드는 그 다음에 짜는 방식.
이걸 크롬 익스텐션 전용 템플릿으로 정리하고 있다. 퇴근 후 한두 시간밖에 없는 사람이 매번 같은 삽질을 처음부터 반복하지 않아도 되도록. 아직 만들고 있다.
'개발 > AI' 카테고리의 다른 글
| AI는 코드를 짜지만 도메인은 모른다 — 코드보다 중요한 도메인 이해 (0) | 2026.04.23 |
|---|---|
| AI 코딩은 공짜가 아니다 — 생산성보다 먼저 부딪히는 건 비용이다 (0) | 2026.04.23 |
| 로봇이 차를 만들어도 책임은 사람에게 남는다 — 오래전부터 주변에 해온 말 (0) | 2026.04.23 |
| 개발자는 코드를 쓰는 사람이 아니다 — AI 시대에 끝까지 남는 자리는 ‘책임’에 있다 (0) | 2026.04.23 |
| 기본 설정을 의심하라 — AI 코딩이 느릴 때, 모델보다 먼저 버려야 할 것들 (0) | 2026.04.23 |
