Skip to content

fix(e2e): E2E dev 서버에서 Astro 도구 막대를 꺼 리스너 수 측정 플레이키를 없앤다 - #221

Merged
CaesiumY merged 2 commits into
mainfrom
fix/listener-leak-projects-flake
Oct 11, 2026
Merged

CaesiumY merged 2 commits into
mainfrom
fix/listener-leak-projects-flake

Conversation

@CaesiumY

Copy link
Copy Markdown
Owner

요약

E2E의 리스너 누수 테스트(/projects 왕복)가 CI에서 가끔 재시도 끝에만 통과하던 원인을 찾아 고쳤습니다. 앱 코드의 누수가 아니었습니다. dev 서버에만 붙는 Astro 개발 도구 막대가 리스너를 늦게 달아 측정이 어긋난 것입니다. 그래서 E2E가 띄우는 dev 서버에서는 도구 막대를 끕니다. 배포 사이트에는 원래 도구 막대가 없으므로 동작에는 변화가 없습니다.

증상

e2e/listener-leak.spec.ts의 "/projects 왕복 후 영속 타겟 리스너 수가 늘지 않는다"가 2026-10-11 CI 세 곳(#217, #218, #219)에서 1차 실패 후 재시도로 통과했습니다. 세 실행(run 38144040598, 38144648938, 38145433836)의 실패 모양은 모두 같았습니다. 다른 리스너 수는 그대로이고 document:astro:page-load만 기준값 6에서 7로 1 늘었습니다. React 버전과도 무관했습니다(#217, #218은 React 6).

원인

dev 도구 막대는 앱들을 requestIdleCallback으로 유휴 시간에 초기화합니다. 그중 audit 앱은 init()에서 페이지 전체 lint(await run())를 끝낸 뒤에야 astro:page-load 리스너를 답니다(astro/dist/runtime/client/dev-toolbar/apps/audit/index.js). 카드와 이미지가 많은 /projects에서는 이 lint가 오래 걸립니다. 느린 CI에서는 테스트가 기준값을 잰 뒤에 이 리스너가 붙어 1이 늘어난 것처럼 보였습니다.

측정 근거:

  • /projects를 불러온 뒤 astro:page-load 등록 시점을 기록하면, 앱 리스너와 xray 앱은 약 50~150ms 안에 붙고 audit 앱만 약 1.1초 뒤에 붙습니다(CPU 6배 감속 시 약 2.5초 뒤).
  • 실제 스펙에서 audit 청크 응답만 2.5초 늦추자 4회 중 4회 실패했습니다. 다른 리스너 수는 그대로이고 astro:page-load만 늘었습니다.
  • 참고로 CPU 감속(3배, 4배)만으로는 12회 모두 통과해 재현되지 않았습니다. CPU 감속은 브라우저만 느리게 하고 dev 서버는 그대로 두기 때문으로 보입니다.

수정

  • astro.config.ts: devToolbar.enabled를 E2E_DISABLE_DEV_TOOLBAR !== "1"로 둡니다. 평소 pnpm dev에서는 그대로 켜져 있습니다.
  • playwright.config.ts: webServer.env에 E2E_DISABLE_DEV_TOOLBAR: "1"을 넣습니다. Playwright는 이 값을 process.env와 합쳐 넘기므로 기존 환경 변수는 유지됩니다.
  • AGENTS.md: 도구 막대를 E2E에서 다시 켜면 이 문제가 돌아온다는 점을 Playwright 항목에 적었습니다.

audit 앱은 DOM이 바뀔 때마다 lint를 다시 돌리는 MutationObserver도 겁니다. 그래서 도구 막대를 끄면 E2E 도중의 불필요한 CPU 사용도 함께 사라집니다.

테스트 쪽에서 도구 막대의 리스너만 걸러 내는 방법도 검토했습니다. 하지만 dev에서 청크 이름이 audit-<해시>.js로 바뀌어 호출 위치로 구분하기 어렵고, 앱 초기화 완료를 기다리는 방법은 Astro 내부 구현에 기대야 해서 택하지 않았습니다.

검증

  • 같은 재현 조건(audit 청크 2.5초 지연)에서 수정 후 6회 중 6회 통과 (수정 전 4회 중 4회 실패)
  • E2E가 띄운 dev 서버에서 astro-dev-toolbar 요소 수: 환경 변수 있음 0, 없음 1
  • E2E 전체: 76개 통과
  • listener-leak.spec.ts + continue-reading.spec.ts 3회 반복(재시도 없음): 처음 39건 중 1건 실패(아래 "아직 남은 불안정성"), 진단 코드를 넣고 다시 2번 돌린 78건은 모두 통과
  • /projects 테스트 단독 12회 반복: 모두 통과
  • astro check 0 errors, astro build 성공, ESLint, Prettier, node scripts/e2e-scope.mjs --check, node scripts/check-agent-docs-sync.mjs 통과

아직 남은 불안정성

같은 테스트에서 다른 모양의 실패가 로컬(Windows)에서 두 번 있었습니다. 수정 전 오늘 첫 실행의 재시도에서 1번, 수정 후 위 3회 반복 실행에서 1번입니다. 뒤로/앞으로 이동한 뒤 주소는 /tags로 바뀌었는데 astro:page-load가 오지 않아 30초 시간 초과가 났습니다. 리스너 수 문제와는 별개입니다. CI 세 실행에서는 이 모양이 나오지 않았습니다. 진단 코드(전체 새로 고침 여부, 카운터 값)를 넣고 90회를 더 돌렸지만 다시 나오지 않아 원인을 찾지 못했습니다. 이 PR이 고쳤다고 주장하지 않습니다.

범위 밖

같은 날 continue-reading.spec.ts:133(스크롤 복원 후 토스트)도 #219와 예전 Dependabot React 7 PR CI에서 재시도로 통과한 적이 있습니다. 이 PR이 그 테스트도 고친다는 근거는 없어서 주장하지 않습니다.

로컬에서 주의할 점

로컬에서는 reuseExistingServer가 켜져 있습니다. 직접 띄워 둔 dev 서버가 있으면 Playwright가 그 서버를 재사용하므로 도구 막대가 켜진 채로 테스트가 돕니다. CI(CI=true)는 항상 새 서버를 띄웁니다.

도구 막대의 audit 앱은 페이지 전체 lint를 비동기로 끝낸 뒤에야 astro:page-load 리스너를 단다. 느린 CI에서는 listener-leak 스펙이 기준값을 잰 뒤에 이 리스너가 붙어 /projects 왕복 테스트가 6에서 7로 실패하고 재시도로만 통과했다(#217, #218, #219 CI). playwright webServer.env로 E2E_DISABLE_DEV_TOOLBAR=1을 넘기고 astro.config의 devToolbar.enabled가 이를 읽는다.
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@claude

claude Bot commented Oct 11, 2026

Copy link
Copy Markdown

Review

작고 범위가 명확한 PR입니다. 원인 분석(audit 앱이 페이지 전체 lint 뒤에야 astro:page-load 리스너를 다는 문제)과 재현 근거(청크 지연 시 4/4 실패 → 수정 후 6/6 통과)가 탄탄합니다.

Code quality

  • 변경은 astro.config.ts, playwright.config.ts, AGENTS.md 세 곳뿐이고 서로 주석으로 연결돼 있습니다. 기존 코드의 한국어 주석 톤과도 맞습니다.
  • 환경 변수가 정확히 "1"일 때만 꺼지므로 평소 pnpm dev의 동작은 바뀌지 않습니다.
  • 규칙대로 AGENTS.md(단일 정본)만 수정했고 CLAUDE.md는 건드리지 않았습니다.

Potential issues

  • 로컬에서 직접 띄운 dev 서버를 reuseExistingServer가 재사용하면 도구 막대가 켜진 채로 돕니다. PR 본문과 AGENTS.md에 적어 둔 것으로 충분합니다. 다만 로컬에서 같은 플레이키가 보이면 이것부터 확인해야 합니다.
  • 도구 막대를 끄면 E2E가 "도구 막대가 있는 dev" 환경은 더 이상 검증하지 않습니다. 배포 빌드에는 도구 막대가 없으니 문제 없다고 봅니다.
  • 본문에 적은 별개의 간헐 실패(/tags 이동 후 astro:page-load 미도착 타임아웃)는 이 PR로 해결되지 않습니다. 아직 모르는 문제라고 솔직하게 밝혀 둔 점이 좋습니다. 이슈로 따로 남겨 두면 추적하기 좋겠습니다.

Performance: E2E 중 audit의 MutationObserver lint가 사라져 CI CPU 사용이 줄어듭니다. 부수 효과로 이득입니다.

Security: 해당 사항 없음. 환경 변수는 dev 서버 설정에만 쓰이고 배포 산출물에는 영향이 없습니다.

Test coverage: 새 로직이 설정 한 줄이라 별도 테스트는 필요 없어 보입니다. listener-leak.spec.ts 자체가 회귀 검증 역할을 합니다. 선택 사항으로, 도구 막대가 꺼졌는지(astro-dev-toolbar 요소 0개)를 확인하는 짧은 단언을 넣으면 누가 webServer.env를 지워도 바로 잡을 수 있습니다.

LGTM입니다. 위 내용은 모두 비차단 제안입니다.

🤖 Generated with Claude Code

listener-leak 스펙의 리스너 수 비교는 도구 막대가 꺼져 있다는 전제 위에 있다. playwright.config.ts의 webServer.env가 사라지면 이 단언이 먼저 실패한다. 로컬은 직접 띄운 dev 서버를 재사용할 수 있어 CI에서만 확인한다.
@CaesiumY
CaesiumY merged commit b192a86 into main Oct 11, 2026
2 checks passed
@CaesiumY
CaesiumY deleted the fix/listener-leak-projects-flake branch October 11, 2026 15:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant