티스토리 뷰

timezone 때문에 짜증나서 남겨놓는다.

내가 현재 당면하고 있는 일은, 간단하게 말하자면 이렇다.

google dataproc 에 cluster 작성 → cluster 에 spark job 을 보내서 대용량 계산(흔히 말하는, 뭐 있어 보이는 빅데이터 처리 근데 별거 아닌게 함정)  계산결과


내가 처리하는 데이터는 전세계에서 온다. 

독일에서도 오고, 일본에서도 오고, 아마도 미국에서도 올거고 하여튼 이곳저곳에서 온다.

현대를 살아가는 사람들이라면 알겠지만, 지구는 둥그니까 자꾸자꾸 걸어 나가면 내가 가진 시계와 현지의 시계가 맞지 않다는 것을 알 수 있을 것이다.. 각 국가 혹은 지방의 시계 local time, 지방시 地方時 (Givenchy 아니다) 가 있고, 그 때문에 각 국가마다 시차(time difference)가 있기 때문이다.


어떤 역사로 이렇게 되었는지는 기억이 잘 나지 않지만.. 영국 런던의 그리니치 시간(GMT 혹은 UTC)을 기준으로 거기에서 동쪽으로 가면 시간이 빨라지고, 서쪽으로 가면 시간이 느려지게 된다. 해는 동쪽에서 떠서 서쪽으로 지기 때문에, 동쪽이 더 빨리 해를 보게 된다. 

ex) KST(한국)과 JST(일본)은 GMT+9 혹은 UTC+9이다. 런던보다 9시간 빠르다.


착한 어른이들은 해가 동쪽에서 부터 보이기 시작하면 잠에서 깨어나고 해가 서쪽으로 내려가면 자는 습관을 가지고 있기 때문에 그 때를 수치화 해 두면 살기 편했을 것이다. 각 지방마다 태양이 하늘 중천에 떠있는 시간을 오후 12시라고 정해놓고 살면, 옆집 친구에게 오전 10시 혹은 오후 3시에 어디서 만나서 커피 한잔 하자 라고 약속을 만들기 쉬웠을 것이다. 마치 해시계.

이것은 사람들이 좁은 지역에서 살아갈 때는 참 편하다. 해와 지구는 엄청나게 멀리 떨어져 있어서 내가 있는 곳에서 1km 떨어진 곳에서 해를 봐도 해의 위치는 변하지 않기 때문이다. 그래서 같은 지방의 친구와 언제 어디서 만나자고 해도 문제가 없다. 


하지만, 교통이 발전해서 (증기기관차나 비행기 따위의 발명)되어 사람들의 생활 반경이 넓어지게 되었다. 파리와 베를린이 증기기관차로 1시간 거리라고 가정해 보자. 파리에 사는 P와 베를린에 사는 B가 베를린에서 해가 중천에 떠 있는 12시에 만나기로 약속을 했다. 그래서 P는 해가 중천에 뜨기 1시간 전에 기차를 타고 동쪽으로 달려갈 것이다. 파리에서 베를린 까지는 증기기관차로 1시간이 걸리고, 자기가 있던 곳에서는 아직 해가 중천에 뜨려면 1시간이 남았기 때문이다. 하지만, 베를린에 가보니 해는 중천을 이미 지난 상태이다. 이것은 자기의 지방시만을 고려했기 때문에 생기는 문제이다. 내가 지금 회사에서 노예짓 하고 있다고 지구 반대편에 있는 친구에게 전화해 '야 너 왜 근무시간에 자' 라고 말하면 욕 먹을 것이다.



전세계는 지금도 동일하게 매초매초 시간이 흘러가고 지구의 사람 모두가 동일한 순간을 살아가고 있는데, 한국/일본은 11시, 영국은 2시.. 이런식으로 같은 순간인데도 다른 시간을 가리키고 있다. 2시인 영국은 사람이 자는 시간이겠지. 하지만 모두 같은 순간을 살고 있다. 이렇게 각 지방시가 있는 것은 나같이 전세계의 데이터를 모아서 처리를 해야하는 사람에게는 굉장히 힘든 것이다.

내가 처리해야 할, 각 국가에서 오는 데이터에는 시간정보도 같이 들어 있는데, 어디는 시간을 UTC로 보내고, 어디는 JST로 보내는 것이다.


근데, 나와 같이 시간을 다뤄야 하는 사람들은 지구의 변방 표준시인 KST 나 JST 같은 local time 말고, 세계표준인 UTC를 쓰는게 제일 안전하다. 각 순간순간을 사람이 느낄 수 있는 몇시 몇분 이런게 아니라, 숫자로 그 순간을 가리키고 있기 때문이다.


배경지식은 이정도로.

1. date 명령어를 이용해 각 머신에 지정된 시간대(timezone)를 확인해 볼 것이다.

2. 내가 실제로 작업에 사용하는 것은 spark이기에, spark-shell 을 기동시켜 간단히 동작을 확인해 보았다.


테스트1 (개인 맥북을 이용)

date 명령어는 머신에 지정되어 있는 시간을 가져온다. JST 라고 적혀 있는 것이 보일 것이다. JST 는 UTC 에 9시간을 더한 시간이다. 

unixtime 은 1970-01-01 00:00:00 UTC로 부터 지난 시간을 초 단위로 알려주는 것이다. 즉 입력된 시간이 1970-01-01 00:00:00 부터 몇초 지난 시간일까요? 이다. 이것이 순간순간을 알려주는 시간이라고 볼 수 있다.

이 머신에서는 a : 1518152144, b : 1518120000 라는 값을 얻었다.


테스트2 (google dataproc : asia-northeast1)

이 머신에서도 date를 쳐서 시간대를 보니 UTC로 나온다. 즉 여기에 입력된 시각은 전부 UTC로 자동인식한다는 말이다.

같은 날, 같은 시를 unixtime으로 변환해 보았다.

이 머신에서는 a : 1518184544, b : 1518152400 라는 값을 얻었다.


결론

각 테스트에서 얻은 결과를 가지고 계산을 해보자.

a : 1518184544 - 1518152144 = 32400

b : 1518152400 - 1518120000 = 32400


머신환경에 따라 a, b 각각 32400 라는 값의 차이가 있다. 위에서도 말했듯이, 이것은 초다. 즉 동일한 입력값인데도, 머신에 따라 출력값이 다르다는 것을 알 수 있다. 또한, google dataproc 에서 계산 한 값이 개인 맥북에서 보다 32400초 지난 시각으로 나온다. 


32400초는 얼마나 긴 시간일까?

1시간은 60분, 1분은 60초이다. 즉 1시간은 3600초이다. 

32400초 / 3600초 = 9시간

9시간의 차이가 난다.


개인 맥북은 unix_timestamp으로 입력받은 값을 JST라고 지 멋대로 판단해 9시간을 빼서 그것을 초로 바꾸었다.

google dataproc 은 unix_timestamp에서 입력받은 값을 UTC라고 판단해 9시간을 빼지 않고 그대로 둔 채로 초로 바꾸었다.


시간 계산은 정말 귀찮으면서 머리 아프게 만든다. 데이터에 시간 정보가 들어있는 경우에는 꼭 UTC 혹은 unixtime으로 처리하도록 하자. 데이터 받는 쪽에서 이게 우리쪽 지방시인지, 보내는 쪽 지방시인지, 아니면 UTC 인지 헷갈리게 된다. 그리고 spark 를 구동하는 머신의 시간대도 맞춰서 계산해 주는 것이 굉장히 중요하다.


사실 a로 입력된 시간은 JST를 의도했고, b는 UTC였다. 어느 회사는 UTC로 보내고, 어느 회사는 JST로 보내기 때문에.. 내부적으로 9시간을 빼서 UTC로 맞춘 후 작업을 진행해야 한다. 후... 다시 한번 말하지만, 시간계산을 할 때에는 데이터도 머신도 UTC 혹은 unixtime 으로 통일 시켜놓고 하는게 제일 안전하다.

댓글
댓글쓰기 폼