You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[config] React 19.3.1 마이그레이션 및 useEffectEvent 도입 - #530
Vite 8 이전 이후 React 18.3.1을 React 19.3.1로 갱신하면서 기존 타이머·청중 공유·투표 동작을 유지함. React 19 타입에서 재현된 ref 초기값·null 호환 오류를 수정하고, 탭 복귀 훅의 최신 콜백 처리만 useEffectEvent로 단순화했음.
의존성과 호환성
React·React DOM은 ^19.3.1, 양쪽 타입은 ^19.3.0, Hooks ESLint 플러그인은 ^7.1.1로 선언하고 같은 버전을 설치했음.
TypeScript 5.7.3·Vite 8.3.4·Storybook 10.6.2와 다른 직접 의존성의 잠금 버전, Query/MSW 제한과 override를 유지했음. lockfile의 다른 변경은 scheduler·Hooks 플러그인의 전이 의존성과 불필요한 prop-types 타입 제거 및 dev 표식 갱신임.
React 19 타입 오류를 먼저 재현한 뒤 LiveShareModal의 복사 타이머 Ref에 undefined 초기값을 주고 TimerPageLogics의 DOM RefObject에 null을 명시했음. 강제 설치·타입 단언으로 우회하지 않았음.
useDocumentVisibility(onVisible, { enabled, throttleMs })의 공개 계약은 유지함. 예를 들어 청중 화면의 복귀 콜백이 렌더마다 바뀌어도 리스너를 재등록하지 않고, 탭이 다시 보이는 시점에 최신 콜백을 호출함. 기존 콜백 Ref와 동기화 effect를 제거하고 effect가 등록한 visibilitychange 핸들러에서 Effect Event를 호출함.
활성 옵션·재실행 제한 시간·마지막 실행 시각 Ref는 유지하며, enabled 또는 throttleMs 변경만 재구독 조건임. Effect Event를 반환하거나 다른 훅·컴포넌트에 전달하지 않음. Hooks 플러그인은 기존 rules-of-hooks·exhaustive-deps 두 규칙만 명시적으로 활성화했고 Compiler·새 폼 처리·화면 전환·다른 훅의 일괄 변환은 포함하지 않음.
회귀 테스트와 문서
최신 콜백·콜백 변경 시 재등록 없음·옵션 변경과 실행 시각 보존을 검증함.
Strict Mode 재실행·재마운트에서 리스너·소켓 구독·timer·Portal 정리를 검증함.
실제 Router·Query Provider로 오류 화면·홈 복구와 Sentry의 렌더 오류 1회 수집·이미 수집된 API 오류의 추가 수집 방지를 검증함.
기존 복사 완료 테스트 한 건은 React 19에서 비동기 화면 반영 전에 단언해 실패했음. findByRole와 비동기 act로 반영을 기다리도록 수정했으며 제품의 표시 시간·동작은 변경하지 않았음.
문서 지도의 React 버전, React UI의 Effect Event 사용 계약과 구조 문서의 참조를 갱신했음. 마이그레이션을 추적하던 임시 문서 future.md는 사용자 요청으로 삭제하고 검증·후속 확인 기록은 이 PR에 보존함.
실제 검증 결과
Windows·Node 24.21.0·npm 11.19.1에서 수행했음. 브라우저 확인은 로컬 Chromium이며 아래 사용자 실제 서버 검증과 구분함.
검증
결과
React 18 기준
엄격한 설치·의존성·546개 테스트·lint·앱/Storybook 빌드·doctor 통과
React 19 엄격한 설치·의존성
최종 manifest·lockfile로 npm ci --engine-strict --strict-peer-deps 및 npm ls --depth=0 통과
React 19 전체 테스트·lint·앱 빌드
61개 파일·555개 테스트, ESLint·Stylelint·타입, 생산 빌드 통과. PR 준비 시 재실행도 통과
Storybook 빌드·doctor·색인
통과. 123개 Story·47개 문서이며 ID 추가·누락 없음
Storybook 개발·정적
양쪽 UpdateModal 12개 play·이미지/스크롤/화면 크기·양방향 args·Actions·Portal 닫기·Docs·청중 모바일 375×812 확인
MSW·청중 시뮬레이터
양쪽 테이블 조회·투표 GET/POST 200·입력/선택/확인/취소 시 보존, 가짜 소켓 SYNC·PLAY·카운트다운·STOP·자유토론·FINISHED 이동 확인
앱 재시작
Storybook 빌드 후 재시작. HTML·진입 모듈·CSS 200, 공개 템플릿의 비회원 타이머·Space·차례 이동·팀 전환·도움말 Esc·영어 홈 확인
실제 개발 서버
사용자가 로그인·저장·사회자/청중 동기화·탭 복귀·재연결·사회자 교체·종료·투표 제출/결과의 시나리오 1~10을 직접 수행하고 모두 정상이라고 보고함
코드 리뷰·문서
새 상·중·하·컨벤션 위반 발견 사항 없음. 코드 형식·문서 링크·분량·diff 검사 통과
단일 투표 Story의 POST 뒤에는 현재 routePattern에서 완료 경로가 ID로 해석돼 잘못된 링크를 표시했음. Story의 API 응답 검증과 앱의 실제 완료 검증을 구분했으며, 앱의 완료·결과 화면은 사용자 시나리오로 확인했음.
관찰 사항과 한계
사용자가 최초 접속에서 Pretendard 미적용 후 새로고침 시 적용된 현상을 보고했음. 이번 폰트 설정 변경은 없고 후속 CDN CSS·woff2 조회는 HTTP 200, font-display는 swap이었음. 발생 당시 Network 기록이 없어 원인과 React 이전 관련성은 미확정이며 수정했다고 주장하지 않음.
투표 모달 취소 후 입력은 보존되지만 포커스는 body로 돌아왔음. useModal 포커스 코드는 변경하지 않았으며 React 18 브라우저 직접 비교·전체 키보드 포커스 복원은 미검증임.
기존 npm 감사 7건(낮음 1·높음 6), ESLint 비권장 버전·설치 스크립트 허용 안내와 큰 묶음 경고·Rolldown 안내는 남아 있음. 최대 앱 JS는 949.85 → 1,028.89 kB, gzip은 302.13 → 324.96 kB였음. 관련 없는 정비·경고 숨김은 하지 않았음.
이번 React 변경의 Linux·원격 CI·미리보기·Safari/Firefox 실제 실행·Chromatic dry-run/게시/시각 비교·Sentry 인증된 sourcemap 업로드는 PR 생성 전에 미실행임.
🗣️ 리뷰 요구사항 (선택)
React·DOM·타입의 버전 정합성과 다른 직접 의존성·제한·override 보존을 확인함.
최신 콜백을 읽는 Effect Event의 호출 위치와 enabled·throttleMs 재구독·마지막 실행 시각 정책이 유지되는지 확인함.
ref 타입 수정과 복사 상태 테스트의 비동기 대기가 실제 호환성 문제만 해결하는지 확인함.
PR 생성 후 Linux CI의 설치·전체 테스트·lint와 미리보기 결과를 확인함. 생성 전 결과를 통과로 기록하지 않음.
일반 PR CI가 수행하지 않는 엄격한 설치·doctor·앱/Storybook 빌드·브라우저 검증은 아래 명령과 동작으로 보완함.
npm ci --engine-strict --strict-peer-deps
npm ls --depth=0
npx --no-install vitest run
npm run lint
npm run build
npm run build-storybook -- --disable-telemetry
npx --no-install storybook doctor
npm run storybook
npx --no-install vite preview --outDir storybook-static --port 6007
npm run dev
Storybook 개발·정적 결과에서 UpdateModal 12개 play·긴 설명 스크롤·체크박스·닫기·양방향 args·Actions·Docs, 청중 모바일 실제 크기와 MSW 테이블·투표·청중 시뮬레이터를 확인함. 고정 viewport는 관리 화면의 미리보기 공간을 충분히 확보하고 iframe의 실제 크기를 확인함. 빌드 후 앱 서버를 재시작해 정상 진입과 의존성 탐색을 확인함.
실제 개발 서버의 사용자 검증은 아래와 같으며 사용자가 1~10 모두 정상 동작했다고 보고했음. 배포된 다른 프런트엔드의 성공과 혼동하지 않도록 이번 로컬 React 19 앱과 개발 API·소켓을 연결해 확인했음. 로그인한 사회자 A, 별도 청중 세션 B, 사회자 교체용 추가 탭 C로 검증했음.
번호
사용자 실행 시나리오
기대 결과와 보고
1
로그인·테스트 테이블 저장·재조회
이름·주제·팀명·순서·시간 유지, 통과함
2
A에서 라이브 공유·링크 복사 후 B 접속
같은 테이블·순서·시간 표시, 통과함
3
재생·정지·Space·다음/이전 순서
B 동기화와 중복 실행·차례 이동 없음, 통과함
4
자유토론의 발언 팀 전환·정지·재개
활성 팀·전체/발언 시간 동기화, 통과함
5
A와 B 각각 다른 탭 뒤에서 15초 대기 후 복귀
현재 시간 보정과 초기화·중복 실행 없음, 통과함
6
A와 B 각각 Network Offline 후 복구
연결·재구독 복구와 최신 상태 반영, 통과함
7
C에서 같은 테이블 공유 후 A에서 다시 공유
이전 사회자 교체 안내와 활성 사회자 전환, 통과함
8
마지막 순서 후 토론 종료
A·B 각각 종료 화면 이동, 통과함
9
투표 생성·이름/팀 선택·취소·재제출
빈 입력 차단·입력 보존·완료 화면·참여자 목록 반영, 통과함
10
투표 종료 후 결과 확인
참여자 수·팀별 결과가 제출 내용과 일치, 통과함
남은 확인 범위임.
Safari·Firefox의 주요 화면·타이머·모달·입력·스크롤과 전체 Tab 이동·닫기 후 포커스 복원을 확인함.
최초 폰트 미적용이 재현되면 새로고침 전에 Pretendard CSS·woff2 요청 실패와 실제 사용 폰트를 확인함.
인증된 환경에서 Sentry sourcemap 생성·업로드·업로드 후 삭제를 확인함. 현재 검증으로 실제 업로드 성공을 주장하지 않음.
필요 시 Linux 엄격한 설치·doctor·Storybook 빌드와 npm run chromatic -- --dry-run --no-interactive --disable-telemetry를 실행함. 실제 Chromatic 게시·시각 비교는 별도 권한 범위에서 수행함.
Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.
Walkthrough
React 18에서 React 19로 의존성을 갱신했습니다. useDocumentVisibility는 useEffectEvent로 최신 콜백을 호출합니다. Strict Mode에서 훅과 포털의 정리 동작을 확인하는 테스트를 추가하고, React 19에 필요한 타입 변경을 반영했습니다.
This PR upgrades React to 19 and simplifies the tab-visibility hook while preserving its public contract. No specific merge-blocking risk was identified in the supplied changes. Remote CI and cross-browser checks should still run as usual before release.
Pre-merge checks: 4 · 1
Failed checks: 1 warning
Check name
Status
Explanation
Resolution
Docstring Coverage
Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 10 files. (4 skipped: …
Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed checks: 4 passed
Check name
Status
Explanation
Description Check
Check skipped - CodeRabbit’s high-level summary is enabled.
Title check
제목은 React 19.3.1 마이그레이션과 useEffectEvent 도입이라는 PR의 주요 변경 사항을 정확하고 간결하게 설명합니다.
Linked Issues check
직접 연결된 활성 이슈 #529의 코딩 요구사항을 충족함. package.json은 React·React DOM을 ^19.3.1, 타입 패키지를 ^19.3.0, eslint-plugin-react-hooks를 ^7.1.1로 갱신함. LiveShareModal의 timer ref와 TimerPageLogics.volumeRef의 Re…
Out of Scope Changes check
변경 범위는 #529의 React 19 마이그레이션, useEffectEvent 도입, 호환성 수정, 회귀 테스트, 관련 문서와 검증 기록에 연결됨. ESLint 설정 변경은 이슈가 요구한 기존 Hooks 규칙 유지와 연결됨. future.md 삭제는 PR 설명상 임시 추적 문서 정리이며 검증 한계와 후속 기록을 PR에 보존함. 타이머·소켓·Port…
Full details: Docstring Coverage
Explanation
Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 10 files. (4 skipped: 4 unsupported.)
Fix all pre-merge checks with AI
✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
Commit to this branch
Create a new PR
🧪 Generate unit tests (beta)
Commit to this branch
Create a new PR
Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🚩 연관 이슈
Closes #529
📝 작업 내용
Vite 8 이전 이후 React 18.3.1을 React 19.3.1로 갱신하면서 기존 타이머·청중 공유·투표 동작을 유지함. React 19 타입에서 재현된 ref 초기값·null 호환 오류를 수정하고, 탭 복귀 훅의 최신 콜백 처리만 useEffectEvent로 단순화했음.
의존성과 호환성
^19.3.1, 양쪽 타입은^19.3.0, Hooks ESLint 플러그인은^7.1.1로 선언하고 같은 버전을 설치했음.탭 복귀 처리
useDocumentVisibility(onVisible, { enabled, throttleMs })의 공개 계약은 유지함. 예를 들어 청중 화면의 복귀 콜백이 렌더마다 바뀌어도 리스너를 재등록하지 않고, 탭이 다시 보이는 시점에 최신 콜백을 호출함. 기존 콜백 Ref와 동기화 effect를 제거하고 effect가 등록한 visibilitychange 핸들러에서 Effect Event를 호출함.활성 옵션·재실행 제한 시간·마지막 실행 시각 Ref는 유지하며, enabled 또는 throttleMs 변경만 재구독 조건임. Effect Event를 반환하거나 다른 훅·컴포넌트에 전달하지 않음. Hooks 플러그인은 기존 rules-of-hooks·exhaustive-deps 두 규칙만 명시적으로 활성화했고 Compiler·새 폼 처리·화면 전환·다른 훅의 일괄 변환은 포함하지 않음.
회귀 테스트와 문서
실제 검증 결과
Windows·Node 24.21.0·npm 11.19.1에서 수행했음. 브라우저 확인은 로컬 Chromium이며 아래 사용자 실제 서버 검증과 구분함.
단일 투표 Story의 POST 뒤에는 현재 routePattern에서 완료 경로가 ID로 해석돼 잘못된 링크를 표시했음. Story의 API 응답 검증과 앱의 실제 완료 검증을 구분했으며, 앱의 완료·결과 화면은 사용자 시나리오로 확인했음.
관찰 사항과 한계
🗣️ 리뷰 요구사항 (선택)
일반 PR CI가 수행하지 않는 엄격한 설치·doctor·앱/Storybook 빌드·브라우저 검증은 아래 명령과 동작으로 보완함.
Storybook 개발·정적 결과에서 UpdateModal 12개 play·긴 설명 스크롤·체크박스·닫기·양방향 args·Actions·Docs, 청중 모바일 실제 크기와 MSW 테이블·투표·청중 시뮬레이터를 확인함. 고정 viewport는 관리 화면의 미리보기 공간을 충분히 확보하고 iframe의 실제 크기를 확인함. 빌드 후 앱 서버를 재시작해 정상 진입과 의존성 탐색을 확인함.
실제 개발 서버의 사용자 검증은 아래와 같으며 사용자가 1~10 모두 정상 동작했다고 보고했음. 배포된 다른 프런트엔드의 성공과 혼동하지 않도록 이번 로컬 React 19 앱과 개발 API·소켓을 연결해 확인했음. 로그인한 사회자 A, 별도 청중 세션 B, 사회자 교체용 추가 탭 C로 검증했음.
남은 확인 범위임.
Summary by CodeRabbit