본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 01. 11:38

Scarab Diagnostic Suite 현장 테스트 #003: Vite에서의 Dev/Build 계약 드리프트 (Contract Drift)

요약

Scarab Diagnostic Suite(SDS)의 세 번째 테스트를 통해 AI 앱을 넘어 Vite 빌드 시스템의 계약 드리프트(Contract Drift) 문제를 진단하는 과정을 다룹니다. dev 모드와 build 모드 간의 플러그인 훅 필터 동작 불일치 사례를 통해 SDS의 일반화 능력을 검증합니다.

핵심 포인트

  • SDS는 AI 앱 런타임을 넘어 프레임워크 빌드 시스템의 버그도 진단 가능함
  • Vite의 dev/build 모드 간 플러그인 훅 필터 동작 불일치 사례 분석
  • 런타임 모드 간 계약 드리프트(Contract Drift) 개념 제시
  • 프레임워크 내부 실행 모드 간의 일관성 경계 식별 능력 확인

이것은 저의 Scarab Diagnostic Suite 시리즈 중 세 번째 현장 테스트입니다.

첫 번째 현장 테스트에서는 SDS가 알려진 Open WebUI 제공자/설정(provider/config) 문제를 제한된 복구 경로(bounded repair lane)로 변환하는 것을 보여주었습니다.

두 번째 현장 테스트는 더 강력했습니다. SDS는 해당 이슈 텍스트가 기능적 증거로 사용되기 전에 Memory/RAG 검색 경계(retrieval boundary)를 식별해냈습니다.

이번 세 번째 현장 테스트는 완전히 다른 종류의 리포지토리(repo)로 이동했습니다.

AI 애플리케이션이 아닙니다.

RAG 파이프라인도 아닙니다.

제공자 어댑터(provider adapter)도 아닙니다.

이번 타겟은 Vite였습니다.

구체적으로는, 플러그인 변환 훅(plugin transform hook) 필터가 dev 모드와 build 모드에서 다르게 동작하는 Vite 이슈 #21979입니다.

이는 Scarab Diagnostic Suite에 있어 중요한 전환점입니다. 왜냐하면 진단 모델이 AI 앱 런타임 버그를 넘어 프레임워크/빌드 시스템 계약(framework/build-system contracts)까지 일반화할 수 있는지를 테스트하기 때문입니다.

이슈 (The issue)

보고된 버그는 표면적으로는 작았습니다:

하나의 Vite 플러그인이 id 필터가 포함된 변환 훅(transform hook)을 정의합니다:

ts filter: { id: { include: '*/.(js)', }, }

dev 모드에서는 필터가 적용되어 변환이 JavaScript 파일에 도달합니다.

build 모드에서는 동일한 형태의 필터가 적용되지 않습니다.

보고자는 *_/_.js는 dev와 build 모두에서 작동하지만, *_/_.(js)는 작동하지 않는다고 언급했습니다. 그들의 기대는 단순했습니다. 특정 glob 구문이 특이하더라도, Vite의 훅 필터는 dev와 build 사이에서 일관되게 동작해야 한다는 것이었습니다.

그것이 중요한 부분입니다.

이것은 단순히 "glob 패턴이 이상하다"는 문제가 아니었습니다.

진정한 계약(contract)은 다음과 같았습니다:

동일한 플러그인 훅 필터는 dev와 build에서 동일한 의미를 가져야 한다.

이것이 바로 SDS가 포착할 수 있어야 하는 일관성 경계(consistency boundary)의 전형적인 모습입니다.

SDS가 발견한 것 (What SDS found)

SDS는 이 실패를 프레임워크/빌드 라이프사이클 핫스팟(framework/build lifecycle hotspot)으로 드러냈습니다.

핵심 진단 형태는 다음과 같았습니다:

framework_runtime_mode_filter_contract_consistency

쉬운 영어로 풀이하면:

런타임 모드 전반에 걸쳐 일관되게 동작해야 하는 필터 계약이 Vite가 dev로 실행되는지 build로 실행되는지에 따라 서로 다른 결과를 생성하고 있었습니다.

이는 Open WebUI 테스트와는 매우 다른 표면(surface)입니다.

Open WebUI #25038에서는 불안정한 경계(unstable boundary)가 Memory/RAG 소스 컨텍스트 경로를 통과하는 검색 진실(retrieval truth)이었습니다.

Vite #21979에서 불안정한 경계는 두 가지 실행 모드(execution modes)를 통과하는 프레임워크 동작이었습니다:

dev 모드 (dev mode)

build 모드 (build mode)

동일한 플러그인 계약(plugin contract).

다른 결과.

이것이 바로 런타임 모드 계약 드리프트 (runtime-mode contract drift)입니다.

이것이 중요한 이유

프레임워크 사용자들은 보통 "내부 실행 모드 계약 발산 (internal execution mode contract divergence)"이라는 관점으로 생각하지 않습니다.

그들은 다음과 같이 생각합니다:

"플러그인 훅 (plugin hook)을 작성했어."

"dev 모드에서는 잘 작동해."

"왜 build에서는 다르게 동작하지?"

이것이 바로 이러한 버그들이 중요한 이유입니다.

Dev/build 발산은 아주 고약한 종류의 신뢰 문제를 야기합니다. 개발자는 로컬에서 무언가를 테스트하고 dev 모드에서 작동하는 것을 확인한 뒤, build 과정에 이르러서야 해당 계약이 실제로 안정적이지 않았음을 발견하게 됩니다.

이는 프레임워크 내부(internals)에 숨어들 수 있는 종류의 버그입니다. 왜냐하면 외부로 드러나는 증상은 작기 때문입니다:

"build 중에 내 플러그인이 실행되지 않았어."

하지만 더 깊은 문제는 다음과 같습니다:

"시스템이 동일하게 선언된 필터 (filter)를 서로 다른 의미론적 경로 (semantic paths)를 통해 해석하고 있다."

Scarab의 역할은 바로 그 더 깊은 경계를 찾아내는 것입니다.

수정 경로 (The repair lane)

수정은 build 변환 경로 (build transform path)로 한정되었습니다.

로컬 변경 사항은 하위 수준의 build 필터링 동작이 해당 경로를 먼저 결정하도록 두는 대신, build 래퍼 (wrapper)가 플러그인 핸들러 (plugin handler)를 호출하기 전에 Vite의 변환 훅 (transform hook) 필터를 적용하도록 만들었습니다.

목표는 훅 필터 (hook filters)를 재설계하는 것이 아니었습니다.

목표는 모든 glob 의미론 (glob semantics)을 변경하는 것이 아니었습니다.

목표는 Rolldown을 광범위하게 패치하는 것도 아니었습니다.

목표는 단 하나의 좁은 계약 수정이었습니다:

보고된 필터 형태 (filter shape)에 대해, build는 dev와 일관되게 변환 (transform)을 적용해야 합니다.

이것이 수정 범위 (repair slice)입니다.

Red/green 증명

집중된 회귀 테스트 (regression test)를 통해 보고된 동작을 증명했습니다.

수정 전:

build 중에 변환 훅 (transform hook)이 /src/main.js에 도달하지 못했기 때문에 테스트가 실패했습니다.

실패한 형태는 다음과 같았습니다:

text expected false to be true

수정 후:

동일한 집중 테스트가 통과되었습니다.

검증 패키지는 단일 유닛 테스트 (unit test)보다 강력했습니다:

집중 회귀 테스트 (focused regression) 통과,

수정된 파일에 대한 eslint 통과,

oxfmt 통과,

Vite build-bundle 통과,

Vite build-types 통과,

Vite typecheck 통과.

이것이 중요한 이유는 프레임워크/빌드 시스템 (framework/build-system) 패치가 단순히 "테스트 하나가 통과되었다"는 것 이상의 것을 필요로 하기 때문입니다.

이러한 패치에는 변경 사항이 주변의 빌드 파이프라인 (build pipeline)을 방해하지 않는다는 확신이 필요합니다.

수정 후의 SDS

수정 후, SDS는 대상을 상대로 다시 실행되었습니다.

특정 런타임 모드 필터 계약 (runtime mode filter contract) 발견 사항이 해결되었습니다.

더 넓은 범위의 리포지토리 (repo)가 마법처럼 깨끗해지지는 않았으며, 이는 괜찮습니다.

SDS는 단 하나의 버그 수정 후에 전체 리포지토리가 완벽해진 것처럼 가장할 의도가 없습니다.

중요한 부분은 선택된 진단 영역 (diagnostic surface)이 예상된 방향으로 변화했다는 점입니다:

집중된 계약 (contract) 발견 사항이 해결되었고,

선택된 핫스팟 (hotspot)이 Stepwise가 다음 단계로 넘어갈 수 있을 만큼 충분히 조용해졌으며,

수정이 문제 형태의 실패 (issue-shaped failure) 범위 내로 제한되었습니다.

이것이 바로 SDS 루프가 다시 작동하는 방식입니다:

영역을 진단하고,

선택된 경로 (lane)만 수정하며,

동작을 증명하고,

진단을 다시 실행하여,

대상 발견 사항이 변경되었음을 확인하는 것입니다.

업스트림 형태 (Upstream shape)

업스트림 PR (Pull Request)은 Scarab 또는 SDS를 언급하지 않고 준비되었습니다.

이는 의도적인 것입니다.

메인테이너 (Maintainers)들이 코드를 리뷰하기 위해 저의 진단 시스템을 이해할 필요는 없습니다.

공개된 PR 언어는 일반적인 Vite 언어였습니다:

transform hook filter,

dev/build consistency,

build wrapper,

regression coverage.

내부적인 SDS 언어는 내부적으로 유지되었습니다.

이러한 분리는 중요합니다.

Scarab Diagnostic Suite가 작업을 가이드할 수는 있지만, 업스트림 PR은 리포지토리 고유의 증거 (repo-native evidence)를 바탕으로 서야 합니다.

이 현장 테스트가 증명한 것

현장 테스트 #003은 새로운 사실을 증명했습니다:

SDS는 AI 앱의 버그에만 유용한 것이 아닙니다.

프레임워크/빌드 시스템의 계약 드리프트 (contract drift)를 감지할 수 있습니다.

이는 Open WebUI 테스트와는 다른 클래스의 실패입니다.

Open WebUI 사례는 런타임 데이터 (runtime data)와 응답 형태 (response-shape) 경계에 관한 것이었습니다.

Vite 사례는 빌드 도구 내부의 실행 모드 일관성 (execution-mode consistency)에 관한 것이었습니다.

이것이 중요한 이유는 SDS (Scarab Diagnostic Suite) 모델이 단순히 한 종류의 버그를 암기하는 것이 아님을 시사하기 때문입니다. SDS는 서로 다른 소프트웨어 표면 (software surfaces) 전반에 걸쳐 저장소의 진실 (repo truth)에 대해 추론하는 방법을 학습하고 있습니다.

이 사례에서 진실은 다음과 같았습니다:

“플러그인 훅 필터 (plugin hook filter)는 개발 (dev) 모드와 빌드 (build) 모드에서 동일한 의미를 가져야 한다.”

이 진실이 깨졌을 때, SDS는 해당 표면을 찾아냈습니다.

내부 분류 (Internal classification)

현장 테스트 (Field Test) #003

프로젝트: Vite

이슈: #21979

표면 (Surface): 프레임워크 실행 모드 필터 계약 (framework runtime-mode filter contract)

계약 클래스 (Contract class): dev/build 훅 필터 일관성 (hook-filter consistency)

모드: 맹목적 진단 표면 탐지 후 집중적인 red/green 수리 (blind diagnostic surface detection followed by focused red/green repair)

결과: 로컬 수리 성공, 타겟팅된 SDS 탐지 해결, 집중 회귀 테스트 통과, 업스트림 PR 제출

주요 교훈: SDS는 프레임워크/빌드 라이프사이클 계약 드리프트 (lifecycle contract drift)를 탐지하고 수리를 가이드할 수 있다.

이것이 Scarab에게 중요한 이유

이 현장 테스트는 제품의 스토리를 확장하기 때문에 중요합니다.

Scarab Diagnostic Suite는 단순한 버그 수정 봇 (bug-fix bot)이 아닙니다.

하나의 저장소에 종속되지 않습니다.

AI 애플리케이션 미들웨어 (AI application middleware)에 국한되지도 않습니다.

이는 AI 지원 개발을 위한 진단 감독 계층 (diagnostic supervision layer)임을 의미합니다.

즉, SDS는 다음과 같은 다양한 종류의 저장소 진실 (repo truth)을 이해해야 합니다:

프로바이더 설정 진실 (provider config truth),

검색 컨텍스트 진실 (retrieval context truth),

외부 API 메타데이터 진실 (external API metadata truth),

실행 모드 동작 진실 (runtime-mode behavior truth),

빌드 아티팩트 진실 (build artifact truth).

Vite #21979는 새로운 진실을 추가했습니다:

실행 모드 계약 진실 (execution-mode contract truth).

동일한 입력.

동일한 플러그인 계약.

다른 실행 모드.

다른 동작.

이것이 바로 실제적인 진단 표면 (diagnostic surface)입니다.

그리고 SDS는 이를 찾아냈습니다.

더 큰 패턴

처음 세 번의 현장 테스트를 통해 패턴이 더욱 명확해지고 있습니다.

가치는 AI 에이전트가 코드를 빠르게 작성할 수 있다는 점에 있지 않습니다.

가치는 AI 에이전트가 코드를 작성하기 시작하기 전에 SDS가 수리 범위를 더 작게 만든다는 점에 있습니다.

이것이 관리되지 않는 AI 코딩 (unmanaged AI coding)과 진단 주도형 수리 (diagnostic-led repair)의 차이입니다.

관리되지 않는 AI는 종종 증상에서 시작하여 방황합니다.

SDS는 경계 (boundary)에서 시작합니다.

이 현장 테스트에서 경계는 “Vite가 고장 났다”가 아니었습니다.

그것은 다음과 같았습니다:

“Vite의 transform hook 필터 계약 (filter contract)이 dev와 build 사이에서 일치하지 않는다.”

그것은 더 구체적입니다.

그것은 테스트 가능합니다.

그것은 수리 가능합니다.

그것이 바로 Scarab Diagnostic Suite의 목적입니다.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0