본문 바로가기

IT/AI

MCP는 잊어라, 진짜 고수는 CLI로 LLM을 부린다

300x250
반응형

모두가 MCP에 열광할 때, 저는 셸 스크립트를 선택했어요

요즘 LLM 에이전트 개발하는 분들 사이에서 MCP(Model Context Protocol)가 완전 대세더라구요. 2024년 11월 Anthropic이 처음 공개한 이후, 불과 1년 만에 업계 표준으로 자리 잡았다고 해도 과언이 아니에요. 실제로 최근 통계에 따르면 MCP SDK의 월간 다운로드 수가 9,700만 건을 넘겼고, OpenAI, 구글 딥마인드, 마이크로소프트까지 공식 채택하면서 "에이전트에 SaaS 기능 연결하려면 MCP 서버 만드는 게 정석"이라는 분위기가 팽배해졌죠.

그런데 저는 좀 다른 길을 택했어요. 바로 커맨드라인 인터페이스, 즉 CLI를 활용하는 방식이었어요.

2026년 초 현재, 업계에서는 LLM의 컨텍스트 윈도우 안에 툴을 어떻게 구성할지 크게 의견이 갈리고 있거든요. 한쪽에서는 세밀한 작업을 수행하는 고수준 툴을 제공하자는 입장이고(예: GitHub 리포지토리의 풀 리퀘스트 목록 조회), 다른 한쪽에서는 새로운 툴을 만드는 대신 모델에게 유용한 셸 명령어를 알려주자는 입장이에요. 저는 후자가 훨씬 현실적이고 혁신적이라고 봐요.


유닉스 셸의 진짜 매력은 파이프라인이에요

유닉스 셸의 가장 큰 장점이 뭔지 아세요? 바로 명령어 조합이에요. 여러 단계의 툴 호출을 모델이 직접 파이프라인으로 엮을 수 있다면, 매번 모델을 재호출할 필요가 없어져요.

이게 토큰 비용 절감 측면에서 얼마나 큰 차이인지 한번 생각해보세요. Anthropic의 엔지니어링 블로그에서도 지적한 것처럼, 도구 호출 결과가 중간에 모델 컨텍스트로 계속 흘러들어오면 토큰 소비가 폭발적으로 늘어나요. 예를 들어 2시간짜리 회의 녹취록 하나가 두 번 호출을 거치면 5만 토큰 이상이 추가로 소모될 수 있거든요.

게다가 파이프라인으로 만들어진 CLI 워크플로우는 스크립트로 저장할 수도 있고, 사람이 직접 커스터마이징해서 실행할 수도 있어요. 커맨드라인은 사람과 기계 모두와 호환되는 인터페이스니까요. 모델이 이미 텍스트를 아주 잘 다루는데, 굳이 기계 전용 프로토콜로 되돌아갈 이유가 있을까요?


OpenAPI 스펙만 있으면 충분해요, MCP 서버 안 만들어도 돼요

"그래도 MCP는 SaaS 기능을 에이전트에 쉽게 노출할 수 있잖아요"라는 반론이 있을 수 있어요. 맞아요. 근데 MCP 없이도 그걸 해낼 수 있거든요.

최근에 구글 Docs와 구글 Groups에 접근하는 에이전트를 만들면서 이 문제를 직접 풀어봤어요. 구글은 파일 목록 조회, 마크다운 읽기, 댓글 스레드 이해 같은 기능을 제공하는 훌륭한 API를 갖고 있어요.

처음엔 당연히 구글 클라우드 프로젝트를 만들고, API 문서를 LLM에 붙여넣어서 gdrive CLI를 생성했어요. 잘 작동했어요. 근데 곰곰이 생각해보니, 이 스크립트는 그냥 보일러플레이트에 불과했어요. 존재할 필요가 없는 코드였던 거죠.

구글을 비롯한 많은 SaaS 벤더들은 이미 자신들의 모든 API를 호출할 수 있는 프로그램을 정의해뒀어요. 바로 OpenAPI 스펙이죠. 이 프로그램을 실행할 적절한 인터프리터만 있으면 되는 거예요.

구글링 끝에 Restish라는 툴을 발견했어요. OpenAPI 스펙이 프로그램이라면, Restish는 그 인터프리터인 셈이에요. 사용법은 이렇게 간단해요.

# cool-api라는 새 API 등록
$ restish api configure cool-api https://api.rest.sh/openapi.yaml

# API 설명서에서 사용 가능한 모든 명령어 확인
$ restish cool-api --help

# API 작업 호출 (list-images)
$ restish -r cool-api -H 'Accept: application/json' list-images | jq '.[0].name'
"Dragonfly macro"

Restish는 심지어 API 엔드포인트와 파라미터에 대한 셸 자동완성까지 생성해줘요. 처음 써봤을 때 저도 꽤 놀랐어요.

다만 두 가지 아쉬운 점이 있었어요. Restish가 인증을 직접 처리하려 한다는 점, 그리고 스펙을 미리 등록해야 한다는 점이었죠. 그래서 래퍼 스크립트를 만들어서 임시 스펙 디렉토리를 만들고, 제가 원하는 인증 플로우를 수행한 뒤 토큰을 주입하는 방식으로 해결했어요.


OAuth 2.0도 결국 "프로그램"이에요

처음 만들었던 복잡한 스크립트를 보니 OAuth 2.0 클라이언트가 통째로 들어 있더라구요. 구글 인증 플로우를 타서 토큰을 받고, 만료되면 갱신하는 코드요. 근데 생각해보면 OAuth 2.0도 표준이잖아요. 특정 파라미터 세트(구글 OAuth URL, 클라이언트 ID, 클라이언트 시크릿, 권한 부여 타입, 스코프)를 OAuth 2.0 클라이언트 언어로 작성된 유효한 프로그램으로 볼 수 있는 거죠.

여기서도 인터프리터만 있으면 됐어요. 그래서 찾은 게 oauth2c라는 커맨드라인 OAuth 2.0 클라이언트예요. 앞서 말한 파라미터들을 입력하면 플로우가 시작되고(보통 브라우저가 열려요), 결과 토큰을 표준 출력으로 반환해줘요.

이 퍼즐 조각이 맞춰지니, 원래 수백 줄짜리 빽빽한 파이썬 코드가 이렇게 바뀌었어요.

oauth2c "https://accounts.google.com/..." | restish google drive-files-list

코드 양이 한 자릿수로 줄어든 거예요. 유지보수할 게 거의 없어진 셈이죠.

완성된 스크립트는 bmwalters/gdrive-client 리포지토리에 공개해뒀어요. 셸 자동완성을 전파하는 멋진 방법도 들어있으니 참고해보세요.


macOS에서 토큰을 안전하게 보관하는 의외의 방법

잠깐 팁 하나 드릴게요. macOS 셸 스크립트에서 민감한 데이터를 안전하게 저장하는 잘 알려지지 않은 방법이 있어요.

구글 OAuth 플로우의 결과물은 두 가지예요. 짧은 수명의 액세스 토큰(약 1시간 유효)과 긴 수명의 갱신 토큰(6개월 유효)이죠. 갱신 토큰을 평문으로 두기엔 불안했어요.

macOS 키체인을 쓰고 싶었고, 특히 갱신 토큰을 읽을 때 생체인증이나 암호를 요구하는 보안 수준이 필요했어요. macOS에는 security라는 편리한 키체인 CLI가 있어요.

security add-generic-password -s google-api -a my-account -w $REFRESH_TOKEN

근데 생체인증을 간단하게 지원하지 않더라구요. Swift 래퍼를 만들면 된다는 검색 결과가 나오긴 했는데, 막상 만들어보니 kSecAttrAccessControl 속성을 쓰려면 Apple Developer Program을 통한 실제 서명된 entitlement가 필요했어요. 너무 복잡해진 거죠.

그래서 security 맨 페이지를 Claude Opus 4.5에 넣어서 돌려봤어요. 모델이 아주 흥미로운 발견을 해줬어요.

security add-generic-password -T"" ...

-T 플래그에 빈 문자열을 주면, 어떤 애플리케이션도 사용자 인증 없이 비밀번호를 읽지 못하게 막아요. 실제로 비밀을 읽으려 하면 기기 암호를 입력하라는 화면이 뜨더라구요. 제 용도에는 딱이었어요.

모든 게 조합되니, CLI 실행 시 저장된 액세스 토큰으로 먼저 시도하고, 토큰이 무효하면 oauth2c로 자동 갱신하고, 그것도 실패하면 Authorization Code 플로우로 브라우저를 열어 재인증하는 구조가 완성됐어요. 맞춤형 코드는 하나도 없이요.


API가 없다면? 역공학으로 직접 만들어버려요

기계가 읽을 수 있는 API 스펙을 제공하는 서비스라면 다행이지만, 그렇지 않은 곳도 많아요. 구글 Groups가 그랬어요. 토론 기록을 내보내서 지식 베이스로 쓰고 싶었는데, 구글에서 그런 API를 제공하지 않더라구요.

이런 문제는 저는 LLM을 이용해서 푸는 걸 좋아해요. 워크플로우는 이렇게 해요.

새 프라이빗 브라우저 창을 열고, 개발자도구 네트워크 탭에서 HTML, XHR, WS, Other로 필터링해요. 그리고 자동화하고 싶은 작업을 직접 수행한 뒤(사이트 로드, 페이지 이동, 특정 대화 읽기), Firefox 개발자도구에서 "모두 HAR로 저장"을 클릭해요. cloudflare/har-sanitizer로 민감 정보를 제거한 다음, LLM에게 "이 HAR 파일 기반으로 파이썬 클라이언트 만들어줘"라고 요청하면 끝이에요. 생성된 파일에 의미 있는 User-Agent 문자열과 백링크를 추가하면 쓸 만한 클라이언트가 완성돼요.

이 워크플로우를 이미 세 번 이상 써봤고, 앞으로도 몇 번 더 쓸 것 같아요. 아직 OpenAPI 스펙 자동 생성과 역공학 OAuth 파라미터 추출을 한 번에 해달라는 요청은 안 해봤는데, 논리적으로 다음 단계가 될 것 같아요.


MCP의 성장세와 그 이면에 있는 현실

사실 MCP 자체가 나쁜 건 절대 아니에요. 실제로 2024년 11월 출시 이후 성장세가 엄청나거든요. 월간 SDK 다운로드 수 9,700만 건, OpenAI·구글·마이크로소프트의 공식 채택, 그리고 2025년 12월에는 리눅스 재단 산하 Agentic AI Foundation(AAIF)으로 이관되면서 진정한 오픈 표준이 됐어요.

근데 그 이면에는 조심해야 할 지점도 있어요. Thoughtworks의 Technology Radar에서는 "무분별한 API의 MCP 서버 전환(naive API-to-MCP conversion)"에 대해 경고하며 Hold 등급을 매겼어요. 보안 리스크도 현실이에요. 툴 포이즈닝, 크로스 서버 툴 섀도잉, 프롬프트 인젝션 같은 공격 벡터가 이미 연구자들에 의해 문서화되고 있거든요.

CLI 방식은 이런 복잡성에서 상대적으로 자유로워요. 코드가 적으면 버그도 적고, 관리 포인트도 줄어요.


CLI 조합의 힘, 당신도 한번 써보세요

CLI를 조합하는 데엔 진짜 대단한 힘이 있어요. 사람과의 상호작용과 현세대 LLM과의 상호작용을 동시에 잡을 수 있거든요. 그리고 약간의 창의력만 있다면, 개인이 특정 서비스용 MCP 서버 대신 CLI를 유지보수하는 게 충분히 가능해요. 심지어 해당 MCP 서버가 만들어지기 전에도요.

MCP의 생태계가 급격히 커지고 있는 건 사실이에요. 그 흐름을 무시하기보다는, 어떤 상황에서 MCP를 쓰고 어떤 상황에서 CLI가 더 나은지를 스스로 판단할 수 있어야 한다고 생각해요. 무겁고 복잡한 프레임워크가 필요한 상황도 있고, 가볍고 조합 가능한 셸 파이프라인 하나로 충분한 상황도 있어요.

진짜 고수는 유행을 따르는 게 아니라, 도구를 선택하는 이유를 알고 있는 사람이니까요.


핵심 요약

MCP가 대세로 자리 잡고 있는 2026년 초, LLM 에이전트에 SaaS 기능을 연결하는 방법은 MCP만이 아니에요. OpenAPI 스펙을 "프로그램"으로, Restish와 oauth2c를 "인터프리터"로 활용하면 커스텀 코드 없이도 강력한 CLI 파이프라인을 만들 수 있어요. API가 없는 서비스는 HAR 캡처와 LLM 역공학으로 클라이언트를 만들 수 있고요. 이 방식은 토큰 비용을 줄이고, 유지보수 부담을 낮추며, 사람과 기계 모두 쓸 수 있는 인터페이스를 제공해요. MCP도 훌륭하지만, 상황에 따라 CLI가 더 가볍고 실용적인 선택일 수 있다는 걸 기억해두세요.

300x250
반응형