본문 바로가기

개발 & IT/백엔드

MySQL 타임존 SYSTEM 설정과 UTC 저장 문제 해결하기

MySQL 쓰다 보면 SELECT @@global.time_zone, @@session.time_zone; 결과가 SYSTEM으로 나오는데, 막상 DB에 저장된 TIMESTAMP 값을 보면 UTC 기준으로 들어가 있는 당황스러운 상황, 겪어보셨나요?

오늘은 이 문제의 원인과 해결 방법을 차근차근 정리해볼게요!


먼저 알아야 할 것: TIMESTAMP vs DATETIME

MySQL의 TIMESTAMP는 좀 특별해요.

  • 내부적으로 UTC로 저장
  • 조회할 때 세션의 time_zone 기준으로 변환되어 표시됨

반면 DATETIME은?

  • 변환 없이 입력한 값 그대로 저장
  • 단순하게 "보이는 시간"만 맞추고 싶다면 DATETIME도 방법!
-- TIMESTAMP는 UTC로 저장 후 세션 타임존으로 변환
CREATE TABLE test (
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- DATETIME은 그대로 저장
CREATE TABLE test2 (
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

SYSTEM 타임존이 뭐예요?

@@global.time_zone이나 @@session.time_zone이 SYSTEM이면 MySQL이 운영체제(OS)의 시스템 시간대를 따라간다는 뜻이에요.

확인해보기

SELECT @@system_time_zone, @@global.time_zone, @@session.time_zone;

결과 예시

+------------------+--------------------+---------------------+
| @@system_time_zone | @@global.time_zone | @@session.time_zone |
+------------------+--------------------+---------------------+
| KST              | SYSTEM             | SYSTEM              |
+------------------+--------------------+---------------------+

이 경우는 정상이에요! MySQL이 한국 시간(KST, UTC+9)을 잘 따르고 있는 거예요.


그래도 UTC로 저장된다면? 

여전히 UTC로 저장되는 경우는 이런 상황일 수 있어요:

  • MySQL의 타임존 데이터가 비어 있음
  • default-time-zone 설정이 명시되지 않음
  • 애플리케이션에서 타임존을 UTC로 강제 설정

해결 방법 (Step by Step)

Step 1: 시스템 시간 확인

timedatectl

이렇게 나오면 정상이에요:

Time zone: Asia/Seoul (KST, +0900)

Step 2: MySQL 설정 파일 수정

/etc/mysql/mysql.conf.d/mysqld.cnf 파일을 열어서 [mysqld] 섹션에 아래 내용을 추가하세요.

[mysqld]
default-time-zone = '+09:00'

💡 TIP: 'Asia/Seoul' 대신 '+09:00'을 쓰는 게 더 안전해요! (타임존 테이블이 없어도 동작하거든요)


Step 3: MySQL 재시작

sudo systemctl restart mysql

Step 4: 확인하기

SELECT @@global.time_zone, @@session.time_zone, @@system_time_zone;

이렇게 나오면 완벽! 🎉

+--------------------+---------------------+------------------+
| @@global.time_zone | @@session.time_zone | @@system_time_zone |
+--------------------+---------------------+------------------+
| +09:00             | +09:00              | KST              |
+--------------------+---------------------+------------------+

애플리케이션에서도 타임존 설정하기 💻

DB만 설정하면 끝이 아니에요! 애플리케이션 연결 설정도 확인해야 해요.

Java (JDBC)

jdbc:mysql://localhost:3306/mydb?serverTimezone=Asia/Seoul

Node.js (Sequelize)

const sequelize = new Sequelize('database', 'username', 'password', {
  host: 'localhost',
  dialect: 'mysql',
  timezone: '+09:00'
});

Python (SQLAlchemy)

engine = create_engine(
    'mysql://user:pass@localhost/db',
    connect_args={'init_command': "SET time_zone='+09:00'"}
)

Spring Boot (application.yml)

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb?serverTimezone=Asia/Seoul

참고: 타임존 테이블 직접 로드 (선택사항)

Asia/Seoul 같은 이름을 명시적으로 쓰고 싶다면 시스템의 zoneinfo 데이터를 MySQL에 로드할 수 있어요.

sudo mysql_tzinfo_to_sql /usr/share/zoneinfo | sudo mysql -u root -p mysql

이후 설정 파일을:

default-time-zone = 'Asia/Seoul'

이렇게 바꾸면 돼요.


주의사항

운영 중인 DB라면?

  • 백업 필수! 설정 변경 전 반드시 백업하세요
  • 기존 TIMESTAMP 데이터는 설정 변경해도 값이 바뀌지 않아요 (이미 UTC로 저장된 데이터는 그대로)
  • 세션 레벨에서만 바꾸고 싶다면: SET time_zone = '+09:00';

타임존 변경의 영향

  • 새로 입력되는 데이터부터 적용됨
  • 기존 데이터를 보는 관점이 바뀔 수 있음
  • 애플리케이션 로직 확인 필수

정리하면?

구분 의미 비고

@@system_time_zone OS의 실제 타임존 KST면 정상
@@global.time_zone MySQL 전역 타임존 SYSTEM 또는 +09:00 권장
@@session.time_zone 현재 세션의 타임존 세션별로 다르게 설정 가능
TIMESTAMP UTC 저장, 세션 타임존 기준으로 변환 타임존 영향 ⭕
DATETIME 변환 없이 그대로 저장 타임존 영향 ❌
default-time-zone MySQL 설정 파일에서 기본 타임존 지정 '+09:00' 또는 'Asia/Seoul'

핵심 요약

✅ SYSTEM = OS 시간대를 따름 (나쁜 게 아니에요!)
✅ KST = 정상적으로 Asia/Seoul 시간대 사용 중
✅ TIMESTAMP는 UTC 저장, 조회 시 변환됨
✅ 설정을 고정하고 싶으면 default-time-zone='+09:00' 추가
✅ 애플리케이션 연결 설정도 꼭 확인!


실전 팁

  1. 개발/운영 환경 모두 동일하게 설정하세요
  2. 로그나 모니터링 시스템도 타임존 체크 필수
  3. API 응답 시 ISO 8601 형식(YYYY-MM-DDTHH:mm:ss+09:00) 권장
  4. 글로벌 서비스라면 UTC 기준으로 저장하고 표시할 때만 변환
반응형