본 포스트는 HTTP Response Header 의 값 중 서버 시간을 구해서 사용하는 방법에 대한 설명입니다.
클라이언트에서 서버의 시간을 참조할 일이 있을 경우, 서버 API에서 응답값에 현재 시간을 보통 포함시켜서 전달합니다. 하지만 정말로 딱! 시간만 필요한 경우는 아래와 같이 빈 페이지나 빈 API의 Response Header의 Date를 참조하면 손쉽게 서버 시간을 구할 수 있습니다.
인터페이스를 하면 아래와 같이 Response Header가 응답에 포함되어 있습니다.
아래와 같은 식으로 간단하게 Response Header에 있는 Date 값을 구할 수 있습니다.
본 포스트는 JavaScript의 getTimeZoneOffset() 메소드를 사용하여 UTC 시간을 구한 뒤 서버와 클라이언트의 시간을 동일하게 계산할 수 있는 방법에 대한 설명입니다.
요즘 개발하는 서비스들은 대부분 국내에서 뿐만 아니라 해외에서도 사용 가능한 형태로 개발합니다. 해외에서 서비스를 사용하는 경우 뿐 아니라 사용자가 각자 사용하는 Device의 국가, 시간 설정을 대한민국이 아닌 다른 곳으로 해두었을 경우 JavaScript의 new Date() 는 해당 국가 설정을 참조하여 시간을 return 합니다.
현재 제가 사용하는 Device는 대한민국 표준시를 사용하도록 설정되어 있습니다.
이 상태에서 아래 코드의 결과는 다음과 같습니다.
new Date();
//Thu Jun 23 2022 07:36:14 GMT+0900 (한국 표준시)
이번에는 Device의 시간을 미국으로 변경해 보겠습니다.
그러면 동일한 코드는 아래와 같은 결과를 보여줍니다.
new Date();
//Wed Jun 22 2022 17:35:43 GMT-0500 (북미 중부 하계 표준시)
서비스의 성격에 따라 판단할 문제이지만 만약 서버에서 시간을 체크해야 하는데 화면의 Request에서 시간을 받아서 검증이나 사용을 하게될 경우 서버는 대한민국 표준시를 사용하지만, 화면은 북미 중부 표준시를 사용하게 되므로 대한민국 표준시를 사용하지 않는 사용자는 적절하지 않은 오류를 만나게 될 수도 있습니다.
경우에 따라 다르지만 클라이언트 JavaScript 코드에서도 대한민국 표준시로 통일하는 방법이 있습니다.
const now = new Date();
const utcDate = now.getTime() + (now.getTimezoneOffset() * 60 * 1000);
const korDate = new Date(utcDate + 9 * 60 * 60 * 1000);
우리나라는 그리니치 표준시 + 9H를 사용하므로, UTC 기준시각에 9시간을 더해주는 로직입니다.
위와 같이 코드를 작성하면 클라이언트에서 북미 중부 표준시를 사용하더라도 대한민국 표준시를 화면에서 사용할 수 있습니다. 물론 위와 같은 코드보다는 서버의 시간을 Response Header에서 참조하여 변환하는게 좀 더 일반적인 사용 방법입니다.
몇 년 전에도 모 프로젝트에서 지원 요청이 와서 한 번 Code Review 하여 해결을 했었고, 얼마 전에도 운영 중인 시스템에서도 동일한 Case가 있었던 것을 보면 아주 기초적인 사항임에도 생각보다 잘 지켜지지 않는 부분일 수 있겠다는 생각이 듭니다.
jQuery 사용
대기업에서 SI 프로젝트에 몸 담고 있다보면, 혹은 대기업 SI 프로젝트에서 개발한 시스템을 인수하는 운영 담당자의 역할로 있다보면 서비스 기업들에서 많이들 사용하는 Vue, React 등의 Framework, Library는 구경하기 힘들고 2022년인 현재도 많은 프로젝트들이 jQuery 기반으로 진행되는 것을 알 수 있습니다.
대규모 SI 프로젝트의 경우 개발자가 수십~수백 명에 이르는데 Vue나 React를 사용하는 개발자들을 충분히 소싱하기 힘들고, 상용 UI 솔루션들과 연계해야 하는 상황에서 아직 jQuery 기반으로 제공되는 솔루션들이 많아 어쩔 수 없는 선택이 되곤 합니다.
(사실 Zepto 등의 경량 Library도 고려 대상일 수 있겠으나, 이미 검증된 수많은 Plug-in이 있다는 점은 SI 프로젝트에 너무 매력적인 요소로 작용하는 듯 합니다.)
jQuery 기반의 프로젝트에서 업무 화면이 복잡해져서 하나의 프로그램에서 수행하는 XHR과 calback이 많아지면 아래와 같은 문제들이 종종 발생하게 됩니다.
화면 특정 영역에 데이터가 나오다 말다 해요
A와 B 두 개의 function이 있습니다. A function은 DOM을 초기화하는 function이고, B function은 서버에서 데이터를 받아와 A function이 구성한 DOM에 Data를 Bind하는 역할을 하는 function 입니다.
function A() {
// 특정 조건에 따라 UI에 특정 영역을 표시하거나 제거합니다.
}
function B() {
// $.ajax 등의 함수로 서버와 통신하여 A 영역에서 생성한 DOM에 Data를 Bind 합니다.
}
생각보다 많은 개발자들이 아래와 같이 작성하고 (물론 위와 같이 너무 단순한 구조는 아닙니다만), 사실 또 대부분의 경우에 연산은 또 순식간에 일어나므로 올바르게 동작합니다.
A();
B();
하지만 복잡한 Front-end 프로그램을 개발하다 보면 아주 많은 경우의 수가 발생합니다. 사용자의 휴대폰이 구형이라 브라우저의 동작 자체가 느린 환경도 있고, 데이터 음영 구간도 있고, 접속 상태가 좋지 못한 Wi-Fi를 사용하여 Network가 느린 경우도 있어 반드시 작성한 순서대로 실행을 보장하지는 않습니다.
Callback function 사용
순서가 반드시 보장되어야 하는 코드들은 정확히 실행해야 하는 타이밍을 callback function을 사용하여 구현합니다.
위와 같은 경우에도 A function에서 생성해야 할 DOM이 생성되지 않은 상태에서 B function의 Data bind가 수행이 되는 경우가 발생하면 해당 영역에는 올바르게 Data를 표시하지 못하는 경우가 발생합니다.
순서를 보장하기 위해서는 아래와 같이 작성합니다.
function A(callback) {
//특정 조건에 따라 UI에 특정 영역을 표시하거나 제거합니다.
if (callback && typeof callback === 'function') callback();
}
function B() {
//$.ajax 등의 함수로 서버와 통신하여 A 영역에서 생성한 DOM에 Binding 합니다.
}
A(B);
위와 같은 형태로 작성하면 DOM을 구성하는 작업이 완료된 후 B function을 실행하므로 화면을 올바르게 표시할 수 있습니다.
사실 수백~수천 라인에 달하는 프로그램에서 모든 순서가 정확하게 보장되기가 쉽지가 않습니다. 이 과정에서 callback 지옥 역시 발생합니다. ES6+에서는 async/await, Promise를 사용하여 이런 callback 지옥 구조를 많이 개선했지만 아직 많은 대고객 서비스에서는 I.E를 지원해야 하기 때문에 여전히 callback 지옥을 헤어 나오기는 힘듭니다.