sleep(1)은 누가 1초를 세고 있을까?

포비·2026년 3월 18일

알아보자

목록 보기
58/111

언어가 아니라 OS와 하드웨어가 시간을 만든다

우리는 너무 자연스럽게 이렇게 생각한다.

sleep(1) → 1초 기다림

근데 진짜로 누가 1초를 세고 있을까?

언어? 런타임?
아니면 CPU가 속으로 “하나… 둘…” 하고 있을까?

결론부터 말하면:

❌ 프로그래밍 언어는 “초를 세지 않는다”
✅ OS + 하드웨어 타이머 + 스케줄러가 시간을 만든다

이 글에서는 그걸 끝까지 파고들어서 설명해보겠다.


1. sleep의 진짜 의미

우리가 쓰는 대부분의 sleep은 이런 의미다:

"지금 실행을 멈추고,
이 시각 이후에 다시 실행되게 해줘"

즉, 핵심은 이거다:

❌ "1초 동안 기다리기"
✅ "1초 후에 깨워달라고 예약하기"

이건 엄청 중요한 차이다.


2. 전체 흐름 (핵심 구조)

time.sleep(1)이 실행되면 내부에서 이런 일이 일어난다:

[언어 코드]
   ↓
[런타임]
   ↓
[OS 시스템콜 (nanosleep 등)]
   ↓
[커널 타이머 등록]
   ↓
[하드웨어 타이머 인터럽트]
   ↓
[스레드 깨움]
   ↓
[스케줄러가 CPU 다시 할당]

한 줄 요약:

sleep은 “시간을 재는 함수”가 아니라
“미래 시점에 실행을 예약하는 시스템”이다


3. 언어는 사실 OS한테 맡긴다

예를 들어 Python:

import time
time.sleep(1)

이건 내부적으로 대략 이렇게 된다:

nanosleep(1)

Java:

Thread.sleep(1000);

→ OS 타이머 사용

Rust:

std::thread::sleep(Duration::from_secs(1));

→ 역시 OS 타이머


👉 즉:

대부분의 언어는 직접 시간을 재지 않는다
그냥 OS에게 맡긴다


4. OS는 어떻게 시간을 다룰까?

여기부터가 진짜 핵심이다.

OS는 “타이머 하나”로 동작하지 않는다.

4가지 핵심 구성요소가 있다:


4.1 Clock Source (시간 읽기)

"지금 몇 시냐?"

이걸 담당한다.

특징:

  • 계속 증가하는 카운터
  • 절대 뒤로 가지 않음 (monotonic)
  • 나노초 단위로 변환 가능

예:

123456789012 ticks → ns 변환

👉 핵심:

시간을 “세는 게 아니라”
이미 흐르고 있는 값을 읽는다


4.2 Clock Event (깨우기 예약)

"이 시각에 인터럽트 발생시켜라"

역할:

  • 특정 시간에 CPU 인터럽트 발생
  • sleep 깨우기 트리거

👉 핵심:

시간을 체크하는 게 아니라
미래에 알람을 맞춘다


4.3 Timer 시스템 (hrtimer)

OS 내부에는 타이머 큐가 있다.

sleep(1)
→ 현재 시간 + 1초 = deadline
→ 타이머 큐에 등록

구조:

  • red-black tree
  • 시간순 정렬

👉 그래서 OS는:

가장 가까운 타이머만 신경쓴다


4.4 Scheduler (진짜 중요)

여기서 많은 사람들이 틀린다.

시간이 끝났다고 바로 실행되는 게 아니다

타이머 만료
→ 스레드 "깨울 준비됨"
→ 스케줄러가 CPU 줄 때까지 기다림

👉 핵심:

sleep 끝 = 실행 시작 ❌
sleep 끝 = 실행 가능 상태 ⭕


5. 하드웨어 레벨까지 내려가보자

OS 아래에는 하드웨어 타이머가 있다.

대표 구조:

[카운터] 계속 증가
[비교기] 특정 값 도달 시 인터럽트 발생

예:

현재: 1000
목표: 2000

→ 2000 되면 인터럽트 발생

👉 이게 진짜 “시간”이다.


6. 그래서 sleep은 정확하지 않다

많은 사람들이 궁금해하는 부분:

sleep(1)은 1초가 아닐까?

이유는 여러 개다.


6.1 타이머 해상도 (resolution)

1ns 요청 → 실제는 1ms 단위일 수도 있음

6.2 스케줄러 지연

시간 끝남 → CPU 없음 → 대기

6.3 OS 최적화 (timer slack)

"비슷한 타이머들 한 번에 깨우자"
→ 일부러 늦춤

6.4 이벤트 루프 (JS)

setTimeout(() => {}, 0)

→ 즉시 실행 ❌
→ 큐에 들어감 ⭕


👉 결론:

sleep은 정확한 시간이 아니라
최소 대기 시간 보장이다


7. sleep vs delay (진짜 중요한 차이)

sleep (일반적인 경우)

CPU를 놓는다
OS가 깨워준다

delay (busy wait)

while (time < target) {}

특징:

  • CPU 계속 사용
  • 매우 정확
  • 매우 비효율

👉 OS 커널에서도 둘을 명확히 구분한다.


8. 더 깊은 개념: monotonic vs realtime

realtime (벽시계)

2026-03-18 12:00:00

문제:

  • 변경 가능
  • NTP 동기화 영향 받음

monotonic (경과 시간)

시스템 시작 이후 시간

특징:

  • 절대 안 뒤로 감
  • sleep / timeout에 사용됨

👉 핵심:

sleep은 거의 항상 monotonic 기반이다


9. 실무에서 중요한 팁

❌ 이렇게 하면 drift 생김

while True:
    do_something()
    time.sleep(1)

✅ 이렇게 해야 정확함

next_time = time.monotonic()

while True:
    next_time += 1
    do_something()
    sleep(next_time - time.monotonic())

👉 이유:

sleep 누적 오차 제거


10. 진짜 결론

이 글의 핵심을 한 줄로 정리하면:

sleep은 시간을 재는 함수가 아니다
미래에 실행을 예약하는 시스템이다

그리고 그 아래에는:

  • 언어 ❌
  • OS 타이머 ⭕
  • 하드웨어 카운터 ⭕
  • 인터럽트 ⭕
  • 스케줄러 ⭕

이 모든 게 얽혀 있다.


🔥 한 줄 요약

sleep = (현재 시간 + duration) → OS 타이머 등록 → 인터럽트 → 스케줄러 → 실행

profile
무엇이든 필요한 것을 합니다. https://mint-middle-1e5.notion.site/2b7655e8316980ad9422d96a6f3947de

0개의 댓글