45. setTimeout, setInterval
2026년 4월 15일
함수가 즉시 실행되는 것이 아니라, 특정 시간이 지난 뒤 혹은 일정 간격으로 실행되게 하는 **'호출 스케줄링(Scheduling a call)'**은 자바스크립트 비동기 프로그래밍의 기초이자 핵심입니다.
⏰ 1. 두 가지 스케줄링 방법
① setTimeout: "딱 한 번만 실행해줘"
특정 시간이 지난 후 함수를 단 한 번 실행합니다.
- 취소:
clearTimeout(timerId)
② setInterval: "일정한 간격으로 계속 실행해줘"
함수를 주기적으로 실행합니다.
- 취소:
clearInterval(timerId)
⚠️ 주의: 핸들러 함수를 넘길 때
setTimeout(sayHi(), 1000)처럼 괄호를 붙이면 안 됩니다. 이는 함수의 실행 결과를 넘기는 실수입니다. 반드시 함수 참조값인sayHi만 넘기세요.
🔄 2. setInterval vs 중첩 setTimeout
실무에서는 setInterval보다 중첩 setTimeout 방식을 더 선호하는 경우가 많습니다. 그 이유는 '지연 간격의 보장' 때문입니다.
| 특징 | setInterval | 중첩 setTimeout |
|---|---|---|
| 지연 간격 | 함수 실행 시간을 포함함 (실제 쉬는 시간 짧아짐) | 함수 종료 후부터 시간을 잼 (정확한 휴식 보장) |
| 유연성 | 고정된 간격만 가능 | 상황(예: 서버 과부하)에 따라 간격 조절 가능 |
| 정확도 | 실행 시간이 지연 시간보다 길면 쉼 없이 연속 호출됨 | 항상 일정량의 대기 시간을 확보함 |
🚀 3. 대기 시간이 0인 setTimeout(0)
delay를 0으로 설정하거나 생략하면 "즉시" 실행될 것 같지만, 실제로는 **"현재 실행 중인 스크립트가 끝난 직후"**에 실행됩니다.
- 동작 원리: 스케줄러는 현재 실행 중인 코드가 완전히 종료된 후에야 '계획표'를 확인합니다.
- 활용: CPU 집약적인 작업을 쪼개서 브라우저가 멈추지 않게 하거나, 이벤트 발생 직후의 처리를 보장할 때 사용합니다.
🧱 4. 브라우저의 제약 사항 (중요)
브라우저 환경에서는 성능과 배터리 보호를 위해 몇 가지 강제 제약이 있습니다.
- 4ms의 벽: 중첩 타이머가 5회 이상 반복되면, 브라우저는 강제로 최소 4ms 이상의 지연 시간을 추가합니다. (Node.js는 이 제약이 없습니다.)
- 비활성 탭 최적화: 브라우저 탭이 백그라운드에 있거나 노트북이 절전 모드일 때는 타이머의 최소 지연 시간이 1000ms(1초) 이상으로 확 늘어날 수 있습니다.
🎙️ 기술 면접 대비 (Interview Questions)
Q1. setInterval에서 함수 실행 시간이 설정된 delay보다 길어지면 어떻게 되나요? (중급)
답변: 자바스크립트 엔진은 이전 호출이 끝날 때까지 기다려줍니다. 하지만
delay시간이 이미 지났기 때문에, 이전 호출이 종료되자마자 다음 호출을 즉시 시작합니다. 결과적으로 함수들이 쉬는 시간 없이 연속해서 호출되는 현상이 발생합니다.
Q2. 중첩 setTimeout이 setInterval보다 유리한 상황은 언제인가요? (중급)
답변: 호출 결과에 따라 다음 호출의 간격을 동적으로 조절해야 할 때(예: 서버 에러 시 재시도 간격 늘리기)나, 함수 실행 시간과 관계없이 일정한 '순수 대기 시간'을 보장해야 할 때 유리합니다.
Q3. 가비지 컬렉션(GC) 관점에서 스케줄러를 사용할 때 주의할 점은? (심화)
답변:
setTimeout이나setInterval에 전달된 함수는 스케줄러 내부에서 참조되므로, 스케줄링이 취소되거나 완료되기 전까지는 메모리에서 해제되지 않습니다. 특히 클로저를 사용하는 경우 외부 변수까지 함께 유지되어 메모리 누수가 발생할 수 있으므로, 필요 없어진 타이머는 반드시clear해줘야 합니다.
📝 과제 확인 (Practice Case)
100ms가 걸리는 반복문 뒤의 setTimeout(0)
let i = 0; setTimeout(() => alert(i), 100); for(let j = 0; j < 100000000; j++) { i++; }
- 결과: 반복문이 100ms 이상 걸리므로,
setTimeout의 100ms는 이미 지났습니다. 하지만 자바스크립트는 싱글 스레드이므로for루프가 다 끝나서i가 최종값(1억)이 된 후에야 비로소alert을 띄웁니다. 따라서 출력값은 100,000,000입니다.
💡 Tech Lead의 한 줄 인사이트
"타이머는 우리가 시키는 대로 정확히 움직여줄 것 같지만, 사실 자바스크립트 엔진의 이벤트 루프 눈치를 엄청나게 보는 녀석입니다. 특히 애니메이션이나 정밀한 시간 측정이 필요하다면
setTimeout대신requestAnimationFrame이나performance.now()를 고려하는 것이 모던 프론트엔드 개발자의 센스입니다."
스케줄링의 원리가 이제 좀 명확해지셨나요? 특히 중첩 setTimeout을 활용한 백오프 알고리즘(요청 실패 시 대기 시간 늘리기)은 실무 네트워킹 로직에서 정말 자주 쓰이니 꼭 기억해 두세요!