GUI는 결국 클라이언트였을 뿐 — 에이전트가 쓸 수 있는 도구의 모양

GUI는 결국 클라이언트였을 뿐 — 에이전트가 쓸 수 있는 도구의 모양

앞 글에서는 STM32CubeMX2를 해부해 보고 발견한 네 가지 신호 — UI 교체, 빌드 시스템 위임, 데이터 모델 패키지화, 자동화 1급 시민화 — 를 묶어 "임베디드 도구가 마침내 현대 SW 사고방식에 합류하고 있다"는 이야기를 했다. 그중 네 번째 항목, 자동화 1급 시민이라는 대목은 짧게 끊고 넘어갔는데, 실은 이 한 가지가 따로 글 한 편 감이다. 이번 글은 그 이야기다.

"CLI도 있습니다"라는 말의 두 가지 의미

도구 소개 페이지에 "CLI도 지원합니다"라는 말이 적혀 있을 때, 그 말은 완전히 다른 두 가지를 의미할 수 있다.

첫 번째 의미는 "GUI를 먼저 만들고 나서 CLI 래퍼를 끼워 넣었다"는 뜻이다. 이런 도구에서 CLI는 보통 GUI의 일부 기능만 노출하고, 스크립트 친화적이지 않고, 출력이 깨지고, 새 기능은 언제나 GUI에 먼저 들어간 뒤 한참 후에야 CLI에 따라온다. 자동화 파이프라인을 짜려고 하면 중간중간 "이 동작은 CLI에 없습니다" 하는 벽이 계속 나온다.

두 번째 의미는 "GUI와 CLI가 같은 백엔드의 두 클라이언트다"라는 뜻이다. 이 경우 GUI는 본체가 아니라 클라이언트다. 본체는 별도의 프로세스 — 보통 로컬 서버 — 이고, GUI도 CLI도 같은 API로 그 본체에 붙는다. 새 기능은 백엔드에 먼저 들어가고, GUI와 CLI는 자동으로 함께 따라온다.

이 두 부류는 겉으로 비슷해 보이지만, 도구의 가능성이 근본적으로 다르다. 그리고 에이전트 시대에는 그 차이가 전부다.

STM32CubeMX2는 두 번째 부류다

STM32CubeMX2의 CLI 헬프를 한번 살펴보자.

$ cube mx --help
Usage: mx [options] [command]

Commands:
  start [options] [projectPath]
  clock              CLI for SW clock validation
  composer           CLI for sw composer feature
  dma                CLI for dma feature
  exti               CLI for exti feature
  finder             보드/디바이스 마케팅 정보 검색
  global-services    프로젝트 레벨 옵션 활성/구성/비활성
  hw-platform        CLI for hardware platform feature
  ide-project        Cube IDE Project CLI
  middleware         CLI for middleware feature
  nvic               CLI for nvic feature
  pack-manager       CLI for pack manager feature
  parts              CLI for parts feature
  peripherals        CLI for peripherals feature
  pinout             Pinout CLI for STM32CubeMX2
  project            Project lifecycle
  sw-config          CLI for sw-configuration feature
  utilities

GUI의 왼쪽 패널에 있는 거의 모든 항목이 1:1로 보인다. 핀아웃, 클럭, DMA, NVIC, EXTI, 미들웨어, 페리페럴, 소프트웨어 컴포저, HW 플랫폼, 팩 매니저, 빌드 export — 전부. 그런데 여기서 결정적인 대목은 그 아래다.

거의 모든 서브커맨드에 다음 두 옵션이 달려 있다.

--port <port>   MX backend port
--host <host>   MX backend host (default: "127.0.0.1")

이게 왜 결정적이냐면, MX 자체가 HTTP 백엔드 서버라는 뜻이기 때문이다. cube mx start를 치면 백엔드 하나가 뜬다. GUI(Electron)를 열면 그 GUI는 자기 백엔드를 띄우고 거기에 프런트엔드로 붙는다. 그리고 터미널에서 친 cube mx pinout assign-signal --port 4000 ...같은 백엔드에 다른 클라이언트로 붙는다. 같은 백엔드에 GUI와 CLI가 동시에 붙을 수 있다. CI에서 만든 구성을 GUI로 열어서 시각 확인하는 워크플로우가 자연스럽다.

이건 CLI를 나중에 끼워 넣은 도구가 아니다. 처음부터 백엔드가 본체였고, GUI는 그 위에 얹힌 Electron 클라이언트의 한 종류일 뿐이다.

이 분리가 가능하게 하는 것들

한 번 이 분리가 이뤄지면, 그 위에서 가능해지는 것들이 질적으로 달라진다.

헤드리스 자동화가 자연스럽다. 본체 안에 start-and-load-headless-bin.js라는 파일명이 있다. 헤드리스 모드가 곁다리가 아니라 1차 시민이라는 강한 신호다. 백엔드를 띄우고 셸 스크립트로 cube mx project create-from-board ..., cube mx pinout assign-signal ..., cube mx clock set-value ..., cube mx ide-project generate --format CMake ...를 차례로 호출하면 보드 선택부터 빌드 결과물 export까지 GUI 한 번 열지 않고 끝난다. CI 러너에 그대로 올라간다.

두 번째는 CI/CD 통합이다. 펌웨어 프로젝트의 구성(핀아웃, 클럭 트리, 페리페럴 활성화, 미들웨어 선택)을 코드 리뷰의 대상으로 만들 수 있다. .ioc2 파일을 git에 넣고, PR마다 cube mx ide-project generate가 돌면서 빌드 결과물이 동일한지 검증한다. 지금까지 이런 걸 진지하게 해 보려 한 임베디드 팀은 대부분 자체 Python 스크립트로 .ioc 파일을 파싱해서 diff하는 조잡한 방식으로 흉내 내고 있었다. ST가 이걸 1급으로 올렸다.

세 번째는 원격 작업이다. --host 옵션은 127.0.0.1 기본값을 가진다. 하지만 옵션이 존재한다는 건 다른 호스트도 가능하다는 뜻이다. 강력한 개발 머신이나 빌드 서버에 MX 백엔드를 띄워 두고, 여러 개발자가 각자의 노트북에서 얇은 클라이언트로 붙어서 쓰는 시나리오가 구조적으로 열려 있다.

그리고 네 번째가, 이 글의 진짜 주제다.

에이전트는 GUI 앞에서 길을 잃는다

AI 에이전트 — LLM에 도구 사용 기능을 붙인 실행 주체 — 가 실제로 무언가를 만들게 하려면, 그 에이전트가 다룰 수 있는 인터페이스가 필요하다. 어떤 인터페이스를 노출하느냐가 도구의 유용성을 결정한다.

현대의 에이전트가 가장 잘 다루는 인터페이스는 셋이다.

  1. CLI 명령과 그 stdout/stderr — 가장 흔하고, 가장 구조화하기 쉽다.
  2. HTTP/JSON API — 요청과 응답이 명시적이고, 에러가 코드로 돌아온다.
  3. 파일 시스템 위의 텍스트 파일 — git diff로 변경을 관찰할 수 있다.

에이전트가 다루기 어려운 인터페이스도 셋이다.

  1. GUI — 스크린샷과 좌표 기반 상호작용. 비싸고, 느리고, 부서지기 쉽다.
  2. 상태가 숨어 있는 바이너리 도구 — 내부 상태를 읽거나 재현할 수 없다.
  3. 기능이 CLI 서브셋에만 노출된 도구 — 에이전트가 막다른 길에 계속 부딪힌다.

이 관점에서 STM32CubeMX2를 다시 보면, 이 도구는 거의 교과서처럼 "에이전트가 쓸 수 있는 형태"를 하고 있다. 모든 동작이 CLI에 있다 — 1번 조건 충족. 본체가 HTTP 백엔드다 — 2번 조건 충족. 프로젝트 상태가 .ioc2 파일 하나로 디스크에 떨어진다 — 3번 조건 충족. 에이전트를 앉히고 "이 보드로 I2C 2채널 쓰는 프로젝트를 만들어 줘"라고 시키는 그림이 완전히 현실적이다.

반대로, 아직 자바 Swing GUI에서 마우스 클릭으로 클럭 트리를 끌어 맞추는 구형 도구들은 에이전트가 들어갈 자리가 사실상 없다. 스크린샷을 찍고 OCR을 돌려서 "여기쯤을 클릭해 봐"라고 시키는 프랑켄슈타인 수준의 접근이 한계다.

도구의 새로운 평가축

지금까지 개발 도구의 평가축은 크게 둘이었다. 기능의 풍부함GUI 사용성. 두 축은 결국, 한 사람이 그 도구 앞에 앉아서 얼마나 생산적으로 작업할 수 있는지를 재는 잣대였다.

여기에 세 번째 축이 추가되고 있다. 에이전트 사용성 (agent-usability). 사람 대신 에이전트가 그 도구 앞에 앉았을 때, 얼마나 잘 쓸 수 있는가.

이 축에서 평가할 질문은 이런 것들이다.

  • 모든 동작이 CLI나 API로 노출되어 있는가? 아니면 GUI에만 있는 기능이 있는가?
  • 상태가 텍스트 파일 한 곳에 응축되는가? 아니면 내부에 숨어 있는가?
  • 결과가 표준 포맷(JSON, YAML, CMake, ELF)인가? 아니면 독점 포맷인가?
  • 실패 시 에러가 구조화돼 있는가? exit code와 stderr가 유의미한가?
  • 같은 작업을 스크립트로 10번 돌렸을 때 결과가 결정적인가?
  • 여러 인스턴스가 동시에 붙을 수 있는가?

이 축으로 재기 시작하면, 지금까지 "좋은 도구"라고 여겨지던 많은 것들이 "사람에게 좋지만 에이전트에게는 나쁜" 쪽으로 분류된다. 그리고 CubeMX2 같은 도구가 "사람에게도 좋고 에이전트에게도 좋은" 쪽으로 넘어온다.

결국 백엔드 + 클라이언트다

지난 10년 사이에 많은 일반 소프트웨어가 공통적으로 이 방향으로 움직였다. VS Code — 코어 워크벤치가 본체고, 데스크탑 Electron / 브라우저 / 원격 SSH가 다 같은 코어의 변주다. Figma — 렌더러가 본체고, 브라우저가 클라이언트다. Docker — 데몬이 본체고, docker CLI와 Docker Desktop이 클라이언트다. Language Server Protocol — IDE는 프런트엔드, LSP 서버가 본체다. Postgres, Kubernetes, Terraform — 전부 같은 패턴이다.

백엔드 본체와 여러 클라이언트라는 구조는, 의식하고 보면 현대 소프트웨어의 기본 형태다. 그 위에 GUI가 있고, 그 옆에 CLI가 있고, 그 옆에 이제 에이전트가 또 하나의 클라이언트로 앉는다. 에이전트는 새로운 UI가 아니라, 기존 백엔드에 붙는 새로운 클라이언트의 한 종류일 뿐이다.

이 관점에서 보면, 앞으로의 "좋은 도구"는 자기 백엔드의 API를 명확하게 노출하는 도구다. GUI는 그 API의 예쁜 표현일 뿐이다. CLI는 그 API의 기계 친화적인 표현일 뿐이다. 에이전트는 그 API의 자율 실행 주체일 뿐이다. 이 셋이 한 뿌리에서 자라 나오지 않으면, 에이전트 시대에 살아남을 수 없다.

ST가 STM32CubeMX2를 이런 구조로 다시 지은 건 우연이 아닐 것이다. 에이전트를 구체적으로 염두에 뒀든 아니든, 이런 형태의 도구는 자동으로 에이전트가 잘 쓰는 도구가 된다. 그리고 이 패턴이 일단 한 벤더에서 자리를 잡으면, 경쟁 벤더가 안 따라올 수가 없다.

마치며

앞 글에서 "임베디드 도구가 마침내 현대 SW의 사고방식에 합류하고 있다"는 이야기를 했다. 이 글은 그 합류가 왜 에이전트 시대와 정확히 맞아떨어지는지에 대한 이야기였다.

개발 도구 영역에서 다음에 주목해 볼 질문은 이런 것이다. 우리가 매일 쓰는 도구 중, GUI 없이도 동일한 기능을 할 수 있는 도구는 몇 개인가? 그 중에서 같은 백엔드에 GUI와 CLI가 동시에 붙을 수 있는 도구는 몇 개인가? 그 중에서 에이전트에게 맡겼을 때 막다른 길 없이 끝까지 작업을 완료할 수 있는 도구는 몇 개인가?

이 질문에 대한 답이 지금은 대부분 "많지 않다"일 것이다. 하지만 STM32CubeMX2 같은 도구가 하나씩 늘어나면서, 그 답은 조금씩 바뀌고 있다. 그리고 그 변화의 속도는 생각보다 빠를 것 같다. 왜냐하면 한 번 이런 구조의 도구를 경험하고 나면, 이전 방식으로 돌아갈 이유가 거의 없기 때문이다.