Skip to content

refactor: 대형 프론트엔드·백엔드 모듈 경계 분리와 ASIO 검증 보강 - #154

Open
lee-sihun wants to merge 246 commits into
mainfrom
refactor/code-quality-modularization
Open

refactor: 대형 프론트엔드·백엔드 모듈 경계 분리와 ASIO 검증 보강#154
lee-sihun wants to merge 246 commits into
mainfrom
refactor/code-quality-modularization

Conversation

@lee-sihun

@lee-sihun lee-sihun commented Aug 31, 2026

Copy link
Copy Markdown
Member

개요

동작과 공개 계약을 유지하면서 대형 프론트엔드·백엔드 파일을 책임 경계별로 분리하고, Grid의 키·통계·그래프·노브 표면을 실제 재사용 가능한 단위로 공용화함. 동시에 하드웨어 없이 검증할 수 있는 ASIO 정책과 오류 계약을 테스트로 고정하고 Windows ASIO CI를 추가함

작업 중 main에 먼저 들어간 2.0.2 변경 33개 커밋도 최종 단계에서 병합했다. 물리 좌표 기반 패널 drag·overlay 복원, 탭 rename/reorder/bar count, pointer focus, gooey·motion 정책을 리팩터링 이전 구조로 되돌리지 않고 분리된 모듈에 반영했다

  • 리팩터링 기준: af1bc19c
  • 최종 main 기준: 4b4d6c22 (2.0.2)
  • 리팩터링 커밋: 243개 + 최종 main 통합·Windows CI 보정 커밋 3개 (총 246개)
  • 변경 규모: 371개 파일
  • 상세 결과와 후속 분류: docs/code-quality-refactoring-plan.md

변경 내용

프론트엔드 책임 분리

프로퍼티 패널

  • PropertiesPanel.tsx를 선택 route, 표시 모델, commit runtime, plugin 설정, rename, layer action으로 분리
  • single/batch 패널을 타입별 섹션으로 나누고 graph/knob/key-like 공통 설정과 commit runtime을 재사용
  • color/image/sound picker의 열림·취소·preview·commit 소유권을 전용 controller/hook으로 이동
  • rename과 layer context action의 focus, selection, async 실패 계약을 characterization test로 고정

Grid와 공용 표면

  • KeyElementFace: 키·통계 placeholder, border, image/error, label, inside counter 표면
  • CounterPreviewBody / CounterPreviewLayer: 키·통계 외부 카운터 body와 layer
  • GraphPanel: Grid와 overlay 그래프 표면
  • KnobFace: 링, 이미지, indicator 표면
  • NativeGridElements: 네이티브 요소 scene 조립과 adapter
  • nativeElementReferenceRegistry: mount/unmount ref 등록·삭제 계약
  • selection drag, resize, paste, clipboard, smart guide, gradient axis를 순수 모델과 세션 hook으로 분리

Graph 데이터 adapter, Knob 회전 상태, Key active 상태, Stat 정수 정규화처럼 의미가 다른 정책은 공통 컴포넌트 조건문으로 합치지 않았다

입력·팝업·에디터 runtime

  • Dropdown, FloatingPopup, NumberInput, ColorPicker, counter animation editor, sound trim의 상태 머신과 UI를 분리
  • pointer로 연 popup/modal은 잔류 focus를 만들지 않고 keyboard 진입과 focus 복원 계약은 유지
  • editorCoordinator의 queue/retry/rebase/projection과 elementOps의 property/group/style/geometry 연산을 분리
  • React Compiler 대상 hook/ref 선언 순서와 use no memo 경계를 유지

백엔드 책임 분리

  • state/store.rs: 22,978줄 → 829줄 façade. persistence/writer/recovery/asset/editor/plugin transaction 분리
  • state/editor_ops.rs: 10,154줄 → 49줄 façade. property/structural/transition 연산과 검증 분리
  • state/migration.rs: 6,053줄 → 275줄. normalization/recovery/assets/tests 분리
  • state/editor.rs: 5,777줄 → 176줄. request/limits/violations/tests 분리
  • state/app_state.rs: 9,314줄 → 1,259줄. window geometry, keyboard, counter, lifecycle, panel/overlay runtime 분리
  • preset load, key sound, audio engine, history, OBS bridge도 I/O·정책·테스트 경계로 분리

store 분리에서는 다음 불변식을 그대로 유지했다

  • orphan 자산은 직접 삭제하지 않고 trash/<세션>/에 30일 격리
  • 손상 복구가 발생한 세션은 asset sweep 생략
  • keys[mode][i]keyPositions[mode][i]의 인덱스 결합 유지
  • writer/transaction의 기존 lock, persist, event 순서 유지
  • editor commit 오류 코드와 frontend allowlist의 대응 유지

최신 main 변경 통합

  • 충돌 13개 파일을 기존 façade와 추출 모듈 양쪽 의미를 보존하도록 수동 통합
  • tabOrder, barCount, custom tab rename/reorder를 migration, preset, history, bootstrap, overlay 메뉴에 함께 반영
  • 저장된 native overlay 좌표의 echo 검증, trust/taint, 사용자 이동 종료·reset 신뢰 회복을 유지
  • panel native drag의 presenting→starting→dragging 상태와 terminal outcome을 유지
  • 최신 좌표 로직이 다시 한 파일에 집중되지 않도록 window_geometry 공통 좌표와 overlay_placement를 분리
  • 2,489줄 panel_drag.rs를 공통 상태 머신·기하, Windows native adapter, 테스트로 순수 이동 분리
  • 현재 Tauri command는 origin/main과 동일한 150개이며 permissions, 생성 schema, API 문서도 origin/main과 일치
  • 최신 main 추가 Rust 함수·테스트 이름 전체 대조에서 누락 0개
  • 머지 직전 origin/main을 다시 확인하고, 이후 추가된 선행 커밋·PR이 있으면 기능을 제외하지 않고 현재 모듈 경계에 먼저 통합하는 것을 머지 조건으로 둠

ASIO 검증 보강

  • ASIO driver catalog와 실제 open 경계를 주입 가능하게 분리
  • driver name, buffer frame, output config, availability, 오류 코드, startup fallback 정책을 하드웨어 독립 테스트로 고정
  • 프론트엔드 출력 설정 계약 테스트 보강
  • PR/수동 실행용 Windows ASIO workflow 추가
  • Windows release build 전에 ASIO focused suite 실행

동작 동일성 검증 방식

  • 리팩터링 전에 preview/commit, rollback, cleanup, close/await/RAF/focus 순서를 characterization test로 고정
  • 공개 반환 객체, hook/ref 선언 순서, event/command 이름, 저장 schema를 전후 대조
  • 대형 이동은 AST/토큰 또는 rustfmt 정규화 결과를 비교
  • panel_drag 최종 분리는 origin/main 원본을 재조립해 core/Windows/tests 세 파일 모두 rustfmt 기준 정확히 동일함을 확인
  • 최신 main과 branch의 Tauri command 이름·개수, permissions/schema/docs 차이를 별도 확인
  • 코드 그래프 재색인 후 Grid/shared/state/ASIO 경계의 fan-in, 복잡도, 변경 blast radius를 재감사

검증

  • npx tsc --noEmit 통과
  • npm run lint 통과, 오류·경고 0
  • npm run format:check 통과
  • 전체 Vitest: 372개 파일, 3,596개 통과, 18개 skip, 실패 0
  • npm run build 통과. 기존 700 kB 초과 chunk 경고만 유지
  • cargo fmt --all -- --check 통과
  • cargo check --all-targets 통과
  • cargo clippy --all-targets -- -D warnings 통과
  • cargo test --all-targets --quiet: 1,044개 통과, 6개 ignored, 실패 0
  • cargo check --all-targets --features asio-backend 통과
  • cargo clippy --all-targets --features asio-backend -- -D warnings 통과
  • ASIO focused suite: 18개 통과, 실패 0
  • GitHub Windows ASIO CI: 포맷, feature 컴파일, Clippy -D warnings, 정책 테스트 통과
  • 최종 merge tree git diff-tree --check 통과

Vitest에는 기존 React act(...), mock DOM prop, CSS parser stderr가 남아 있으나 실패와 분리되어 있고 이번 변경으로 새 lint warning은 없다

리뷰 순서 권장

GitHub의 전체 diff보다 커밋 단위로 보는 편이 의도와 검증 경계를 확인하기 쉽다

  1. docs/code-quality-refactoring-plan.md에서 전체 경계와 보존 불변식 확인
  2. test: 커밋의 characterization contract 확인
  3. 바로 다음 refactor: 커밋에서 동일 동작의 파일 이동·의존성 축소 확인
  4. Grid 공용 표면과 PropertiesPanel single/batch 조립 확인
  5. store/editor/migration/history façade와 transaction 경계 확인
  6. ASIO 정책 주입점, focused tests, Windows workflow 확인
  7. 마지막 merge: 커밋에서 2.0.2 선행 기능과 분리 구조 통합 확인

리뷰 시 주의할 지점

Grid·PropertiesPanel

  • KeyElementFace, GraphPanel, KnobFace가 DOM/CSS만 공유하고 각 요소의 데이터 의미를 섞지 않는지
  • selection/history 반영 중 ref registry가 stale 요소를 가리키지 않는지
  • batch preview/cancel/commit이 single 경로와 다른 기존 semantics를 유지하는지
  • React Compiler가 필요한 파일의 use no memo와 manual memo 경계가 보존됐는지

store·migration·history

  • asset 참조 수집 누락이나 직접 삭제 경로가 생기지 않았는지
  • recovery session에서 sweep을 건너뛰고 인덱스 결합 배열을 제자리 대체하는지
  • tabOrderbarCount가 undo/redo, preset, 손상 복구에서 함께 이동하는지
  • editor/plugin compound transaction이 persist 실패 시 양쪽 모두 rollback되는지

팝업·focus·탭 UI

  • pointer 진입은 focus 복원을 생략하고 keyboard 진입은 초기 focus와 restore를 유지하는지
  • popup drag 후보와 실제 drag를 구분해 일반 click에서는 정상 dismiss되는지
  • tab reorder 응답이 대기 중 들어온 권위 이벤트를 generation guard 없이 덮지 않는지

Windows native 좌표

  • logical/physical/native 좌표와 scale factor를 같은 연산에서 혼용하지 않는지
  • stored native position은 logical echo가 맞을 때만 신뢰하는지
  • panel drag lifecycle 정리에서 terminal event가 누락되지 않는지
  • panel_drag/windows.rs는 순수 이동이지만 macOS 로컬 빌드가 Windows API type-check를 대신하지 못하므로 Windows CI 통과 결과와 실기 동작을 함께 확인

ASIO

  • 테스트 주입점이 production driver catalog/open 경로를 우회하거나 결과를 바꾸지 않는지
  • unsupported build, driver missing, open failure의 오류 구분과 fallback이 유지되는지

알려진 한계와 머지 전 실기 확인

  • Windows 혼합 DPI: 첫 tear-off seed, monitor 경계 통과, dock/snap-back, Escape, 버튼 선해제, panel destroy 확인 필요
  • Windows overlay: 이전 저장값 복원, 모니터 구성 변경, 사용자 이동 후 native trust 회복, 위치 reset 확인 필요
  • 실제 ASIO 장치: driver open, 다른 앱 점유, buffer 변경, 앱 재시작 후 장치 복원 확인 필요
  • OBS/Tauri window lifecycle과 실제 WebView timing은 단위 테스트가 완전히 대체하지 못함
  • GPU resource 수명(WebGLTracksOGL/noteBuffer)과 note timing은 별도 harness가 필요

아래 기존 결함은 동작 동일성을 위해 이번 PR에서 수정하지 않았다. 기대 동작을 먼저 정한 별도 bug-fix가 필요하다

  • PluginElement 비동기 subscription의 unmount 경계와 같은 tick shallow state 경쟁
  • NativeGridElements의 type+index action이 reorder/delete와 경합하는 경우
  • SoundTrimModal, useLayerDnD, 일부 picker/dialog의 직접 unmount cleanup 경계
  • counter animation preview의 Escape/window blur와 복수 press 첫 release 동작

@eun-yeon

Copy link
Copy Markdown
Member

+123,940
-106,571

?

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.

2 participants