MySQL 현재 시간: NOW(), CURDATE(), UTC_TIMESTAMP(), 시간대 및 모범 사례

目次

1. MySQL에서 현재 시간 가져오기 (핵심: 가장 짧은 SQL 치트 시트)

MySQL에서 현재 시간을 가져오려면 기억해야 할 SQL 함수가 몇 개뿐입니다.
아래는 검색 키워드 “MySQL get current time”에 대한 가장 짧은 답변입니다.

1.1 MySQL 현재 날짜와 시간: NOW() / CURRENT_TIMESTAMP

현재 날짜 + 시간 (YYYY-MM-DD HH:MM:SS)을 반환합니다.

SELECT NOW();
SELECT CURRENT_TIMESTAMP;

예시 출력

2025-02-01 15:30:45
  • NOW()CURRENT_TIMESTAMP는 보통 동일한 결과를 반환합니다.
  • 두 함수 모두 현재 날짜와 시간을 반환합니다.
  • 밀리초가 필요하면 아래를 사용하세요.
    SELECT NOW(3);
    

주의 사항 (일반적인 실수)

  • 서버의 시간대 설정에 따라 달라집니다.
  • UTC 환경에서는 일본 시간 대신 UTC가 반환될 수 있습니다.
  • 쿼리 실행 중에는 기본적으로 동일한 시간(단일 문장 내에서 고정된 시간)을 반환합니다.

1.2 MySQL 현재 날짜: CURDATE()

날짜만 반환합니다 (시간 없음).

SELECT CURDATE();

예시 출력

2025-02-01

사용 사례

  • 오늘의 데이터를 조회
  • 날짜 비교 (예: 오늘 기록만 필터링)

주의 사항

  • 반환값은 DATE 타입입니다.
  • 시간대 처리(시간이 필요한 경우)에는 적합하지 않습니다.

1.3 MySQL 현재 시간: CURTIME()

시간만 반환합니다.

SELECT CURTIME();

예시 출력

15:30:45

사용 사례

  • 영업시간 확인
  • 시간 창에 따른 분기 로직

주의 사항

  • 날짜 정보가 포함되지 않습니다.
  • DATE 타입 컬럼과 비교할 수 없습니다.

1.4 MySQL 현재 UTC 시간: UTC_TIMESTAMP()

서버 시간대 설정과 관계없이 UTC(협정 세계시) 시간을 반환합니다.

SELECT UTC_TIMESTAMP();

예시 출력

2025-02-01 06:30:45

사용 시점

  • 글로벌 서비스
  • 로그를 일관되게 UTC로 저장하는 설계

일반적인 실수

  • NOW()와 혼용하면 시간 오프셋이 발생합니다.
  • 앱이 JST(일본 표준시)를 가정한다면 9시간 차이가 나타납니다.

1.5 밀리초가 포함된 MySQL 현재 시간: NOW(3) / CURRENT_TIMESTAMP(3)

MySQL 5.6 이후 버전에서는 소수 초를 지원합니다.

SELECT NOW(3);
SELECT CURRENT_TIMESTAMP(3);

예시 출력

2025-02-01 15:30:45.123

저장 시 주의 사항

컬럼도 소수 초를 지원해야 합니다.

DATETIME(3)
TIMESTAMP(3)

지원되지 않는 컬럼에 저장하면 소수 부분이 잘려버립니다.

1.6 목적별 빠른 치트 시트

PurposeSQL
Current date and timeSELECT NOW();
Get UTCSELECT UTC_TIMESTAMP();
Date onlySELECT CURDATE();
Time onlySELECT CURTIME();
Get millisecondsSELECT NOW(3);

일반적인 함정 요약

  • 시간대 확인을 하지 않아 시간 오프셋이 발생함
  • NOW(3)을 밀리초를 지원하는 컬럼 없이 사용함
  • UTC와 로컬 시간을 혼용함
  • DATETIME과 TIMESTAMP의 차이를 이해하지 못함

MySQL DATETIME と TIMESTAMP の違いを示した図。TIMESTAMPはUTC変換され、DATETIMEは変換されない。

MySQL DATETIME과 TIMESTAMP의 차이 (시간대 변환 여부 비교)

2. MySQL NOW()와 CURRENT_TIMESTAMP의 차이점

NOW()CURRENT_TIMESTAMP는 비슷해 보이지만, 언제 사용해야 하는지와 동작 방식을 오해하면 쉽게 버그가 발생할 수 있습니다. 여기에서 차이점, 올바른 사용법, 일반적인 함정을 정리합니다.

2.1 어느 것을 사용해야 할까요? (SELECT 사용 / DEFAULT 사용)

■ SELECT에서 현재 날짜/시간을 조회할 때

SELECT NOW();
SELECT CURRENT_TIMESTAMP;

보통 두 함수는 동일한 결과를 반환합니다.

  • 동등한 함수(동의어)입니다.
  • 반환값은 DATETIME과 동일합니다.
  • 시간대 설정의 영향을 받습니다.

실용적인 요점

  • 가독성을 위해 → NOW()
  • 표준 SQL 스타일을 위해 → CURRENT_TIMESTAMP

■ 컬럼 기본값을 설정할 때

CREATE TABLE logs (
    id INT AUTO_INCREMENT PRIMARY KEY,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

여기서 핵심 포인트는:

기본값으로는 CURRENT_TIMESTAMP를 사용하는 것이 일반적입니다.

일부 환경에서는 NOW()도 허용하지만 동작은 MySQL 버전 및 SQL 모드에 따라 다를 수 있습니다. 더 안전한 선택은 CURRENT_TIMESTAMP입니다.

2.2 DEFAULT / ON UPDATE의 올바른 사용법

자동으로 “updated at” 타임스탬프를 업데이트하려면:

CREATE TABLE logs (
    id INT AUTO_INCREMENT PRIMARY KEY,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        ON UPDATE CURRENT_TIMESTAMP
);

동작

  • INSERT 시 → created_at / updated_at에 현재 시간 설정
  • UPDATE 시 → updated_at만 업데이트

일반적인 실수

  • DATETIME 사용 시 소수 초 정밀도가 일치하지 않음
  • 여러 TIMESTAMP 컬럼 사용 시 오래된 MySQL 제한에 걸림 (MySQL 5.6 및 이전 버전에는 제한이 있었음)

2.3 NOW()와 SYSDATE()의 차이점 (중요)

놓치기 쉬운 점은 SYSDATE()와의 차이입니다.

SELECT NOW(), SYSDATE();

■ 동작 차이

  • NOW() → 쿼리 시작 시점에 고정
  • SYSDATE() → 호출 시점의 시간을 반환

예시:

SELECT NOW(), SLEEP(3), NOW();

NOW()는 동일한 값을 반환합니다.

SELECT SYSDATE(), SLEEP(3), SYSDATE();

SYSDATE()는 3초 차이를 보여줍니다.

2.4 어느 것을 사용해야 할까요?

FunctionBehaviorRecommended use
NOW()Fixed within a queryLogging, consistency-focused
SYSDATE()Call-time valuePrecise real-time retrieval

실제 시스템에서 NOW()가 자주 권장되는 이유

  • 트랜잭션 내부에서 일관성을 유지 (여러 SQL 문을 함께 처리하는 메커니즘)
  • 복제 환경에서 더 안전함

2.5 일반적인 오해와 문제점

❌ “NOW()와 CURRENT_TIMESTAMP는 완전히 동일하므로 신경 쓸 필요가 없습니다.”

→ 환경에 따라 기본값이나 업데이트 동작에서 차이가 나타날 수 있습니다.

❌ “SYSDATE()가 더 정확하므로 항상 더 좋습니다.”

→ 복제 환경에서 문제가 발생할 수 있습니다.

❌ 시간대를 확인하지 않음

SHOW VARIABLES LIKE '%time_zone%';

확인 없이 사용하면 시간 오차가 발생할 수 있습니다.

2.6 실용적인 모범 사례

  • SELECT 조회 → NOW()
  • 컬럼 기본값 → CURRENT_TIMESTAMP
  • 자동 업데이트 → ON UPDATE CURRENT_TIMESTAMP
  • 일관성 중시 → 기본값을 NOW()로 설정
  • UTC 기반 설계 → TIMESTAMP + UTC로 저장
  1. MySQL 현재 시간 포맷팅 (DATE_FORMAT / TIME_FORMAT)
    MySQL에서 현재 시간을 가져온 후, 표시 형식을 변경하는 경우가 매우 흔합니다.
    검색 의도 “MySQL current time format”에 가장 중요한 함수는 DATE_FORMAT() 입니다.

3.1 MySQL datetime 포맷팅: DATE_FORMAT(NOW(), …)

기본 구문:
SELECT DATE_FORMAT(target_datetime, 'format_string');

예시: 현재 시간 포맷팅
SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s');

예시 출력
2025-02-01 15:30:45

일반적으로 사용되는 포맷 지정자

포맷 지정자의미예시
%Y연도 (4자리)2025
%m월 (2자리)02
%d일 (2자리)01
%H시 (24시간)15
%h시 (12시간)03
%i30
%s45
%pAM/PMPM

3.2 일본식 또는 12시간 포맷 변환

■ 일본식 포맷
SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i');
예시 출력:
2025-02-01 15:30

■ 12시간 포맷 + AM/PM
SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %h:%i:%s %p');
예시 출력:
2025-02-01 03:30:45 PM

3.3 MySQL 시간 전용 포맷팅: TIME_FORMAT()

TIME 타입 데이터 전용 포맷팅 함수.
SELECT TIME_FORMAT(CURTIME(), '%H:%i');
예시 출력:
15:30

주의
TIME_FORMAT()TIME 타입에만 사용합니다.
DATETIME 에는 DATE_FORMAT() 을 사용하세요.

3.4 문자열 → datetime 변환: STR_TO_DATE()

문자열 데이터를 datetime 타입으로 변환합니다.
SELECT STR_TO_DATE('2025-02-01 15:30:45', '%Y-%m-%d %H:%i:%s');
예시 출력:
2025-02-01 15:30:45

흔한 실수
– 포맷이 맞지 않으면 NULL 반환
%m%c 를 혼동 (앞에 0을 채우는 월 vs 채우지 않는 월)

3.5 운영 환경에서의 중요 포인트

❌ 포맷팅 후 비교 금지
잘못된 예:

sql
WHERE DATE_FORMAT(created_at, '%Y-%m-%d') = '2025-02-01';

이는 인덱스가 무효화되어(쿼리 성능 저하) 권장되지 않습니다.

권장 방법:

sql
WHERE created_at >= '2025-02-01' AND created_at < '2025-02-02';

❌ DB 측에서 과도하게 포맷팅하지 말 것
웹 애플리케이션에서는 표시용 포맷팅을 애플리케이션 측에서 처리하는 것이 보통 더 유연합니다.
데이터베이스는 “저장 및 계산”에 집중해야 합니다.

3.6 밀리초 단위 포맷팅

SELECT DATE_FORMAT(NOW(3), '%Y-%m-%d %H:%i:%s.%f');
%f 는 마이크로초(6자리)를 나타냅니다.

주의
컬럼이 DATETIME(3) 등으로 정의되지 않은 경우, 소수점 이하 부분이 잘려 나갑니다.
MySQL 5.6 이상에서 지원됩니다.

3.7 포맷팅 목적별 요약

목적함수
표시 형식 변경DATE_FORMAT
시간만 포맷팅TIME_FORMAT
문자열 → datetime 변환STR_TO_DATE
밀리초 표시%f

4. MySQL 날짜·시간 더하기/빼기 (DATE_ADD / DATE_SUB)

현재 시간을 가져올 수 있더라도, “X일 후” 혹은 “X시간 전” 같은 날짜·시간 계산 없이 운영 환경에서 효과적으로 활용할 수 없습니다.
여기서는 DATE_ADD()DATE_SUB() 를 현재 시간과 함께 사용하는 방법을 설명합니다.

4.1 MySQL datetime 더하기: DATE_ADD()

기본 구문:
SELECT DATE_ADD(base_datetime, INTERVAL value unit);

예시: 현재 시점부터 7일 후
SELECT DATE_ADD(NOW(), INTERVAL 7 DAY);

예시: 현재 시점부터 2시간 후
SELECT DATE_ADD(NOW(), INTERVAL 2 HOUR);

일반적으로 사용되는 단위

단위의미
SECOND
MINUTE
HOUR
DAY
MONTH
YEAR

4.2 MySQL datetime 빼기: DATE_SUB()

기본 구문:
SELECT DATE_SUB(base_datetime, INTERVAL value unit);

예시: 30일 전
SELECT DATE_SUB(NOW(), INTERVAL 30 DAY);

예시: 1시간 전
SELECT DATE_SUB(NOW(), INTERVAL 1 HOUR);

활용 사례
– 만료 여부 확인
– 오래된 로그 삭제
– 최근 데이터 추출

4.3 일반적인 운영 패턴

■ 최근 24시간 데이터 조회

sql
SELECT * FROM logs WHERE created_at >= DATE_SUB(NOW(), INTERVAL 1 DAY);

■ 7일 뒤 마감일 설정

sql
INSERT INTO tasks (deadline) VALUES (DATE_ADD(NOW(), INTERVAL 7 DAY));

4.4 일반적인 실수와 주의사항
❌ 컬럼에 함수를 적용하기
Bad example:
WHERE DATE(created_at) = CURDATE();
이렇게 하면 인덱스가 비활성화됩니다(쿼리 성능 최적화).
Recommended:
WHERE created_at >= CURDATE() AND created_at < DATE_ADD(CURDATE(), INTERVAL 1 DAY);
❌ 시간대 무시
NOW()는 서버 시간대를 기준으로 합니다
UTC로 저장한다면, 기본값으로 UTC_TIMESTAMP()를 사용하세요
Example:
SELECT DATE_ADD(UTC_TIMESTAMP(), INTERVAL 1 DAY);
❌ 월 단위 추가 시 함정
SELECT DATE_ADD('2025-01-31', INTERVAL 1 MONTH);
→ 월말 조정으로 인해 날짜가 변경될 수 있습니다.
(환경에 따라 결과가 2025-02-28이 될 수 있습니다.)
월 단위 계산을 사용하기 전에 사양을 이해하세요.
4.5 밀리초 단위 추가
SELECT DATE_ADD(NOW(3), INTERVAL 500 MILLISECOND);
※ MySQL은 MILLISECOND를 직접 지원하지 않습니다.
마이크로초 단위로 지정하세요:
SELECT DATE_ADD(NOW(3), INTERVAL 500000 MICROSECOND);
4.6 모범 사례
Standardize on NOW() or UTC_TIMESTAMP() as your base
Do not apply functions to columns in the WHERE clause
Understand the behavior of month-based addition
If precision is required, use DATETIME(3) or higher

5. MySQL에서 날짜/시간 차이 계산 (DATEDIFF / TIMESTAMPDIFF)

운영 시스템에서는 현재 시간을 단순히 가져오는 것만으로는 충분하지 않습니다. 보통 경과한 일수남은 시간을 계산해야 합니다.

5.1 날짜 차이 계산: DATEDIFF()

DATEDIFF()는 두 날짜 사이의 일수 차이를 계산합니다.

SELECT DATEDIFF('2025-02-10', '2025-02-01');

결과

9

핵심 포인트

  • 일수만 차이를 반환합니다
  • 시간 부분은 무시됩니다
  • 결과가 음수가 될 수 있습니다

예시: 생성 이후 일수 계산

SELECT DATEDIFF(NOW(), created_at)
FROM users;

5.2 단위별 차이 계산: TIMESTAMPDIFF()

TIMESTAMPDIFF()를 사용하면 단위를 지정할 수 있습니다.

SELECT TIMESTAMPDIFF(unit, start_datetime, end_datetime);

예시: 시간 차이

SELECT TIMESTAMPDIFF(HOUR, '2025-02-01 10:00:00', '2025-02-01 15:00:00');

결과

5

일반적인 단위

UnitMeaning
SECONDSeconds
MINUTEMinutes
HOURHours
DAYDays
MONTHMonths
YEARYears

예시: 로그인 이후 분 계산

SELECT TIMESTAMPDIFF(MINUTE, login_at, NOW())
FROM users;

5.3 실제 사용 사례

  • 세션 타임아웃 검사
  • 구독 만료 검사
  • 로그에서 경과 시간 계산
  • 속도 제한 로직

5.4 일반적인 실수

❌ 정밀한 시간이 필요할 때 DATEDIFF 사용

DATEDIFF()는 시간과 분을 무시합니다.

❌ 인자 순서 뒤바꾸기

순서는 다음과 같습니다:

TIMESTAMPDIFF(unit, start, end)

뒤바꾸면 결과가 음수가 됩니다.

❌ 시간대 무시

UTC와 로컬 시간을 혼용하면 차이가 올바르지 않을 수 있습니다.

5.5 모범 사례

  • 시간이 중요한 경우 TIMESTAMPDIFF()를 사용하세요
  • 간단한 일수 계산에는 DATEDIFF()를 사용하세요
  • 일관된 시간대 사용을 보장하세요
  • 분산 시스템에서는 UTC를 표준화하세요

6. 현재 시간을 이용한 날짜 범위 쿼리

가장 흔한 실제 요구사항 중 하나는 다음과 같은 특정 시간 범위 내의 레코드를 조회하는 것입니다:

  • 오늘의 레코드
  • 최근 7일
  • 최근 24시간
  • 이번 달

6.1 오늘 레코드 조회 (인덱스 친화적)

SELECT *
FROM logs
WHERE created_at >= CURDATE()
  AND created_at < DATE_ADD(CURDATE(), INTERVAL 1 DAY);

왜 올바른지

  • 컬럼에 함수가 적용되지 않음
  • 인덱스를 그대로 사용할 수 있음
  • 효율적인 범위 쿼리

6.2 최근 7일

SELECT *
FROM logs
WHERE created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY);

6.3 최근 24시간

SELECT *
FROM logs
WHERE created_at >= DATE_SUB(NOW(), INTERVAL 1 DAY);

6.4 이번 달

SELECT *
FROM logs
WHERE created_at >= DATE_FORMAT(NOW(), '%Y-%m-01')
  AND created_at < DATE_ADD(DATE_FORMAT(NOW(), '%Y-%m-01'), INTERVAL 1 MONTH);

프로덕션 시스템에서는 경계를 애플리케이션 측에서 계산하고 매개변수로 전달하는 것이 종종 더 좋습니다.

6.5 일반적인 성능 실수

❌ 인덱스가 있는 컬럼에 함수 적용

WHERE DATE(created_at) = CURDATE();

이는 인덱스 사용을 방지하고 전체 테이블 스캔을 일으킵니다.

❌ BETWEEN을 부주의하게 사용

BETWEEN은 포함 연산이며 1초 오차 문제를 일으킬 수 있습니다.

6.6 모범 사례 요약

  • 날짜 필터링 시 항상 범위 조건을 사용하세요
  • 인덱스가 있는 컬럼에 함수 적용을 피하세요
  • 글로벌 시스템에서는 UTC 저장을 선호하세요
  • 시간대 가정에 대해 명확히 명시하세요