"분명 방금 글을 올렸는데 작성 시간이 9시간 전으로 찍혀요." PHP로 웹을 만들다 보면 한 번쯤 마주치는 황당한 버그다. 기능은 멀쩡한데 시간만 어긋난다. 범인은 십중팔구 시간대(timezone) 설정이다. 오늘은 PHP와 MySQL 사이에서 시간이 꼬이는 이유와, 깔끔하게 맞추는 방법을 실무 관점에서 정리한다.

왜 9시간이 어긋날까

PHP의 기본 시간대가 UTC로 설정돼 있는데, 우리가 사는 한국은 Asia/Seoul(UTC+9)이다. 이 9시간 차이가 그대로 드러난 것이다. 서버에서 현재 시각을 찍어 보면 바로 확인된다.

<?php
echo date_default_timezone_get();   // UTC
echo date('Y-m-d H:i:s');           // 한국 시각보다 9시간 이전

즉 코드가 틀린 게 아니라, 서버가 "지금 몇 시인지"를 다르게 알고 있는 것이다. 출발점이 어긋났으니 결과가 어긋나는 건 당연하다.

시간 버그의 8할은 로직이 아니라 '시간대 설정'에서 시작된다.

PHP 쪽 시간대부터 맞추기

가장 확실한 방법은 애플리케이션 진입점에서 시간대를 명시적으로 지정하는 것이다. 공통으로 불러오는 설정 파일 맨 위에 한 줄 넣어 두면 된다.

<?php
date_default_timezone_set('Asia/Seoul');
echo date('Y-m-d H:i:s');   // 이제 한국 시각

php.inidate.timezone 값을 직접 Asia/Seoul로 바꾸는 방법도 있지만, 서버 환경이 바뀌어도 흔들리지 않으려면 코드에서 명시하는 편이 안전하다. 협업이나 서버 이전 상황에서 특히 그렇다.

MySQL은 별도로 살아 있다

여기서 많은 사람이 놓치는 함정이 있다. PHP를 맞춰도 MySQL은 따로 논다는 점이다. DB가 NOW()CURRENT_TIMESTAMP로 시간을 기록한다면, MySQL 자체의 시간대도 확인해야 한다.

SELECT @@global.time_zone, @@session.time_zone, NOW();

세션 시간대를 한국으로 맞추려면 연결 직후 이렇게 지정한다.

SET time_zone = '+09:00';

PHP에서 PDO로 접속한다면, 연결 직후 한 번 실행해 주면 깔끔하다.

<?php
$pdo = new PDO($dsn, $user, $pass);
$pdo->exec("SET time_zone = '+09:00'");

어디에 맞추는 게 정답일까

실무에서 자주 갈리는 고민이다. 두 가지 접근이 있다.

  • 모두 한국 시각으로 통일: 서비스가 국내용이고 단순하다면 PHP와 MySQL 모두 Asia/Seoul로 맞추는 게 직관적이다.
  • 저장은 UTC, 표시만 변환: 글로벌 서비스이거나 추후 해외 확장을 염두에 둔다면, DB에는 UTC로 저장하고 화면에 보여 줄 때만 사용자 시간대로 변환하는 방식이 안전하다.

후자는 처음엔 번거롭지만, 나중에 여러 지역 사용자를 다룰 때 빛을 발한다. 어느 쪽이든 핵심은 '기준을 하나로 정하고 일관되게 지키는 것'이다. 여기저기 다른 기준이 섞이는 순간 디버깅 지옥이 시작된다.

점검 체크리스트

점검 위치확인 명령
PHPdate_default_timezone_get()
MySQL 세션SELECT @@session.time_zone
실제 저장값테이블의 created_at 직접 확인

세 곳이 같은 기준을 바라보는지 한 번씩만 확인해도 시간 버그의 대부분이 사라진다.

정리하면, PHP의 시간 어긋남은 무서운 버그가 아니라 '출발점을 안 맞춘' 단순한 문제다. 진입점에서 date_default_timezone_set()로 PHP를 잡고, DB 연결 직후 SET time_zone으로 MySQL을 잡고, 저장 기준을 하나로 정한다. 이 세 가지만 습관처럼 챙기면, "시간이 왜 이래?"로 밤새우는 일은 더 이상 없을 것이다.