
API 키는 필요 없었다 ── Excel 버튼 하나로 AI 채팅에 업무를 시킨 이야기
요약
API 키 없이 Windows UI Automation과 PowerShell을 활용하여 Excel에서 AI 채팅 인터페이스를 직접 제어하는 자동화 방법을 소개합니다. 브라우저 기반의 AI 채팅 화면을 조작함으로써 조직 내 보안 정책이나 API 관리 부담 없이 업무 자동화를 구현할 수 있습니다.
핵심 포인트
- API 키 없이 UI Automation을 통해 AI 채팅창을 직접 조작 가능
- VBA, PowerShell, 클립보드를 결합한 경량 자동화 워크플로우
- 조직 내 API 사용 제한 문제를 우회하여 업무 도구로 활용 가능
- Markdown 표 변환부터 결과값 회수까지 전 과정 자동화
Excel에서 생성 AI (Generative AI)를 호출하려면 API 키가 필요하다.
이 연재에서도, 세상의 구현 사례에서도, 줄곧 그 전제를 바탕으로 써왔다. 이전에 VBA에서 생성 AI를 호출하는 사례를 전 세계에서 찾아보게 한 적이 있는데, 발견된 것은 거의 전부 키(Key)를 전제로 하고 있었다.
그 전제가 무너졌다.
지난번에는 Windows에 기본적으로 탑入되어 있는 UI Automation이라는 메커니즘을 PowerShell을 통해 호출하여, Excel에서 다른 소프트웨어를 지목하여 조작하는 이야기를 썼다.
그 도구를 3일 뒤에 다른 상대를 향해 사용해 보았다. 상대는 브라우저로 열려 있는 생성 AI의 채팅 화면이다.
결과부터 말하겠다. Excel에서 셀을 선택하고 버튼을 누르면, 알아서 채팅창이 열리고, 표가 입력되며, 검품 결과가 Excel 셀로 돌아왔다. API 키는 단 한 글자도 사용하지 않았다.
- Excel 버튼 하나로 선택 범위를 Markdown 표로 포장하여 브라우저의 AI 채팅으로 던지고, 답을 셀에 다시 쓰는 것까지 통과했다.
- 인간의 손이 움직이는 것은 버튼을 누를 때 단 한 번뿐이다. 사용한 것은 **VBA와 PowerShell, Windows 표준 UI Automation과 클립보드(Clipboard)**뿐이다. API 키 발행도, 계약 변경도, 설치도, 관리자 권한도 필요 없다. 실측 결과, 한 마디만 답하게 하는 단순 왕복은 3초, 표를 전달하여 검품하게 하는 것은 4.8초였다. 심어둔 오류 3개를 3개 모두 맞혔다. 요청하지 않았는데도 AI는 스스로 검산 코드를 실행하고 있었다.
- 채팅 버전은 순수 API보다 똑똑할 때가 있다. 빠진 함정은 3가지였다. 엔터로는 전송되지 않는다 / 전송하면 페이지가 전환되어 잡고 있던 요소가 빈 껍데기가 된다 / 답변 작성 중에는 UI Automation 탐색이 멈춘다 - 브릿지(Bridge)가 하고 있는 것은 「새 채팅 열기 · 붙여넣기 · 전송 버튼 누르기 · 작성이 끝날 때까지 기다리기 · 복사 누르기」뿐이므로, 특정 AI 전용은 아니다. 실험용이며, 현재로서는 공개할 예정이 없다.
먼저, 왜 이것을 하려고 했는지 쓰겠다.
생성 AI를 업무 도구로 편입시키려 하면 가장 먼저 API 키 이야기가 나온다. 키를 발행하고, 과금 설정을 하고, 코드 어딘가에 두고, 유출되지 않도록 관리한다. 개인적으로 즐기는 수준이라면 아무것도 아니지만, 이것이 조직 안에서는 갑자기 무거워진다. 키를 발행할 수 있는지 여부는 대개 사용하는 사람 측에서 결정할 수 없다.
반면, 채팅 쪽은 사정이 다르다. 「AI 채팅은 사용해도 좋다」라는 직장은 지금 급속도로 늘어나고 있다. 브라우저로 열어서, 질문하고, 답을 읽는다. 그것은 허용되어 있다.
즉, 사용해도 좋은 AI와 도구로 편입할 수 있는 AI 사이에 벽이 있었다.
정문에는 자물쇠가 채워져 있다. 열쇠는 스스로 얻을 수 없다. 그런데 문득 옆을 보니, **매일 그곳을 지나다니는 통용구(뒷문)**가 있다. 바로 채팅 화면이다.
지난번에 만든 도구는 바로 「화면의 부품을 이름으로 잡아, 누르거나 글자를 넣거나 읽는」 것이었다. 채팅 화면에도 입력란이 있고, 전송 버튼이 있으며, 답변 복사 버튼이 있다. 전부 이름이 붙은 부품이다.
그렇다면 통과할 수 있을 터였다.
만든 것은 단순하다. 4단계뿐이다.
포장 ── 매크로가 선택 범위를 Markdown 표로 정형화하고, 지시문과 합쳐서 파일로 쓴다 -
던지기 ── PowerShell이 새 채팅을 열고, 붙여넣고, 전송 버튼을 누른다 -
감시 ── 작성이 끝난 것을 감지하여 답변 복사 버튼을 누른다 -
다시 쓰기 ── Excel이 클립보드를 받아 셀에 쓴다
VBA 측은 지난 기사에 쓴 네 가지 단계와 완전히 같은 형태다.
' (1) 프롬프트를 UTF-8로 파일에 쓰기 출력
' (2) PowerShell을 화면 없이 실행. 기다리지 않고 복귀
Set sh = CreateObject("WScript.Shell")
...
CreateObject만 사용했다. 참조 설정은 제로, Function도 쓰지 않고 Sub 하나뿐이다. 호출하는 상대가 계산기에서 AI 채팅으로 바뀌었을 뿐, 그릇은 그대로였다.
재미있었던 것은 포장 설계다.
지시문만 던져도 답은 부실해진다. 「이 표를 검품해줘」라고 말해도 표가 없으면 AI는 아무것도 볼 수 없다. 그렇다고 시트의 내용을 그대로 붙여넣으면 읽기 어렵다.
그래서, 전달 형식을 스스로 결정하지 않고 받는 쪽에게 물었습니다. AI 자신에게 "Excel 시트를 검품하려면 어떤 형태로 전달하는 것이 읽기 쉬운가"라고 물은 것입니다. 돌아온 대답은 Markdown 표였습니다.
실제로 매크로가 짐을 꾸린(packing) 결과물이 이것입니다.
당신은 Excel 시트의 검품 담당자입니다. 다음 시트 발췌본(Markdown)을 검사하여,
이상한 점을 불렛 포인트(bullet point)로 간결하게 나열해 주세요. 서론과 결론 문구는 불필요합니다.
| 행 | 상품 | 단가 | 수량 | 금액 |
...
행 번호를 왼쪽에 붙인 것이 핵심(mis)입니다. 이것이 없으면 AI가 오류를 찾아내더라도 "포도 행"이라고밖에 말할 수 없습니다. 행 번호를 덧붙여 두면 "4행"이라고 답해주므로, 받는 쪽에서 위치를 특정할 수 있습니다.
지시 사항과 함께 문맥(context)을 기계가 자동으로 짐을 싸듯 준비합니다. 이 부분이 효과적이며, 그렇기에 버튼 하나로 내용이 알찬 결과물을 돌려받을 수 있는 것입니다.
주제는 검품으로 정했습니다. 과일 매출표를 만들고, 일부러 세 가지 오류를 섞었습니다.
- 4행 포도 ── 금액 계산이 맞지 않음 (300 × 5는 1,500이어야 하는데 1,400)
- 5행 복숭아 ── 수량이 마이너스
- 6행 없음 ── 수량이 공란
모두 사람의 눈이라면 찾아낼 수 있는 오류입니다. 문제는 그것을 기계의 손으로 전달하고, 기계의 손으로 받아낼 수 있는가였습니다.
A1:E6을 선택하고 매크로를 실행합니다. 그 외에는 아무것도 건드리지 않습니다.
화면이 알아서 움직이고, 브라우저에 새로운 채팅창이 열리며, 표와 지시 사항이 입력되고, 전송 버튼이 눌립니다. 몇 초 기다리면 Excel로 돌아왔을 때, A8 셀에 답이 들어있었습니다.
돌아온 결과를 그대로 올립니다.
* **4행(포도)**: 금액 계산 결과가 틀렸습니다 (정답은 300 × 5 = 1,500).
* **5행(복숭아)**: 수량이 마이너스(-3)이며, 금액도 마이너스로 계산되었습니다.
* **6행(없음)**: 수량이 입력되지 않았습니다 (공란).
세 가지 모두 맞혔습니다.
게다가, 이 불렛 포인트 앞에는 요청하지도 않은 것이 붙어 있었습니다.
Row 2: calc=1200, actual=1200
Row 3: calc=1600, actual=1600
Row 4: calc=1500, actual=1400
...
AI가 스스로 검산 코드를 작성하여 실행하고, 그 출력값을 덧붙여 온 것입니다. 제가 요청한 것은 "이상한 점을 불렛 포인트로"뿐이었습니다.
이것은 채팅 버전만의 덤이라고 생각합니다. 순수한 API를 호출하면 모델은 텍스트만 반환할 뿐입니다. 하지만 채팅 화면 너머에는 코드를 실행하는 메커니즘까지 포함된 일련의 시스템이 준비되어 있습니다. 동일한 요금(즉, 무료 범위)으로 그 기능을 사용할 수 있다는 뜻입니다.
여기서부터가 이 글에서 가장 실용적인 부분이라고 생각합니다. 순탄하게 진행되지는 않았습니다.
붙여넣은 후 키보드의 Enter를 누르면 전송되어야 했습니다. 하지만 되지 않았습니다. 글자는 입력되어 있는데, 전송되지 않는 것입니다.
채팅 입력창은 Enter로 줄바꿈을 하는 구조일 수도 있고, 전송을 하는 구조일 수도 있는 등 상황에 따라 다릅니다. **키를 보내는 것은 결국 맹목적인 입력(blind typing)**이며, 지난 글에서 썼던 약점이 그대로 드러났습니다.
답은 단순했습니다. 화면의 전송 버튼을 이름으로 잡아 눌러버리는 것이었습니다.
$send = Find-Buttons (Get-Doc) '^(送信|Send)$|プロンプトを送信|Send message' 'コピー|Copy'
Click-Element $send[-1]
버튼의 이름으로 찾고 있기 때문에 화면의 모습이 다소 바뀌어도 작동합니다. 일본어와 영어 양쪽을 후보에 넣어둔 것은 표시 언어가 바뀌었을 때를 대비한 보험입니다.
전송하는 순간 페이지가 "새 채팅"에서 "대화 중인 화면"으로 전환됩니다. 그러면 그때까지 잡고 있던 화면의 부품(element)은 내용이 없는 빈 껍데기가 됩니다. 건드리려고 하면 오류가 발생하며 떨어집니다.
대책은 다시 잡는(re-grab) 것입니다. 처음에 창의 핸들(window handle, 창 자체의 번호)만 기억해 두었다가, 부품이 필요할 때마다 핸들로부터 다시 잡는 것입니다.
function Get-Doc() {
$w = [System.Windows.Automation.AutomationElement]::FromHandle($script:hwnd)
$d = $w.FindFirst([TreeScope]::Descendants, $condDoc)
...
나아가 「잡고 나서 누르기」를 하나로 통합하여, 실패하면 다시 잡고 재시도하는 방식으로 만들었습니다. 잡은 순간과 누르는 순간 사이에 페이지가 움직이는 경우가 있기 때문입니다.
이것이 가장 큰 복병이었습니다.
짧은 답변을 반환하게 하는 실험은 통과하는데, 긴 답변을 반환하게 하면 프로그램 자체가 멈춰버립니다. 원인은 답변을 작성하는 동안 화면이 끊임없이 갱신되고 있어서, 그 와중에 화면의 구성 요소(UI elements)를 전부 세려고 하면 탐색(exploration)이 돌아오지 않게 되는 것이었습니다.
즉, 「다 썼는지 확인하러 가기」라는 행위 자체가 작성 중에는 성립하지 않습니다.
해결책은 무식한 방법(力技)입니다. 확인하러 가는 역할을 일회용 자식 프로세스(child process)로 만들어서, 10초 동안 응답이 없으면 죽이고 다시 실행하는 것입니다.
$p = Start-Process powershell -ArgumentList @('-File','probe.ps1', ...) -PassThru -WindowStyle Hidden
if (-not $p.WaitForExit(10000)) {
$p.Kill() # 멈췄다 = 아직 작성 중인 것으로 간주
...
멈추는 것 자체를 「아직 쓰고 있다」는 신호로 사용하는 형태가 되었습니다. 예의 바른 방식은 아니지만, 확실합니다.
확인하러 가는 역할은 화면의 버튼을 보고 세 가지 중 하나를 반환하기만 하는, 20줄 정도의 코드입니다.
# COPY=답변 복사 버튼 있음 (완료) / STOP=정지 버튼 있음 (작성 중) / NONE=둘 다 없음
if ($n -match 'コピー|Copy' -and $n -notmatch 'コード|code|許可|プロンプト|翻訳') { $copy = $true }
if ($n -match '回答を停止|停止|Stop') { $stop = $true }
생성 중에는 전송 버튼이 「정지」로 바뀌고, 작성이 끝나면 답변 아래에 「복사」가 나타납니다. 화면이 내보내는 신호를 그대로 읽는 것입니다. 글자 수를 세어서 더 이상 늘어나지 않으면 완료라고 판단하는 식의 추측보다, 이 방법이 훨씬 확실했습니다.
또 하나, 손으로 PowerShell을 실행하면 성공하는데 Excel의 매크로(Macro)에서 실행하면 실패하는 시기가 있었습니다.
원인은 Windows의 규칙입니다. 백그라운드에서 실행된 프로그램은 창을 전면(foreground)으로 올릴 권한이 없습니다. 멋대로 화면을 가로채는 소프트웨어를 방지하기 위한 메커니즘이며, 올바른 동작입니다.
회피책은 예전부터 알려진 방법인데, Alt 키를 한 번 눌렀다 뗀 후 전면화를 요청하면 통과됩니다.
[BridgeNative]::keybd_event(0x12, 0, 0, [UIntPtr]::Zero) # Alt 누름
[BridgeNative]::keybd_event(0x12, 0, 2, [UIntPtr]::Zero) # Alt 뗌
[BridgeNative]::SetForegroundWindow($script:hwnd)
참고로, 이 연결 통로(bridge)는 실패하면 실패 원인을 그대로 답변 파일에 적어서 돌아가도록 만들어 두었습니다. 「전송 버튼을 누를 수 없었다」, 「창을 전면화할 수 없었다」와 같은 한 줄이 Excel 측으로 반환되므로, 아무 말 없이 150초 동안 기다려야 하는 일이 없습니다. 에러가 지나갈 통로를 만들어 두는 것은, 이런 도구에서는 속도보다 먼저 고려해야 할 사항입니다.
측정한 것은 두 가지입니다.
| 실험 | 결과 |
|---|---|
| 단순 왕복 (한 마디만 답변하게 함) | 전송 후 3초 만에 회수 |
| 표를 전달하여 검수하게 함 | 전송 후 4.8초 만에 회수 · 지적 사항 3건 중 3건 적중 |
둘 다 전송을 누른 후, 답변이 파일로 떨어지기까지의 시간입니다. 화면이 앞으로 나오고, 글자가 흐르고, 복사가 눌릴 때까지 인간은 아무것도 하지 않습니다. 10초도 걸리지 않아 표 점검이 한 바퀴 돌아갑니다.
참고로, 이 수치에는 새로운 채팅을 열고 페이지가 로드될 때까지의 몇 초는 포함되지 않습니다. 이를 포함하면 전체적으로 십수 초입니다.
이 실험에서 가장 가치 있는 점은 속도가 아니라고 생각합니다.
준비할 것이 아무것도 없다는 점입니다.
- API 키 발급 ── 필요 없음
- 계약 변경 ── 필요 없음
- 설치 ── 필요 없음
- 관리자 권한 ── 필요 없음
사용한 것은 VBA, PowerShell, UI Automation, 클립보드(Clipboard)입니다. PowerShell은 2006년부터 있었고, UI Automation도 비슷한 시기부터 Windows에 포함되어 있습니다. 어떤 PC에도 처음부터 들어있는 도구들만으로 작동합니다.
지난 기사에서 "RPA의 심장부는 처음부터 손에 쥐고 있었다"라고 썼습니다. 이번에는 거기서 한 걸음 더 나아가, 그 심장부로 AI를 호출할 수 있었다는 이야기를 해보려 합니다.
또 하나, 중요한 지점입니다.
다리가 수행하고 있는 것은 결국 이것뿐입니다.
- 새로운 채팅창을 연다
- 붙여넣는다
- 전송 버튼을 누른다
- 작성이 끝날 때까지 기다린다
- 복사 버튼을 누른다
어떤 AI 채팅 서비스에도 있는 부품들뿐입니다. 버튼의 이름으로 찾는 방식으로 만들었기 때문에, 일본어든 영어든 찾아낼 수 있습니다. 사용하는 채팅 서비스가 무엇이든, 같은 방식으로 다리를 놓을 수 있다는 논리가 성립합니다.
솔직히 말씀드리면, 이 부분은 아직 이론적인 단계입니다. 실제로 통과시킨 것은 단 하나의 서비스뿐이며, 다른 서비스는 테스트하지 않았습니다. 다만, 5가지 부품 중 특수한 것은 하나도 없기에 성공할 것이라고 생각합니다.
지난 기사에 썼듯이, 저는 약 10년 전 "Excel로 RPA"를 해보려다가 반년 동안 실패한 적이 있습니다.
이번에 깨달은 것은, 그 시절의 책상 위에 오늘의 부품들이 전부 놓여 있었다는 사실입니다. PowerShell도, UI Automation도, 클립보드(Clipboard)도, WScript.Shell도 말이죠. 부족했던 것은 도구가 아니었습니다.
부족했던 것은 자료와, 물어볼 수 있는 상대였습니다. 2016년에 사무 업무를 하면서 "PowerShell에서 UI Automation으로 브라우저의 부품을 잡는" 방법을 독학으로 찾아내는 것은 현실적으로 불가능했습니다. 애초에 그 조합으로 가능하다는 사실을 알 수 있는 수단이 없었습니다.
AI가 바꾼 것은 새로운 기술을 가져온 것이 아니라, 바로 그 지점이라고 생각합니다. 예전부터 있던 것과, 그것을 사용할 수 없었던 사람 사이의 간극이 메워진 것입니다.
관례에 따라 분류하겠습니다.
사실: Excel의 버튼으로부터 브라우저의 AI 채팅으로 프롬프트(Prompt)를 던지고, 답변을 Excel 셀에 다시 쓰는 것까지 성공했다는 점. 순수 왕복은 3초, 표를 전달한 검품은 4.8초였다는 점 (2026년 8월 실측·전송부터 회수까지). 심어둔 오류 3건을 3건 모두 지적했다는 점. AI가 요청받지 않은 검산 코드를 스스로 실행했다는 점 (출력을 본문에 전재함). 엔터 키로 전송이 되지 않는 점, 전송 후 잡은 요소(Element)가 무효화되는 점, 답변 작성 중에 UI Automation 탐색이 돌아오지 않는 점, 백그라운드에서 실행한 프로세스가 전면으로 나올 수 없는 점 (모두 실제로 겪은 문제). 사용한 것이 VBA, PowerShell, UI Automation, 클립보드뿐이라는 점.
견해: "어떤 AI 채팅에서도 같은 방식으로 연결 가능하다"는 부품의 일반성에 기반한 추측입니다. 실제로 통과시킨 것은 단 하나의 서비스뿐입니다. "채팅 버전이 순수 API보다 똑똑할 때가 있다"는 것도 검산이 나온 한 가지 사례를 통한 견해입니다. "준비할 것이 아무것도 없기에 조직에서도 쓸 수 있다"는 것도 제 환경에서 성립했을 뿐, 각 직장의 조건까지는 알지 못합니다.
실험용 코드입니다. 현재로서는 공개할 예정이 없습니다. 북(Book)도 다리(Bridge) 스크립트도 제 환경에서만 작동한 것입니다. - 확인한 것은 Windows 11 · PowerShell 5.1 · Chrome의 조합뿐입니다. - 화면 구성이 바뀌면 그 부분은 수정해야 합니다. 이것은 RPA의 숙명입니다. 버튼 이름으로 찾는 방식이라 외형 변경에는 어느 정도 강하다는 것뿐이며, 이름 자체가 바뀌면 멈춥니다. - 전송과 답변 사이, 채팅 화면은 전면으로 나옵니다. 숨기지 않았습니다. 무엇이 일어나고 있는지 보이는 편이 중간 과정을 파악하기 좋다고 판단했습니다. - 답변 내용이 맞는지 틀린지는 사람이 확인해야 하는 업무입니다. 이번에는 심어둔 오류를 맞혔지만, AI가 놓치지 않는다는 보장은 어디에도 없습니다. - 상대방의 서비스를 어떻게 사용할지는 각 서비스의 이용 조건에 따릅니다. 본인의 환경에서 확인하시기 바랍니다. - PowerShell 실행이 제한된 환경에서는 이 방법이 작동하지 않습니다.
이 기사의 내용은 영상으로도 정리되어 있습니다. 본문의 삽화는 원래 이 영상을 위해 그린 것입니다.
잠긴 정문 앞에서 아주 오랫동안 서 있었던 기분이 듭니다.
키(Key)가 없으면 시작할 수 없다고 생각했습니다. 그런데 옆을 보니 매일 다니던 통행구가 있었습니다. 게다가 그 문을 여는 법은 사흘 전에 다른 용무로 막 배운 것이었습니다.
도구가 도구를 불러, 닿지 못했던 곳에 닿습니다. 새로운 기술은 하나도 사용하지 않았습니다.
API 키는, 필요 없었다.
AI, Claude Fabre(클로드 페이블)조차 API가 없다면 절대 불가능할 것이라고 말했던 일이었음에도, 그럼에도 포기하지 않고 계속했더니 해낼 수 있었습니다.
하지만, 해내기까지의 다양한 지식은 Fabre에게 배웠기 때문에, 역시 이것은 AI, Claude Fabre가 없었다면 할 수 없었던 일입니다.
대화하면서 매크로 (Macro)를 수정하는 방식은, 이처럼 지금까지 할 수 없었던 일을 할 수 있게 만드는 좋은 방법이라고 생각합니다.
그럼, 다음에 뵙겠습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기