본문 바로가기
프로그래밍/C++

C++] std::chrono 라이브러리

by eteo 2025. 5. 12.

 

 

C++ std::chrono 라이브러리

 

C++의 chrono 라이브러리는 시간과 관련된 작업을 처리하기 위한 도구다. 이 글에서는 C++ chrono 라이브러리의 세 가지 주요 클럭 구조체와 클럭 구조체와 함께 사용되는 duration, time_point 클래스에 대해 정리해보고자 한다.

 

 

🔍 클럭 구조체

 

클럭 구조체는 다음의 3가지가 존재한다.

 

  1. std::chrono::system_clock
    • 현재 시스템 시간을 나타내는 클럭이다.
    • 시스템 시간이 변경되거나 NTP(Network Time Protocol) 동기화 등으로 수정되면 system_clock의 값도 영향을 받는다.
    • Windows에서는 GetSystemTimePreciseAsFileTime 함수를 래핑한 구조체로 구현된다.
    • 해상도는 밀리초 수준이다.
    • 주로 현재 시간을 출력하고 타임스탬프를 기록하는 데 사용한다.
  2. std::chrono::steady_clock
    • 시간이 항상 앞으로만 흐르는 단조 시계(monotonic clock)이다.
    • Windows에서는 QueryPerformanceCounter를 래핑한 구조체로 구현된다.
    • 해상도는 나노초 수준이다.
    • 시스템 시간이 변경되더라도 영향을 받지 않으므로 정확한 경과시간을 측정할 때 유용하게 사용한다.
  3. std::chrono::high_resolution_clock
    • 시스템에서 가장 높은 해상도를 제공하는 클럭으로, steady_clock이나 system_clock의 alias로 사용된다.
    • Windows에서는 steady_clock과 동일한 기능을 제공한다.

 

즉, 구조체는 3개지만 high_resolution_clock은 그 중 하나의 alias 이므로 사실상 2개나 마찬가지이다.

 

클럭 구조체의 현재 시간은 now()함수를 통해 가져올 수 있다.

 

 

 

 

🔍 duration 클래스

 

duration 클래스는 내부적으로는 시간 단위와 시간 간격을 나타내는 숫자로 구성되며, count()를 통해 객체 내부에 저장된 시간을 정수 값으로 반환할 수 있고 필요에 따라 duration_cast<>()를 통해 원하는 시간 단위로 캐스팅할 수 있다.

  • std::chrono::nanoseconds: 나노초
  • std::chrono::microseconds: 마이크로초
  • std::chrono::milliseconds: 밀리초
  • std::chrono::seconds: 초
  • std::chrono::minutes: 분
  • std::chrono::hours: 시

 

 

🔍 time_point 클래스

 

time_point는 특정 시계의 특정 시점을 나타내는 클래스이다. system_clock()의 경우 time_since_epoch() 함수를 사용하면 epoch(1970년 1월 1일 00:00:00 UTC) 이후 얼마나 경과했는지 반환할 수 있다.

 

 

✔️ system_clock을 사용하여 현재 시간을 포맷팅하여 출력하는 예시

 

➖ C++ 스타일

#include <iostream>
#include <chrono>
#include <ctime>
#include <iomanip>

int main() {
    // 현재 시각 time_point로 구하기
    auto now = std::chrono::system_clock::now();

    // time_t로 변환
    time_t now_time = std::chrono::system_clock::to_time_t(now);

    // tm 구조체로 변환
    struct tm* local = localtime(&now_time);

    // C++ 스타일 포맷 출력
    std::cout << "현재 시간: "
              << std::put_time(local, "%Y-%m-%d %H:%M:%S")
              << std::endl;
    
    return 0;
}

 

➖ C 스타일

#include <stdio.h>
#include <time.h>

int main() {
    time_t now = time(NULL);                  // 현재 시간 time_t로 반환
    struct tm* local = localtime(&now);       // tm 구조체로 변환
    
    // C 스타일 포맷 출력
    char buffer[100];
    strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", local);

    printf("현재 시간: %s\n", buffer);
    return 0;
}

 

현재 시간을 사람이 읽을 수 있는 문자열 형태로 출력하려면 C 스타일과 동일하게 time_t 값으로 변환하고, 다시 tm 구조체로 변환한 다음 시간 포매팅 함수를 사용해 문자열로 출력하는 과정을 거쳐야 한다. 변환 과정을 정리하면 다음과 같다.

 

  • std::chrono::system_clock::now()로 반환한 값은 time_point 객체이다.
  • std::chrono::system_clock::to_time_t() 를 사용해 이를 time_t 값으로 변환해야 한다. time_t는 <time.h> 또는 <ctime>에 포함된 타입으로 epoch로부터 경과한 시간을 초단위의 정수로 표현한다.
  • <time.h> 또는 <ctime>에 포함된 localtime() 함수를 사용해 time_t를 tm 구조체로 변환한다. tm 구조체는 시각을 년도, 월, 일, 시, 분, 초 단위로 쪼개서 멤버 변수로 저장하며, localtime() 함수는 time_t 포인터를 받아 내부 static 변수로 tm 구조체를 저장해두고 그 주소를 포인터로 반환한다.
  • C++ 스타일로는 put_time(), C 스타일로는 strftime() 함수를 사용하면 tm 구조체 포인터를 인자로 받아 사람이 읽기 쉬운 형태의 문자열로 시간을 포매팅할 수 있다.

 

 

 

 

 

 

 

✔️ steady_clock을 사용하여 코드 실행 시간 측정하는 예시

#include <iostream>
#include <chrono>

int main() {
    // 시작 시점 time_point 기록
    auto start = std::chrono::steady_clock::now();

    // 테스트할 코드
    for (int i = 0; i < 1000000; ++i);

    // 종료 시점 time_point 기록
    auto end = std::chrono::steady_clock::now();

    // 경과 시간 계산 (duration 타입)
    auto elapsed = end - start;

    // duration_cast로 밀리초 단위 변환
    auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(elapsed);

    // count()로 숫자 출력
    std::cout << "코드 실행 시간: " << ms.count() << "ms" << std::endl;

    return 0;
}

 

 

 

 

 

🔍 std::this_thread::sleep_for 및 std::this_thread::sleep_until

 

위 두 함수는 thread 라이브러리에 속하지만 시간지연을 하는 함수로 std::chrono::duration 클래스와 함께 쓰인다.

 

std::this_thread::sleep_for(std::chrono::seconds(1));
std::this_thread::sleep_until(std::chrono::steady_clock::now() + std::chrono::seconds(3));