Timestamp 와 Datetime
Timestamp와 Datetime 이슈
Timestamp
와 Datetime
의 가장 큰 차이점은 timezone
의 정보의 유무이다.
우리 팀이 구현한 API 서버의 로직은 Java
코드에서 LocalDateTime.now()
를 호출하여 API 서버 컴퓨터의 timezone
의 시간 정보를 이용하여 LocalDateTime 객체를 생성하고, timestamp
타입의 created_at
컬럼에 데이터를 넣는 방식으로 구현되어 있다.
AWS에 API 서버를 배포하고 테스트하니, created_at에 데이터가 기대했던 값과 달리 -9시간으로 처리되어 보이는 문제가 발생했다.
이는 AWS에 만든 인스턴스의 기본 timezone
환경 변수가 UTC
로 설정되어 있었기 때문이다.
ubuntu
의 timezone
설정을 여러가지 방법으로 바꿔보고, terminal
창에서 date
명령어를 입력하여 KST
로 변경된 것을 확인하고, 계속 시도해 보았으나 해결에 어려움을 겪었다.
정규 시간이 끝나고 테스트 하며 알아보니, timezone
변수를 수정했던 작업들이 ubuntu OS상에서 표시 되는 설정만 건드렸을 뿐, 실제 java
코드가 사용하는 시스템 환경변수는 변경되지 않았던 것이 문제 였던 것 같다.
Java
코드에서 LocalDateTime
은 해당 실행 환경 컴퓨터의 timezone
설정을 따라가는데, timezone
설정을 KST
로 변경했지만, Java
가 바라보는 timezone
설정은 계속 UTC
로 되어 있어, Java
단에서 잘못 된 시간으로 쿼리문이 만들어졌던 것이다.
## 테스트 과정..
우선 위와 같이 테스트용 java
코드를 만들고, ubuntu 서버의 timezone
환경 변수를 변경하며 테스트를 진행했다.
1. tzselect 설정 방법
$ sudo tzselect
Asia/Seoul
로 변경 했음에도 java
가 바라보는 timezone
은 UTC
인 것을 확인할 수 있다.
하지만 date
명령어를 입력하면?
KST
시간으로 나오고 있다. 이 때문에 환경 변수가 제대로 변경 되었다고 착각하게 되었고, 어려움을 겪었다.
2. ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime 설정 방법
$ sudo ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime
마찬가지로, java
는 아직 UTC
로 인식하고 있다.
3. timedatectl set-timezone 'Asia/Seoul' 설정 방법
$ sudo timedatectl set-timezone 'Asia/Seoul'
생각이 꼬여 어려웠던 부분
며칠 전 Timestamp
와 Datetime
의 차이에 대해서 학습할 때, 가장 큰 차이는 timezone
의 반영유무 이다. 라는 말을, timestamp
는 저장되는 data 자체에 timezone
의 정보가 들어있는 것이라 생각을 하고 테스트를 진행하다가 안맞는 부분들이 너무 많아서 한참을 헤맸다. 이는 틀린 생각 이였고,
DB는 단순히 timestamp
타입의 컬럼 데이터를 저장할 땐, 쿼리로 들어온 문자열 값을 UTC
형태로 변환하여 저장하고, 읽어들일 땐 저장된 UTC
형태의 데이터에 호출 시점의 DB timezone
시간을 반영하여 반환하는 작업을 할 뿐이다.
그렇기 때문에 테이블 하나에 전 세계 사람들의 게시글 data와 작성 된 시간을 저장해놓고, 나라마다 알맞은 시간으로 보일 수 있게끔 반환 한다는 건 timestamp
컬럼 하나 만으로는 불가능한 일 이였다.
생각해 본 예제, timestamp를 적용하여 만들 수 있는 서비스
-
DB는 1개로 두고,
timezone
설정은UTC
로 설정한다. -
테이블을 나라별로 구분하여,
한국에서 쓴 글을 모아둔 테이블
,미국에서 쓴 글을 모아둔 테이블
... 형태로 만들어 각 나라에서 글을 작성한 시간을 저장해둔다.
서버에서 DB로 연결할 때 각각의 연결마다 별도의 timezone
을 설정하면 테이블에 저장되어 있는 글 작성 시간을 각 나라에 맞는 시간으로 제공할 수 있을 것이다.
결국 우리가 신경써야 할 점은, 쿼리문을 전달하여 timestamp
컬럼에 데이터를 넣을 때, 시간을 '2022-04-12 22:15:00'
의 형태로 만들어진 것을 넣어주느냐, 아니면 쿼리문에서 now()를 호출하여 DB 서버 자체에 설정 된 timezone
을 이용하여 시간을 넣어줄 것이냐만 신경쓰면 된다.
전자의 경우, java
단에서 각 나라별 timezone
에 맞는 현재 시간을 생성하여 쿼리문에 넣어주기만 하면 깔끔하게 처리가 가능하다.
후자의 경우 now()를 사용하게 되면, DB 서버의 timezone
설정을 신경써서 시차에 맞게끔 쿼리문에 들어갈 시간 오차를 넣어주는 처리를 추가 해야함을 신경써야 한다. 아래와 같은 형태처럼 말이다.
insert into task (..., created_at) values (... ,CONVERT_TZ(now(),'+00:00','+09:00'));
결국 글로벌로 제공해야 하는 서비스를 만들 때 timestamp
형식을 채택한다면
-
한국에 사는 A
와,일본에 사는 B
가 글을 동시에 작성한다면,미국에 사는 C
가 2개의 글을 읽더라도 각각1분 전 작성된 글 입니다.
라고 표시하는 처리가 수월할 것이다. -
참조 :
Author And Source
이 문제에 관하여(Timestamp 와 Datetime), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@kyu/Timestamp-와-Datetime저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)