반응형

1회성 시간 비교가 아닌 타이머 같은 시스템을 구현할 경우 서버 시간과 클라이언트 시간이 차이가 나거나 이용자의 악의적인 클라이언트 시간 변경에 따른 시간차가 발생할 경우가 예상될 경우 해결방법은 여러가지가 있겠다.
가령 매 초마다 ajax로 호출하여 서버쪽 시간을 받아오고 클라이언트 시간은 사용 자체를 안한다던지
좀 더 투박한 방법이지만 hidden iframe 등을 사용하여 지속 갱신해가며 마찬가지로 클라이언트 시간은 사용 안하는 방법 등등

하지만 두 방법 모두 지속적인 서버 호출이란 단점이 존재하므로 사용하기엔 바람직해보이지 않는다.

아래 소개하는 방법을 요약하자면

  1. 페이지가 처음 로딩될 때 서버시간을 받아온다.
  2. 클라이언트 시간을 추출한 후 서버시간과 클라이언트와의 시간차를(초) 구하여 클라이언트 시간을 보정해주면 그만이다.
  3. 이제 타이머를 동작시키면 정확히 서버와 클라이언트 시간은 일치하게 된다.

그런데 여기서 한가지 문제가 있다.
만약 시간이 지속 경과하는 와중에 페이지가 로딩된 이후 클라이언트 컴퓨터의 시간을 바꿔버린다면 위 로직은 망가져버린다.
때문에 interval함수 내부에는 매번 클라이언트 시간을 구하지 말고 페이지가 로딩될 당시의 클라이언트 시간에 interval의 간격시간만큼 더해주면 깔끔하게 해결된다.

아무리 시간을 앞으로 더하든 뒤로 돌리든 서버시간과 일치하는 타이머가 구현된다.

<%
Function CONVERTDATETIME(objDate, dateFormat)
Dim rtnValue

    if false = IsDate(obj_date) then
        obj_date = now
            end if

            if dateFormat = "" then
                dateFormat = "yyyy-mm-dd h:n:s"
            end if

    rtnValue = Replace(dateFormat, "yyyy", Year(objDate))
    rtnValue = Replace(rtnValue, "mm", right("0" & Month(objDate) , 2))
    rtnValue = Replace(rtnValue, "dd", right("0" & Day(objDate) , 2))
    rtnValue = Replace(rtnValue, "h", right("0" & Hour(objDate) , 2))
    rtnValue = Replace(rtnValue, "n", right("0" & Minute(objDate) , 2))
    rtnValue = Replace(rtnValue, "s", right("0" & Second(objDate) , 2))

    CONVERTDATETIME = reValue
End Function
%>


<script type="text/javascript">
        var tStart = new Date("<%=regESADATE %>");
        var tClient = new Date();

<%
       Dim SERVERTIME
       SERVERTIME = CONVERTDATETIME(Now(), "")
%>

        var tServer = new Date("<%=SERVERTIME %>");
        var rSecond = (tClient.getTime() - tServer.getTime()) / 1000;

        if (rSecond < 0) {
            tClient = new Date(tClient.getTime() + (Math.abs(rSecond) * 1000));    
        } else {
            tClient = new Date(tClient.getTime() + ((rSecond * (-1)) * 1000));
        }

var progressTimerId;

progressTimerId = setInterval(function() {
    var tStart = new Date("<%=regESADATE %>");
    tClient = new Date(tClient.getTime() + 1000);
}, 1000);
</script>
반응형
Posted by Hippalus
,