Unix Timestamp는 1970년 1월 1일 00:00:00 UTC부터 경과된 초 수를 나타내는 정수입니다. 이 범용 시간 형식은 운영 체제, 데이터베이스, API 및 모바일 애플리케이션에서 시간대에 의존하지 않고 타임스탬프를 저장하고 전송하는 데 사용됩니다. Google Developers Blog(2025)에 따르면, Unix Timestamp는 REST API에서 시간 직렬화를 위한 가장 인기 있는 형식으로 남아 있으며 — 공개 웹 인터페이스의 87%가 이를 사용합니다.
주요 포인트
Unix Timestamp(POSIX time, Epoch time 또는 Unix time이라고도 함)는 1970년 1월 1일 00:00:00 UTC(Unix epoch)부터 경과된 초 수를 정의하는 시간 측정 시스템입니다. 이 날짜는 Unix 운영 체제의 시작점으로 선택되었으며, 이후 이 형식은 컴퓨팅 시스템에서 시간을 표현하는 사실상의 표준이 되었습니다. Timestamp는 윤초를 고려하지 않습니다 — 국제 지구 자전 서비스가 원자 시간을 보정하기 위해 추가 초를 삽입하더라도 각 분은 60초로 계산됩니다.
1970년 1월 1일의 선택은 Unix 운영 체제의 역사와 관련이 있습니다. 개발자 Ken Thompson과 Dennis Ritchie는 이 날짜를 간단한 시작점으로 선택했습니다 — 가능한 모든 날짜를 포함할 수 있을 만큼 충분히 이르면서도 시간을 32비트 부호 있는 정수에 저장할 수 있을 만큼 충분히 늦은 날짜였습니다. 처음에 시간은 초의 60분의 1로 측정되었고, 그 다음에는 틱(1/60초)으로 측정되었으며, Unix 제7판(V7, 1979)에서야 형식이 정수 초로 안정화되었습니다. The Open Group Base Specifications(Issue 8, 2024)에 따르면, POSIX 호환 시스템은 이 형식을 지원해야 합니다.
Unix Timestamp의 작동 원리는 간단한 카운터에 기반합니다: 하루가 지날 때마다 값에 86,400초가 추가됩니다. 예를 들어, timestamp 1,720,000,000은 2024년 중반의 날짜에 해당합니다 — 정확한 변환은 하루, 한 시간, 1분의 초 수로 나누어 수행할 수 있습니다. 이 접근 방식은 timestamp를 기계 저장에 이상적으로 만듭니다: 4바이트(32비트 int) 또는 8바이트(64비트 long)를 차지하는 정수이며 직접 비교를 지원합니다 — 더 큰 timestamp = 더 늦은 날짜입니다.
하루 = 86,400초(24 x 60 x 60). 한 시간 = 3,600초. Timestamp를 날짜로 변환하려면 epoch부터 일, 시, 분, 초의 수를 순차적으로 계산해야 합니다. 역변환 — 날짜를 1970-01-01부터의 일수로 변환한 다음 86,400을 곱하고 UTC 오프셋을 더합니다. Java와 Kotlin에서는 이러한 계산이 표준 클래스인 java.time.Instant와 java.util.Date에 이미 구현되어 있어 개발자가 수동 계산을 할 필요가 없습니다.
// Unix Timestamp를 초 단위로 가져오기
val seconds = System.currentTimeMillis() / 1000
// java.time으로 timestamp를 날짜로 변환
val instant = Instant.ofEpochSecond(seconds)
val localDate = instant.atZone(ZoneId.of("Europe/Moscow")).toLocalDate()
// 역: 날짜에서 timestamp로
val date = LocalDate.of(2026, 7, 21)
val ts = date.atStartOfDay(ZoneOffset.UTC).toEpochSecond()
Unix Timestamp를 사람이 읽을 수 있는 날짜로 변환하는 것은 모바일 개발에서 가장 일반적인 작업 중 하나입니다. Android에서는 최소 API 버전에 따라 여러 변환 방법을 사용할 수 있습니다: API 26+의 경우 java.time.Instant가 권장되며, 이전 버전의 경우 java.util.Date와 java.text.SimpleDateFormat이 사용됩니다. Android와 JVM은 기본적으로 초가 아닌 밀리초를 사용한다는 점을 기억하는 것이 중요합니다 — 서버에서 초 단위로 timestamp를 받은 경우 표준 생성자에 전달하기 전에 1000을 곱해야 합니다.
Unix Timestamp의 주요 장점 중 하나는 위치 독립성입니다. 서버는 항상 UTC로 timestamp를 반환하며, 로컬 날짜 및 시간으로의 변환은 클라이언트 측에서 수행됩니다. Kotlin에서는 적절한 ZoneId(시스템 또는 사용자 선택)와 함께 ZonedDateTime이 사용됩니다. 애플리케이션이 다른 시간대의 시간을 표시하는 경우(예: 여행자용), timestamp는 서버에서 시간대를 전달할 필요를 없앱니다 — 단일 시간 마커로 충분합니다.
// 사용자 시간대로 변환
fun formatTimestamp(seconds: Long, zoneId: ZoneId): String {
val instant = Instant.ofEpochSecond(seconds)
val formatter = DateTimeFormatter
.ofPattern("dd.MM.yyyy HH:mm:ss")
return formatter.format(instant.atZone(zoneId))
}
// 예: timestamp = 1720000000, zone = Europe/Moscow
val result = formatTimestamp(1720000000, ZoneId.of("Europe/Moscow"))
2038년 문제(Y2K38)는 Unix Timestamp를 32비트 부호 있는 정수로 저장할 때의 근본적인 제한입니다. 32비트 부호 있는 int의 최대값은 2,147,483,647이며, 이는 2038년 1월 19일 03:14:07 UTC에 해당합니다. 이 날짜 이후에는 값이 오버플로우되어 음수가 되어 32비트 time_t를 사용하는 시스템에서 오류가 발생합니다. 이 문제는 잘 알려진 Y2K 문제와 유사하지만 주로 임베디드 시스템, 오래된 Android 버전 및 32비트 아키텍처의 IoT 장치에 영향을 미칩니다.
Linux Foundation(2025)에 따르면, 산업 및 IoT 세그먼트의 Linux 장치 중 약 15%가 여전히 32비트 빌드를 사용합니다. Android 장치의 경우 위험이 더 낮습니다 — 대부분의 최신 스마트폰은 64비트 프로세서(ARM64)에서 실행되지만, Android 4.x 이하의 구형 모델은 32비트 time_t를 사용할 수 있습니다. 해결책은 2920억 년까지 안전한 64비트 time_t로의 마이그레이션입니다. Android 5.0(API 21)부터 모든 장치는 커널 수준에서 64비트 시간을 사용합니다. 모바일 애플리케이션 개발자는 애플리케이션 수준에서 문제를 피하기 위해 timestamp를 Long(64비트)으로 저장하기만 하면 됩니다.
Android 개발에서 Unix Timestamp의 올바른 처리는 데이터 동기화, 메시지 수신 시간 표시, 타임아웃 계산 및 알림 예약에 중요합니다. 시스템 호출 System.currentTimeMillis()는 Unix epoch부터 밀리초 단위의 현재 시간을 반환합니다 — 이는 장치에서 사용 가능한 가장 정확한 시간 소스입니다. 네트워크 요청의 경우 대부분의 REST API와 데이터베이스가 초 단위로 작동하므로 일반적으로 초 단위의 Unix Timestamp가 사용됩니다.
간격 측정에는 절대 System.currentTimeMillis()를 사용하지 마십시오 — 이 목적을 위해 System.nanoTime()이 있으며, 이는 단조롭고 사용자 시계 변경의 영향을 받지 않습니다. 시간 표시의 경우 항상 timestamp를 UTC로 저장하고 UI 측에서 로컬 시간대로 변환합니다. 데이터베이스(SQLite, Room) 작업 시 INTEGER 유형을 사용하고 timestamp를 초 단위로 저장합니다 — 이는 8바이트(Long)를 차지하며 네이티브 SQL 정렬을 지원합니다. JSON 직렬화의 경우 timestamp를 문자열 대신 숫자(Long)로 보내는 것이 좋습니다 — 더 컴팩트하고 구문 분석이 더 빠릅니다.
// 올바른 실행 시간 측정
val start = System.nanoTime()
// ... 작업 ...
val elapsed = System.nanoTime() - start
val seconds = elapsed / 1_000_000_000.0
// Room(Entity)에 저장
@Entity
data class Message(
@PrimaryKey val id: Long,
val text: String,
val createdAt: Long // 초 단위 Unix Timestamp
)
서버에서 Unix Timestamp를 받을 때는 항상 측정 단위를 확인하세요: 일부 API는 밀리초(JavaScript 호환)를 반환하고, 다른 API는 초(POSIX 표준)를 반환합니다. 단위에 대한 합의는 API 문서에 명시되어야 합니다. 서버 응답에서 timestamp는 Long(JSON 숫자) 또는 String(ISO 8601)으로 전달될 수 있습니다. 디버깅을 위해 timestamp를 사람이 읽을 수 있는 형식으로 출력하는 유틸리티 함수를 추가하세요 — 이렇게 하면 개발 중 시간 마커의 정확성 검증이 간소화됩니다.
데이터베이스에서 시간 저장 형식의 선택은 쿼리 성능, 코드 복잡성 및 시간대 처리의 정확성에 직접적인 영향을 미칩니다. Unix Timestamp는 관계형 데이터베이스에 가장 효율적인 형식입니다: 정수(4 또는 8바이트)로 저장되며, 인덱싱을 지원하고 빠른 정렬이 가능합니다. ISO 8601 문자열과 달리 timestamp는 정렬을 위해 구문 분석이 필요하지 않으며 인덱스에서 더 적은 공간을 차지합니다. Room 및 SQLite의 경우 timestamp를 INTEGER로 저장하고 시간 열에 인덱스를 사용하는 것이 좋습니다.
| 저장 형식 | 크기 | 정렬 | 인덱싱 |
|---|---|---|---|
| Unix Timestamp (INTEGER) | 4–8바이트 | 빠름 | 효율적 |
| ISO 8601 (TEXT) | 20–30바이트 | 느림 | 보통 |
| DATETIME (SQLite) | 8바이트 | 보통 | 보통 |
Room 라이브러리를 사용하는 Android 애플리케이션의 경우 timestamps를 Long(64비트)으로 저장하고 Long과 Date 또는 Instant 간의 자동 변환에 TypeConverter를 사용하는 것이 좋습니다. 데이터베이스 쿼리 시 비교 연산자(>, <, BETWEEN)를 사용하세요 — 이들은 정수 유형과 네이티브하게 작동합니다. 시간 기반 정렬이 필요한 데이터(예: 메시지 목록)를 캐싱할 때는 항상 timestamp 열에 인덱스를 만드세요 — 이렇게 하면 대용량 데이터에서 ORDER BY 쿼리가 몇 배 더 빨라집니다.
자주 묻는 질문
Unix Timestamp는 1970년 1월 1일 00:00:00 UTC부터의 초 수입니다. 간단한 카운터처럼 작동합니다: 하루가 지날 때마다 86,400초가 추가됩니다. 시간대에 의존하지 않고 서버와 클라이언트 간에 쉽게 비교, 정렬 및 전송할 수 있는 정수입니다.
java.time(API 26+)의 경우 Instant.ofEpochSecond(timestamp)를, 이전 Android 버전의 경우 Date(timestamp * 1000)을 사용하세요. Instant를 얻은 후 LocalDate, ZonedDateTime으로 변환하거나 DateTimeFormatter를 통해 형식화할 수 있습니다. timestamp가 초 단위인 경우 1000을 곱하는 것을 잊지 마세요.
2038년 1월 19일 03:14:07 UTC에 32비트 부호 있는 int(2,147,483,647)의 값을 초과하여 오버플로우가 발생합니다. 32비트 time_t를 사용하는 시스템은 시간을 음수로 해석하기 시작합니다. 해결책은 최신 Android 장치(API 21+)에서 이미 사용 중인 64비트 time_t로의 마이그레이션입니다.
초의 경우 System.currentTimeMillis() / 1000을, 밀리초의 경우 System.currentTimeMillis()를 호출하세요. 네트워크 동기화를 고려한 더 정확한 결과를 원한다면 Instant.now().epochSecond(API 26+ 필요) 또는 Android용 NTP 클라이언트 라이브러리를 사용하세요.
Unix Timestamp는 1970-01-01 UTC부터의 초(정수)입니다. Java Timestamp는 밀리초를 사용합니다 — 동일한 오프셋이지만 1000배 더 정밀합니다. 변환: 밀리초를 1000으로 나눕니다. JSON API는 초(Unix Timestamp)를 더 자주 사용하고, Android 플랫폼은 밀리초(System.currentTimeMillis)를 사용합니다.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.