Claude가 만든 취약점을 Gemini에게 수정하게 된 밤의 이야기
요약
사용자가 개발한 Excel 환경에서 Claude CLI를 이용해 AI 기능을 구현했으나, 특정 조건부 서식 요청 시 시스템이 멈추는 문제가 발생했습니다. 원인은 Claude CLI의 업데이트로 JSON 출력 구조가 변경되면서, 기존 VBA 수신 코드가 고정된 키 순서를 전제로 오류를 일으킨 것이었습니다. Gemini가 이 문제를 진단하고 안전한 탐색 로직으로 수정하여 해결했습니다.
핵심 포인트
- 조건부 서식 요청 시 Excel 환경이 프리징되는 문제가 발생함.
- 문제의 근본 원인은 Claude CLI 업데이트로 인한 JSON 키 순서 변경임.
- 기존 VBA 코드가 고정된 패턴을 전제하여 취약점을 가짐.
- Gemini가 안전한 문자열 탐색 로직으로 코드를 수정하고 테스트를 완료함.
어느 날 밤, 집 컴퓨터로 Excel 테스트를 돌리고 있을 때의 일입니다.
제가 직접 개발한 개발 환경인 '秀コンボ'에는 화면상의 버튼을 누르기만 하면 AI를 호출하여 표 가공이나 수식 삽입, 조건부 서식 설정 등을 자연어로 실행할 수 있는 기능이 있습니다.
내부적으로는 Claude CLI가 작동하며, Excel의 UserForm에서 전달된 지시를 해석하고 결과를 반환하는 구조입니다.
다른 테스트용 시트들은 모두 경쾌하게 움직였습니다.
지시를 입력하고 실행 버튼을 누르면 몇 초 만에 셀이 수정되고 의도한 결과가 돌아옵니다.
그런데 '테스트용3'이라고 이름 붙인 시트를 열고 특정 지시를 실행했을 때, 동작이 멈춰버렸습니다.
D열에, 재고 수가 발주점을 밑돌면 '발주 필요'라고 표시하는 수식을 넣고
'발주 필요' 행의 배경을 빨간색으로 하는 조건부 서식을 적용해줘
버튼을 눌러도 응답이 돌아오지 않습니다.
화면은 처리 중인 상태로 침묵했고, 아무리 기다려도 결과가 표시되지 않았습니다.
직전에 다른 매크로의 키워드 조정을 했었기 때문에, 처음에는 'Gemini가 어딘가의 배선을 건드려서 고장 낸 것이 아닐까'라고 생각했습니다.
혹은 '또 Claude 사용 한도에 걸려서 API 측에서 차단된 것은 아닐까'라고도 생각했습니다.
하지만 실제 장치의 로그를 물리적으로 열어 조사해 본 결과, 예상치 못한 사실을 알게 되었습니다.
Claude는 차단된 것이 아니었습니다.
지시를 받은 지 불과 1.5초 만에 완벽한 답을 파일에 작성하여 대기하고 있었던 것입니다.
그렇다면 왜 Excel은 계속 침묵했을까요?
원인을 찾아냈을 때, 저도 모르게 쓴웃음이 흘러나왔습니다.
과거 Claude 자신이 작성했던 VBA 코드의 취약한 틈을, Claude 자신의 최신 업데이트가 뒤에서 공격하고 있었던 것입니다.
그 전말과 오늘 밤 책상을 나란히 놓고 있던 Gemini에게 깔끔하게 수정받은 일련의 과정을 기록으로 남기고자 합니다.
조건부 서식으로 인한 갑작스러운 프리징: 다른 시트는 순조롭게 작동하는데, '테스트용3' 시트에서 조건부 서식을 요청한 순간, Excel 컨보가 응답을 기다리며 멈췄습니다. -
Claude는 1.5초 만에 답변했음: 사용 제한이나 깊은 생각 시간을 의심했지만, 통신 로그(out.jsonl)를 열어보니 Claude CLI는 지시로부터 불과 1.5초 만에 완벽한 답변을 출력한 상태였습니다. -
원인은 JSON 키 순서 변경: Claude CLI의 버전 업데이트로 인해, 출력되는 JSON의 맨 앞에 처리 시간(duration_api_ms) 등의 측정 데이터가 포함되게 되었습니다. -
맨 앞 16글자 고정 패턴 함정: VBA 측 수신 코드는 이전에 Claude 자신이 작성한 것이었습니다. 그곳에는 키 순서가 절대 변하지 않는 것을 전제로 한 Left$(ln, 16) = "{\"type\":\"result"}"와 같은 판별식이 작성되어 있었습니다. -
Gemini에 의한 수정: Gemini가 로그와 VBA 코드를 대조하여 원인을 특정하고, InStr를 이용한 안전한 탐색과 오류 즉시 감지를 구현했습니다. 이로써 67개의 관문 테스트를 전 항목 통과시켰습니다. -
GitHub 공개 리포지토리 업데이트: 최신 Claude CLI를 사용하는 사용자 측에서도 동일하게 멈추는 문제였기 때문에, 공개 리포지토리(shu1551/shu-excel-manager)의 760개 테스트를 거쳐 최신 버전을 푸시했습니다.
발단은 재고 관리표를 모방한 '테스트용3' 시트에서 확인 작업을 하던 것이었습니다.
품명, 재고 수량, 발주점이라는 열이 나열되어 있었고, 여기에 다음과 같은 지시를 주고 실행 버튼을 눌렀습니다.
D열에, 재고 수가 발주점을 밑돌면 '발주 필요'라고 표시하는 수식을 넣고
'발주 필요' 행의 배경을 빨간색으로 하는 조건부 서식을 적용해줘
정상적인 작동이었다면 UserForm에 전송 중이라는 표시가 나온 후, 2~3초 만에 D열에 `=IF(B6<C6,
지시문(指示文)에 있던 '빨갛게 하다'라는 단어에, 디자인 미화 정리함의 '노블 보르도(Noble Bordeaux, 빨간 계열 미화)' 매크로 등록 단어가 반응하고 있었습니다.
그래서, 단일 문자만으로 반응하는 것을 막고, 조건부 서식과 같은 고급 지시는 정리함을 거치지 않고 AI에게 바로 전달되도록 가드를 설치했습니다.
하지만, 그 부분을 고쳐도 상황은 변하지 않았습니다.
확실하게 Claude에게 지시가 전달되었다는 로그가 나오고 있음에도 불구하고, 거기서부터 한 줄도 진행되지 않는 것입니다.
'Claude의 사용량 제한에 걸린 것일까?'
그렇게 생각했습니다.
하지만 평소라면 사용량 제한에 걸렸을 경우 '사용량 상한입니다'라는 메시지가 반환되어야 합니다.
말없이 멈춰 있는 것은 도무지 납득이 가지 않았습니다.
추측으로 생각해 봐도 어쩔 수 없었습니다.
저는 Gemini에게 지시를 내리고, 백그라운드에서 작동하는 통신 로그를 물리적으로 열어 내용을 점검하게 했습니다.
秀コンボ의 Claude CLI 연동은, 상주(常駐)하고 있는 Claude 프로세스에 표준 입력으로 JSON을 보내고, Claude가 표준 출력에 추가해 나가는 파일(out.jsonl)을 VBA 측에서 타이머로 감시하며 읽어오는 구조입니다.
만약 프로세스가 다운되었다면 프로세스 목록에 나타나지 않을 것이며, 오류가 발생했다면 표준 에러 출력(err.log)에 기록이 남아 있어야 합니다.
Gemini가 조사한 결과는 예상 밖의 것이었습니다.
프로세스: 정상 작동 중
오류 로그: 공백 (오류 없음)
출력 파일(out.jsonl):
...
Claude는 멈춰 있지 않았습니다.
지시를 받은 지 불과 1.5초 후에, 완벽한 수식과 조건부 서식의 절차를 생성하여 파일 끝에 깔끔하게 출력하고 이미 처리를 마친 상태였습니다.
답은 눈앞에 있었습니다.
그런데 왜 VBA는 그것을 무시하며 계속 기다리고 있었던 것일까요?
이유는 VBA 측에서 결과 도착을 판정하던 단 한 줄의 코드에 있었습니다.
Excel 콤보의 UserForm에는 out.jsonl에서 새로운 결과 행을 가져오는 함수가 있습니다.
그 안에 다음과 같은 판정이 적혀 있었습니다.
' 이전 코드 (Claude가 작성한 것)
For i = 0 To UBound(L)
ln = Trim$(Replace(L(i), vbCr, ""))
...
이 코드를 보고 깨달았습니다.
행두의 16글자만 잘라내어 일치하는지 확인하고 있었던 것입니다.
이전 버전의 Claude CLI에서는 결과 행을 출력할 때 확실히 키의 시작이 type에서 시작했습니다.
{"type":"result","result":"###완료### ..."}
이 형태라면, 왼쪽부터 16글자를 자르면 정확히 {"type":"result"가 됩니다.
고속화를 위해 무거운 파서(parser)를 거치지 않고, 문자열의 좌측 끝만 보고 '도착했다'고 판단하는 단축키를 설치했던 것입니다.
그리고 이 코드를 과거에 작성한 것은 다름 아닌 Claude 자신이었습니다.
그런데 최근 Anthropic이 Claude CLI를 업데이트했습니다.
출력되는 JSON에 API 통신 시간을 나타내는 duration_api_ms 같은 측정 필드가 추가된 것입니다.
그 결과, 신 버전의 출력은 이렇게 바뀌었습니다.
{"duration_api_ms":1524,"type":"result","result":"###완료### ..."}
여기서부터 앞 16글자를 자르면, {"duration_api_m이 됩니다.
일치할 리가 없습니다.
VBA의 루프는 눈앞에 도착한 Claude의 답변 행을 바라보면서,
'시작이 {"type":"result"로 시작하지 않으니 아직 결과가 아니다'라고 무시하고 지나치고 있었던 것입니다.
영원히 오지 않을 '행두부터 시작하는 결과 행'을 기다리며, 타임아웃까지 침묵하고 있던 것이 프리징의 정체였습니다.
우편함에 비유하자면, 편지를 받는 쪽이 '가로 폭 정확히 16mm인 봉투만 받는다'고 완강하게 결정했던 것과 같습니다.
배달원이 조금 친절해져서, 배달 시간 스탬프를 봉투 끝에 찍어 가져다주게 되자, '스탬프 때문에 가장자리의 무늬가 다르니, 이것은 편지가 아니다'라며 핑계를 대고 계속 무시하고 있었던 것입니다.
게다가, 그 좁은 우편함을 만든 장본인과 스탬프를 찍기 시작한 장본인이 같은 Claude였다는 결말이었습니다.
그렇다면 왜 다른 테스트 시트(테스트용 1, 테스트용 2)는 문제없이 작동했을까요?
만약 CLI의 출력 형식 변경이 원인이라면, 모든 시트에서 멈췄어야 합니다.
왜 테스트용 3만 멈춘 걸까요?
그 이유는 슈콘보(秀コンボ)의 '정형 매크로(선행 실행)'에 있었습니다.
슈콘보에서는 전각/반각 통일, 공백 줄 삭제, 주소나 회사명 표기 오류 수정 같은 정형 처리는 AI를 호출하지 않고 손안의 VBA 매크로가 한 번에(0.1~0.4초) 처리합니다.
테스트용 1과 테스트용 2에서 진행했던 작업은 모두 이 정형 매크로 범위 내였습니다.
즉, 처음부터 Claude CLI를 호출하고 있지 않았던 것입니다.
손안의 매크로만으로 빠르게 완료되었기 때문에, CLI 연동 수신 로직이 파괴되었다는 사실을 깨닫지 못했습니다.
반면, 테스트용 3의 과제는 '조건부 서식'이었습니다.
조건부 서식은 고정된 매크로 정형 범위에 포함되어 있지 않기 때문에, 여기서 처음으로 백그라운드의 Claude CLI가 호출되었습니다.
그리고 호출되는 순간, 그 '선두 16자 판별'의 함정을 빠져나간 것입니다.
정형 매크로가 너무 뛰어나서 AI를 호출할 기회가 적었던 것이, 아이러니하게도 발밑의 버그 발견을 늦추고 있었습니다.
원인이 파악되었으니 고치는 것은 어렵지 않습니다.
Gemini에게 지시하여 수신 판별을 안전한 방식으로 개수했습니다.
선두를 기계적으로 판단하는 것을 중단하고, 행 내 어디에 `
왜 처음에 강제 지정(先頭決め打ち)을 했는지: 한때 코드를 작성했던 Claude는 VBA에 표준 JSON 파서가 없는 상황에서, 외부 라이브러리를 사용하지 않고 빠르게 감지하기 위한 간편한 수단으로 시작 부분 비교를 선택했다고 생각됩니다. 단기적으로는 작동했지만, 외부 형식 변경에 취약하게 만들어진 구조였습니다.
-
AI 간의 보완 관계: 단일 AI만으로 코드를 작성하게 하면, 해당 AI의 착각이나 안이한 단축키(ショートカット)에気づ기 어려운 면이 있습니다. 이번처럼 다른 AI가 로그를 조사하여 원인을 파악하고 안전한 코드로 다시 작성하는 접근 방식은 실용적인 개발에서 매우 효과적이라고 느낍니다.
-
동작 환경: Windows 11, Microsoft 365(데스크톱 버전 Excel), Claude CLI가 도입된 환경을 대상으로 합니다.
-
이번 수정 범위: Claude CLI의 출력 JSON에서 키 순서가 어떻게 변해도 결과 행을 확실하게 가져올 수 있도록 했습니다. 또한, CLI 측에서 오류가 발생했을 때도 타임아웃을 기다리지 않고 즉시 중지합니다.
-
남아있는 한계: 이번 개修는 결과 수신 판정을 안전하게 만든 것이며, CLI 프로세스 자체가 무응답이 되었거나 네트워크가 완전히 끊어진 경우에는 OS 측의 타이머 감시에 맡겨집니다.
사람이 작성한 코드든, AI가 작성한 코드든, 사소한 전제 차이로 시스템이 멈추는 일은 드물지 않습니다.
JSON 키 순서라는 기본적인 사양의 함정에 최신 AI 도구 자신이 걸려 있었다니, 참으로 흥미로운 사건이었습니다.
하지만 Claude가 남긴 구멍을 Gemini가 로그에서 특정하여 고치는 일련의 흐름을 보고 있자니, AI를 활용한 개발 방식도 상당히 변해왔다고 느낍니다.
완벽한 코드를 한 번에 작성하는 AI를 바라는 것보다, 작동하지 않을 때 원인을 냉정하게 파악하고 고쳐줄 수 있는 파트너가 곁에 있는 것이 실무에서는 훨씬 마음이 놓입니다.
손안의 Excel도, GitHub 리포지토리도 이제 이것으로 최신 환경에 대응할 수 있게 되었습니다.
또 하나의 시스템이 견고해진 밤이었습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기