개요
KST 기준 하루(00~24시) 채팅 수를 집계하려고 했는데,
9시간 전까지의 데이터만 조회되는 문제가 발생.
원인 파악
•
쿼리 결과에서 시간대별 데이터가 KST 하루로 안 맞고, UTC 기준 하루처럼 보임.
•
예를 들어 2025-08-15 기준 데이터를 보면, 0~8시 데이터가 빠지거나 섞여 있음.
뭐가 문젤까?
1.
브라우저에서 파라미터를 잘못 보내는지?
2.
*서버(day.js)**에서 KST
UTC 변환이 틀린지?
3.
RDS TimeZone 설정 문제인지?
4.
TypeORM이 날짜 파라미터 변환 과정에서 문제를 만드는지?
5.
DB 쿼리에서 타임존이 꼬이는지?
검증 과정
DB 직접 조회
•
DBeaver로 WHERE createdAt BETWEEN '2025-08-14T15:00:00Z' AND '2025-08-15T15:00:00Z' 실행
•
AT TIME ZONE 'Asia/Seoul' 변환까지 포함해보니,
→ UTC/KST 모두 기대한 데이터 범위가 정확히 나옴
•
DB 저장 데이터 자체에는 문제 없음 확인.
서버 로그 확인
•
API 요청 시 전달되는 startDate, endDate 파라미터 출력
•
day.js로 KST 하루 → UTC 변환 결과 확인
•
서버에서 만드는 파라미터도 정상.
RDS TimeZone 확인
•
SHOW TIME ZONE; → Asia/Seoul
•
이미 세션 타임존은 KST
•
RDS 설정 자체 문제 아님.
TypeORM 동작 확인
•
TypeORM의 createQueryBuilder로 WHERE createdAt >= :start AND createdAt < :end 정상 작동 확인
•
값 전달에는 문제 없음.
→ 여기까지 오면 데이터 저장, 전달, 필터 조건 모두 정상.
남은 건 SELECT 절에서 뭔가 꼬였다는 의심.
문제 지점 발견 – EXTRACT
SELECT EXTRACT(HOUR FROM chat.createdAt) ...
SQL
복사
•
timestamptz 컬럼에서 EXTRACT(HOUR FROM ...) 하면,
세션 타임존(KST) 기준으로 변환 후 hour를 뽑음.
•
필터는 UTC 기준이었는데, 집계는 KST로 → 시간대가 9시간 밀린 값이 나옴.
•
이게 “9시간 전까지만 나오는” 원인이었음.
해결
EXTRACT(HOUR FROM (chat.createdAt AT TIME ZONE 'Asia/Seoul'))
SQL
복사
•
날짜 범위는 반열림 < :next로 설정해 경계 문제 제거.
결론?
•
원인: EXTRACT가 세션 타임존을 사용하기 때문에, 필터(UTC)와 집계(KST)가 불일치
•
해결: AT TIME ZONE으로 명시적으로 타임존을 고정 → 원하는 시간대 기준으로 정확히 집계 가능
