늘모자란, 개발 :: issue - when local time not matched server side time

늘모자란, 개발

제목을 영어로 하는데 문법이 맞나 안맞나도 잘 모르겠다.
국내에서만 서비스하면 상관없겠지만, 해외에서도 서비스를 사용하고자 하는 사람도 있다.
대개는 문제가 없다. 왜냐면 서버에서 요구하는데로 보여지기 때문인데, 클라이언트에서 timer등을 이용해 유저에게 보여지는 식으로 구성했을때는 문제가 된다

요컨데 싴갤러스- 밀수업자 기능에서 사용하고 있는 방법은,
먼저 서버에서 데이터를 받아와 표를 만들고, 마지막 데이터를 로컬 시간에 저장해놨다가 그 시간까지 타이머를 돌리는 반영구적인 타이머를 구성해두었다. 하지만 서버에서 반환하는 값은 서버사이드의 시간이고, 로컬에서 처리하는 시간은 컴퓨터의 시간을 읽으니까, 타이머의 역할을 수행하지 못하는 버그(?) 가 있었다

이를 처리하기 위해서 처음에는 new date().getTime() 을 서버 사이드로 보내고, 서버 사이드에서 diff를 처리하는 식으로 수행했다

클라이언트
var d = new Date();

$.ajax...
data: { "date" : d.getTime(); }
...


서버(PHP)
$diff = (time() - round($_POST['date']/1000))*-1;
if ( $diff > 0 ) { $diff = "+".$diff; }

strtotime(TIME."$diff seconds");


이렇게 하면 로컬에서 보내는 시간과 서버의 초 차이를 계산해, 서버 사이드에서 데이터를 계산해 출력해주게 된다.
근데 이상하게 잘 안되었다. 분명히 클라이언트와 서버시간이 달라야하는데, 같은 값을 받을때가 더 많았다. 결론은, 실패였다
(테스트를 컴퓨터 시간을 바꿔가면서만 테스트 했기 때문일지도 모르지만 크게 다를것이라고 생각하진 않음)

그래서 두번째로 시도한것은,
서버에서 시간을 당겨와 현재 로컬타임을 계산해버리자는 것이었다.
jquery에서 ajax로 임의 페이지에 질의하면 header에는 반드시 date 헤더가 실려오게 된다. 이를 js 로 다시 파싱하면 서버기준으로 시간을 처리할 수 있게 된다. 원래 이런 목적은 type에 head를 사용해주면 되는데, forbidden 이 뜬다. 그래도 시간 얻는데는 문제가 없으니..

$.ajax { ...
  success: function (dt, status, request) {
      servertime = request.getResponseHeader('date');
}


이런식으로 servertime을 얻어서 처리하면 되는데 ajax이기때문에 callback과 async에서 짜증을 겪을 수 있다. 적절히 처리하면 되긴하지만..

그런 다음,
data: { "date" : (d.getTime()/1000) - (new Date(servertime).getTime()/1000) },


이렇게 클라이언트에서다 처리해서 보내주기로 했다. 그러나, 처음했던 것 처럼 시간이 제멋대로 놀아나는 바람에 역시 제대로 계산되지가 않았다. 조금 더 고민해보다가.. 애초에 지역으로 나뉜 시간을 쓴다면 해당 지역의 offset을 보내줘버리고 내가 모두 처리해버리자 싶어서 검색하다가 다음을 찾았다

data: { "date" : d.getTimezoneOffset() },


이렇게 하면 현재 로컬 시간이 gmt와 얼마나 차이나는지 알려준다. 우리는 한국시간이니까 -540이 리턴된다. 나누기 60 하면 9니까..
그래서 서버에서 540을 기준으로 잡아놓고, 로컬 시간과 서버 사이드 시간이 얼마나 차이가 나는지 확인하면 된다

$diff = (540 + ((int)$_POST['date']))*-1;


아주 어려운 코딩은 아니었지만, 해외 유저들을 전혀 고려한적조차 없었고 (문제가 될줄도 몰랐기 때문에), 많이 당황했던 하루였다.
로컬에서 시간 관련 타이머를 사용한다면 반드시 고려해보자

2017/09/03 04:52 2017/09/03 04:52