🔍 상이한 타임존이 가져오는 문제점
지금 하고 있는 "Voca-World"는 언어 학습 웹 서비스로 다양한 국가의 사용자가 이용할 예정이므로 서로 다른 타임존이 갖는 문제를 해결해야 했다. 가장 큰 문제는 오늘 공부한 단어를 조회하는 로직이었다.
만약 한국 시간으로 2023/07/28 06:00시에 단어를 저장했다면 UTC 시간을 갖는 국가의 경우 2023/07/27 21:00시가 된다. 즉 오늘 공부한 단어 조회가 안되게 된다.
🔍 단어 조회 로직
단어 조회 로직은 파라미터로 클라이언트의 시간을 전달받아서 날짜를 추출하는 형식으로 구성되어있다.
@Override
public List<Word> findWordsWithDate(WordDTO.Request request) {
LocalDate now = DateFormatter.from(request.getDate()).toLocalDate();
LocalDateTime start = LocalDateTime.of(now, LocalTime.of(0, 0, 0));
LocalDateTime end = LocalDateTime.of(now, LocalTime.of(23, 59, 59));
return wordRepository.findByUserAndCreatedAtBetween(request.getUser(), start, end);
}
🔍 해결 과정
1. 데이터베이스와 JVM의 타임존을 UTC기준으로 변경하였다. UTC 기준으로 변경했을 때 상이한 시간에 대한 계산 처리가 쉽기 때문이다.
2. 프론트 서버에서 클라이언트의 현재 시간을 추출하여 파라미터로 API서버에 전달한다. timezone 추출은 다음과 같이 할 수 있다.
console.log(new Date().toTimeString().slice(9)); // GMT+0900 (Korean Standard Time)
console.log(Intl.DateTimeFormat().resolvedOptions().timeZone); // Asia/Seoul
console.log(new Date().getTimezoneOffset() / -60); // 9
개인적으로 시간의 차이만 필요하기 때문에 세 번째 방법을 이용하였다.
3. 파라미터로 offset을 받아서 날짜의 범위를 계산해주었다. (참고: 더 정확한 계산을 위해서는 프론트 서버에서 현재 시간에 대한 정보도 넘겨주는 것이 좋다.)
@Override
public List<Word> findWordsWithDate(WordDTO.Request request) {
LocalDateTime localDateTime = LocalDateTime.now();
LocalDateTime start = localDateTime.minusHours(request.getOffset());
LocalDateTime end = localDateTime.plusHours(request.getOffset());
return wordRepository.findByUserAndCreatedAtBetween(request.getUser(), start, end);
}