Date는 캘린더와 시간대와 무관하게 특정 시점을 나타내는 Foundation 구조체입니다. 이 타입은 2001년 1월 1일 기준일로부터 경과한 초 수를 저장하며, 시간 간격 비교 및 계산을 위한 기본 연산을 제공합니다. Apple Developer Documentation(2025)에 따르면, Date는 UIKit과 SwiftUI에서 CloudKit과 Core Data에 이르기까지 모든 Apple 프레임워크에서 사용됩니다. Date의 작동 방식을 이해하는 것은 모든 iOS 개발자에게 필수적이며, 이것 없이는 애플리케이션에서 시간을 관리하는 것이 불가능합니다.
핵심 요점
Date는 Foundation 프레임워크의 값 타입으로, 단일 절대적 시점을 캡처합니다. 캘린더 표현(년, 월, 일)과 달리 Date는 시간대나 캘린더 시스템에 의존하지 않습니다 — 순수하게 숫자 타임스탬프 값입니다.
Date의 내부 표현은 TimeInterval(Double의 타입 별칭)이며, 기준일(2001년 1월 1일 00:00:00 UTC)로부터의 상대적 초 수를 저장합니다. Apple은 iOS와 macOS가 구축된 레거시 NeXTSTEP 시스템과의 호환성을 위해 Unix epoch(1970년) 대신 이 날짜를 선택했습니다.
Date는 모든 Apple API에서 표준 시간 타입으로 사용됩니다: UIDatePicker, DatePicker, UserDefaults, Codable, Core Data, CloudKit. Date 없이는 일정, 타이머, 캘린더 이벤트, 데이터 직렬화 및 시간 관련 작업을 처리하는 것이 불가능합니다.
Date는 사람이 읽을 수 있는 값이 아닌 물리적 타임스탬프를 나타낸다는 점에서 캘린더 타입과 다릅니다. 동일한 Date가 다른 시간대에서 다른 캘린더 날짜에 해당할 수 있습니다. 구성 요소(년, 월, 일)를 추출하려면 Calendar와 DateComponents를 통해 Date를 변환합니다.
Date는 Grand Central Dispatch에서 작업 디스패치에 사용되는 DispatchTime과도 다릅니다. DispatchTime은 시스템 부트 시간에 상대적인 반면, Date는 저장, 전송 및 복원이 가능한 절대적 타임스탬프입니다.
Date()는 현재 시간으로 객체를 생성하는 가장 간단한 방법입니다. 매개변수 없는 초기화자는 호출의 정확한 시간을 반환합니다. 과거나 미래의 날짜를 생성하려면 TimeInterval과 addingTimeInterval 메서드, 또는 기존 Date에서 초기화를 사용합니다.
구성 요소에서 임의의 날짜를 생성하려면 Calendar와 DateComponents 쌍을 사용합니다. Calendar는 사람이 읽을 수 있는 구성 요소(년, 월, 일, 시, 분)를 Date로 변환합니다. ISO8601DateFormatter를 통해 ISO 8601 문자열에서, 또는 DateFormatter를 통해 임의의 문자열 표현에서 Date를 초기화할 수도 있습니다.
Date.distantPast와 Date.distantFuture는 과거와 미래의 무한히 먼 시점을 나타내는 두 정적 속성입니다. 이들은 알고리즘에서 날짜 필터링 및 정렬을 위한 경계 값으로 사용됩니다.
import Foundation
// 현재 시간으로 Date 생성
let now = Date()
print("Current time: \(now)")
// 1시간(3600초) 후 날짜
let inOneHour = now.addingTimeInterval(3600)
// 구성 요소로부터 날짜
var components = DateComponents()
components.year = 2025
components.month = 12
components.day = 25
let christmas = Calendar.current.date(from: components)!
예제는 Date를 생성하는 세 가지 방법(현재 시간, 간격 추가, DateComponents를 통한 생성)을 보여줍니다. 세 접근 방식 모두 밀리초 정밀도의 Date 타입 값을 반환합니다. Calendar.current는 사용자의 시스템 캘린더를 사용합니다 — Apple 기기에서는 일반적으로 그레고리력입니다.
TimeInterval은 두 시점 사이의 초 수를 나타내는 Double의 타입 별칭입니다. TimeInterval의 정밀도는 밀리초의 분수까지 도달하며, 대부분의 실용적 작업에 충분합니다. 음수 TimeInterval은 기준점에 대해 과거를 나타냅니다.
Date는 모든 표준 비교 연산자를 지원합니다: ==, <, >, <=, >=. Swift는 내부 TimeInterval 값을 자동으로 비교합니다. compare 메서드는 더 명시적인 비교를 위해 .orderedSame, .orderedAscending, .orderedDescending 옵션과 함께 ComparisonResult를 반환합니다.
Date.distance(to:)는 지정된 날짜까지의 TimeInterval을 반환하는 메서드입니다. 대상 날짜가 과거인 경우 결과는 음수입니다. advanced(by:)는 현재 날짜에 지정된 TimeInterval을 추가하여 새 날짜를 생성합니다. 이 메서드들은 Strideable 프로토콜을 구현하여 Date를 Range 및 ClosedRange에서 사용할 수 있게 합니다.
let start = Date()
let end = start.addingTimeInterval(86400)
// 연산자로 비교
if start < end {
print("start is earlier")
}
// 두 날짜 사이의 TimeInterval
let interval: TimeInterval = end.timeIntervalSince(start)
print("Seconds: \(Int(interval / 60)) minutes")
// 범위에서 Date 사용
let range = start...end
let mid = start.addingTimeInterval(43200)
if range.contains(mid) {
print("mid is between start and end")
}
86400의 TimeInterval은 하루에 해당합니다. 더 복잡한 간격(주, 월, 년)에는 Calendar와 DateComponents를 사용하세요. 이러한 단위는 가변 길이(윤년, 썸머타임)를 가지기 때문입니다. TimeInterval은 초 단위의 고정 간격에만 적용됩니다.
Calendar는 Date와 사람이 읽을 수 있는 구성 요소 사이의 다리 역할을 합니다. Calendar는 시간대와 로케일을 고려하여 Date를 DateComponents(년, 월, 일, 시, 분, 초)로 변환합니다. Calendar 없이는 Date에서 년이나 월을 추출하는 것이 불가능합니다 — Date는 절대적 특성으로 인해 이 정보를 포함하지 않습니다.
Calendar.component 메서드는 Date에서 단일 구성 요소(년, 월, 일, 시, 분, 초, 요일, 분기)를 추출합니다. Calendar.dateComponents 메서드는 한 번의 호출로 구성 요소 집합을 추출합니다 — 이는 각 필드에 대해 개별적으로 component를 호출하는 것보다 효율적입니다.
Calendar.isDateInToday, isDateInTomorrow, isDateInYesterday는 상대적 날짜를 확인하는 편리한 메서드입니다. Calendar.dateInterval은 지정된 기간(일, 주, 월, 년)의 시작과 끝을 반환합니다. Calendar.compare는 지정된 구성 요소까지의 정밀도로 날짜를 비교합니다 — 예를 들어, 월과 일을 고려하지 않고 년만 비교합니다.
let calendar = Calendar.current
// 구성 요소 추출
let year = calendar.component(.year, from: Date())
let month = calendar.component(.month, from: Date())
// 상대적 날짜 확인
if calendar.isDateInToday(someDate) {
print("Today!")
}
// 하루의 시작과 끝
let dayInterval = calendar.dateInterval(of: .day, for: Date())!
print("Day start: \(dayInterval.start)")
print("Day end: \(dayInterval.end)")
Calendar.current는 사용자의 시스템 설정(캘린더, 시간대, 로케일)을 사용합니다. 테스트나 특정 계산을 위해 Calendar(identifier: .gregorian)를 통해 특정 매개변수로 Calendar를 생성하고 timeZone 속성을 통해 원하는 TimeZone을 설정할 수 있습니다.
DateFormatter는 Date를 사용자에게 표시해야 할 때 필수 구성 요소입니다. DateFormatter는 지정된 형식과 로케일에 따라 Date를 문자열로 변환합니다. String(describing:)을 통해 Date를 직접 문자열로 변환하면 기준일과 TimeInterval이 포함된 기술적 표현이 반환됩니다 — 이는 사용자용이 아닙니다.
기본 접근 방식은 사전 설정 스타일 dateStyle과 timeStyle을 사용하는 것입니다. iOS는 4가지 스타일(.short, .medium, .long, .full)을 지원합니다. 날짜와 시간 스타일의 조합으로 유연한 표시 구성을 할 수 있습니다. DateFormatter는 자동으로 지역화를 적용합니다: 러시아어 로케일의 경우 날짜가 “2026년 7월 21일” 형식으로 표시됩니다.
ISO8601DateFormatter는 ISO 8601용 특수 포맷터로, API와 데이터 교환에 가장 일반적인 형식입니다. 이 포맷터는 DateFormatter보다 빠르게 작동하며 로케일에 의존하지 않으므로 JSON에서 날짜 직렬화에 선호됩니다.
// 사전 설정 스타일
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .short
let userString = formatter.string(from: Date())
// API용 ISO 8601
let isoFormatter = ISO8601DateFormatter()
let apiString = isoFormatter.string(from: Date())
// 문자열에서 구문 분석
let parsed = isoFormatter.date(from: "2026-07-21T10:30:00Z")!
DateFormatter 작업 시 성능을 기억하는 것이 중요합니다: 새 포맷터 생성은 비용이 많이 드는 작업입니다. 포맷터를 캐시하거나 한 번 생성하여 재사용하는 것이 좋습니다. 포맷터의 속성으로 timeZone을 설정할 수 있습니다 — 기본적으로 시스템 시간대가 사용되지만, 서버 날짜의 경우 TimeZone(identifier: “UTC”)가 자주 필요합니다.
iOS 애플리케이션에서 Date를 사용하는 일반적인 시나리오를 살펴보겠습니다. 첫 번째 시나리오는 사용자의 생년월일에서 나이 계산입니다. 두 번째는 이벤트까지의 카운트다운 타이머입니다. 세 번째는 테이블 섹션으로 표시하기 위한 날짜별 레코드 그룹화입니다.
Calendar.dateComponents를 [.year] 플래그와 함께 사용하면 두 날짜 간의 차이를 계산합니다. 올바른 시간대 설정이 중요합니다 — Calendar에서 timeZone을 지정하지 않으면 다른 시간대에서 자정을 넘어 결과가 하루 차이날 수 있습니다.
func calculateAge(from birthDate: Date) -> Int {
let calendar = Calendar.current
let now = Date()
let components = calendar.dateComponents(
[.year], from: birthDate, to: now
)
return components.year ?? 0
}
카운트다운 타이머는 TimeInterval을 사용하여 구현됩니다. 대상 날짜와 현재 날짜의 차이를 계산하고, 초 단위 나머지를 구한 다음 일, 시, 분으로 변환합니다. 정기적 업데이트에는 1초 간격의 Timer를 사용합니다. @Published 속성이 있는 ObservableObject를 통해 SwiftUI가 자동으로 인터페이스를 업데이트할 수 있습니다.
날짜별 그룹화는 Date를 키로 하는 딕셔너리를 사용하여 구현됩니다. Calendar.dateInterval(of: .day, for:)는 날짜를 하루의 시작으로 정규화하여 같은 날에 속하는 레코드를 그룹화할 수 있게 합니다. 동일한 접근 방식이 주, 월, 년에도 적용됩니다 — dateInterval의 구성 요소를 .weekOfYear나 .month로 변경하기만 하면 됩니다.
| 시나리오 | 주요 API | 참고 |
|---|---|---|
| 나이 계산 | Calendar.dateComponents | timeZone 고려 |
| 카운트다운 | Date.timeIntervalSince | Timer+Combine |
| 날짜 그룹화 | Calendar.dateInterval | 일 단위로 정규화 |
| JSON 직렬화 | ISO8601DateFormatter | Locale 영향 없음 |
자주 묻는 질문
Date는 캘린더와 로케일에 종속되지 않는 시간의 내부 표현입니다. 문자열은 사용자 설정에 의존하는 형식화된 표시입니다. Date는 100% 정확도로 비교, 직렬화 및 수학적 처리가 가능하지만, 문자열 표현은 항상 포맷터를 통한 구문 분석이 필요합니다.
Date는 시간대에 의존하지 않는 절대적 타임스탬프(기준일로부터 초 수)입니다. 시간대는 표시 컨텍스트입니다. UTC와 모스크바의 동일한 Date는 동일한 물리적 순간을 나타내지만 다른 캘린더 시간으로 표시됩니다.
Date는 Core Data에서 속성 타입으로 네이티브 지원됩니다. Core Data는 자동으로 Date를 저장소에 직렬화합니다. 날짜 필터링이 있는 쿼리의 경우 비교 연산자와 함께 NSPredicate를 사용하세요 — Core Data는 SQLite 수준에서 시간대를 올바르게 처리합니다.
CFAbsoluteTime은 동일한 기준일(2001년 1월 1일)을 사용하는 Core Foundation 타입입니다. Date와 CFAbsoluteTime은 직접 변환을 통해 상호 교환 가능합니다. Date(timeIntervalSinceReferenceDate:)는 CFAbsoluteTime을 받아들이고, Date.timeIntervalSinceReferenceDate는 CFAbsoluteTime을 반환합니다.
Date는 밀리초 정밀도를 가지지만 iOS/macOS 하드웨어 제한으로 인해 나노초 정밀도를 보장하지 않습니다. 고정밀 측정에는 하드웨어 프로세서 사이클 카운터에서 작동하는 mach_absolute_time 또는 Swift 5.7+의 ContinuousClock을 사용하세요.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.