
Claude Code로 만든 데스크톱 앱, 그 후 3개월간 어떻게 되었나
요약
Claude Code를 활용해 99% AI가 작성한 데스크톱 앱 'Rendu'의 출시 3개월 후 운영 기록을 다룹니다. AI가 작성한 코드의 보안 취약점 발견 사례와 외부 컨트리뷰터의 참여 등 실제 운영 과정에서의 경험을 공유합니다.
핵심 포인트
- AI가 작성한 코드에서 실제 보안 취약점(임의 코드 실행) 발견
- 코드 작성의 99%를 AI가 담당하며 테스트 코드도 동량으로 생성
- 외부 컨트리뷰터의 PR 리뷰 및 방향성 결정은 인간의 핵심 역할
- AI 제작 오픈소스 프로젝트의 지속 가능한 운영 가능성 확인
서론
약 3개월 전, Claude Code에게 데스크톱 앱을 만들게 했더니 7일 만에 첫 출시를 할 수 있었다는 글을 썼습니다. Markdown 읽기 전용 데스크톱 앱인 Rendu (Tauri + React)를 코드의 99%를 AI에게 쓰게 하여 만든 이야기입니다.
당시에 쓴 내용은 "만들기 시작해서 첫 출시까지"에 대한 것이었습니다. 그렇다면 그 후, 방치되지 않고 계속 움직였는가, AI가 작성한 코드가 운영을 견뎌냈는가. 이것은 꽤 리얼한 "AI 제작 OSS의 그 후"에 대한 기록입니다.
결론부터 말하자면, 가장 흥미로웠던 점은 **"AI가 작성한 코드를 AI에게 감사(Audit)하게 했더니, 진짜 취약점(1클릭으로 임의 코드 실행)이 나타났다"**는 것이었습니다. 이 이야기를 메인으로 삼으면서, 3개월간의 수치와 실패를 나열해 보겠습니다.
우선 수치 (이전 글과의 비교)
| 이전 글 시점 | 현재 (v0.10.0) | |
|---|---|---|
| 커밋 수 | 112 | 199 |
| ... | 15 (beta 포함 시 27) | |
| 테스트 케이스 | 174 | 280 (TS 236 + Rust 44) |
| 외부 컨트리뷰터 (External Contributor) | 0 | 2 |
| 코드 (테스트 제외) | 약 3.2K 행 | 약 5.3K 행 |
| 테스트 코드 | — | 약 2.5K 행 |
여전히 기능 코드와 거의 동량의 테스트가 AI로부터 생성되고 있습니다. 그리고 코드를 작성하고 있는 것은 지금도 99% AI입니다. 제가 하고 있는 것은, 후술하겠지만 "무엇을 만들 것인가"와 "정말로 올바른가"에 대한 판단뿐입니다.
3개월 동안 추가된 주요 사항:
- KaTeX 수식 렌더링 (
$$...$$) - 내부 Markdown 링크의 앱 내 전환 (
[link](./other.md)를 클릭하면 히스토리를 포함하여 이동) - 기동 속도 향상 (수식을 포함하지 않는 문서에서는 KaTeX를 전혀 로드하지 않는 지연 로딩)
- 다국어 대응 (간체 중국어 + System 테마) ← 이것은 외부 컨트리뷰터가 넣어주었습니다.
- 보안 체제 (Dependabot / cargo audit / npm audit / 주간 스캔 / SECURITY.md)
"그 후"에 일어난, 소소하지만 큰 변화
1. PR이 왔다 (심지어 중국에서)
이전 글 마지막에 "AI가 작성한 코드라고 하면 미묘하게 분위기가 싸해진다"라는 사회적 어색함에 대한 이야기를 썼습니다. 그 후, 어느 날 GitHub 알림이 와서 열어보니 **낯선 중국 분으로부터 온 Pull Request (PR)**였습니다. 내용은 간체 중국어 로케일 추가.
솔직히 외부에서 PR을 받을 것을 예상하지 못했기에 조금 당황했습니다. AI 제작이라고 명시한 개인 OSS에 바다 건너편에서 사람이 기여해 주다니. 이런 일이 있을 수 있나? 하고 말이죠. ……그리고 여기서부터는 허둥지둥 타임입니다. 우선 저는 중국어를 읽을 수 없습니다. 추가된 번역이 타당한지 그 자리에서 판단할 수 없습니다. 게다가 그 PR에는 "System 테마 (OS의 다크/라이트 모드 추종)"까지 함께 들어있어서, 이쪽은 이쪽대로 기존 테마 처리에 침범하는 변경이었습니다.
결과적으로 로케일 추가만이었다면 이해하기 쉬웠을 텐데 하는 생각을 하며, 컬러 피커가 사라짐 / Dark와 Light의 배색이 섞임 / 리셋 경로가 없음과 같은 세세한 문제가 발생하여 팔로업(Follow-up) PR도 넣었습니다. 영어로 메시지를 보내면서, 평소처럼 AI에게 "이 Tauri의 이벤트 API 사용법, 공식 권장 패턴과 맞니?"라고 확인을 시키며 어떻게든 머지(Merge)까지 도달했습니다.
여기서 절감한 것은, 외부 PR의 리뷰야말로 인간(나)의 업무라는 점입니다. 앱의 방향성이 AI에게 충분히 전달되어 있다면 좋겠지만, AI에게 미래상이나 방향성을 전부 전달하기란 쉽지 않습니다. 타인의 코드는 더더욱 그렇습니다. 이 수정이 필요한지 아닌지, Rendu에 맞는지 아닌지를 판단하는 것이 필요합니다. "AI에게 리뷰시키면 돼"로 끝나지 않는 영역이, 사람이 등장한 순간 처음으로 나타났습니다. 기쁨과 당혹감이 동시에 찾아온 좋은 경험이었습니다.
2. 보안 운영이 "1인 + AI"로 돌아가게 되었다
개인 개발에서 가장 뒤로 밀리기 쉬운 것이 보안 운영입니다. 하지만 지금은,
- Dependabot이 매주 npm / cargo / GitHub Actions의 업데이트 PR을 생성
- CI에서
npm audit
및 cargo audit가 실행됩니다. 주간 스캔에서 취약점이 발견되면 Issue가 자동으로 생성되는 체계를 AI에게 맡겨 유지하고 있습니다. 실제로 지난 3개월 동안 quick-xml의 RUSTSEC 취약점(의존성의 의존성 문제로, 상위 라이브러리가 semver 비호환이라 즉시 업데이트할 수 없었던 건)이나 DOMPurify의 런타임 XSS가 발생했으며, 그때마다 "무시(ignore)하고 추적 Issue를 생성한다" 또는 "오버라이드(override)로 해결한다"와 같은 판단을 내렸습니다. 판단은 사람이 하지만, 조사와 구현은 AI가 합니다. 개인 개발의 방어 범위가 명확하게 넓어졌다는 실감이 듭니다.
본론: AI가 만든 코드를 AI에게 감사(Audit)시켰더니, 진짜 취약점이 나왔다
이 부분이 이번에 가장 쓰고 싶었던 이야기입니다.
앱이 어느 정도 성숙해졌고 fable5로 열광하던 타이밍이었기에, "한번 모든 소스 코드를 리뷰해 보자"라고 결심했습니다. 방법은 4개의 리뷰 에이전트(Review Agent)를 병렬로 실행하는 것이었습니다 (Rust 백엔드 / 프론트엔드 핵심 / 프론트엔드 주변 / 설정·CI). 각각에 영역을 할당하여 독립적으로 지적 사항을 내도록 했습니다.
그러자 3개의 계통에서 독립적으로 동일한 지적이 올라왔습니다. 요약하자면 다음과 같습니다:
Markdown 내의 링크
[부록](../../evil.command)
를 클릭하면, ..를 통해 워크스페이스 외부로 나가는 로컬 경로가 OS의 "기본 앱으로 열기"로 전달되어, macOS에서는 .command 파일이 실행됩니다.
즉, 신뢰할 수 없는 .md 파일을 열고 링크를 한 번 클릭하는 것만으로 코드 실행이 성립됩니다. 심지어 HTML 새니타이제이션 (Sanitization)을 우회할 필요조차 없습니다 (<a href>의 상대 링크는 정상적으로 작동하기 때문입니다). 이는 AI가 작성한 코드이며, 제가 "내부 링크 전환을 구현해 줘"라고 가볍게 지시한 결과였습니다.
솔직히 아찔했습니다. 동시에 흥미롭기도 했습니다. AI가 작성한 코드의 허점을 AI의 리뷰가 찾아낸 것입니다.
"AI가 찾았다"로 끝내지 않기
여기서 중요한 것은 리뷰 에이전트의 지적을 무조건 믿지 않는 것이었습니다. LLM의 리뷰는 "그럴듯해 보이지만 틀린" 지적을 흔히 섞어서 내놓습니다. 따라서 지적이 오면 제가 실제 코드와 대조하고, 나아가 Playwright로 실제 브라우저를 띄워 "정말로 클릭 한 번으로 실행되는가"를 재현하여 확정 지었습니다. 재현 가능한 것만을 "진짜"로 취급했습니다.
수정은 다층 방어 (Defense in Depth) 방식으로 진행했습니다:
- 프론트엔드에서 미지의 스킴 (
file:,vscode:등)을 차단 - PDF, 이미지, 문서 등 수동적인 확장자만 열 수 있도록 허용. 그 외에는 확인 다이얼로그 표시 - Rust 측에서 실행 가능한 확장자 (만약 프론트엔드가 뚫리더라도 마지막 보루가 될
.command,.exe,.app,.pkg등)를 강력하게 거부
그리고 수정된 diff를 이번에는 적대적으로 리뷰(Adversarial Review) 시켰습니다. Codex(다른 AI 리뷰어)에게 "이 거부 목록에 빠진 것은 없는가"라고 던지자, ".pkg와 .msix가 빠져 있다" $\rightarrow$ 추가 $\rightarrow$ "아직 ClickOnce의 .application이 빠져 있다"라며 라운드를 거듭하며 압박해 주었습니다. 여기서도 어디서 멈출지를 결정하는 것은 인간입니다 (거부 목록은 무한히 늘릴 수 있지만, 핵심적인 방어는 허용 목록 (Allowlist) 측에 있으므로 적절하다고 판단하여 3라운드에서 멈췄습니다).
같은 리뷰를 통해 그 외에도 "업데이트 알림 URL 검증 미비 (file://도 통과됨)", "webview에 $HOME 전역에 대한 쓰기 권한을 부여함"과 같은 허점들이 발견되어 한꺼번에 막았습니다.
CI를 통과해도 실기기에서 망가진다, 라는 당연한 이야기
보안 수정 이후, 실기기 검증을 수행했습니다. 여기서 테스트와 CI는 모두 통과(Green)되었음에도 불구하고, 실기기에서만 발생하는 버그 2개를 발견했습니다.
그 첫 번째: PDF 출력 다이얼로그가 멈춤.
PDF 저장 위치 다이얼로그를 Rust 측에서 호출하도록 설정했더니, 다이얼로그는 표시되지만 OK 버튼이 비활성화(Grayed out)되어 조작할 수 없는 문제가 발생했습니다. 원인은 Tauri v2의 동기식 명령(Synchronous command)은 메인 스레드에서 동작한다는 사양을 몰랐기 때문입니다. 그 상태에서 네이티브 저장 다이얼로그(이 또한 메인 스레드를 요구함)를 호출하면, 자기 자신을 차단하여 데드락(Deadlock)이 발생합니다. async로 변환하여 별도의 스레드로 분리했더니 해결되었습니다.
그 두 번째: Mermaid 도표의 노드가 대량으로 사라짐.
여러 줄 라벨을 포함하는 플로우차트를 열면, 화살표와 텍스트만 남고 박스가 사라집니다. 이 역시 실기기에서 보고를 받고 발견했습니다. 원인을 Chromium과 jsdom 양쪽 모두에서 재현하여 특정한 결과, Mermaid가 SVG 라벨에 출력하는 닫히지 않은 <br> 태그를, 저희 측에서 **엄격한 XML 파서(Strict XML parser)**로 재파싱하면서 첫 번째 에러에서 도표의 대부분이 잘려 나가고 있었습니다. 파서를 text/html로 바꾸는 것만으로 해결되었습니다 (26개 노드 중 8개만 그려지던 것이 26개 전부 그려지게 됨).
두 가지 모두, 테스트와 CI를 통과하고 실기기에서만 나타난 버그입니다. 지난 기사에서 "AI는 손이지 머리가 아니다"라고 썼지만, 그 "머리"의 업무에는 마지막에 자신의 손으로 실물을 만져보는 것이 확실히 포함됩니다. 이 부분은 완전히 자동화할 수 없습니다.
고칠 수 없는 것도 있다 (솔직한 이야기)
모든 것이 깔끔하게 고쳐진 것은 아닙니다.
- 릴리스 도중에 Apple Developer 계약이 만료되어, 공증(Notarization)이 403 에러로 실패했습니다. 이는 코드의 문제가 아니라, developer.apple.com에서 계약에 다시 동의해야만 하는 문제입니다. AI가 어찌할 수 없는 영역입니다.
- 이전 버전의 "업데이트 알림 URL"은 고칠 수 없습니다. OS별 직접 링크를 제공하는 수정을 넣었지만, 그것은 새로운 버전에만 반영됩니다. 이미 배포된 바이너리의 동작은 코드로 바꿀 수 없습니다. 앞으로 나아가는 방향으로만 수정이 가능하므로, 이전 버전에서 온 사용자들을 위해 릴리스 노트의 도입부를 고민하는 정도가 최선의 대책이었습니다.
이러한 "기술로 해결되지 않거나 / 사후에만 수정 가능한" 문제가 있다는 것을 3개월간 운영하며 실감했습니다.
메타적인 이야기: "판단의 질"에서 "검증의 질"로
지난 기사의 결론은 **"AI는 손이지 머리다. 무엇을 만들지 결정하는 판단의 질이 차이를 만든다"**였습니다. 3개월간 운영하며 이 결론을 조금 업데이트하고 싶어졌습니다.
코드를 작성하는 비용이 거의 제로가 되면, 병목 구간은 "쓰는 것"에서 **"정말로 옳은지 확인하는 것"**으로 옮겨갑니다. 이번 3개월 동안 제가 실제로 했던 일은 대부분 검증이었습니다:
- 리뷰 에이전트의 지적을 무조건 믿지 않고 실제 코드와 실제 동작으로 확인하기
- 수정을 적대적으로 리뷰하게 하기 ("반증해 봐"라고 던지기)
- 여러 에이전트에게 다각적으로 확인시키기
- 그리고 마지막에 자신의 손으로 실기기를 만져보기
"무엇을 만들 것인가"에 대한 판단은 물론 지금도 인간의 업무입니다. 하지만 그 이상으로, **"AI가 내놓은 것을 어떻게 의심하고, 어떻게 확인할 것인가"**가 개인 개발의 질을 결정하게 되었습니다. 속도가 빨라진 만큼, 검증과 책임은 오히려 더 무거워지고 있다는 것이 3개월 후의 실감입니다.
AI가 작성한 코드라서 위험한 것도 아니고, AI가 리뷰했으니까 안전한 것도 아닙니다. 다층적으로 의심하고, 실물로 확인한다. 그것이 현재로서의 답입니다.
마치며
Rendu는 현재 v0.10.0이며, 여전히 MIT 라이선스이고, Homebrew로도 설치할 수 있습니다.
brew install --cask kashioka/tap/rendu
3개월이 지났어도 이 앱은 99%가 AI 제작인 상태 그대로입니다. 하지만 "AI에게 통째로 맡기고 방치하기"와는 정반대의 3개월이었습니다. 쓰는 것은 순식간, 확인하는 것은 꾸준하게. 그 균형이 아마 앞으로의 개인 개발의 실상일 것이라고 생각합니다.
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기