Spring Boot v2.7.18, Mybatis, MariaDB 환경에서 개발하던 중 발생한 문제
검색 이력 저장 시 milliseconds 단위까지 저장되지 않음(24.03.14)
문제
검색 이력을 담는 테이블의 Mapper를 JUnit5로 테스트 하던 중 검색 이력 저장 시 milliseconds 단위까지 저장되지 않는다는 것을 발견했습니다.
현재 사용자의 login_id와 검색 시간인 search_date 두개의 컬럼을 PK로 사용하고 있고, search_date가 milliseconds 단위까지 포함해야 데이터 중복이 일어나지 않기 때문에, milliseconds 단위의 저장은 필수로 이루어져야 합니다.
해결 과정
알고보니 DB별로 TIMESTAMP 타입의 사용법이 달랐고, MariaDB의 TIMESTAMP 타입은 milliseconds 단위를 저장하지 않는 타입인 것을 알게 되었습니다.
다음은 DB 별 사용법을 정리해보았습니다.
DB종류 | Oracle DB | MySQL | MariaDB |
milliseconds를 저장할 수 있는 데이터 타입 | TIMESTAMP | TIMESTAMP(6) | TIMESTAMP(6) |
TIMESTAMP(6)를 이용하면 나노초까지 표현이 가능하지만, JavaScript에서는 milliseconds 까지만 지원하기 때문에, TIMESTAMP(3)으로 변경했습니다.
특이사항
- Java의 LocalDateTime타입에서 .withNano(0) 메서드를 이용하면 LocalDateTime 생성부터 나노초를 버리고 생성할 수 있음
검색 이력 저장 시 시간대 설정(24.03.15)
문제
검색 기능을 실행할 때, 검색 이력을 저장하는 api를 호출하는데, 이때 Javascript의 new Date()를 이용하여 searchdate(검색시간)를 서버에 전달하고 검색어와 검색시간, login_id를 저장함
그런데, DB에 검색이력을 저장할 때, UTC 시간대로 저장되고 있었음
해결 과정
- MariaDB 현재 시간 및 TimeZone 확인
select now(), @@system_time_zone AS Timezone; 명령어로 현재 시간과 TimeZone 을 확인했는데, 정상적으로 KST로 적용되어 있는 것을 확인했고, DB TimeZone문제는 아닌 것으로 판단했습니다.
2. 검색 페이지에서 new Date()로 TimeZone확인
현재 검색시간을 new Date()로 생성하고 있어서 해당 페이지의 javascript file에서 console.log(new Date());를 실행해 보았으나, KST가 반영되어 있었습니다.
알고보니 개발자 도구에서 ‘console.log()’로 날짜를 출력할 때 브라우저가 날짜를 로컬 타임존으로 변환해서 출력한다고 합니다. 실제로 ‘Date’객체 자체는 타임존 정보를 포함하지 않는다고 합니다.
3. Debug 모드 활용
Controller에서 Service를 호출하는 과정에서 dto가 전달되기 때문에 debug모드를 활용해서 확인해보았습니다.
Javascript에서 보낸 값을 dto로 받을 때 시간이 UTC를 적용한 채로 전달되는 것으로 확인했습니다.
4. JavaScript에서 KST 시간으로 변환
JavaScript에서 시간객체를 생성할 때 UTC 시간으로 생성되는 것으로 판단했습니다.
따라서 client에서 JavaScript로 ‘Date’객체를 생성할 때, KST 타임존 오프셋을 적용해서 KST 시간으로 변환한 후 서버에 전달하는 것으로 해결했습니다.
'Java > Spring Boot' 카테고리의 다른 글
유효성 검사 / 데이터 검증 (Validation) (0) | 2024.05.31 |
---|---|
View에 사용자 이름을 전달하는 Controller 중복 코드 제거 (0) | 2024.03.19 |
페이지네이션 구현 시 onClick 함수 호출 오류(24.03.14) (0) | 2024.03.19 |
Spring Security CSRF 적용하기(With Thymeleaf) (0) | 2024.03.17 |
도로명 주소 API 구현 (0) | 2024.03.13 |