유닉스 타임스탬프란?
유닉스 타임스탬프(Unix time, epoch time)는 1970년 1월 1일 00:00:00 UTC(협정 세계시)를 0으로 두고 그 뒤로 흐른 시간을 하나의 정수로 센 값입니다. 보통은 초 단위이고, 환경에 따라 밀리초·마이크로초·나노초 단위를 씁니다. 날짜를 "2025년 1월 1일 오전 9시", "Jan 1st, 2025 09:00 KST", "2025-01-01T00:00:00Z"처럼 적으면 형식·언어·시간대에 따라 해석이 갈리지만, 숫자 하나는 해석이 갈릴 수 없습니다. 그래서 서버 로그, API 응답, 데이터베이스, JWT 토큰의 만료 시각(exp) 같은 곳에서 널리 쓰입니다. 또 정수이므로 두 시각의 차이는 뺄셈 한 번으로, 정렬은 숫자 비교로 끝납니다.
변환 원리와 단위 자동 인식
초 단위 타임스탬프에 1000을 곱하면 밀리초 단위입니다. 자바스크립트의 Date 객체는 밀리초를 받으므로 초 단위 값은 new Date(ts * 1000)으로 만들어야 하고, 이를 빠뜨려 "1970년 1월 20일" 같은 엉뚱한 날짜가 나오는 것이 가장 흔한 실수입니다. 이 도구는 입력값의 크기로 단위를 추정합니다. 절댓값이 1천억(1011) 미만이면 초, 100조(1014) 미만이면 밀리초, 1017 미만이면 마이크로초, 그 이상이면 나노초로 해석합니다. 현대의 날짜에서는 아래 표처럼 단위별 자릿수가 달라 구분이 확실합니다. 다만 1973년 3월 이전 시각을 밀리초로 적으면 11자리 이하라 초 단위로 읽히고, 서기 5138년 이후를 초로 적으면 밀리초로 읽히므로, 이런 특수한 값은 "단위"를 직접 지정하세요.
아래는 2026-01-01 00:00:00 UTC를 각 단위로 표현한 값입니다(빌드 시 계산).
| 단위 | 값 | 자릿수 | 주로 쓰는 곳 |
|---|---|---|---|
| 초 (s) | 1767225600 | 10 | 유닉스·PHP·Python time.time() 정수부, MySQL UNIX_TIMESTAMP() |
| 밀리초 (ms) | 1767225600000 | 13 | 자바스크립트 Date.now(), 자바 System.currentTimeMillis() |
| 마이크로초 (µs) | 1767225600000000 | 16 | Python datetime·일부 DB 타임스탬프 |
| 나노초 (ns) | 1767225600000000000 | 19 | Go time.Now().UnixNano(), 자바 Instant 일부 |
시간대: 타임스탬프에는 시간대가 없다
타임스탬프는 "UTC 기준으로 에포크 이후 몇 초"라는 하나의 사실이며, 시간대는 그 값을 사람이 읽는 시각으로 바꿀 때만 필요합니다. 같은 숫자 1735689600은 UTC로는 2025-01-01 00:00:00, 한국에서는 같은 순간을 2025-01-01 09:00:00으로 읽습니다. 한국 표준시(KST)는 UTC보다 9시간 빠른 UTC+9이며, 현재 한국은 서머타임(일광절약시간)을 시행하지 않아 연중 오프셋이 일정합니다. 반대로 미국·유럽 시간대는 서머타임 때문에 오프셋이 해마다 바뀌므로, 날짜 → 타임스탬프 변환에서 "내 브라우저 시간대"를 선택하면 입력한 날짜에 해당하는 규칙이 적용됩니다. 로그를 분석하거나 서버 간 데이터를 맞출 때는 저장은 항상 UTC(타임스탬프)로, 표시할 때만 지역 시간으로 바꾸는 것이 안전합니다.
ISO 8601 표기 읽는 법
결과의 ISO 8601 칸은 2025-01-01T00:00:00.000Z 형태입니다. 날짜와 시각 사이의 T는 구분 문자, 소수점 이하는 밀리초, 맨 끝의 Z는 "UTC(오프셋 0)"를 뜻합니다. 한국 시각을 같은 방식으로 적으면 2025-01-01T09:00:00+09:00처럼 Z 대신 오프셋이 붙고, 두 표기는 같은 순간을 가리킵니다. Z나 오프셋이 없는 2025-01-01T09:00:00은 "어느 시간대인지 모르는 시각"이라 파서에 따라 UTC로도 로컬로도 해석되므로, 로그나 API 명세에서 이런 표기를 만나면 시간대 규칙을 먼저 확인해야 합니다. API를 설계하는 쪽이라면 시간대가 명시된 ISO 8601 문자열이나 정수 타임스탬프 중 하나로 통일하고, 단위(초/밀리초)를 필드명이나 문서에 못 박아 두는 것이 혼동을 막는 가장 확실한 방법입니다.
기억해 둘 만한 타임스탬프
| 타임스탬프 | UTC | KST | 의미 |
|---|---|---|---|
| 0 | 1970-01-01 00:00:00 | 1970-01-01 09:00:00 | 유닉스 시간의 시작(에포크) |
| 1000000000 | 2001-09-09 01:46:40 | 2001-09-09 10:46:40 | 10억 초 |
| 1234567890 | 2009-02-13 23:31:30 | 2009-02-14 08:31:30 | 1234567890 (개발자들이 기념하는 숫자) |
| 1735689600 | 2025-01-01 00:00:00 | 2025-01-01 09:00:00 | 2025년 새해 |
| 1767225600 | 2026-01-01 00:00:00 | 2026-01-01 09:00:00 | 2026년 새해 |
| 2147483647 | 2038-01-19 03:14:07 | 2038-01-19 12:14:07 | 부호 있는 32비트 정수의 최댓값 (2038년 문제) |
| 4294967295 | 2106-02-07 06:28:15 | 2106-02-07 15:28:15 | 부호 없는 32비트 정수의 최댓값 |
검산된 계산 예시
예시 1. 타임스탬프 → 날짜
1735689600는 UTC로 2025-01-01 00:00:00, 한국시간으로 2025-01-01 09:00:00입니다. 13자리로 적은 1735689600000(밀리초)도 같은 시각이고, 이 도구는 자릿수로 알아서 구분합니다.
예시 2. 한국 시각 → 타임스탬프
2026-03-01 09:00:00 KST를 UTC로 바꾸면 9시간을 빼 2026-03-01 00:00:00 UTC이고, 그 타임스탬프는 1772323200(ISO 8601: 2026-03-01T00:00:00.000Z)입니다. 이 도구의 ②번에 같은 시각을 KST로 넣으면 동일한 값이 나옵니다.
예시 3. 두 시각의 간격
2026년 새해(1767225600)에서 2025년 새해(1735689600)를 빼면 31536000초이고, 86,400으로 나누면 365일입니다. 타임스탬프끼리의 뺄셈은 윤년·월별 일수를 신경 쓰지 않고 정확한 경과 시간을 줍니다. 다만 "한 달 뒤"처럼 달력 규칙이 필요한 계산에는 쓸 수 없습니다.
흔한 실수와 한계
- 초와 밀리초 혼동: 서버는 초, 자바스크립트는 밀리초를 쓰는 식으로 섞이면 날짜가 1970년 또는 5만 년 뒤로 튑니다. 자릿수를 먼저 확인하세요.
- 윤초는 세지 않습니다: 유닉스 시간은 하루를 항상 정확히 86,400초로 칩니다. 실제 UTC에 삽입된 윤초(마지막은 2016년 12월 31일)는 타임스탬프에 반영되지 않고, 시스템이 그 순간을 늘이거나 반복해 처리합니다. 초 단위로 천문학적 정밀도가 필요한 용도에는 적합하지 않습니다.
- 2038년 문제: 타임스탬프를 부호 있는 32비트 정수에 저장하면 2147483647(UTC 2038-01-19 03:14:07)가 마지막입니다. 그 다음 초에 값이 음수로 뒤집혀 1901년으로 읽힙니다. 오래된 임베디드·DB 컬럼 정의가 대상이며, 64비트 정수를 쓰면 사실상 문제가 없습니다.
- 표현 범위: 자바스크립트
Date는 에포크 기준 ±8.64×1015밀리초(약 ±27만 년) 범위만 다루며, 최댓값은 +275760-09-13T00:00:00.000Z입니다. 이 범위를 넘는 값은 "범위를 벗어났다"고 안내합니다. - 음수 타임스탬프: 1970년 이전은 음수로 표현합니다. 이 도구는 음수도 변환하지만, 시스템에 따라 음수를 지원하지 않는 경우가 있습니다.
- 밀리초 미만 정밀도: 마이크로초·나노초 값은 변환 시 밀리초 미만을 버립니다.
- 법적·정산 용도: 로그 확인과 개발 보조용입니다. 계약 기한이나 금융 정산처럼 효력이 달린 시각은 해당 기관의 공식 시각 기준을 따르세요.
언어·도구별 현재 타임스탬프와 변환 코드
| 환경 | 현재 시각(초) | 타임스탬프 → 날짜 |
|---|---|---|
| JavaScript | Math.floor(Date.now() / 1000) | new Date(ts * 1000) |
| Python | int(time.time()) | datetime.fromtimestamp(ts, timezone.utc) |
| Java | Instant.now().getEpochSecond() | Instant.ofEpochSecond(ts) |
| PHP | time() | date("Y-m-d H:i:s", $ts) |
| Go | time.Now().Unix() | time.Unix(ts, 0) |
| MySQL | UNIX_TIMESTAMP() | FROM_UNIXTIME(ts) |
| PostgreSQL | EXTRACT(EPOCH FROM now()) | to_timestamp(ts) |
| Bash(GNU) | date +%s | date -d @ts |
표의 코드는 각 환경의 대표적인 호출이며 사용 중인 버전·라이브러리에 따라 임포트나 시간대 지정이 추가로 필요할 수 있습니다(예: 파이썬에서 시간대를 지정하지 않으면 컴퓨터의 로컬 시간대로 해석).
변환 결과 활용법
- JWT 토큰의
exp,iat값이 언제인지 확인하려면 JWT 디코더로 페이로드를 꺼낸 뒤 여기에 붙여 넣으세요. - 응답이 JSON이라면 JSON 포맷터로 먼저 정리해 타임스탬프 필드를 찾기 쉽게 만들 수 있습니다.
- 다른 나라 시각과 비교하려면 세계 시간대 변환기나 시간대 변환기를 함께 쓰세요.
- 경과 시간만 궁금하면 시간 길이 변환기, 날짜 표기 규칙은 날짜·시간 형식 가이드가 도움이 됩니다.
자주 묻는 질문
10자리와 13자리는 어떻게 구분되나요?
현재(2020년대) 초 단위 타임스탬프는 10자리(약 17억대), 밀리초 단위는 13자리(약 1조 7천억대)입니다. 이 도구는 값의 크기로 단위를 추정하며(1천억 미만 초, 100조 미만 밀리초 등), 애매하면 "단위"를 직접 선택하세요.
다른 시간대(예: 미국 동부시간)로도 확인하고 싶어요.
이 도구는 UTC, KST, 내 브라우저 시간대를 보여 줍니다. 여러 국가의 시간대를 비교해야 한다면 세계 시간대 변환기나 시간대 변환기를 함께 사용해 보세요.
변환한 날짜가 1970년 1월로 나옵니다. 왜죠?
밀리초 값을 초로 해석했거나 그 반대일 가능성이 높습니다. 예를 들어 1735689600을 밀리초로 읽으면 1970년 1월 21일경이 됩니다. 단위를 직접 지정해 확인하세요.
입력한 시각이 서버에 전송되나요?
아니요. 모든 계산은 브라우저 안에서 이루어지며 입력값은 저장되거나 전송되지 않습니다.
타임스탬프는 윤년과 서머타임을 어떻게 처리하나요?
타임스탬프는 UTC 기준의 경과 초이므로 윤년이나 서머타임의 영향을 받지 않습니다. 이들은 타임스탬프를 사람이 읽는 날짜로 바꾸는 단계에서만 반영됩니다. 따라서 서머타임이 있는 지역의 "날짜 → 타임스탬프" 변환에서는 시각이 존재하지 않거나(건너뛰는 시간) 두 번 존재하는(되풀이되는 시간) 구간에 주의해야 합니다.
2038년 문제는 지금 쓰는 서비스에도 영향이 있나요?
64비트 정수나 현대 언어의 기본 시간 타입을 쓰는 서비스는 영향이 없습니다. 오래된 32비트 시스템, 임베디드 기기, 타임스탬프를 32비트 정수 컬럼에 저장하는 데이터베이스 스키마가 점검 대상입니다. 만료일이 2038년 이후인 인증서·계약·쿠폰 같은 미래 날짜 데이터는 이미 영향을 받을 수 있습니다.