직관에 의존하는 것을 멈추다: Expo의 에이전트 스킬을 위한 평가 하네스 구축 과정
요약
본 글은 코딩 에이전트가 Expo의 다양한 기능을 활용하는 스킬을 개발하고 테스트하는 과정에 대한 내용을 다룹니다. 기존에는 직접적인 호출만으로는 실제 사용자 시나리오를 반영하기 어려웠으며, 이를 해결하기 위해 평가(eval) 하니스를 구축했습니다. 이 하니스는 에이전트가 일반적인 요청 속에서 필요한 스킬을 스스로 발견하여 사용하는 능력을 측정할 수 있게 해주었습니다.
핵심 포인트
- 에이전트 개발 시 '내 기기에서는 작동'하는 테스트만으로는 부족합니다.
- 실제 사용자는 스킬 이름을 언급하지 않으므로, 에이전트의 자발적 발견 능력이 중요합니다.
- 평가(eval) 하니스를 구축하여 에이전트의 실제 활용률을 측정했습니다.
- 하네스 도입 후 관련 Expo 스킬 로드 비율이 9%에서 55%로 크게 증가했습니다.
이 게시글은 Georgian AI Lab의 Aditya Shukla, Kartik Gupta, David Tingle과 함께한 협업 포스팅입니다. 저희는 그들과 파트너십을 맺고 코딩 에이전트가 Expo의 에이전트 스킬을 어떻게 찾고 사용하는지 측정했습니다.
개발자로서 여러분은 코딩 에이전트 플러그인을 위한 스킬을 작성하고, 해당 기능을 이름으로 언급하는 프롬프트로 테스트해보고, 에이전트가 올바르게 작동하는 것을 확인한 후 배포합니다. 이것이 AI 툴링에 대한 기본적인 "내 기기에서는 작동했지만" 상황입니다. 문제는 실제 사용자의 모호하고 평범한 요청이 에이전트로 하여금 해당 스킬을 아예 호출하게 만들지 않을 수 있다는 점입니다.
이것이 Expo가 가지고 있던 격차였습니다. 저희는 네이티브 인터페이스, 내비게이션, 데이터 가져오기(data fetching), 애니메이션, Expo Modules, 그리고 클라우드 서비스를 포괄하는 에이전트 스킬들을 하나의 플러그인으로 묶어 Claude Code와 Codex에 적용했습니다. 저희는 스킬을 계속 추가하고 설명을 다듬었지만, 이 모든 것이 실제로 사용자에게 도달하고 있는지에 대한 실제 신호가 없었습니다. 그래서 저희는 Georgian AI Lab과 함께 평가(eval) 하니스를 구축하여 CI에 연결했고, 이를 사용하여 우리가 가지고 있다는 사실조차 몰랐던 문제를 발견했습니다. 바로 우리의 스킬들이 거의 로드되지 않고 있었다는 것입니다. 한 가지 목표 지향적인 수정 이후, 관련 Expo 스킬을 로드한 에이전트 세션의 비율은 9%에서 55%로 증가했습니다.
어떻게 그곳에 도달했는지, 그리고 이것이 단순히 감으로 테스트하는 것이 아니라 AI 툴링을 테스트하는 것에 대해 무엇을 가르쳐 주었는지 알려드립니다.
직접 호출만으로는 생각보다 부족하다
스킬을 작성하는 입장에서 우리는 이미 호출 패턴을 알고 있습니다. Expo UI 스킬을 테스트한다는 것은 Claude Code에서 문자 그대로 /expo-ui를 입력하거나 Codex에서 $expo-ui를 입력한 다음, 에이전트가 로드된 후 이를 잘 사용했는지 확인하는 것을 의미했습니다.
이는 해당 스킬이 컨텍스트 내에서 유용하다는 것만 알려줄 뿐, 발견(discovery)에 대해서는 아무것도 알려주지 못합니다. 실제 사용자는 스킬의 이름을 붙이지 않습니다. 그들은 “Expo를 이용해 iOS 투두 앱을 만들고 네이티브하게 보이게 해줘” 또는 “이 앱에 탭과 설정 화면을 추가해줘”와 같은 말을 합니다. 어떤 가이드라인도 도움이 되기 전에, 에이전트는 먼저 스스로 판단하여 해당 스킬이 열기에 충분히 관련성이 있다고 결정해야 합니다. 우리는 그 결정을 측정할 방법이 없었습니다.
이는 Georgian AI Lab에서 더 일반적인 주제로 다룬 내용과 일치합니다. 최종 답변만으로는 그 과정에서 무슨 일이 있었는지 모든 것을 보여주지 못합니다. Your AI Systems Need an Eval Loop에서 Asna Shafiq은 트레이스(traces)가 에이전트의 행동을 관찰할 수 있게 해주지만, 그 관찰 내용을 측정 가능한 무언가로 바꾸려면 평가(evals)가 필요하다고 설명합니다. 우리는 같은 아이디어를 스킬에 적용했습니다. 단순히 스킬이 고립적으로 작동하는지 확인하는 대신, 에이전트가 일반적인 앱 개발 작업을 수행하면서 적절한 조합의 스킬을 찾아내는지 테스트합니다.
우리가 측정하기로 결정한 것
이 하네스(harness)는 제품 요구사항 문서(product requirements document, PRD)를 태스크로 받아 코딩 에이전트(coding agent)를 구동하고, 과정(에이전트의 궤적 및 스킬 사용)과 결과물(만들어진 앱)을 모두 평가합니다.
저희 데이터셋의 각 시나리오—단발성 앱 빌드, 디버깅을 위한 충돌하는 개발 빌드, 또는 기존 앱에 추가할 기능 등—는 사전에 에이전트가 유용하다고 발견할 것으로 예상되는 스킬, 가이드라인이 실제로 따라졌다면 나타나야 할 증거, 그리고 종단 간(end-to-end) 태스크가 내포하는 기능 원시 요소(feature primitives)로 주석 처리됩니다.
이를 통해 우리는 세 가지 계층의 증거를 얻습니다:
- 스킬 트리거링 (Skill triggering): 에이전트가 해당 태스크와 관련된 스킬을 로드했는가?
- 스킬 수용 (Skill uptake): 에이전트가 로드한 가이드라인을 따랐다는 증거가 있는가?
- 앱 동작 (App behavior): 결과로 나온 앱이 PRD에서 설명하는 대로 작동하는가?
이러한 요소들은 개별적으로 측정되어야 합니다. 로드되지 않는 스킬은 아무것도 영향을 미칠 수 없으므로, 트리거링(triggering) 자체를 별도로 측정해야 합니다. 또한 스킬이 로드되더라도 무시될 수 있으므로, 실제 사용률(uptake) 역시 별도의 검증 항목입니다. 그리고 에이전트는 우리가 기대했던 스킬을 건드리지 않고도 기존 지식만으로 작동하는 기능을 구축할 수 있는데, 이는 괜찮습니다. 만약 에이전트가 우리의 문서(documentation)를 참조하지 않았다는 이유만으로 올바르게 작업을 수행했다는 점에 대해 패널티를 주고 싶지는 않습니다. 오히려 그것은 해당 스킬의 기능이 모델 역량에 의해 불필요해졌다는 신호일 수 있습니다. 이러한 요소들을 개별 레이어로 분리함으로써, 실제로 어느 부분에 개입해야 할지 훨씬 쉽게 파악할 수 있었습니다.

이 하네스(harness)는 제품 요구사항과 예상 동작을 기반으로 시작하여, 코딩 에이전트를 통해 작업을 실행하고, 구축된 앱과 에이전트 추적 기록(agent trace)을 모두 아티팩트로 보관합니다. 이를 바탕으로 스킬 트리거링 여부, 소스 트리의 사용 증거(evidence of uptake), 그리고 iOS에서의 앱 동작을 개별적으로 확인합니다.
하네스는 EAS Workflows에서 실행되며 Expo Skills repository와 연결되어 있습니다. 스킬 변경 사항을 배포하는 사람은 풀 리퀘스트(pull request, PR)에 eval 레이블을 추가할 수 있으며, 하네스는 선택된 시나리오를 main 브랜치와 해당 PR 브랜치 모두에서 실행하고 결과를 PR에 직접 게시합니다. 이제 스킬은 코드를 개발하는 방식대로 개발됩니다. 변경 사항을 만들고, 일련의 시나리오로 테스트하며, 증거를 살펴보고, 다음에 무엇을 할지 결정하는 것입니다.
추적 기록으로 본 우리의 스킬들은 로드되지 않았다
이것은 출력물을 육안으로 확인해서 놓치기 쉬웠는데, 앱들이 여전히 괜찮아 보였기 때문이다. 에이전트는 이미 Expo와 React Native에 대해 충분히 알고 있어서 우리의 도움 없이도 합리적인 코드를 생성할 수 있었으므로, 몇 개의 파일을 스캔한다고 해서 우리 플러그인이 아무것도 기여하지 않았다는 것을 알아내기는 어려웠다. 트레이스(trace)는 최종 답변으로는 보여줄 수 없었던 방식으로 그 간극을 눈에 띄게 만들었다.
우리는 세 가지 후보 설명을 가지고 있었다: 에이전트가 이미 충분히 자신감을 느껴 안내를 찾는 과정을 건너뛸 수도 있다는 것, 프런트매터(frontmatter)의 스킬 설명이 각 스킬을 언제 사용해야 하는지 제대로 전달하지 못할 수도 있다는 것, 또는 플러그인의 증가하는 스킬 개수가 단순히 전체 모음을 고르기 어렵게 만들 수도 있다는 것이었다. 우리는 가장 쉬운 수정부터 시작했다. 바로 스킬 이름과 설명을 다시 작성하는 것이었는데, 이는 에이전트가 관련성을 결정할 때 문자 그대로 읽는 내용이기 때문이다. 이것은 도움이 되었지만 충분하지 않았다. 그 결과, 오랫동안 의심해 왔던 세 번째 가설로 우리를 이끌었다.
에이전트에게 통과할 수 있는 하나의 문을 제공하기
Expo의 표면적(surface area)은 넓다: Expo SDK, Expo Router, Expo Modules, 네이티브 UI, 클라우드 서비스. 이를 집중된 스킬로 분할하면 컨텍스트 사용을 합리적으로 유지할 수 있지만, 동시에 에이전트가 다른 어떤 일을 하기 전에 20개가 넘는 스킬 중에서 선택해야 한다는 것을 의미한다.
그래서 우리는 Expo와 EAS 작업을 위한 진입점(entrypoint) 스킬이자 라우터인 [expo-overview](https://github.com/expo/skills/pull/107)를 구축했다. 이 설명은 이를 모든 Expo, EAS 또는 React Native 요청의 시작점으로 확립한다. 내부적으로는 맵이 일반적인 목표들을 실제 관련 안내가 포함된 더 전문화된 스킬들과 연결하고, 또한 Expo SDK 버전을 감지하거나 npx expo install로 패키지를 설치하는 것과 같이 어디에나 적용되는 작은 설정 규칙들(setup rules)을 연결한다. (Sentry와 Convex는 자체 스킬 플러그인에 대해 유사한 패턴으로 독립적으로 착수했다.)
오버뷰 스킬은 에이전트가 결국 선택해야 하는 스킬의 개수를 줄이지는 않습니다. 대신 다른 실패 모드를 해결합니다. 즉, 에이전트가 어떤 Expo 스킬도 아예 열지 않는 경우입니다. 앱 빌드 작업 자체가 에이전트에게 많은 것을 요구하기 때문에(아키텍처, 의존성, 네비게이션, 상태 등), 여기에 "20개 이상의 스킬 중에서 올바르게 선택하기"라는 과제가 추가되자 마치 이 단계를 완전히 건너뛰는 것이 더 쉬워진 것처럼 보였습니다. 명확한 첫 번째 도약 지점을 제공하는 것만으로도 스킬을 아예 찾으려는 활성화 에너지(activation energy)를 낮춥니다.

진입점(entrypoint)은 첫 번째 도약의 마찰을 줄여, 에이전트가 관련 스킬을 아예 찾으려는 가능성을 높입니다.
9%에서 55%로
저희는 eval 레이블이 붙은 PR에 대해 테스트를 실행했고, 처음 받은 신호는 에이전트 스스로 결정 과정을 설명하는 것이었습니다.
"이 작업은 Expo/React Native 앱을 빌드하는 것을 포함하므로, expo-overview 스킬부터 로딩하겠습니다..."
다른 실행에서는 다음과 같았습니다.
"어떤 Expo/EAS 작업이든 가장 먼저 실행되어야 하므로, Expo overview 스킬부터 로딩하겠습니다."
누구도 프롬프트에 expo-overview라는 이름을 언급하지 않았습니다. 에이전트는 Expo 형태의 작업을 인식하고, 진입점(entrypoint)을 선택했으며, 그 안에 있는 라우팅 정보를 사용하여 무엇을 추가로 로드할지 결정했습니다. 세 가지 샘플 PRD를 분석한 결과, 추적 과정은 일관된 체인을 보여주었습니다: 노트 앱의 경우 expo-overview → expo-project-structure로 이어지고, 네비게이션이 있는 앱의 경우 expo-router까지 확장되었으며, 커스텀 UI가 필요한 앱의 경우 심지어 expo-ui에 이르렀습니다.
이것이 유지되는지 확인하기 위해, 우리는 sonnet-5-high를 사용하여 10개의 그린필드 앱 PRD(Expo를 언급하지만 스킬 이름을 명시하지 않은 경우)에 대해 Claude Code를 재실행했습니다. 변동성을 줄이기 위해 플러그인을 적용하기 전과 후로 각각 세 번씩 비교했습니다. 기준선에서는 에이전트 세션 중 약 10%만이 어떤 Expo 스킬이라도 로드했습니다. expo-overview를 사용하자, 이 수치는 한 개 이상의 다운스트림 스킬을 로드하는 세션의 55%로 급증했으며, 모든 세션에서 오버뷰 자체는 로드되었습니다.

다운스트림 스킬(downstream skill)이란 expo-overview가 아닌 모든 스킬을 의미합니다. 기준선에서는 expo-overview 없이 단순히 어떤 Expo 스킬이든 해당됩니다. 채택률(Uptake)은 작성된 소스에서 예상되는 패턴이 나타났다는 증거입니다.
더 중요한 수치인 관련 스킬 재현율(Relevant Skill Recall, 에이전트가 해당 작업에 매핑한 특정 스킬을 로드했는지 여부)은 2%에서 18%로 상승했습니다. 개선되었지만, 여전히 에이전트가 일반적으로 관련 내용의 일부만을 가져간다는 것을 보여줍니다. 개별 스킬을 살펴보면, 가장 많이 사용된 스킬들은 프로젝트를 구축(scaffolding the project)하거나 라우트를 설정하는(expo-project-structure) 등 초기적이고 구체적인 결정과 관련이 있었습니다. 한 트레이스에서는 오버뷰를 로드한 후 에이전트가 다음과 같이 말했습니다: "이제 Expo Router를 사용하도록 변환하고(탭 탐색에 필요함), 라우터 스킬을 설정 단계용으로 확인해 봅시다."
실패 사례 역시 마찬가지로 유익했습니다. 한 경우 에이전트는 expo-data-fetching을 전혀 열지 않고도 자체 지식만으로 RSS 및 Atom 피드 가져오기(fetching) 기능을 구축했습니다. 또 다른 경우에는, expo-overview가 이들을 함께 사용하도록 권장함에도 불구하고 컨트롤을 위해 expo-ui를 로드했지만 expo-native-ui는 건너뛰었고, 결과 코드는 스킬이 유도했을 패턴 대신 Dimensions.get()과 React Native의 SafeAreaView를 사용했습니다. 데이터셋 전반에 걸친 패턴은 다음과 같습니다: 에이전트들은 개요(overview)를 읽자마자 관련 스킬을 찾으려 하지만, 작업이 진행됨에 따라 그 의존도가 낮아집니다. 마치 개요가 한 번만 읽히는 것이지, 돌아와 참조할 수 있는 라우터(router)로 취급되지 않는 것처럼 말입니다.
이는 여전히 소수의 태스크에서 나온 초기 신호일 뿐, 해결된 문제는 아닙니다. 하지만 우리가 이전에 가질 수 없었던, 측정 가능한 실제 차이점임은 분명합니다.
카탈로그는 토큰 예산이 있으며, 스킬 설명이 잘릴 수 있습니다
Claude Code에서의 테스트를 통해 우리는 다른 에이전트들에 대해서도 궁금증을 갖게 되었고, 그래서 오픈 소스 Codex CLI를 살펴보았습니다. 시스템 프롬프트 이후, Codex는 사용 가능한 각 스킬의 이름, 설명, 파일 경로를 나열하는 _Skill Catalog_를 구축하며, 이 카탈로그는 설치된 모든 스킬에 걸쳐 공유되는 고정 총 길이를 가집니다. 우리가 확인한 버전에서는 그 할당량이 컨텍스트 창의 정확히 2%인 5,440 토큰(272k 중)이었습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기