ANSI C를 사용하여 시간을 밀리 초 단위로 측정하는 방법은 무엇입니까?


127

ANSI C 만 사용하여 밀리 초 이상의 정밀도로 시간을 측정 할 수있는 방법이 있습니까? time.h를 검색했지만 두 번째 정밀도 함수 만 찾았습니다.


4
정밀도와 정확도의 차이에 유의하십시오. 시간을 초 단위 로 취하고 1000을 곱하면 밀리 초 정밀도 로 시간을 얻을 수 있지만 이는 소용이 없습니다. ms 정밀도 함수는 일반적으로 1 초 정확도보다 우수하지만 반드시 ms 정확도를 가질 필요는 없습니다.
Steve Jessop

2
간단한 대답은 아니오입니다. ANSI C는 밀리 초 이상의 정밀도를 지원하지 않습니다. 더 복잡한 대답은 여러분이하려는 일에 달려 있습니다. 솔직히 말해서 전체 영역은 악몽입니다. ​​널리 사용 가능한 Posix 기능을 사용할 수 있더라도 말입니다. "측정"이라는 용어를 사용하므로 "벽시계"시간보다는 간격에 관심이 있다고 가정합니다. 그러나 프로세스의 절대 기간 또는 CPU 사용량을 측정하려고합니까?
Dipstick 09.08.09

2
그냥 SOF에게 방금 내 베이컨을 구했다고 말하고 싶었습니다. ;-)
corlettk

답변:


92

1 초 이상의 시간 분해능을 제공하는 ANSI C 기능은 없지만 POSIX 기능 gettimeofday은 마이크로 초 분해능을 제공합니다. 시계 기능은 프로세스가 실행하는 데 소요 된 시간만을 측정하며 많은 시스템에서 정확하지 않습니다.

이 기능을 다음과 같이 사용할 수 있습니다.

struct timeval tval_before, tval_after, tval_result;

gettimeofday(&tval_before, NULL);

// Some code you want to time, for example:
sleep(1);

gettimeofday(&tval_after, NULL);

timersub(&tval_after, &tval_before, &tval_result);

printf("Time elapsed: %ld.%06ld\n", (long int)tval_result.tv_sec, (long int)tval_result.tv_usec);

이것은 Time elapsed: 1.000870내 컴퓨터에 반환 됩니다.


30
약간의주의 사항 : gettimeofday ()는 단조롭지 않습니다. 즉, 예를 들어 컴퓨터가 네트워크 시간 서버 또는 다른 시간 원본과 동기화를 유지하려고 시도하는 경우 건너 뛸 수 있으며 뒤로 이동할 수도 있습니다.
Dipstick 09.08.09

3
정확하게하려면 : (내가 ANSI C와이 부분에서 호환라고 생각합니다)에서 ISO C99의 경우에도 보장이없는 임의의 시간 해상도가. (ISO C99, 7.23.1p4)
Roland Illig

6
timeval::tv_usec항상 1 초 미만이며 반복 된다는 점 은 주목할 가치가 있습니다. 즉 1 초보다 큰 시간 차이를 이용하려면, 다음을 수행해야합니다long usec_diff = (e.tv_sec - s.tv_sec)*1000000 + (e.tv_usec - s.tv_usec);
알렉산더 Malakhov

4
@Dipstick : 그러나 예를 들어 NTP는 명시 적으로 지시 할 때까지 시계를 뒤로 이동시키지 않습니다.
thejh

1
@AlexanderMalakhov 시간 빼기 논리는 timersub함수 내부에 캡슐화 됩니다. tval_result값 (tv_sec 및 tv_usec)을있는 그대로 사용할 수 있습니다 .
x4444

48
#include <time.h>
clock_t uptime = clock() / (CLOCKS_PER_SEC / 1000);

CLOCKS_PER_SEC는 많은 시스템에서 1000000으로 설정됩니다. 이 방식으로 사용하기 전에 값을 인쇄하여 확인하십시오.
ysap

16
초당 클럭이기 때문에 어떤 값인지는 중요하지 않으므로 clock () / CLOCKS_PER_SEC의 결과 값은 초 단위입니다 (적어도 그래야 함). 1000으로 나누면 밀리 초로 바뀝니다.
David Young

14
C Reference Manual에 따르면 clock_t 값은 약 36 분에서 시작하여 줄 바꿈 할 수 있습니다. 긴 계산을 측정하는 경우이를 알고 있어야합니다.
CyberSkull

4
또한 정수 나눗셈 CLOCKS_PER_SEC / 1000이 정확하지 않아 최종 결과에 영향을 미칠 수 있습니다 (내 경험상 CLOCKS_PER_SEC항상 1000의 배수 였음에도 불구하고 ). 수행 (1000 * clock()) / CLOCKS_PER_SEC은 부정확 한 분할에 덜 취약하지만 반면에 오버플로에 더 취약합니다. 고려해야 할 몇 가지 문제입니다.
Cornstalks

4
이것은 벽 시간이 아니라 CPU 시간을 측정하지 않습니까?
krs013

28

나는 항상 clock_gettime () 함수를 사용하여 CLOCK_MONOTONIC 시계에서 시간을 반환합니다. 반환 된 시간은 epoch의 시스템 시작과 같이 과거에 일부 지정되지 않은 시점 이후의 시간 (초 및 나노초)입니다.

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

int64_t timespecDiff(struct timespec *timeA_p, struct timespec *timeB_p)
{
  return ((timeA_p->tv_sec * 1000000000) + timeA_p->tv_nsec) -
           ((timeB_p->tv_sec * 1000000000) + timeB_p->tv_nsec);
}

int main(int argc, char **argv)
{
  struct timespec start, end;
  clock_gettime(CLOCK_MONOTONIC, &start);

  // Some code I am interested in measuring 

  clock_gettime(CLOCK_MONOTONIC, &end);

  uint64_t timeElapsed = timespecDiff(&end, &start);
}

5
clock_gettime ()이 ANSI C가 아닙니다.
PowerApp101

1
또한 CLOCK_MONOTONIC은 많은 시스템 (많은 Linux 플랫폼 포함)에서 구현되지 않습니다.
Dipstick 2009-08-09

2
@ PowerApp101이 작업을 수행하는 좋은 / 강력한 ANSI C 방법은 없습니다. 다른 많은 답변은 ANCI C가 아닌 POSIX에 의존합니다. 즉, 저는 오늘 그렇게 믿습니다. @Dipstick 오늘날 저는 대부분의 최신 플랫폼 [인용 필요] 지원을 믿으며 clock_gettime(CLOCK_MONOTONIC, ...)기능 테스트 매크로도 _POSIX_MONOTONIC_CLOCK있습니다.
omninonsense

22

휴대용 솔루션 구현

시간 측정 문제에 대해 충분한 정밀도를 가진 적절한 ANSI 솔루션이 없다고 여기에서 이미 언급했듯이, 휴대용 및 가능하면 고해상도 시간 측정 솔루션을 얻는 방법에 대해 작성하고 싶습니다.

단조로운 시계 대 타임 스탬프

일반적으로 시간 측정에는 두 가지 방법이 있습니다.

  • 단조로운 시계;
  • 현재 (날짜) 타임 스탬프.

첫 번째는 미리 정의 된 주파수로 틱을 계산하는 단조 시계 카운터 (틱 카운터라고도 함)를 사용하므로 틱 값이 있고 주파수를 알고 있다면 틱을 경과 시간으로 쉽게 변환 할 수 있습니다. 실제로 단조로운 시계가 어떤 식 으로든 현재 시스템 시간을 반영한다는 보장은 없으며 시스템 시작 이후 틱을 계산할 수도 있습니다. 그러나 시스템 상태에 관계없이 시계가 항상 증가하는 방식으로 실행되도록 보장합니다. 일반적으로 주파수는 하드웨어 고해상도 소스에 바인딩되어 있기 때문에 높은 정확도를 제공합니다 (하드웨어에 따라 다르지만 대부분의 최신 하드웨어는 고해상도 클럭 소스에 문제가 없습니다).

두 번째 방법은 현재 시스템 시계 값을 기반으로 (날짜) 시간 값을 제공합니다. 해상도가 높을 수도 있지만 한 가지 큰 단점이 있습니다. 이러한 종류의 시간 값은 시간대 변경, 일광 절약 시간 (DST) 변경, NTP 서버 업데이트, 시스템 최대 절전 모드 등과 같은 다른 시스템 시간 조정의 영향을받을 수 있습니다. 의 위에. 경우에 따라 음의 경과 시간 값을 가져와 정의되지 않은 동작을 유발할 수 있습니다. 실제로 이러한 종류의 시간 원본은 첫 번째 시간 원본보다 신뢰성이 떨어집니다.

따라서 시간 간격 측정의 첫 번째 규칙은 가능하면 단조로운 시계를 사용하는 것입니다. 일반적으로 정밀도가 높고 설계 상 신뢰할 수 있습니다.

대체 전략

휴대용 솔루션을 구현할 때 폴백 전략을 고려할 가치가 있습니다. 가능한 경우 단조로운 클록을 사용하고 시스템에 단조로운 클록이없는 경우 타임 스탬프 방식으로 폴백합니다.

윈도우

소프트웨어 및 하드웨어 지원에 대해 알아야 할 모든 세부 정보를 설명하는 Windows의 시간 측정에 대한 MSDN의 고해상도 타임 스탬프 획득 이라는 훌륭한 기사가 있습니다 . Windows에서 고정밀 타임 스탬프를 얻으려면 다음을 수행해야합니다.

  • QueryPerformanceFrequency를 사용하여 타이머 빈도 (초당 틱)를 쿼리합니다 .

    LARGE_INTEGER tcounter;
    LARGE_INTEGER freq;    
    
    if (QueryPerformanceFrequency (&tcounter) != 0)
        freq = tcounter.QuadPart;

    타이머 빈도는 시스템 부팅시 고정되므로 한 번만 가져 오면됩니다.

  • QueryPerformanceCounter를 사용하여 현재 틱 값을 쿼리합니다 .

    LARGE_INTEGER tcounter;
    LARGE_INTEGER tick_value;
    
    if (QueryPerformanceCounter (&tcounter) != 0)
        tick_value = tcounter.QuadPart;
  • 경과 시간, 즉 마이크로 초로 눈금을 조정합니다.

    LARGE_INTEGER usecs = (tick_value - prev_tick_value) / (freq / 1000000);

Microsoft에 따르면 대부분의 경우 Windows XP 이상 버전에서이 방법에 문제가 없어야합니다. 그러나 Windows에서 두 가지 대체 솔루션을 사용할 수도 있습니다.

  • GetTickCount 는 시스템이 시작된 이후 경과 된 밀리 초 수를 제공합니다. 49.7 일마다 포장되므로 더 긴 간격을 측정 할 때는주의해야합니다.
  • GetTickCount64 는의 64 비트 버전 GetTickCount이지만 Windows Vista 이상부터 사용할 수 있습니다.

OS X (macOS)

OS X (macOS)에는 단조 시계를 나타내는 자체 마하 절대 시간 단위가 있습니다. 시작하는 가장 좋은 방법은 Apple의 기사 Technical Q & A QA1398 : Mach Absolute Time Units (코드 예제와 함께)에서 Mach 특정 API를 사용하여 단조로운 틱을 얻는 방법을 설명합니다. 또한 카운터 주파수가 분자와 분모의 형태로 사용되기 때문에 Mac OS X 에서는 clock_gettime 대안 이라는 로컬 질문 이 있습니다. 따라서 경과 시간을 얻는 방법에 대한 간단한 예 :

  • 클럭 주파수 분자와 분모를 얻으십시오.

    #include <mach/mach_time.h>
    #include <stdint.h>
    
    static uint64_t freq_num   = 0;
    static uint64_t freq_denom = 0;
    
    void init_clock_frequency ()
    {
        mach_timebase_info_data_t tb;
    
        if (mach_timebase_info (&tb) == KERN_SUCCESS && tb.denom != 0) {
            freq_num   = (uint64_t) tb.numer;
            freq_denom = (uint64_t) tb.denom;
        }
    }

    한 번만 수행하면됩니다.

  • 다음을 사용하여 현재 눈금 값을 쿼리합니다 mach_absolute_time.

    uint64_t tick_value = mach_absolute_time ();
  • 이전에 쿼리 한 분자와 분모를 사용하여 틱을 경과 시간, 즉 마이크로 초로 조정합니다.

    uint64_t value_diff = tick_value - prev_tick_value;
    
    /* To prevent overflow */
    value_diff /= 1000;
    
    value_diff *= freq_num;
    value_diff /= freq_denom;

    오버플로를 방지하는 주요 아이디어는 분자와 분모를 사용하기 전에 눈금을 원하는 정확도로 축소하는 것입니다. 초기 타이머 분해능은 나노초이므로 1000마이크로 초를 얻기 위해로 나눕니다 . Chromium의 time_mac.c 에서 사용 된 것과 동일한 접근 방식을 찾을 수 있습니다 . 나노초 정확도가 정말로 필요한 경우 오버플로없이 mach_absolute_time을 어떻게 사용할 수 있습니까? .

Linux 및 UNIX

clock_gettime통화는 POSIX 친화적 인 시스템에서 가장 좋은 방법입니다. 다른 클럭 소스에서 시간을 쿼리 할 수 ​​있으며 필요한 것은 CLOCK_MONOTONIC. 모든 시스템이 clock_gettime지원 CLOCK_MONOTONIC하는 것은 아니므로 가장 먼저해야 할 일은 가용성을 확인하는 것입니다.

  • _POSIX_MONOTONIC_CLOCK값으로 정의 되면 사용 가능함을 >= 0의미합니다 CLOCK_MONOTONIC.
  • 경우 _POSIX_MONOTONIC_CLOCK에 정의 0가 런타임시 작동하는 경우 추가로 확인해야한다는 것을 의미, 내가 사용 제안 sysconf:

    #include <unistd.h>
    
    #ifdef _SC_MONOTONIC_CLOCK
    if (sysconf (_SC_MONOTONIC_CLOCK) > 0) {
        /* A monotonic clock presents */
    }
    #endif
  • 그렇지 않으면 단조로운 시계가 지원되지 않으며 폴백 전략을 사용해야합니다 (아래 참조).

의 사용법 clock_gettime은 매우 간단합니다.

  • 시간 가치를 얻으십시오 :

    #include <time.h>
    #include <sys/time.h>
    #include <stdint.h>
    
    uint64_t get_posix_clock_time ()
    {
        struct timespec ts;
    
        if (clock_gettime (CLOCK_MONOTONIC, &ts) == 0)
            return (uint64_t) (ts.tv_sec * 1000000 + ts.tv_nsec / 1000);
        else
            return 0;
    }

    여기서 시간을 마이크로 초로 줄였습니다.

  • 같은 방법으로받은 이전 시간 값과의 차이를 계산합니다.

    uint64_t prev_time_value, time_value;
    uint64_t time_diff;
    
    /* Initial time */
    prev_time_value = get_posix_clock_time ();
    
    /* Do some work here */
    
    /* Final time */
    time_value = get_posix_clock_time ();
    
    /* Time difference */
    time_diff = time_value - prev_time_value;

최선의 대체 전략은 gettimeofday호출 을 사용하는 것입니다. 단조롭지는 않지만 상당히 좋은 해상도를 제공합니다. 아이디어는와 동일 clock_gettime하지만 시간 값을 얻으려면 다음을 수행해야합니다.

#include <time.h>
#include <sys/time.h>
#include <stdint.h>

uint64_t get_gtod_clock_time ()
{
    struct timeval tv;

    if (gettimeofday (&tv, NULL) == 0)
        return (uint64_t) (tv.tv_sec * 1000000 + tv.tv_usec);
    else
        return 0;
}

다시 말하지만, 시간 값은 마이크로 초로 축소됩니다.

SGI IRIX

IRIXclock_gettime전화가 있지만 CLOCK_MONOTONIC. 대신 with CLOCK_SGI_CYCLE대신 사용해야하는 고유 한 단조로운 클럭 소스가 정의되어 있습니다 .CLOCK_MONOTONICclock_gettime

Solaris 및 HP-UX

Solaris에는 gethrtime현재 타이머 값을 나노초 단위로 반환하는 자체 고해상도 타이머 인터페이스 가 있습니다. 최신 버전의 Solaris에는이있을 수 있지만 이전 Solaris 버전을 지원해야하는 경우 계속 clock_gettime사용할 수 있습니다 gethrtime.

사용법은 간단합니다.

#include <sys/time.h>

void time_measure_example ()
{
    hrtime_t prev_time_value, time_value;
    hrtime_t time_diff;

    /* Initial time */
    prev_time_value = gethrtime ();

    /* Do some work here */

    /* Final time */
    time_value = gethrtime ();

    /* Time difference */
    time_diff = time_value - prev_time_value;
}

HP-UX에는는 clock_gettime없지만 gethrtimeSolaris에서와 같은 방식으로 사용해야하는 것을 지원합니다 .

BeOS

BeOSsystem_time 에는 컴퓨터가 부팅 된 이후 경과 한 마이크로 초 수를 반환하는 자체 고해상도 타이머 인터페이스도 있습니다.

사용 예 :

#include <kernel/OS.h>

void time_measure_example ()
{
    bigtime_t prev_time_value, time_value;
    bigtime_t time_diff;

    /* Initial time */
    prev_time_value = system_time ();

    /* Do some work here */

    /* Final time */
    time_value = system_time ();

    /* Time difference */
    time_diff = time_value - prev_time_value;
}

OS / 2

OS / 2 에는 고정밀 타임 스탬프를 검색하는 자체 API가 있습니다.

  • DosTmrQueryFreq(GCC 컴파일러의 경우)를 사용하여 타이머 주파수 (단위당 틱)를 쿼리합니다 .

    #define INCL_DOSPROFILE
    #define INCL_DOSERRORS
    #include <os2.h>
    #include <stdint.h>
    
    ULONG freq;
    
    DosTmrQueryFreq (&freq);
  • 다음을 사용하여 현재 틱 값을 쿼리합니다 DosTmrQueryTime.

    QWORD    tcounter;
    unit64_t time_low;
    unit64_t time_high;
    unit64_t timestamp;
    
    if (DosTmrQueryTime (&tcounter) == NO_ERROR) {
        time_low  = (unit64_t) tcounter.ulLo;
        time_high = (unit64_t) tcounter.ulHi;
    
        timestamp = (time_high << 32) | time_low;
    }
  • 경과 시간, 즉 마이크로 초로 눈금을 조정합니다.

    uint64_t usecs = (prev_timestamp - timestamp) / (freq / 1000000);

구현 예

위에서 설명한 모든 전략을 구현 하는 plibsys 라이브러리를 살펴볼 수 있습니다 (자세한 내용은 ptimeprofiler * .c 참조).


"시간 측정 문제에 대해 충분한 정밀도를 가진 적절한 ANSI 솔루션이 없습니다.": C11이 있습니다 timespec_get. stackoverflow.com/a/36095407/895245
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

1
이것은 여전히 ​​코드 실행 시간을 측정하는 잘못된 방법입니다. timespec_get단조롭지 않습니다.
Alexander Saprykin

11

timespec_get C11에서

구현 해상도로 반올림하여 최대 나노초를 반환합니다.

POSIX '에서 ANSI ripoff처럼 보입니다 clock_gettime.

예 : a printf는 Ubuntu 15.10에서 100ms마다 수행됩니다.

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

static long get_nanos(void) {
    struct timespec ts;
    timespec_get(&ts, TIME_UTC);
    return (long)ts.tv_sec * 1000000000L + ts.tv_nsec;
}

int main(void) {
    long nanos;
    long last_nanos;
    long start;
    nanos = get_nanos();
    last_nanos = nanos;
    start = nanos;
    while (1) {
        nanos = get_nanos();
        if (nanos - last_nanos > 100000000L) {
            printf("current nanos: %ld\n", nanos - start);
            last_nanos = nanos;
        }
    }
    return EXIT_SUCCESS;
}

C11 N1570 표준 초안 7.27.2.5는 "timespec_get 기능을 말한다"

base가 TIME_UTC 인 경우 tv_sec 멤버는 구현이 정의 된 epoch 이후의 시간 (초)으로 설정되고 전체 값으로 잘리고 tv_nsec 멤버는 시스템 클록의 해상도로 반올림 된 정수 나노초로 설정됩니다. (321)

321) 구조체 timespec 객체가 나노초 해상도로 시간을 설명하지만 사용 가능한 해상도는 시스템에 따라 다르며 1 초보다 클 수도 있습니다.

C ++ 11에 추가 된 기능 std::chrono::high_resolution_clock: C ++ 크로스 플랫폼 고해상도 타이머

glibc 2.21 구현

다음에서 찾을 수 있습니다 sysdeps/posix/timespec_get.c.

int
timespec_get (struct timespec *ts, int base)
{
  switch (base)
    {
    case TIME_UTC:
      if (__clock_gettime (CLOCK_REALTIME, ts) < 0)
        return 0;
      break;

    default:
      return 0;
    }

  return base;
}

너무 명확하게 :

  • TIME_UTC현재 만 지원됩니다.

  • __clock_gettime (CLOCK_REALTIME, ts)POSIX API 인으로 전달됩니다 . http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html

    Linux x86-64에는 clock_gettime시스템 호출이 있습니다.

    이는 다음과 같은 이유로 오류 방지 마이크로 벤치마킹 방법이 아닙니다.

    • man clock_gettime프로그램이 실행되는 동안 일부 시스템 시간 설정을 변경하면이 측정이 불연속 될 수 있음을 나타냅니다. 물론 이것은 드문 이벤트이며 무시할 수 있습니다.

    • 이것은 벽 시간을 측정하므로 스케줄러가 작업을 잊어 버리기로 결정하면 더 오래 실행되는 것처럼 보입니다.

    이러한 이유 때문에 getrusage()더 나은 POSIX 벤치마킹 도구가 될 수 있습니다.

    자세한 정보 : Linux에서 시간 측정-시간 대 시계 대 getrusage 대 clock_gettime 대 gettimeofday 대 timespec_get?


이것은 2017 년 현재 정답입니다. MSVC에도이 기능이 있습니다. 벤치마킹 측면에서 칩 레지스터 (PT 확장이있는 최신 버전의 x86 프로세서 및 해당하는 최신 버전의 Linux 커널 / perf)를

4

얻을 수있는 최고의 정밀도는 x86 전용 "rdtsc"명령어를 사용하는 것입니다.이 명령어는 클럭 수준 해상도를 제공 할 수 있습니다 (ne은 물론 쉽게 측정 할 수있는 rdtsc 호출 자체의 비용을 고려해야합니다. 응용 프로그램 시작).

여기서 가장 중요한 점은 초당 클럭 수를 측정하는 것인데 너무 어렵지 않아야합니다.


3
일부 컴퓨터에서는 RDTSC 호출을 둘 이상의 프로세서로 보내고 해당 RDTSC 카운터가 동기화되지 않을 수 있기 때문에 프로세서 선호도에 대해 걱정해야 할 수도 있습니다.
Will Dean

1
또한 일부 프로세서에는 단조롭게 증가하는 TSC가 없습니다. CPU 주파수를 줄이는 절전 모드를 생각해보십시오. 매우 짧은 현지화 된 타이밍을 제외하고 RDTSC를 사용 하는 것은 매우 나쁜 생각입니다.
snemarch

Btw, @WillDean이 언급하고 타이밍을 위해 rdtsc를 사용하는 핵심 드리프트는 많은 게임이 (초기?) 멀티 코어 AMD64 CPU에서 작동하지 못한 이유입니다. x2 4400+에서 단일 코어 선호도로 제한해야했습니다. 여러 제목.
snemarch

2

대답은 충분하지만 내 솔루션은 더 간단합니다. Linux에서 테스트하고 gcc (Ubuntu 7.2.0-8ubuntu3.2) 7.2.0을 사용합니다.

합니다 alse 사용 gettimeofday은이 tv_sec두 번째 부분이고,는 tv_usec마이크로 하지 밀리 .

long currentTimeMillis() {
  struct timeval time;
  gettimeofday(&time, NULL);

  return time.tv_sec * 1000 + time.tv_usec / 1000;
}

int main() {
  printf("%ld\n", currentTimeMillis());
  // wait 1 second
  sleep(1);
  printf("%ld\n", currentTimeMillis());
  return 0;
 }

인쇄 :

1522139691342 1522139692342, 정확히 1 초.


-4

창문 아래 :

SYSTEMTIME t;
GetLocalTime(&t);
swprintf_s(buff, L"[%02d:%02d:%02d:%d]\t", t.wHour, t.wMinute, t.wSecond, t.wMilliseconds);

1
요청에 따라이 ansi C입니까?
Gyom 2015
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.