Parent Story
Task 개요
타이머 로직을 독립적인 훅으로 분리하여 재사용성을 높이고,
서버-클라이언트 시간 동기화 로직을 구현합니다.
생성 파일
src/domains/catchmind/hooks/useTimer.js (신규)
구현 내용
```javascript
import { useState, useEffect } from 'react';
/**
-
서버 시간 동기화 기반 타이머 훅
-
@param {number} roundStartTime - 라운드 시작 시간 (ms)
-
@param {number} roundDuration - 라운드 시간 (초)
-
@param {number} serverTime - 서버 현재 시간 (ms, 선택)
-
@returns {number} 남은 시간 (초)
*/
export function useTimer(roundStartTime, roundDuration, serverTime) {
const [remainingTime, setRemainingTime] = useState(roundDuration);
useEffect(() => {
if (!roundStartTime || !roundDuration) {
setRemainingTime(roundDuration || 0);
return;
}
// 서버-클라이언트 시간 차이 계산
const timeOffset = serverTime ? (Date.now() - serverTime) : 0;
const updateTimer = () => {
const adjustedNow = Date.now() - timeOffset;
const elapsed = Math.floor((adjustedNow - roundStartTime) / 1000);
const remaining = Math.max(0, roundDuration - elapsed);
setRemainingTime(remaining);
return remaining;
};
// 초기값 설정
updateTimer();
// 100ms 간격으로 업데이트 (부드러운 UI)
const interval = setInterval(() => {
const remaining = updateTimer();
if (remaining <= 0) {
clearInterval(interval);
}
}, 100);
return () => clearInterval(interval);
}, [roundStartTime, roundDuration, serverTime]);
return remainingTime;
}
export default useTimer;
```
사용 예시
```javascript
// GameModePanel.jsx
const remainingTime = useTimer(
gameState?.roundStartTime,
gameState?.roundDuration || 60,
gameState?.serverTime
);
// Timer 표시
{remainingTime}초
```
Acceptance Criteria
테스트 시나리오
- roundStartTime + 60초 duration → 60초부터 카운트다운
- serverTime 차이 2초 → 보정된 타이머 표시
- roundStartTime 변경 → 타이머 리셋
- 컴포넌트 언마운트 → interval 정리
예상 작업량
Parent Story
Task 개요
타이머 로직을 독립적인 훅으로 분리하여 재사용성을 높이고,
서버-클라이언트 시간 동기화 로직을 구현합니다.
생성 파일
src/domains/catchmind/hooks/useTimer.js(신규)구현 내용
```javascript
import { useState, useEffect } from 'react';
/**
서버 시간 동기화 기반 타이머 훅
@param {number} roundStartTime - 라운드 시작 시간 (ms)
@param {number} roundDuration - 라운드 시간 (초)
@param {number} serverTime - 서버 현재 시간 (ms, 선택)
@returns {number} 남은 시간 (초)
*/
export function useTimer(roundStartTime, roundDuration, serverTime) {
const [remainingTime, setRemainingTime] = useState(roundDuration);
useEffect(() => {
if (!roundStartTime || !roundDuration) {
setRemainingTime(roundDuration || 0);
return;
}
}, [roundStartTime, roundDuration, serverTime]);
return remainingTime;
}
export default useTimer;
```
사용 예시
```javascript
// GameModePanel.jsx
const remainingTime = useTimer(
gameState?.roundStartTime,
gameState?.roundDuration || 60,
gameState?.serverTime
);
// Timer 표시
{remainingTime}초
```
Acceptance Criteria
테스트 시나리오
예상 작업량