스톱워치&타이머 feat.setInterval, setTimeout

大 炫 ·2021년 5월 6일
2

react-native

목록 보기
1/1

별안간 반복된 학습에 조금 지쳐,,
유흥(?)으로 react-native를 찍먹하는 과정에...

스톱워치와 타이머를 구현하는 과정 중
알게된 것들과 문제에 직면했을때 해결과정까지 남기려고한다.

같은 코드지만 다른 환경에서 다른 결과

각각 react와 react-native로 완벽하게 같은 코드를 작성했다.

그렇다면 time과 date는 서로 어떤 setInterval을 가지고있을지 살펴보자.

timeStarted.current = setInterval(() => setTime(v => ++v), 10);

time의 방식은 그저 10ms의 delay마다 state를 1씩 업데이트 하는것

const startedTime = Date.now();
dateStarted.current = setInterval(
	() =>  setDate(Date.now() - startedTime), 10, 
);

date의 방식은 쉽게말해서

(setInterval을 통해 업데이트되는 시간) - (버튼을 눌렀을때 시간)

을 통해 흐르는 시간의 시간차를 이용한 기록인 셈이다.
(Date.now()는 new Date()객체에 getTime()과 같은 결과값)

물론 이 방식은 내가 떠올린 것이 아니고 time방식을 React-native에서 적용했을 당시 상당히 당황해서,, 구글링을 통해 무려 6년 6개월 전의 stackoverflow답변을 통해 진행할 수 있었다.

같은 delay의 setInterval을 통한 setState인데 왜 다른 환경에서 이렇게 심한 차이를 보이는걸까 ?

setTimeout과 setInterval .. (ko.javascript)
위의 내용을 읽어보면

중첩 setTimeout을 이용하는 방법은 지연 간격을 보장하지만 setInterval은 이를 보장하지 않습니다.

라는 문구와 함께 setInerval의 스케줄링에 대해 설명하는데

delay를 100ms로 설정한 setInterval은 콜백함수의 실행시간을 고려하지 않는 모습을 보인다.

무슨 말이냐 하면 !!
setInerval은 그림과같이 콜백함수가 종료한 시점으로부터 남은 delay를 통해 interval을 가지게 되는데

만약 ! func(1) 이라는 함수가 만약 100ms보다 오래걸리는 함수라고 가정해보자.

그렇다면 함수종료시점인 100ms가 지난 delay동안
싱글스레드의 javascript가 함수실행중에 알아서 100ms지점마다 함수를 다시 실행시킬까 ?
당연하게도 그렇지 못하기에 맨위와같이 gif이미지처럼 10초동안 두배가량 차이가 벌어지는 모습을 확인할 수 있는것이다.

이때문에 Date.now()의 방식을 쓰며 마치 1ms의 정밀도를 가지는 스톱워치처럼 보이는 방식을 쓰게됬다.
'마치 1ms 정밀도를 가지는' 이라는 표현은 delay가 10이지만 Date.now()가 반환하는 단위는 1ms의 단위를 가지고있기 때문에

위처럼 마치 1ms 정밀도를 가진것 처럼 보이게 되는것이다 !

그 외 참고하면 좋은
React hooks의 커다란 빙산
번역 / 리액트 훅스 컴포넌트에서 setInterval 사용 시의 문제점

profile
대현

0개의 댓글