MySQL은 날짜와 시간 연산을 지원하는 Date Function이 많이 있다. 그중에 날짜를 unit 단위로 더하고 빼는 DATE_ADD
와 DATE_SUB
함수를 자주 사용했는데, 당연하다고 생각했던 로직에 문제가 있었다.
NOW()
는 현재 시간을 반환하는 함수로 시간이 지날수록 증가할 텐데, NOW()
에 임의의 값을 더한 시간은 그러지 않은 경우가 있다. 날짜 연산에 사용한 MONTH
단위가 문제였다.
DATE_ADD(NOW(), INTERVAL 1 MONTH)
NOW()
가 증가하기 때문에 여기에 한 달을 더한 값도 당연히 증가할 거라 생각하고, 이에 기반한 로직이 있었는데 그렇지 않았다. 달이란 항상 일정한 상수가 아니라 현재 속한 월에 따라 개념이 달라지기 때문이다.
1월 15일에 한 달을 더하면 2월 15일이 되고, 2월 15일에 한 달을 더하면 3월 15일이 되는데 전자가 31일이 더해졌다면 후자는 그렇지 않다. 여기까지는 그래도 역행할 여지는 없어 보이지만 1월 마지막 날로 옮겨보면 더 큰 문제가 발생한다.
select
DATE_ADD('2019-01-30 12:00:00', INTERVAL 1 MONTH),
DATE_ADD('2019-01-31 11:00:00', INTERVAL 1 MONTH)
실행하면 다음과 같은 값이 나온다.
2019-02-28 12:00:00
2019-02-28 11:00:00
1월 31일 11시가 30일 12시보다 더 뒤임에도 불구하고 한 달을 더했더니 역행한다.
DATE_SUB
도 마찬가지 문제가 발생할 수 있다.
select
DATE_SUB('2019-03-30 12:00:00', INTERVAL 1 MONTH),
DATE_SUB('2019-03-31 11:00:00', INTERVAL 1 MONTH)
별거 아닌 문법이지만 이로 인해 문제가 발생할 때 생기는 영향은 상상하기 무섭다. 매달 결제하는 정기결제 관리하는 부분도 깊숙이 살펴보면 굉장히 다양한 case 때문에 고려할게 많았는데 쿼리 하나에도 이런 문제가 발생할 줄 몰랐다. 이 경우는 한 달을 30일로 처리하기로 쉽게 우회했지만 의사소통 단계에서부터 명확히 하고 늘 고민하며 코딩해야 함을 또 느꼈다.
'기타' 카테고리의 다른 글
[bash] screen 사용 설명서 (0) | 2019.12.26 |
---|---|
간단한 파일 대칭키 암호화/복호화 (0) | 2019.12.24 |
[bash] 간단한 부하테스트 script (0) | 2019.12.12 |
[bash] sed 사용 설명서 (0) | 2019.12.01 |
[bash] awk 사용 설명서 (0) | 2019.11.21 |
댓글