5초 카운트다운에 6이 표시되는 오류 수정

이 글의 목차 8개 항목
  • 분야: FE
  • 기술 스택: React · TypeScript

문제와 원인

서버 시각 보정 뒤 현재 시각이 시작보다 1ms 이르면 남은 시간은 5,001ms가 된다. 기존 계산은 Math.ceil(5.001)을 적용해 6초를 표시했다. 하한 0만 적용한 식이라 시작 값의 초과를 제한할 수 없었다.

수정 전 코드

카운트다운 표시

남은 초를 올림한 뒤 하한 0만 적용했다.

Math.max(
  0,
  Math.ceil(
    (Date.parse(String(current.countdownEndsAt)) - (Date.now() + offset)) / 1000,
  ),
)

수정 후 코드

groupCountdownSeconds

남은 초의 올림을 유지하면서 상한 5를 추가했다. 종료 시각과 서버의 시험 시작 시각은 그대로 사용하고, 날짜 해석 결과가 유한한 값인지 확인해 잘못된 종료 시각은 0으로 표시한다.

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초로 표시한다.

카운트다운 표시

보정된 현재 시각과 종료 시각을 표시 함수에 전달한다.

groupCountdownSeconds(String(current.countdownEndsAt),Date.now()+offset)

검증 결과

여섯 시각 입력

종료 시각을 시작 시각 + 5,000ms로 고정하고 현재 시각만 바꾼 동일한 여섯 입력으로 수정 전후 함수를 비교했다. 표시 불일치는 1/6개에서 0/6개로 줄었다.

현재 시각 입력기대 표시수정 전수정 후
시작 시각 − 1ms5초6초5초
시작 시각5초5초5초
시작 시각 + 1,000ms4초4초4초
시작 시각 + 4,001ms1초1초1초
시작 시각 + 5,000ms0초0초0초
시작 시각 + 9,000ms0초0초0초

종료 시각을 시작 시각의 5,000ms 뒤로 둔 같은 여섯 입력을 로컬 Node에서 각 1회 다시 실행했다. 시작 1ms 전의 표시만 6초에서 5초로 바뀌었고 나머지 다섯 입력의 결과는 같았다.

시작 1ms 전 6초에서 5초로 변경된 카운트다운원본 보기 (새 창)

시작 1ms 전 6초에서 5초로 변경된 카운트다운

100%원본 보기 (새 창)

확대한 이미지는 상하좌우로 이동할 수 있습니다. 키보드는 이미지 영역에 초점을 두고 방향키를 사용하세요. Esc로 닫습니다.