P1-R1 Native 재검증
결과: 기존 native matrix·lifecycle·OS 복귀 시나리오 PASS. 터치 영역은 코드 소유권·geometry 수준 복원 확인이며 실제 좌표 탭은 미검증이다.
최소 수정과 출처
- 제품 수정은
MyPageView.swift의UpdateBannerView에 한정했다. 변경 전후의 배너 밖 prefix/suffix가 동일함을 검사했다. .onChange(of: scenePhase)가 전달한 새 phase를restartRollTimer(scenePhase:reduceMotion:)에 직접 전달한다. 이전 closure의 캡처된 환경 값을 읽던 경로를 제거했다.- Reduce Motion 콜백의 새 값도 같은 함수의 명시적 인자로 전달한다. Timer의 animation 선택은 이 인자를 사용한다. onAppear·items 변경을 포함한 재시작 호출 4곳을 모두 갱신했다.
- 좌우 24pt·상하 6pt padding을 Button label 내부의
contentShape(Rectangle())앞으로 옮겼다. 값·색상·제목·화살표는 변경하지 않았다. 새 타입·DI·타이머 아키텍처는 추가하지 않았다. - 제품
MyPageView.swiftSHA-256:7f8ac15573ab4c9fe01508431297e40d2e95a22ad37585859f03224475749d02. 추출 배너 SHA-256:69de63603118bafa25a2c8d711489d9e4389d3cd308937f86ad23c652702dc46.
provenance.json에 실제 제품 입력 해시, 배너 밖 동일성, RED 하네스 동일성, 대체한 의존성을 기록했다. 기존 ../native/ 전체 파일의 해시를 비교해 RED 증거가 변경되지 않았음을 확인했다. 부모 plan/review 문서는 수정하지 않았다.
실행과 증거
기존 RED 하네스를 byte-for-byte 그대로 사용했다. 새 시나리오·타이머 복제·주기 단축·웹 대체물을 만들지 않았다. 실제 현재 배너와 helper/DTO/폰트/spacing/color를 재추출·컴파일했다. 전체 앱이 아닌 native UIKit UIHostingController 하네스다.
환경은 iPhone SE3, iOS18.3 런타임, 375pt 폭, Xcode26/SDK26, Intel x86_64다. 모든 36 PNG는 새 배너 추출 이후에 실제 native surface에서 생성된 750×1334 이미지다. matrix/ 27장, lifecycle/ 6장은 native window drawHierarchy; OS 3장은 simctl io screenshot이다.
| 검사 | 관측 결과·근거 |
|---|---|
| 0/1 | matrix/zero.png 미표시, one-initial.png와 6초 이후 one-after-6s.png 동일 |
| 2/3 순서·wrap | two-first/second/wrap-first.png 첫째→둘째→첫째, three-first/second/third/wrap-first.png 첫째→둘째→셋째→첫째. 실제 5초 Timer 유지 |
| 긴 한글·arrow-only | long-korean-dark.png, long-korean-light.png: 제목 ellipsis·화살표 비겹침. 두 PNG 모두 RED와 byte-for-byte 동일하여 정적 geometry/style 변화 없음 |
| inactive/active | inactive-start.png→inactive-after-6s.png 둘째 유지, reactivated-before-5s.png 둘째 유지, reactivated-next.png 셋째 진행. 기존 버그에 의존하던 기대값 C/C를 올바른 B/C로 변경했으며 하네스 자체는 변경하지 않음 |
| 별도 lifecycle | probe의 실제 inactive 확인 후 둘째가 6.007초간 동일. active 전달 4.394초 후에도 둘째, 7.203초 후 셋째. 기존 RED의 중지·재개 실패 해소 |
| OS background/복귀 | task-owned Settings 앱을 열어 willResignActive를 발생시키고 같은 앱 PID로 복귀해 didBecomeActive 확인. os-resume-initial.png 첫째→os-resume-after-6s.png 둘째 진행. 후자는 전환 중 프레임이며 매끄러움 측정은 아님 |
| unmount/remount·축소 | 6초 이상 배너 없음, remount 첫째→5초 전 첫째→이후 둘째. 3→1에서 첫째 초기화 및 고정, 0에서 숨김 |
| payload | 기존 ActionCheck.swift를 현재 실제 DTO/helper로 다시 컴파일해 실행. title·전체 HTML content·date 동일성 10건과 빈 상태 검사 PASS. 상태/추출 콜백 검사이며 GUI 탭 아님 |
verification.json은 19개 native PNG 동일/변경 비교, 36개 PNG 해시·signature·크기·신선도, 올바른 생명주기 기대값을 기록한다. PNG가 다르다는 사실만으로 제목을 판정하지 않았으며 위 제목·순서는 실제 화면을 읽어 확인했다. 정밀 5.000초 주기·애니메이션 성능·장시간 중복 타이머 부재를 보증하지 않는다.
터치 영역과 한계
소스상 label은 전체 375pt 폭, 높이 36pt(내용 24 + 위아래 6)이며 좌우·상하 padding을 포함한 뒤 contentShape가 적용된다. 기존 RED의 내부 내용만 Button이던 327×24pt 영역에서 기존 배너 전체에 해당하는 label 소유권을 복원했다. 제목 폭 295pt와 화살표 위치·배너 크기는 정적 native PNG 동일성으로 확인했다. 44pt 높이로 확장하는 새 디자인 변경은 하지 않았다.
물리/좌표 탭·padding 가장자리 hit-testing은 미검증이다. 기존 하네스의 UIKit 접근성 traversal은 여전히 actionable node를 반환하지 않으며 accessibilityActivateResult=false, captureDelta=0이다. 사용 가능한 좌표 탭 도구가 없어 추가 도구 탐색·설치 없이 중단했다. 실제 detail 화면 이동을 검증했다고 주장하지 않는다.
Reduce Motion 런타임 설정 변경 경로는 미검증이며 새 값 전달·Timer animation 선택의 코드 경로만 확인했다. 전체 앱·로그인·서버·실기기·iOS16.6 런타임·Dynamic Type·다른 화면 폭·VoiceOver 포커스도 이 하네스 범위 밖이다.
명령·진단·정리
bash work/tests/check-my-page-notices.sh: exit 0, 실제 API/Repository/VM/DTO/roller 관련 PASS 4줄. focused-check.log.xcrun swiftc -frontend -parse SodaLive/Sources/MyPage/MyPageView.swift: exit 0. LSP 진단 도구는 제공되지 않아 실행하지 못했다.xcrun --sdk iphonesimulator swiftc ... -target x86_64-apple-ios16.6-simulator ...: 현재 배너 native 컴파일 exit 0. 전체 인자·launch·OS screenshot 명령은 commands.json.- 새 simulator 최초 data migration이 3분 이상 걸려 준비 명령 제한시간에 도달했다. 컴파일은 성공한 상태였고 부팅 완료 후 같은 산출물을
xcrun simctl install CC9EA0CF-1CCF-4EDD-8FDB-80DFC0F54E4E "$QA_ROOT/NoticeNativeQA.app"로 설치해 exit 0 확인했다. matrix·lifecycle은 각각 한 번만 실행했다. $QA_ROOT=/var/folders/yh/8xsbvpsj5wg2qnxzxdp11_gm0000gn/T/opencode/my-notice-native-fix.SxPOl6아래로TMPDIR,NODE_COMPILE_CACHE,BUN_RUNTIME_TRANSPILER_CACHE_PATH를 export했다. cleanup.json은 소유 앱/Settings 종료, 전용 device 삭제, TMP root 삭제 및 제품/RED 해시 최종 확인 영수증이다.
전체 앱 빌드·전체 회귀·최종 리뷰는 부모 작업에 남겼다. 서버 호출·커밋·공유 캐시 정리는 하지 않았다.