팀원 중 한분으로부터 헬프 요청이 왔다. 수정 중인 코드에서 버그가 생겼는데 원인을 도무지 모르겠다는 것이었다.

상황을 대충 들어보니 아래와 같았다.

특정 쿼리가 주기적으로 실행되면서 데이터를 가져온다. 그리고 로그에는 몇 건의 데이터를 가져왔는지를 찍고 있는데, 계속해서 쿼리 결과로 가져오는 데이터가 0건이라는 것이다.

헌데 이상한 것은, 해당 쿼리를 데이터베이스 툴을 통해 직접 때려보면 2건의 데이터가 조회된다.

즉, 똑같은 쿼리를 서버의 런타임에서 날리면 0건, 데이터베이스 툴에서 직접 날리는 2건이 나오는 상황인 것이다.

처음 의심한 포인트는 쿼리가 잘못 구성되었고, 그로 인해 ORM 을 통한 object 바인딩에 실패한 것이지 않을까 하는 부분 이었다. 하지만 object 바인딩에 실패하면 에러가 반환되어야 정상이었다. 문제의 코드에는 에러가 없었다.

그 다음에 의심한 포인트는, 실행중인 코드가 실제 코드와 다른 버전일 가능성을 의심해봤다. 팀원분께 여쭤보니 그건 아니었다.

더 많은 단서를 필요로 했다.

혹 환경 상의 문제는 아닐까 싶어 일단 코드가 돌고있는 pod 으로 직접 ssh 연결을 붙었다. mysql cli 툴을 깔아서 직접 해당 pod 에서 쿼리를 날려봤는데 정상적으로 2건이 반환되었다. 즉, 환경 상의 문제도 아니었다.

한참을 이런 저런 시도를 해봤으나 이상한 점은 보이지 않았다. IDE 에 문제의 쿼리를 띄워놓고 자세히 살펴보기 시작했다.

해당 쿼리가 참조하는 테이블의 컬럼에는 start_time, end_time, timezone 등의 컬럼이 있었다. start_time, end_time 에는 hhMM 포맷의 시간 데이터가 저장되어 있었다. 쿼리는 해당 timezone 을 기준으로 현재 시간이 start_timeend_time 사이에 속하는 행들을 조회하는 쿼리였다.

현재 시간을 timezone 기준으로 변경하는 부분은 아래와 같았다.

... CONVERT_TZ(NOW(), 'GMT', timezone), ...

일단 CONVERT_TZ 함수 자체가 생소했기 때문에 MySQL 공식 문서를 통해 정의를 확인해보았다.

CONVERT_TZ(*dt*,*from_tz*,*to_tz*)

CONVERT_TZ() converts a datetime value dt from the time zone given by from_tz to the time zone given by to_tz and returns the resulting value.

즉, dt 의 timezone 이 from_tz 라고 가정하고 이를 to_tz 기준으로 변경하는 함수인 것이다. 해당 함수의 사용법에는 딱히 문제가 없어보였다. 하지만 문득 든 생각이, NOW() 에서 반환하는 값이 GMT 가 아니라면 쿼리가 정상적으로 반환해야 할 행들을 반환하지 못할 수도 있다는 생각이 들었다.

다시 MySQL 문서를 찾아보니 NOW() 함수는 세션의 timezone 설정에 영향을 받는다고 적혀있었다. 백엔드에서 쿼리 중에 난데없이 세션의 timezone 을 변경할 일은 없다. 하지만 데이터베이스로 연결하는 초기 시점에 연결 문자열에서 세션의 timezone 을 설정할 수 있다. 해당 연결문자열을 찾아보니 아니나 다를까 timezone 이 Asia/Seoul 로 설정되어 있었다.

parseTime=true&charset=utf8&loc=Local&time_zone=%27Asia%2FSeoul%27

잡았다 요놈

연결문자열에서 timezone 설정을 날리고 코드를 다시 돌려보니 역시 정상적으로 2건의 데이터를 조회하는 것을 확인할 수 있었다.