나머지...

Y2K38, "UNIX Millennium Bug"

by 한기수 posted Dec 07, 2017

시작하며

당신은 소프트웨어 엔지니어 입니까.  정보시스템 매니저 입니까, 아니면 평범한 회사원 입니까?

당신이 무엇을 하던지간에 50세 이하라면 당신은 Y2K Millennium Bug를 만나실 수 있습니다.


1990년대 후반의 Y2K 이슈

1990년대 후반에 전 세계가 떠들석했던 이슈가 있었는데 연도를 2자리로 표기해서 생긴 “Y2K”입니다. 

1997-12-23이 아니라 97-12-23 형태로 말입니다. 

90년대 이전 대부분의 정보시스템은 연도를 ‘1997’과 같이 4자리로 표기하지 않고 ‘97’과 같이 2자리로 표현했는데, 

이런 관행이 정보시스템이 2000년과 1900년을 구분을 못하는 문제의 원인이 되었던 것이지요. 

2000년 10월 23일에 태어난 신생아의 주민등록번호는 001023로 시작되는데 이것은 1900년에 태어난 100살의 노인도 마찬가지 입니다, 

주민번호가 고유하지 않을 가능성이 생긴 것입니다. 

정보시스템에서는 치명적이라 할 수 있지요. 

온 세계의 정보 시스템 관리자가 자기의 시스템에서 사용하는 날짜가 4자리로 되어있는지 검사하고 감리하느라고 분주했고 “Y2K 비즈니스”라는 사업분야가 생길 정도였습니다. 

Y2K의 위력에 버금가는 아니 그것보다 클 수 있는 이슈가 Y2K38 Unix Millennium Bug라고  할 수 있습니다. 물론 20년이나 남았지만 말입니다. 


Linux의 시간 정보 보관 방법

32bit 정수를 시간을 표현하기 위한 자료구조(time_t)로 사용하는 Linux 시스템에서, 시간 정보는 ‘2017-12-07 09:11:24’과 같은 문자열 형태로 보관하기도 하지만 

정보시스템 내부 용도로 ‘1512605484’과 같은 정수형 숫자를 많이 사용합니다. 

이 정수형 숫자의 의미는 ‘1970-01-01 00:00:00’부터 현재까지 경과된 초(seconds)를 의미합니다. 

1970-01-01 자정에서 ‘1512605484’ 초가 경과한 날짜는 ‘2017-12-07 09:11:24’라는 의미입니다. 

날짜 계산을 많이 하는 정보시스템은 시간을 정수로 보관하는 것이 저장 용량이나 처리 시간을 고려할 때 훨씬 유리하기 때문에 내부의 자료구조등에서 이러한 방법을 많이 사용합니다.


Y2K38 소개

32bit time_t를 사용하는 Linux 시스템은 32bit 정수에 시간 정보를 보관하는데 

32bit의 정수의 최대치는 2,147,483,647이고 1970-01-01 자정에서 ‘2,147,483,647’초가 경과된 날짜는 ‘2038-01-19 03:14:07’입니다. 

이것이 32bit로 표현할 수 있는 날짜의 한계입니다. 

그러면 여기서 1초가 지나면 정보시스템은 어떻게 될까요? 

2038-01-19 03:14:08 이 정상이나 32bit 연산의 오버플로우가 발생되어 ‘-2,147,483,648’ 이 되고, 

이것을 그대로 문자열 형의 날짜로 바꾸면 1901-12-13 20:45:52가 된다는 것입니다.


아래는 일본의 어느 강좌에서 사용한 Sample C 프로그램 입니다. 

seq가 2까지는 정상 시간을 출력하다가 seq가 3일때, 정수의 최대치를 초과하면서 예상 못한 결과가 출력됩니다. 

Code를 이해할 필요는 없으나 우리가 예상하지 못하는 결과가 발생한다는 것은 알 수 있습니다.

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

void main()
{
        int seq;
        time_t tx;
        struct tm *tp;

        for (seq = 0; seq < 6;seq++)
          {
             tx = 2147483645+seq;
             tp = gmtime(&tx);
             printf ("seq: %d, Date Time: %d-%02d-%02d %02d:%02d:%02d\n",
                seq,
                tp->tm_year+1900, tp->tm_mon+1, tp->tm_mday,
                tp->tm_hour, tp->tm_min, tp->tm_sec);
           }
}


실행결과

seq: 0, Date Time: 2038-01-19 03:14:05
seq: 1, Date Time: 2038-01-19 03:14:06
seq: 2, Date Time: 2038-01-19 03:14:07
seq: 3, Date Time: 1901-12-13 20:45:52
seq: 4, Date Time: 1901-12-13 20:45:53
seq: 5, Date Time: 1901-12-13 20:45:54

Y2K38 Unix Millennium Bug 효과
당신의 정보시스템은 2038-01-19 03:14:07 이후에도 안전하게 작동하려는지요? 
2038-01-19 아침 9시 당신의 교통카드는 거절될 수 있습니다.
당신의 신용카드도 유효 기한 경과로 거부 당할 수 있습니다. 
네비게이션은 엉뚱한 곳으로 당신을 안내할 수도 있습니다. 
ATM/주식거래도 중단될 수 있습니다. 항공 관제 혼란 등의 대란이 올 수도 있습니다. 
물론 과장이지만.

현대는 정보화 시대이고 정보시스템이 일상 생활에 미치는 영향이 크기때문에 Y2K38 버그가 영향을 줄만한 분야는 매우 방대합니다. 
아래를 포함한 거의 모든 분야가 대상이 될 수 있습니다.
  • 수도/전기/교통 등의 공공 인프라

  • 은행/증권 등의 금융 시스템

  • 위성을 포함한 유무선 통신 시스템

  • 의료

  • 정부 서비스

  • 군사 분야

Y2K38 해결하기

해결 방법 중 하나는 시간을 32비트 정수가 아니고 64비트 정수에 보관하는 것입니다. 

이런 경우 290 Billion Year 이전에는 문제가 없습니다. 

당신이 IT 시스템 관리자라면 당신이 사용하고 있는 정보시스템의 OS/DBMS와 같은 시스템 소프트웨어, 플랫폼/Compiler와 같은 개발 도구 뿐만 아니라 

응용 소프트웨어까지 광범위하게 Y2K38 bug free인지 체크해봐야 합니다.


CUBRID와 Y2K38
CUBRID에서는 날짜 시간을 보관하기 위한 여러가지 데이터 타입 (column type)을 제공하는데 
어떤 TYPE이 Y2K38 free인지 아래의 표를 참조하면 됩니다.


 Type

  Bytes  

  Y2K38 Bug Free   

 TIMESTAMP

 4

NO 

 DATETIME

 8

YES 

     TIMESTAMPLTZ    

 4

NO 

 TIMESTAMPTZ

 8

NO 

 DATETIMELTZ

 8

YES 

 DATETIMETZ

 12

YES 



위의 표를 고려할때 다음과 같은 SQL 문은 오류를 발생합니다.

insert into TBL1 values (timestamp'2038-02-01 01:15:45');
insert into TBL1 values (timestampltz'2038-02-01 01:15:45');
insert into TBL1 values (timestamptz'2038-02-01 01:15:45');


다음과 같은 SQL문은 정상 동작합니다.

insert into TBL1 values (datetime'2038-02-01 01:15:45');
insert into TBL1 values (datetimeltz'2038-02-01 01:15:45');
insert into TBL1 values (datetimetz'2038-02-01 01:15:45');


CUBRID에서 제공하는 날짜 관련 여러 data type이 있는 만큼, 정확히 알고 사용하는 것이 좋습니다. 자세한 것은 매뉴얼을 참조하세요 


맺음말

Y2K와 마찬가지로 Y2K38도 사회적 이슈가 되는 문제가 될 것은 명확한 일입니다. 2038년, 당신의 정보시스템은 안전하십니까

올바르게 알고 미리 미리 대처하는 것이 현명한 방법입니다. 검색엔진에 ‘Y2K38’을 입력하세요