Timestamp
와 Datetime
의 가장 큰 차이점은 timezone
의 정보의 유무이다.
우리 팀이 구현한 API 서버의 로직은 Java
코드에서 LocalDateTime.now()
를 호출하여 API 서버 컴퓨터의 timezone
의 시간 정보를 이용하여 LocalDateTime 객체를 생성하고, timestamp
타입의 created_at
컬럼에 데이터를 넣는 방식으로 구현되어 있다.
AWS에 API 서버를 배포하고 테스트하니, 기대했던 값과 달리 데이터가 -9시간으로 처리되어 보이는 문제가 발생했다.
이는 AWS에 만든 인스턴스의 기본 timezone
환경 변수가 UTC
로 설정되어 있었기 때문이다.
ubuntu
의 timezone
설정을 여러가지 방법으로 바꿔보고, terminal
창에서 date
명령어를 입력하여 KST
로 변경된 것을 확인하고, 계속 시도해 보았으나 해결에 어려움을 겪었다.
테스트 하며 알아보니, timezone
변수를 수정했던 작업들이 ubuntu OS상의 timezone
설정을 바꾼 것일뿐, 실제 java
코드가 사용하는 jvm timezone
환경변수는 변경되지 않았던 것이 문제 였던 것 같다.
Java
코드에서 LocalDateTime
은 해당 실행 환경 컴퓨터의 timezone
설정을 따라가는데, timezone
설정을 KST
로 변경했지만, jvm
이 바라보는 timezone
설정은 계속 UTC
로 되어 있어, Java
단에서 잘못 된 시간으로 쿼리문이 만들어졌던 것이다.
우선 위와 같이 테스트용 java
코드를 만들고, ubuntu 서버의 timezone
환경 변수를 변경하며 테스트를 진행했다.
$ sudo tzselect
Asia/Seoul
로 변경 했음에도 java
가 바라보는 timezone
은 UTC
인 것을 확인할 수 있다.
하지만 date
명령어를 입력하면?
KST
시간으로 나오고 있다. 이 때문에 환경 변수가 제대로 변경 되었다고 착각하게 되었고, 어려움을 겪었다.
$ sudo ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime
마찬가지로, java
는 아직 UTC
로 인식하고 있다.
$ sudo timedatectl set-timezone 'Asia/Seoul'
1000-01-01 00:00:00
부터 9999-12-31 23:59:59
까지 지원1970-01-01 00:00:01
부터 2038-01-19 03:14:07
까지 지원Datetime
과 Timestamp
의 차이는, Timestamp
는 DB에 설정 된 time_zone
환경변수를 기반으로 데이터가 변경된다는 점 이다. time_zone
설정에 의존하기 때문에 2011-08-21 14:11:09
라는 데이터가 Datetime
컬럼과, Timestamp
컬럼에 각각 저장되어 있는 상태에서
SET TIME_ZONE = "america/new_york";
Query OK, 0 rows affected (0.00 sec)
위와 같은 형태로 time_zone
설정을 변경해주면,
select * from datedemo;
+---------------------+---------------------+
| mydatetime | mytimestamp |
+---------------------+---------------------+
| 2011-08-21 14:11:09 | 2011-08-21 01:11:09 |
+---------------------+---------------------+
1 row in set (0.00 sec)
timestamp
타입으로 설정한 데이터의 저장값이 변경된다.
timezone 설정은, OS 수준에서의 설정, Mysql 자체 설정 변경, 접속하는 클라이언트 수준에서의 변경의 방법이 있다.
현재 테스트에 사용한 DB는 timezone
설정이 되어 있지 않은 상태이다.
DB 설정이 되어 있지 않은 경우, SYSTEM 환경 변수 설정을 따라가게 되어 있다. timezone
설정의 우선 순위는
의 우선순위를 갖고 있다.
우리가 Java
코드에서 DB와 연결을 맺을 때 DB url을 입력하고 뒤에 붙는 serverTimezone 설정이 사용자 수준의 timezone
설정이다.
String url = "jdbc:mysql://localhost/testDB?serverTimezone=UTC";
글로벌로 제공해야 하는 서비스를 만들 때
timestamp
형식을 사용하면 좋다.
해당 내용을 보고 서비스 제공을 가정하여 timestamp
형식을 사용하여 장점이 될 수 있는 상황을 생각해보았다.
한국에 사는 A
와, 일본에 사는 B
가 글을 동시에 작성한다면, 미국에 사는 C
가 2개의 글을 읽더라도 각각 1분 전 작성된 글 입니다.
표시하는 처리를 수월하게 할 수 있다?timezone
설정을 UTC
로 설정한다.UTC
시간을 담은 insert 쿼리를 DB 서버로 보낸다.이렇게 하면, 어느 나라에서 글을 작성해도 일정한 UTC
기준의 시간이 DB에 저장 될 것이다. 이 후 클라이언트 서버에서 DB의 데이터를 불러올 때 요청한 User의 locale 을 참고하여
String url = "jdbc:mysql://localhost/testDB?serverTimezone=Asia/Seoul";
형태로 DataSource를 변경하여 데이터를 불러오면, DB에 저장 된 글 작성 시간을 각 나라에 맞는 시간으로 제공할 수 있을 것이다.
하지만 Datetime
형식의 고정 된 localTime
형태의 문자열을 저장하고, 클라이언트 서버에서 User locale을 참고하여 시간을 가공하여 제공 하더라도 동일한 동작을 하게 할 수 있고, 이 방법이 훨씬 간단하게 구현할 수 있다고 생각한다.
아직 명확한 장점이 잘 체감되질 않는다.