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' 추가
✅ 애플리케이션 연결 설정도 꼭 확인!
실전 팁
- 개발/운영 환경 모두 동일하게 설정하세요
- 로그나 모니터링 시스템도 타임존 체크 필수
- API 응답 시 ISO 8601 형식(YYYY-MM-DDTHH:mm:ss+09:00) 권장
- 글로벌 서비스라면 UTC 기준으로 저장하고 표시할 때만 변환
'개발 & IT > 백엔드' 카테고리의 다른 글
| Sequelize vs Prisma: Node.js ORM 비교 분석 (0) | 2025.10.26 |
|---|---|
| Prisma로 Next.js 블로그 만들기: 데이터베이스 설정부터 마이그레이션까지 (0) | 2025.10.26 |
| Let's Encrypt 인증서 자동 갱신 완벽 가이드 (1) | 2025.10.14 |
| nginx SSL 설정 중 만난 DNS 캐시 트러블슈팅 (0) | 2025.10.14 |
| apt autoremove란? 리눅스 패키지 관리의 숨은 조력자 (0) | 2025.10.10 |