레이블이 날짜인 게시물을 표시합니다. 모든 게시물 표시
레이블이 날짜인 게시물을 표시합니다. 모든 게시물 표시

2015년 6월 27일 토요일

국제화된 소프트웨어에서 날짜와 시간을 다루는 방법 (18)

개발자들이 소프트웨어를 개발하면서 가끔 하는 실수 중 하나가 현지 시간을 저장했다가 나중에 소프트웨어가 확장되면서 꼬이는 것이다. 보통의 소프트웨어라면 시간에 그렇게 민감하지 않다. 하지만 일정관리, 항공권 예약, 배송 시스템 등 시간에 민감한 소프트웨어들이 있다. 이 외에도 시간을 신경 써서 다뤄야 하는 소프트웨어가 많다. 이런 소프트웨어에서 시간의 기록과 처리를 현지 시간을 기준으로 처리를 하다가는 문제가 발생하고 꼬이게 된다. 



여기서 현지 시간이란 날짜와 시각을 모두 의미한다. 또 현지 시각은 그레고리력을 기준으로 하는 날짜 일 수도 있고 해당 나라에서 사용하는 독특한 달력을 기준으로 한 날짜일 수도 있다. 개인 혼자서 쓰는 시스템, 예를 들어 일기장과 같은 소프트웨어라면 문제가 안되지만 전세계 여러 사용자가 공유하는 시스템이라면 시간의 표시가 지역마다 다르게 표시되어야 한다. 또한 혼자 사용하더라도 일정 관리 소프트웨어 같은 경우에는 지역을 옮겨 다닐 때마다 현지 시간에 맞게 보정해서 보여줘야 한다.

그래서 시스템에 시간을 저장할 때는 절대 시간을 기록해야 한다. 소프트웨어에서 절대 시간이란 유닉스 시간을 말한다. POSIX 시간이라고도 부른다. 유닉스 시간은 영국 그리니치 천문대에서 그레고리력으로1970년 1월 1일 0시 0분 0초에 0으로 시작된 시간 표시로 1초에 1씩 증가한다. 예를 들어 한국에서 2015년6월5일 오전2시16분37초의 유닉스 시간은 1433524597이다. 거의 모든 OS와 Database에서는 유닉스 시간을 기준으로 시간을 처리한다. 그리고 화면에 출력할 때 타임존을 고려하여 변환하여 출력한다. 

따라서 시간을 기록할 때는 유닉스 시간을 얻어와서 DB나 파일에 저장을 하고 입출력 시 사용자의 입맛에 맞게 변환을 해야 한다. 출력 시에는 예를 들어 아래와 같은 변환 과정을 거쳐야 하고, 입력 시는 반대 과정을 거친다.


(유닉스 시간 10억초 달성 기념)

1. 유닉스 시간 : 1433524597
2. 협정 세계시 : 2015-06-05 17:16:37 UTC
3. 달력 변환 : 2015-06-05 17:16:37 UTC
4. 한국의 타임존 : 2015-06-06 02:16:37+09:00(or PDT)
5. 한국의 시간포맷 : 2015년 6월 6일,오전 2시 16분 37초

1~4번까지는 소프트웨어 내부에서 일어나는 변환 과정이고 5번이 사용자에게 보여지게 된다. 또한 형식은 언어(로케일)별로 다르다.

달력 변환에서 그레고리력일 경우에는 변환할 필요가 없지만 사용자가 그레고리력이 아닌 다른 달력을 사용하는 경우에는 변환이 필요하다. 예를 들어 일본 일왕의 연호나 불기, 음력을 사용한다면 변환이 필요하다.

개발 환경 즉, 개발 프레임워크나 라이브러리에서 제공하는 시간 함수들은 여러가지가 있고 위 변환 과정을 거의 모두 지원하는 것도 있고 일부만 지원해서 개발자가 추가로 개발을 해야 하는 경우도 있다. 대부분은 유닉스 시간과 타임존 변환은 제공하지만 달력 변환을 지원하는 경우는 거의 없고 로케일별 시간 포맷 제공도 프레임워크마다 제각각이다. 개발자가 상당한 세심한 신경을 써야 하는 이유다.


(타임존 지도)

그 외에 일정관리나 항공권예약 시스템에서는 시간과 관련해서 좀더 많은 정보를 보관해야 한다. 매 시간마다 위치나 타임존을 기록해서 하나의 시간에 대해서도 현지 시간과 현재 사용자가 있는 위치의 시간을 동시에 보여주기도 한다. 국제화가 잘된 소프트웨어에서는 시간 처리에 여러 가지 신경을 써야 한다.

그럼 국가별, 로케일별로 시간 표시 형식은 어떨까? 우선 로케일별 국가 이름을 보자

ar_SA : 사우디아라비아
de_DE : 독일
en_US : 미국
es_ES : 스페인
fr_FR : 프랑스
id_ID : 인도네시아
it_IT : 이탈리아
ja_JP : 일본
ko_KR : 대한민국
pl_PL : 폴란드
pt_PT : 포르투갈
ru_RU : 러시아
vi_VN : 베트남
zh_CN : 중국
zh_TW : 타이완
de_LI : 리히텐슈타인
th_TH : 태국

로케일(국가)별 시간 형식의 예는 다음과 같다. 

ar_SA : " ٣:٠٢:٢٧ م"
de_DE : "15:02:27"
en_US : "3:02:27 PM"
es_ES : "15:02:27"
fr_FR : "15:02:27"
id_ID : "15.02.27"
it_IT : "15:02:27"
ja_JP : "15時02分27秒"
ko_KR : "오후 3시 2분 27초"
pl_PL : "15:02:27"
pt_PT : "15:02:27"
ru_RU : "15:02:27"
vi_VN : "15:02:27"
zh_CN : "下午3时02分27秒"
zh_TW : "下午3時02分27秒"
de_LI : "15:02:27 "
th_TH : "15 นาฬิกา 2 นาที 27 วินาที "

위 시간의 포맷은 특정 Framework를 사용한 한 예다. 

물론 모든 소프트웨어가 위에서 언급한 타임존, 특수한 달력, 지역에 맞는 형식을 모두 지원하는 것은 아니다. 또한 우리가 만드는 소프트웨어도 모두 지원해야 하는 것은 아니다. 소프트웨어 성격과 판매 지역, 전력에 따라서 지원해야 하는 범위를 개발 초기에 결정해야 한다. 그래야 소프트웨어 국제화가 성공적으로 진행될 수 있다.

날짜 표기 국제 표준은 무엇일까? (14)

지난 12회에서 국가별, 로케일별로 날짜 표기 형식이 매우 다르다는 것을 보았다. 하지만 이런 방식을 따르기만 한다고 해서 날짜 표기 형식 문제가 모두 해결되는 것은 아니다. 시스템에서 제공하는 날짜 표기 형식이 실제로 해당 국가에서 오류라고 생각할 수도 있고, 입력 시 사용자의 실수로 인한 혼동도 무시 못한다.

그래서 국제화가 잘 된 소프트웨어에서는 날짜 형식에 대해서 조금 더 고민을 해야 한다. 우선 날짜를 출력하는 방법은 크게 3가지가 있다. 각각 장단점이 있다.

첫 번째 지난번 12회에서 봤듯이 로케일별로 각각 다른 날짜 형식으로 출력을 하는 것이다. OS나 개발툴, 라이브러리에 따라서 그 형식이 조금씩은 다르지만 웬만큼은 현지에서 받아들여 질만한 형식을 제공한다. 장점으로는 개발자가 날짜 형식을 직접 연구하고 다루지 않기 때문에구현이 상대적으로 간단하다. 하지만 단점으로는 라이브러리나 프레임워크에 따라서 제공하는 포맷이 일정하지 않고 원하는 날짜 형식을 제대로 제공하지 못할 수도 있다. 또한 그렇게 제공한 날짜 형식에 버그가 있을 경우 개별적으로 수정을 해야 하는 번거로움이 있다.
C에서는 strftime()함수를 사용하거나 QT Framework에서는 QDate::toString() 함수를 이용할 수 있다. 




두 번째사용자가 날짜 형식을 선택하거나 직접 입력하도록 하는 방식이다. 개발자가 완벽하게 사용자가 원하는 날짜 포맷을 제공하는 데는 한계가 있다고 생각하고 그 책임을 사용자에게 맡기는 것이다. 예를 들어 yyyy/MM/dd 라고 지정을 하면 2015/05/27이라고 출력을 할 것이다. 유독 월을 표시하는 M만 대문자인 이유는 분을 표시하는 m(minute)와 구분하기 위해서이다. 이 경우에도 요일과 월은 숫자가 아니라 문자로 표시를 할 수 있으므로 똑 같은 형식이라도 로케일별로 다르게 표시가 된다. 
소프트웨어에서 몇 가지 날짜 형식을 보여주고 사용자가 고르는 방법도 있고 사용자가 완전히 자유롭게 형식을 편집할 수 있도록 할 수도 있다. 물론 고르는 방법이 구현도 편하고 좀더 안전하다. 이 방법의 장점은 개발자가 각 나라의 날짜 형식에 대해서 너무 고민할 필요가 없는 것이다. 단점으로는 사용자가 뭔가 선택을 해야 하는 불편함이 있고, 사용하는 개발언어나 라이브러리에 따라서 날짜 포맷 표기법이 조금씩 다르다는 것이다.
그래서 첫 번째 방법과 두 번째 방법을 섞어서 사용하기도 한다.




세 번째국제 날짜 형식 표준을 이용하는 방법이다. 국제화된 소프트웨어를 개발할 때는 항상 날짜 표시 문제가 있다. 그래서 1988년도에 국제 날짜 표준 형식이 제안되었고, ISO8601이 발표되었다. ISO8601에서는 여러 가지 날짜와 시간의 표준 형식을 다루고 있다. 먼저 국제 날짜 표준 형식은 어떤 것인지 보자.
날짜는 2015-05-28과 같이 YYYY-MM-DD의 형식을 따르고 있다. 연도가 뒤에 있을 경우에는 앞에 온 숫자가 월일지 일일지 헷갈리지만 연도가 맨 앞에 오면 전세게 거의 모든 사람들이 연-월-일로 인식을 한다. 물론 예외는 있을 것이다. 이런 국제 날짜 표준 형식은 우리나라에서 흔히 사용하는 형식이라서 다행이다. 
시간과 같이 표시를 할 때는 2015-05-28T09:15:52와 같이 중간에 “T”를 넣어서 표시한다. Time Zone을 포함해서 2015-05-28T09:15:52+09:00과 같이 표시하는 방법도 있다. 기간을 표시하기 위해서 우리는 흔히 ‘~’를 사용하는데 ISO8601에서는 ‘/’를 사용한다. 2015-05-28/2015-06-28과 같이 표시한다.
이렇게 국제 표준 날짜 형식을 사용하면 소프트웨어를 개발하기 매우 편리하다. 나라별, 로케일 별로 고민을 할 필요가 없고 이로 인한 혼란이나 버그가 거의 없다. 하지만 고집이 센 나라에서 받아들여지지 않고 버그로 보고가 될 수도 있는 단점이 존재한다.

위의 모든 경우에 입력의 문제는 여전히 존재한다. 국제화가 잘된 소프트웨어에서도 흔히 날짜 입력의 문제를 해결하지 못하는 경우가 많다. 날짜 출력은 그 나라의 문화에 알맞게 지원을 하는데 날짜 입력에서 제대로 된 형식을 지원하지 못하는 경우도 흔하다. 또한 날짜 입력은 사용자의 실수를 무시할 수 없다. 그래서 날짜는 날짜 선택기 위젯 같은 것을 이용해서 마우스 클릭을 통해서 사용자가 날짜를 선택하게 하는 UI를 제공하는 것이 좋다. 물론 날짜 선택기가 그레고리력만 제공하는지 그 외의 달력도 제공하는지 이슈가 있기는 하다. 또한 날짜 선택기도 지역화를 제공해야 한다.




위에서 어떤 방식을 제공할지는 소프트웨어의 성격 및 회사의 전략에 따라서 달라질 수가 있다. 단, 일단 개발을 해 놓고 문제가 있다고 고치기 시작하면 이미 좀 늦은 것이다. 사전에 국제화 전략을 정해서 제대로 적용하는 것이 가장 효율적인 방법이다.