DevLog

엔지니어링 블로그를 한 곳에서 탐색하고, 최근 발행 흐름을 빠르게 파악할 수 있는 서비스 입니다.

Quick Links

  • Latest Feed
  • Engineering Directory

Support

  • 소개
  • 개인정보처리방침

Contribute

  • 원하는 블로그 추가 (준비 중)
  • Feedback

© 2026 DevLog Inc. All rights reserved.

본 사이트는 공개 RSS 피드를 통해 콘텐츠를 수집하며, 모든 콘텐츠의 저작권은 원저작자에게 있습니다.

Back to Feed
Read Original

Contents

Continue Reading

  • More from 미리디
#Frontend

테스트가 늘수록 느려지던 CI, 16분에서 3분이 되기까지

테스트가 늘수록 느려지던 CI, 16분에서 3분이 되기까지
01

Summary

16분 걸리던 무거운 CI 테스트를 단 3분으로 줄인 미리캔버스의 Vitest 최적화 비결

모듈 격리 제거와 정교한 상태 클린업 안전 가드로 이뤄낸 초고속 모노레포 테스트 빌드 최적화

테스트 코드를 짤수록 피드백 루프가 느려지는 프론트엔드 모노레포의 역설을 해결하기 위해 미리디 엔진팀이 고군분투한 생생한 실전 기록입니다. 단순히 패키지를 쪼개는 임시방편을 넘어, CPU/힙 프로파일러로 찾아낸 핵심 병목인 모듈 격리 환경을 최적화하여 빌드 성능을 무려 78%나 개선했습니다. 지속 가능한 속도를 위해 AI 개발 에이전트와도 협업할 수 있도록 시스템 가이드를 정립한 모범 사례를 소개합니다.

  • 01Vitest 프로파일링 도구(--cpu-prof, --heap-prof)를 활용해 테스트 본문이 아닌 '모듈 로딩 단계'가 병목임을 정확히 진단
  • 02동일 모듈 그래프를 무한 반복 평가하던 격리 모드를 안전하게 해제(isolate: false)하여 가공할 속도 향상 실현
  • 03모듈 전체를 교체해 캐시를 오염시키는 vi.mock 대신 가벼운 vi.spyOn을 권장하는 설계 리팩터링 적용
  • 04flaky 테스트를 방지하기 위한 린트 룰, 런타임 가드, 그리고 에이전트용 스킬 문서로 이어지는 4단계 안전장치 구축
  • 05TypeScript 5.2의 using 문법과 Symbol.dispose를 결합해 테스트 누락 없는 명시적 리소스 cleanup 기법 제안

+RECOMMENDATION

프로젝트 규모가 커짐에 따라 테스트 러너의 실행 속도가 기하급수적으로 느려져 피드백 루프가 깨진 프론트엔드 팀에게 추천합니다. 전역 상태와 캐시 오염을 동반하는 비격리 테스트를 안전하게 제어하고 자동화된 도구로 지켜내는 세련된 실전 아키텍처를 배울 수 있습니다.

The Problem

미리캔버스 모노레포에서 테스트 커버리지 100% 달성 및 TDD 도입으로 테스트 코드가 수만 개로 늘어나면서, CI 유닛 테스트 단계의 대기 시간이 16분까지 늘어나는 문제가 발생했습니다. 원인을 분석한 결과 테스트 본문 실행이 아닌, Vitest의 기본 격리(isolation) 환경으로 인해 대규모 모듈 그래프(약 3,200개 모듈)를 테스트 파일마다 매번 새로 평가하는 모듈 로딩 단계가 병목이었습니다.

The Solution

유닛 테스트 잡에 고성능 8코어 러너를 재배치하고, 상태 정리가 검증된 안전한 파일만 비격리('isolate: false') 프로젝트로 분류하여 모듈 캐시를 공유하도록 처리했습니다. 또한 모듈 캐시 오염을 유발하여 비격리 전환을 방해하던 'vi.mock' 사용처를 런타임에 안전하게 프로퍼티만 가로채는 'vi.spyOn'으로 대거 교체하고, 규칙이 유지될 수 있도록 린트 룰 및 런타임 가드 등의 4단계 안전장치를 도입했습니다.

The Result

세 차례에 걸친 단계별 개선을 통해 유닛 테스트 잡 수행 시간을 16분 15초에서 3분 38초로 약 78% 단축시켰습니다. 특히 비격리 프로젝트는 테스트 파일 개수가 200개에서 400개로 두 배 늘어나도 실행 시간이 거의 증가하지 않는 강력한 확장성을 입증했습니다.

Trade-off

테스트 파일 간 격리를 해제하면서 전역 변수나 DOM 상태가 다음 테스트로 이어져 발생하는 flaky 테스트의 위험도가 크게 증가했습니다. 이를 방지하기 위해 테스트 작성 시 엄격한 리소스 정리(cleanup) 규칙을 지켜야 하며, 파일명 규칙 관리와 비격리 테스트용 가드 등의 도구 유지보수 비용 및 AI 에이전트용 전용 스킬 문서 관리 공수가 추가되었습니다.

03

Key Concepts

Concept · 01

테스트 격리 (Test Isolation)

각 테스트 파일이 서로 영향을 주지 않도록 독립된 샌드박스 환경에서 실행시키는 Vitest의 기본 동작 방식입니다. 다만 모노레포 등 의존성 그래프가 방대한 프로젝트에서는 매 파일마다 모듈을 새로 로드하는 엄청난 성능 낭비가 발생합니다.

  • 모듈의 격리가 필요하지 않은 안전한 테스트 파일들을 모아 isolate: false를 세팅함으로써 모듈 평가 비용을 대폭 축소했습니다.
  • 기본 forks 풀 대신 threads(worker_threads)를 사용하도록 풀 구성을 최적화하여 시너지를 냈습니다.
Concept · 02

vi.mock vs vi.spyOn

vi.mock은 모듈의 전체 export 내용을 모듈 로딩 시점에 가로채서 다른 객체로 대체하며 캐시를 오염시키는 반면, vi.spyOn은 모듈은 그대로 둔 채 이미 로드된 객체의 런타임 특정 메서드만 감시하거나 임시 교체합니다.

  • 비격리 테스트로 갈 수 없게 가로막던 vi.mock 코드들을 런타임 동적 spy 형태인 vi.spyOn으로 우회 전환했습니다.
  • 수정 사항이 테스트 종료 후 자동으로 복원될 수 있게 restoreMocks 설정을 활성화했습니다.
Concept · 03

명시적 리소스 관리 (using declarations)

TypeScript 5.2에 추가된 explicit resource management 기능으로, 변수 선언 시 using 키워드를 사용하면 해당 스코프를 빠져나갈 때 객체의 Symbol.dispose 메서드가 자동으로 실행되어 자원을 반환합니다.

  • 비격리 환경에서 개발자가 수동 정리해야 하는 타이머나 이벤트 구독을 실수로 누락하여 발생하는 테스트 깨짐(flaky) 현상을 막는 솔루션으로 제시되었습니다.
  • using 키워드와 disposable 헬퍼를 결합해 테스트 유틸리티 단계에서 cleanup 누락을 완벽히 차단하는 예시를 제공합니다.
Continue reading · same source

미리디More from 미리디

View all posts from 미리디
  • 외부 API 장애가 우리 서비스 장애로 이어졌다

    Circuit BreakerRedisResilience
    5일 전
  • 미리캔버스의 SVG 필터 활용기: 브라우저에서 이미지 보정하기

    SVGWeb GraphicsImage Processing
    1주 전
  • 미리디 엔진팀이 사내 해커톤 이틀 만에 만든 결과물 30개

    HackathonAI AgentRapid Prototyping
    2주 전
  • AI 잘 쓰는 사람의 노하우, 어떻게 팀 전체로 퍼질까?

    AI EnablementAXAI Native
    3주 전
  • 미리캔버스가 AI 3대로 해외 트렌드에서 진짜를 가려내는 법

    LLM AgentsMulti-Agent OrchestrationTrend Analysis
    1개월 전

Source

미리디
미리디
Engineering Blog

Published · September 15, 2026

Topics

VitestCI-CDMonorepoTest AutomationPerformance Tuning