Skip to content

Commit 1de9611

Browse files
authored
Merge pull request #240 from boostcampwm-2024/fix/useTimer-return-progress-time
Fix/use timer return progress time
2 parents 5830572 + 073105f commit 1de9611

File tree

2 files changed

+46
-64
lines changed

2 files changed

+46
-64
lines changed

apps/frontend/src/blocks/QuizZone/QuizInProgress.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@ const QuizInProgress = ({ currentQuiz, submitAnswer }: QuizInProgressProps) => {
1919
const MAX_TEXT_LENGTH = 100;
2020
const MIN_TEXT_LENGTH = 1;
2121

22-
const playTime = currentQuiz.playTime;
22+
const now = new Date().getTime();
23+
const { playTime, deadlineTime } = currentQuiz;
2324

2425
const { start, time } = useTimer({
25-
initialTime: playTime / 1000,
26+
initialTime: (deadlineTime - now) / 1000,
2627
onComplete: () => {},
2728
});
2829

apps/frontend/src/hook/useTimer.ts

Lines changed: 43 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import { useCallback, useEffect, useRef, useState } from 'react';
2-
import TimerWorker from '@/workers/timer.worker?worker';
1+
import { useState, useEffect, useCallback } from 'react';
32

43
interface TimerConfig {
54
initialTime: number;
@@ -8,85 +7,67 @@ interface TimerConfig {
87
}
98

109
/**
11-
* Web Worker를 활용한 정확한 카운트다운 타이머 커스텀 훅
10+
* 카운트다운 타이머를 관리하는 커스텀 훅입니다.
11+
*
12+
* @description
13+
* 이 훅은 시작 제어 기능을 갖춘 카운트다운 타이머 기능을 제공합니다.
14+
* 초기 시간과 타이머 완료 시 실행될 선택적 콜백을 받습니다.
15+
*
16+
* @example
17+
* ```typescript
18+
* const { time, start } = useTimer({
19+
* initialTime: 60,
20+
* onComplete: () => console.log('타이머 완료!'),
21+
* });
22+
*
23+
* // 타이머 시작
24+
* start();
25+
* ```
1226
*
1327
* @param {TimerConfig} config - 타이머 설정 객체
14-
* @returns {object} 타이머 상태와 컨트롤 함수들
28+
* @param {number} config.initialTime - 카운트다운 초기 시간(초 단위)
29+
* @param {() => void} [config.onComplete] - 타이머 완료 시 실행될 선택적 콜백
30+
*
31+
* @returns {object} 현재 시간과 시작 함수를 포함하는 객체
32+
* @returns {number} returns.time - 카운트다운의 현재 시간
33+
* @returns {() => void} returns.start - 타이머를 시작하는 함수
1534
*/
35+
1636
export const useTimer = ({ initialTime, onComplete }: TimerConfig) => {
1737
const [time, setTime] = useState(initialTime);
1838
const [isRunning, setIsRunning] = useState(false);
19-
const workerRef = useRef<Worker | null>(null);
2039

2140
useEffect(() => {
22-
// Worker가 이미 존재하면 종료
23-
if (workerRef.current) {
24-
workerRef.current.terminate();
25-
}
26-
27-
// 새 Worker 생성
28-
workerRef.current = new TimerWorker();
41+
let timer: NodeJS.Timeout | null = null;
2942

30-
// Worker 메시지 핸들러
31-
workerRef.current.onmessage = (event) => {
32-
const { type, payload } = event.data;
33-
// console.log('Received from worker:', type, payload); // 디버깅용
34-
35-
switch (type) {
36-
case 'TICK':
37-
setTime(payload.time);
38-
break;
39-
case 'COMPLETE':
40-
setTime(0);
41-
setIsRunning(false);
42-
onComplete?.();
43-
break;
44-
}
45-
};
43+
if (isRunning) {
44+
timer = setInterval(() => {
45+
setTime((prev) => {
46+
const nextTime = prev - 0.1;
47+
if (nextTime <= 0) {
48+
setIsRunning(false);
49+
onComplete?.();
50+
return 0;
51+
}
52+
return nextTime;
53+
});
54+
}, 100);
55+
}
4656

47-
// Clean up
4857
return () => {
49-
workerRef.current?.terminate();
58+
if (timer) {
59+
clearInterval(timer);
60+
}
5061
};
51-
}, []);
62+
}, [isRunning, onComplete]);
5263

53-
// 타이머 시작
5464
const start = useCallback(() => {
55-
if (isRunning || !workerRef.current) return;
56-
57-
workerRef.current.postMessage({
58-
type: 'START',
59-
payload: {
60-
duration: initialTime,
61-
serverTime: Date.now(),
62-
},
63-
});
64-
65+
if (isRunning) return;
6566
setIsRunning(true);
66-
}, [isRunning, initialTime]);
67-
68-
// 타이머 정지
69-
const stop = useCallback(() => {
70-
if (!isRunning || !workerRef.current) return;
71-
72-
workerRef.current.postMessage({ type: 'STOP' });
73-
setIsRunning(false);
7467
}, [isRunning]);
7568

76-
// 타이머 리셋
77-
const reset = useCallback(() => {
78-
if (!workerRef.current) return;
79-
80-
workerRef.current.postMessage({ type: 'RESET' });
81-
setTime(initialTime);
82-
setIsRunning(false);
83-
}, [initialTime]);
84-
8569
return {
8670
time,
87-
isRunning,
8871
start,
89-
stop,
90-
reset,
9172
};
9273
};

0 commit comments

Comments
 (0)