프로젝트 진행중 별 생각없이 Date를 사용해서 개발하고 있었다. 그러고 보니 지난번 프로젝트에서는 LocalDateTime을 사용했었는데 무엇이 다른가 해서 알아봤다
자세한 설명은 이 글에서 읽을 수 있다.
(한국사도 어려웠는데 자바 시간라이브러리의 역사마저 어렵다)
대충 요약하자면
- 불변 객체가 아니다( not immutable)
- int 상수 필드의 남용
- 헷갈리는 월 지정
- 일관성 없는 요일 상수
- Date와 Calendar의 불편한 역할 분담
- 오류에 둔감한 시간대 ID지정
- java.util.Date 하위 클래스의 문제
등의 문제로 java8에서는 LocalDateTime
, LocalDate
, LocalTime
을 제공한다고 한다.
결론은 LocalDateTime
을 사용해라...!
그래서 Date
-> LocalDateTime
으로 리팩토링을 했다.
날짜와 시간정보를 따로 사용하기 위해서 LocalDate
와 LocalTime
을 사용하였다.
기존에는 Date
를 매핑하기 위해서 entity클래스에 @Temporal(TemporalType.DATE)
와 @Temporal(TemporalType.TIME)
을 사용하였다.
@Getter
@NoArgsConstructor
@Entity
public class Hours {
... (중략)
@Temporal(TemporalType.TIME)
private Date time;
@Temporal(TemporalType.DATE)
private Date date;
}
위에서 사용한 @Temporal
은 Date
와 Calendar
에만 사용할 수 있는 어노테이션이다.
jpa2.2 버전부터는 LocalDateTime
을 알아서 매핑해준다.
@Getter
@NoArgsConstructor
@Entity
public class Hours {
... (중략)
private LocalTime time;
private LocalDate date;
}
Json과 Date의 변환을 위해서 @JsonFormat
어노테이션을 사용하여 형식, 타임존 등을 지역적으로 설정할 수 있다.
전역 설정을 위해서 설정파일에 적용시킬 수 있으나 Date
에만 지원을 한다고 한다. LocalDateTime
을 전역 설정하기 위해서는 Jackson의 기본Deserializer 을 커스텀하여 사용할 수 있다.
현재는 필드마다 어노테이션을 붙여 사용하고있지만 사용하는 필드가 많아지게되면 커스텀Deserializer을 작성하는게 유용할 것 같다.
Date
의 경우 timezone의 영향을 받아 @JsonFormat
에 timezone을 지정해주지 않으면 원치 않는 시간이 db에 저장되는 불상사를 겪을 수 있다.
@Getter
public class HoursRequestDto {
... (중략)
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "Asia/Seoul")
private Date date;
@JsonFormat(pattern = "HH:mm", timezone = "Asia/Seoul")
private Date time;
}
@Getter
public class HoursResponse {
... (중략)
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "Asia/Seoul")
private Date date;
@JsonSerialize(as = date.class)
@JsonFormat(pattern = "HH:mm", timezone = "Asia/Seoul")
private Date time;
}
time의 경우 db에 HH:mm:ss
형태로 저장되는데 어째서인지 응답에서 @JsonFormat
이 적용되지 않고 HH:mm:ss
형태로 json응답을 보냈다.
@JsonSerialize(as = date.class)
을 함께 사용해주었더니 문제는 해결되었다.
LocalDateTime
에서는 timezone을 사용하지 않는다.
@Getter
public class HoursRequestDto {
... (중략)
@JsonFormat(pattern = "yyyy-MM-dd")
private Date date;
@JsonFormat(pattern = "HH:mm")
private Date time;
}
@Getter
public class HoursResponse {
... (중략)
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate date;
@JsonFormat(pattern = "HH:mm")
private LocalTime time;
}
LocalTime
의 경우에도 db에 HH:mm:ss
형태로 저장된다.
@JsonFormat(pattern = "HH:mm")
의 적용으로 HH:mm
형태로 json응답을 한다.