Timestamp 와 Datetime

박동규·2022년 4월 12일
2

Timestamp와 Datetime 이슈

TimestampDatetime의 가장 큰 차이점은 timezone의 정보의 유무이다.

우리 팀이 구현한 API 서버의 로직은 Java 코드에서 LocalDateTime.now()를 호출하여 API 서버 컴퓨터의 timezone의 시간 정보를 이용하여 LocalDateTime 객체를 생성하고, timestamp 타입의 created_at 컬럼에 데이터를 넣는 방식으로 구현되어 있다.

AWS에 API 서버를 배포하고 테스트하니, 기대했던 값과 달리 데이터가 -9시간으로 처리되어 보이는 문제가 발생했다.

이는 AWS에 만든 인스턴스의 기본 timezone 환경 변수가 UTC 로 설정되어 있었기 때문이다.

ubuntutimezone 설정을 여러가지 방법으로 바꿔보고, terminal창에서 date 명령어를 입력하여 KST로 변경된 것을 확인하고, 계속 시도해 보았으나 해결에 어려움을 겪었다.

테스트 하며 알아보니, timezone 변수를 수정했던 작업들이 ubuntu OS상의 timezone 설정을 바꾼 것일뿐, 실제 java 코드가 사용하는 jvm timezone 환경변수는 변경되지 않았던 것이 문제 였던 것 같다.

Java 코드에서 LocalDateTime은 해당 실행 환경 컴퓨터의 timezone 설정을 따라가는데, timezone 설정을 KST로 변경했지만, jvm이 바라보는 timezone 설정은 계속 UTC로 되어 있어, Java 단에서 잘못 된 시간으로 쿼리문이 만들어졌던 것이다.

## 테스트 과정

우선 위와 같이 테스트용 java 코드를 만들고, ubuntu 서버의 timezone 환경 변수를 변경하며 테스트를 진행했다.

1. tzselect 설정 방법

$ sudo tzselect

Asia/Seoul로 변경 했음에도 java가 바라보는 timezoneUTC인 것을 확인할 수 있다.

하지만 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'


Mysql 날짜 데이터 - Timestamp 와 Datetime

Datetime

  • 1000-01-01 00:00:00부터 9999-12-31 23:59:59까지 지원
  • 문자형
  • 8byte
  • 데이터 값을 입력 해주어야 날짜가 입력 된다.

Timestamp

  • 1970-01-01 00:00:01부터 2038-01-19 03:14:07까지 지원
  • 숫자형
  • 4byte
  • 데이터 값을 입력 해주지 않고 저장 시, 자동으로 현재 날짜가 입력 된다.

DatetimeTimestamp 의 차이는, 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 설정의 우선순위

timezone 설정은, OS 수준에서의 설정, Mysql 자체 설정 변경, 접속하는 클라이언트 수준에서의 변경의 방법이 있다.

현재 테스트에 사용한 DB는 timezone 설정이 되어 있지 않은 상태이다.
DB 설정이 되어 있지 않은 경우, SYSTEM 환경 변수 설정을 따라가게 되어 있다. timezone 설정의 우선 순위는

  1. 클라이언트 수준에서의 설정
  2. DB 설정
  3. OS 설정

의 우선순위를 갖고 있다.

우리가 Java 코드에서 DB와 연결을 맺을 때 DB url을 입력하고 뒤에 붙는 serverTimezone 설정이 사용자 수준의 timezone 설정이다.

String url = "jdbc:mysql://localhost/testDB?serverTimezone=UTC";

timestamp를 적용하여 만들 수 있는 글로벌 서비스

글로벌로 제공해야 하는 서비스를 만들 때 timestamp 형식을 사용하면 좋다.

해당 내용을 보고 서비스 제공을 가정하여 timestamp 형식을 사용하여 장점이 될 수 있는 상황을 생각해보았다.

  • 한국에 사는 A와, 일본에 사는 B가 글을 동시에 작성한다면, 미국에 사는 C가 2개의 글을 읽더라도 각각 1분 전 작성된 글 입니다. 표시하는 처리를 수월하게 할 수 있다?

  • DB 서버의 timezone 설정을 UTC 로 설정한다.
  • 클라이언트 서버에 User가 글 등록 요청을 보내면, 현재 UTC 시간을 담은 insert 쿼리를 DB 서버로 보낸다.

이렇게 하면, 어느 나라에서 글을 작성해도 일정한 UTC기준의 시간이 DB에 저장 될 것이다. 이 후 클라이언트 서버에서 DB의 데이터를 불러올 때 요청한 User의 locale 을 참고하여

String url = "jdbc:mysql://localhost/testDB?serverTimezone=Asia/Seoul";

형태로 DataSource를 변경하여 데이터를 불러오면, DB에 저장 된 글 작성 시간을 각 나라에 맞는 시간으로 제공할 수 있을 것이다.


하지만 Datetime 형식의 고정 된 localTime 형태의 문자열을 저장하고, 클라이언트 서버에서 User locale을 참고하여 시간을 가공하여 제공 하더라도 동일한 동작을 하게 할 수 있고, 이 방법이 훨씬 간단하게 구현할 수 있다고 생각한다.

아직 명확한 장점이 잘 체감되질 않는다.

0개의 댓글