- 분야: FE
- 기술 스택: React · TypeScript
문제와 원인
서버 시각 보정 뒤 현재 시각이 시작보다 1ms 이르면 남은 시간은 5,001ms가 된다. 기존 계산은 Math.ceil(5.001)을 적용해 6초를 표시했다. 하한 0만 적용한 식이라 시작 값의 초과를 제한할 수 없었다.
수정 전 코드
카운트다운 표시
남은 초를 올림한 뒤 하한 0만 적용했다.
좌우로 이동해 전체 내용을 확인하세요. 키보드: ←·→, Home·End
Math.max(
0,
Math.ceil(
(Date.parse(String(current.countdownEndsAt)) - (Date.now() + offset)) / 1000,
),
)
수정 후 코드
groupCountdownSeconds
남은 초의 올림을 유지하면서 상한 5를 추가했다. 종료 시각과 서버의 시험 시작 시각은 그대로 사용하고, 날짜 해석 결과가 유한한 값인지 확인해 잘못된 종료 시각은 0으로 표시한다.
좌우로 이동해 전체 내용을 확인하세요. 키보드: ←·→, Home·End
export function groupCountdownSeconds(endsAt: string, now: number) {
const remaining = Date.parse(endsAt) - now;
return Number.isFinite(remaining)
? Math.min(5, Math.max(0, Math.ceil(remaining / 1000)))
: 0;
}
5,001ms는 5초, 4,000ms는 4초, 999ms와 1ms는 1초로 표시하며 0ms와 음수는 0초로 표시한다.
카운트다운 표시
보정된 현재 시각과 종료 시각을 표시 함수에 전달한다.
좌우로 이동해 전체 내용을 확인하세요. 키보드: ←·→, Home·End
groupCountdownSeconds(String(current.countdownEndsAt),Date.now()+offset)
검증 결과
여섯 시각 입력
종료 시각을 시작 시각 + 5,000ms로 고정하고 현재 시각만 바꾼 동일한 여섯 입력으로 수정 전후 함수를 비교했다. 표시 불일치는 1/6개에서 0/6개로 줄었다.
좌우로 이동해 전체 내용을 확인하세요. 키보드: ←·→, Home·End
| 현재 시각 입력 | 기대 표시 | 수정 전 | 수정 후 |
|---|---|---|---|
| 시작 시각 − 1ms | 5초 | 6초 | 5초 |
| 시작 시각 | 5초 | 5초 | 5초 |
| 시작 시각 + 1,000ms | 4초 | 4초 | 4초 |
| 시작 시각 + 4,001ms | 1초 | 1초 | 1초 |
| 시작 시각 + 5,000ms | 0초 | 0초 | 0초 |
| 시작 시각 + 9,000ms | 0초 | 0초 | 0초 |
종료 시각을 시작 시각의 5,000ms 뒤로 둔 같은 여섯 입력을 로컬 Node에서 각 1회 다시 실행했다. 시작 1ms 전의 표시만 6초에서 5초로 바뀌었고 나머지 다섯 입력의 결과는 같았다.