setInterval, setTimeout 차이

이병우·2023년 1월 9일
0

front-end

목록 보기
1/2

프로젝트 중 React hooks, setInterval을 사용해 전자서명 인증을 받는 함수를 구현했다.

해당 함수가 모바일 웹에서 탭 비활성화 상태 시 에러가 나는 경우가 생겼다. 이 문제를 해결하기 위해 자바스크립트 동작 방식과 inactive 상태에서 setInterval이 어떻게 돌아가는지 확인 하였고, setTimeout으로 코드를 수정했다.

간단하게 비교하자면

  • setInterval = 비동기식으로 delay시간마다 해당 함수를 실행 시킴.
  • setTimeout = 비동기식으로 delay 시간 후 한 번 해당 함수 실행 시킴.
    -> 재귀 함수로 사용 시 delay 시간마다 해당 함수를 실행 시킬 수 있다.
    ※ 대신 함수가 다 실행 된 후 5초 뒤에 실행. ※

setInterval은 delay 시간마다 무조건 함수를 실행하기 때문에 함수안에 Promise를 이용하여 조건 처리하는게 의미가 없음. 어차피 다음 실행 될 함수가 지금 실행되고 있는 함수를 안기다려줌.

이게 이번 함수 에러의 원인: 지금 함수 실행 > 네트워크 지연 > 아직 함수가 안끝남 > 다음 함수가 실행 > 큐에 쌓임 > 또 쌓임 > 네트워크 상태가 좋아짐 > 큐에 쌓였던 함수들이 거의 동시에 리턴을 받아서 처리 > 에러

그래서 나는 setTimeout을 사용하여 해당 문제를 해결 했다.

const COMMON_STATUS = Object.freeze({ "INIT": "INIT", "PREPARE": "PREPARE", "COMPLETE": "COMPLETE", "EXPIRED": "EXPIRED", "ERROR": "ERROR" })

export default function DigitalSignature() {

const [commonStatus, setCommonStatus] = useState<string>(COMMON_STATUS.INIT)

useEffect(() => {
  if(commonStatus !== COMMON_STATUS.PREPARE) return undefined
	
  const timeoutId = setTimeout(async function statusCheck() {
  	/** 전자서명 상태 확인 body 생성 */
    const requestBody = makeRequestBodyForStatusCheck()
    /** 전자서명 상태 확인 */
    const commonStatus = await checkDigitalSignatureStatus(requestBody);
    if(!commonStatus) return undefined;
    
    switch (commonStatus) {
    	case COMMON_STATUS.COMPLETE:
         await 성공()
         break;
        case COMMON_STATUS.EXPIRED:
         errorHandling('인증 시간 만료')
         break;
        case COMMON_STATUS.ERROR:
         errorHandling('인증 실패')
         break;
        default: /** default = COMMON_STATUS.PREPARE */
        /** 준비 상태면 재귀로 다시 statusCheck 호출 */
         setTimeout(statusCheck, 5000)
    }
  }, 5000)

  return () => {
    console.log("clear 되니?");
    clearTimeout(timeoutId)
  }
  
}, [ commonStatus ])

  return (
      <button onClick={() => setCommonStatus(COMMON_STATUS.PREPARE)}>TIMEOUT</button>
  )
}

무조건 5초마다 함수를 실행하는게 아니라 함수 실행 > 함수 리턴 > 상태 확인 > 함수실행 > 함수 리턴 ... 식의 순차적으로 실행 시킬 수 있다. 정확히 5초 간격마다 함수가 실행되진 않지만 안정적으로 실행 시킬 수 있다.

+추가 내용
만약의 setInterval을 사용 할 것이다. 라고 했을 때는
Page Visibility API를 사용하여 사용자가 탭에서 멀어졌는지 또는 다시 탭으로 돌아왔는지 알 수 있다. 탭이 멀어졌을 때 타이머를 일시적으로 일시 중지하고 돌아오면 다시 시작.

resource:
https://developer.mozilla.org/ko/docs/Web/API/setTimeout#%EB%AA%85%EC%84%B8
https://developer.chrome.com/blog/background_tabs/

profile
맛있게 개발하는게 목표!

0개의 댓글