HOWTO · C++
C++에서 시간 지연 추가
이 튜토리얼은 C++ 프로그램에 시간 지연을 추가하는 방법에 대한 간략한 가이드를 제공합니다.
이 페이지의 내용
C++ 프로그램은 플랫폼 API나 표준 라이브러리의 스레드 대기 기능을 사용해 현재 스레드를 잠시 멈출 수 있습니다. 이식성과 대기 기준이 시간 길이인지 시계상의 시각인지에 따라 적절한 기능을 선택하세요. POSIX 시스템의 sleep()은 초 단위, usleep()은 마이크로초 단위이며, C++11의 sleep_for()와 sleep_until()은 각각 시간 길이와 시각을 받습니다. 이 기능들은 호출한 스레드를 일시 중단하지만, 정확한 시점에 다시 실행된다고 보장하지는 않습니다.
C++ 지연 API 선택하기
일반적인 애플리케이션 코드에서 이식 가능한 C++11 상대 대기가 필요하면 sleep_for()를 사용하세요. 시계상의 기한까지 기다려야 한다면 sleep_until()을 사용하면 됩니다. POSIX 함수인 sleep()과 usleep()은 코드가 이미 POSIX 환경에 종속된 경우에 적합하며, 이식 가능한 C++ 기능은 아닙니다. Windows에는 자체 Sleep() API가 있으며, 인수 단위는 밀리초입니다.
지연 함수는 호출한 스레드를 막습니다. 사용자 인터페이스, 서버 또는 작업자 풀이 계속 응답해야 한다면 전용 스레드를 대기시키거나 프레임워크의 비동기 타이머를 사용하고, 메인 스레드나 이벤트 루프 스레드는 막지 마세요.
sleep()으로 초 단위의 플랫폼별 지연 주기
C++에는 이식 가능한 sleep() 함수가 정의되어 있지 않습니다. POSIX 시스템에서는 <unistd.h>를 포함하고 sleep(seconds)를 호출합니다. 신호로 대기가 중단되면 아직 대기해야 하는 초 단위 시간을 반환하고, 요청한 시간이 모두 지나면 0을 반환합니다. Windows에서는 <Windows.h>를 포함하고 Sleep(milliseconds)를 호출합니다. 단위가 밀리초이므로 1초 대기는 Sleep(1000)입니다. POSIX와 Windows의 호출 이름, 헤더, 단위는 서로 다릅니다. Windows 헤더에 관한 안내는 Windows.h 가이드에서도 확인할 수 있습니다.
예를 들어 POSIX에서는 <unistd.h>를 포함한 뒤 sleep(2);를 호출합니다. Windows에서는 <Windows.h>를 포함하고 Sleep(2000);을 사용하세요. 대상 플랫폼에 맞는 분기를 선택해야 합니다. POSIX 선언을 포함해도 Windows에서 sleep()을 사용할 수 있게 되지는 않습니다.
usleep()으로 POSIX 마이크로초 지연 주기
POSIX 시스템에서 usleep()은 <unistd.h>에 선언되어 있으며, 대기 시간을 마이크로초 단위로 받습니다. 예를 들어 usleep(250000);은 4분의 1초 동안 대기하도록 요청합니다. 이 함수는 POSIX 인터페이스이지 이식 가능한 C++ 기능이 아닙니다. 일부 플랫폼이나 기능 설정에서는 제공되지 않을 수 있으므로, 여러 플랫폼에서 동작하는 C++ 코드에는 sleep_for()를 사용하세요. 대기가 완료되면 0을 반환하고, 신호로 중단되거나 다른 이유로 실패하면 -1을 반환합니다. 호출한 코드가 중단에 대응해야 한다면 반환값을 확인하세요. 운영체제가 스레드 실행 시점을 스케줄링하므로 실제 경과 시간은 요청한 시간보다 길어질 수 있습니다.
sleep_for()로 상대 시간만큼 대기하기
상대 시간만큼 기다리려면 <thread>와 <chrono>를 포함하세요. sleep_for()는 스케줄링과 자원 경합의 영향을 받으며, 요청한 시간 이상 현재 스레드를 일시 중단합니다. 다음은 200밀리초 동안 대기한 뒤 확인 메시지를 출력하는 완전한 C++11 프로그램입니다. 예제를 실행해 보세요.
이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.
#include <chrono>
#include <iostream>
#include <thread>
int main() {
std::this_thread::sleep_for(std::chrono::milliseconds(200));
std::cout << "Wait complete\n";
}
Wait complete
의도한 단위를 분명히 나타내는 시간 형식을 사용하세요. 예를 들어 std::chrono::seconds(2) 또는 std::chrono::milliseconds(250)을 사용할 수 있습니다. 대기 함수는 호출한 스레드에만 영향을 주며, 스케줄러의 지연으로 실제 경과 시간이 전달한 시간보다 길어질 수 있습니다. 코드 블록의 예제 문구와 출력은 바이트 단위로 보존되어 영어로 표시됩니다.
sleep_until()으로 특정 시각까지 기다리기
sleep_until()도 <thread>에 포함되어 있지만, 시간 길이가 아니라 시계상의 시각을 받습니다. 시계의 now() 값에 시간 길이를 더해 미래의 기한을 만드세요. 예를 들면 std::this_thread::sleep_until(std::chrono::steady_clock::now() + std::chrono::seconds(3));와 같이 작성할 수 있습니다. 이 코드는 구간 측정용으로 설계되어 벽시계 시간처럼 조정되지 않는 steady_clock의 해당 시각까지 기다립니다. 기한이 이미 지났다면 추가로 대기하지 않습니다. 이 함수는 값을 반환하지 않으며, 스케줄링에 따라 기한이 지난 뒤에야 스레드가 다시 실행될 수 있습니다.
경과 시간 기준의 기한에는 시스템 시계 보정으로 목표 시각이 바뀌지 않도록 steady_clock을 우선 사용하세요. 벽시계 시각 자체가 목표일 때만 system_clock을 사용하고, 대기 중 시계가 바뀔 수 있다는 점을 고려하세요. sleep_for()와 마찬가지로 호출한 스레드를 막습니다.
적절한 지연 방법을 선택하고 스케줄링 고려하기
이식 가능한 C++11 코드에서는 “이만큼 기다리기”가 요구사항이면 sleep_for()를, “이 기한까지 기다리기”가 요구사항이면 sleep_until()을 사용하세요. POSIX 전용 동작이 적절한 경우에만 sleep()이나 usleep()을 사용하고, Windows 전용 코드에서는 Windows의 Sleep()을 사용하세요. 단위를 명확히 하세요. sleep()은 초, usleep()은 마이크로초, Windows의 Sleep()은 밀리초를 받으며, <chrono>는 이름이 있는 형식으로 시간 길이를 나타냅니다.
이 API들 가운데 정밀 타이머는 없습니다. 요청한 시간은 최소 대기 기준이지 정확한 재개 시각을 보장하지 않습니다. 스케줄링, 자원 경합, 중단 여부에 따라 실행이 이어지는 시점이 달라집니다. 스레드를 막지 않아야 하는 짧은 대기에는 플랫폼이나 프레임워크가 제공하는 비동기 타이머를 사용하세요. 이 차이를 이해하면 프로그램의 이식성 요구와 시간 처리 방식에 맞는 지연 기능을 선택할 수 있습니다.