웹사이트에서 특정 동작을 즉시 수행하는 것이 아니라 몇 초 후에 실행해야 하는 경우가 있을 겁니다. 이를 위해 자바스크립트는 `setTimeout` 이라는 기본적인 도구를 제공합니다 . `setTimeout`은 타이머처럼 작동하여, 설정된 시간이 0이 되면 특정 동작을 실행합니다. 언뜻 보기에는 간단해 보이지만, 프로그래밍 시 실수를 방지하기 위해 알아두면 유용한 몇 가지 특징과 기술적인 세부 사항이 있습니다.
브라우저에서 자주 접하게 되는 이 메서드는 자바스크립트 언어 자체의 핵심 기능이 아니라 런타임 환경 에서 제공되는 기능이라는 점을 명확히 해야 합니다 . 즉, 크롬이나 파이어폭스에서 사용하는 이 메서드는 Node.js에서도 사용되지만, 반환 값에는 약간의 차이가 있습니다. 이제 기본부터 애플리케이션을 원활하게 실행하는 데 도움이 되는 고급 기술까지, 이 메서드의 작동 방식을 자세히 살펴보겠습니다.
setTimeout은 정확히 무엇이며 어떻게 사용되나요?

간단히 말해, 이 전역 메서드를 사용하면 지정된 시간이 경과한 후 코드 조각이나 함수의 실행을 예약할 수 있습니다 . 타이머가 만료되고 함수가 실행되면 프로세스가 종료되며 자동으로 반복되지 않습니다. 기본 구문은 수행할 작업과 대기 시간을 지정해야 하며, 대기 시간은 항상 밀리 초 단위 로 표현해야 합니다 (1000ms는 1초와 같습니다).
시작하려면 첫 번째 인수로 함수를 전달할 수 있습니다. 하지만 과거의 이유로 코드가 포함된 문자열을 전달하는 것도 가능했지만 , 오늘날에는 이는 좋지 않은 관행으로 여겨지며, 코드를 깔끔하고 안전하게 유지하기 위해 화살표 함수 나 명명된 함수에 대한 참조를 사용하는 것이 훨씬 좋습니다.
실행상의 매개변수 및 유연성

타이머를 설정할 때 두 번째 매개변수는 지연 시간 입니다 . 아무것도 지정하지 않으면 기본값은 0입니다. 그런데 여기서 흥미로운 점은 함수가 외부 데이터를 필요로 하는 경우 어떻게 처리해야 할까요? 이를 처리하는 주요 방법은 두 가지입니다. 첫 번째는 원래 호출을 래핑하는 익명 함수를 사용하는 것으로, 원하는 인수를 자유롭게 전달할 수 있습니다. 두 번째이자 더 세련된 방법은 `setTimeout` 함수의 세 번째 매개변수부터 추가 인수를 전달하는 것입니다 . 이 인수들은 콜백 함수에 직접 매핑됩니다.
clearTimeout을 사용한 취소 관리

때때로 예상치 못한 상황이 발생하여 아직 실행되지 않은 예약된 작업을 취소해야 할 때가 있습니다. 이를 위해서는 `setTimeout` 함수가 고유 식별자 (`timerId`)를 반환한다는 사실을 알아야 합니다. 브라우저에서는 이 ID가 일반적으로 숫자이지만, Node.js에서는 더 복잡한 객체입니다. 이 값을 변수에 저장해 두면 ` clearTimeout(timerId)` 함수를 호출하여 작업을 취소하고 코드 실행을 막아 시스템 리소스를 절약할 수 있습니다.
비교: setTimeout vs setInterval

이 두 가지 방법을 혼동하는 경우가 매우 흔합니다. `setTimeout`은 함수를 한 번만 실행하는 반면, `setInterval`은 정의된 간격이 경과할 때마다 함수를 반복적으로 실행합니다. 하지만 고급 기술이 하나 있는데, 바로 중첩된 `setTimeout`을 사용하는 것입니다 . 이는 현재 함수의 실행이 끝나는 시점에 새로운 `setTimeout`을 호출하는 방식입니다.
이 기법은 `setInterval`보다 훨씬 유연합니다. 왜냐하면 한 작업이 끝나고 다음 작업이 시작될 때 실제적이고 일정한 지연 시간을 보장하기 때문 입니다. `setInterval`을 사용하면 함수 실행 시간이 간격 시간보다 길어질 경우 호출이 누적되거나 일시 중지 없이 실행될 수 있습니다. 반면 중첩 구조를 사용하면 시간을 동적으로 조정할 수 있습니다. 이는 예를 들어 과부하가 걸린 서버에 요청을 보내고 대기 간격을 늘려야 하는 경우에 매우 중요합니다.
지연이 0인 흥미로운 사례와 그 한계
`setTimeout(func, 0)`을 사용하면 함수가 즉시 실행될 것 같지만, 실제로는 그렇지 않습니다. 스케줄러는 현재 스크립트가 완전히 완료된 후에 가능한 한 빨리 실행되도록 작업을 대기열에 추가합니다 . 즉, "지금 하고 있는 일을 마무리하고, 가능한 한 빨리 이 작업을 실행하세요"라고 말하는 것과 같습니다.
또한, 브라우저는 중첩 타이머가 5회 연속 실행된 후에는 최소 4ms의 지연 시간을 적용한다는 점에 유의해야 합니다 . 이는 이전 버전에서 브라우저 충돌을 방지하기 위해 유지된 기능입니다. 하지만 이 제한은 정확하지 않을 수 있습니다. CPU에 과부하가 걸리거나 탭이 백그라운드 에서 실행 중인 경우 , 배터리 소모를 줄이기 위해 실행이 최대 300ms 또는 심지어 1초까지 지연될 수 있습니다.
최신 프레임워크에서의 구현
이 방법은 React나 Angular 같은 툴에 완벽하게 적용할 수 있습니다. React 에서는 `setTimeout`을 `useEffect` 훅으로 감싸서 컴포넌트의 생명주기를 제어하고, 함수 반환 시 타이머가 초기화되도록 하여 메모리 누수를 방지하는 것이 이상적입니다. Angular 에서는 컴포넌트의 생성자나 생명주기 훅에 쉽게 통합하여 알림을 표시하거나 비동기 데이터를 로드할 수 있습니다.
더욱 복잡한 기능을 구현하고자 하는 경우, 타이머를 Promise 및 async/await 와 함께 사용할 수 있습니다 . 이를 통해 훨씬 더 읽기 쉽고 전문적인 대기 시퀀스를 생성할 수 있으며, 악명 높은 "콜백 지옥"을 피하고 여러 타이머를 비동기적으로 체계적으로 관리할 수 있습니다.
JavaScript에서 시간을 관리하는 능력은 디지털 시계, 애니메이션, 연결 재시도 시스템 등 동적인 인터페이스를 구현하는 데 필수적입니다. `setTimeout`을 숙달하고, `clearTimeout`으로 재정의하며, 이벤트 루프와의 상호 작용 방식을 이해하면 애플리케이션 성능을 최적화하고 최종 사용자 경험을 개선할 수 있습니다. 단, 시간 정확도는 환경과 시스템 부하에 따라 크게 달라진다는 점을 항상 염두에 두어야 합니다.