모바일 개발의 날짜와 시간: 개념, 형식 및 처리 방법

저자: IT Sectr 게시일: 2026-07-22 읽는 시간: 11 분

모바일 개발의 날짜와 시간 — 모바일 엔지니어링의 핵심 주제 중 하나입니다. iOS는 DateFormatter와 ISO8601DateFormatter를 사용하고, Android는 java.time의 DateTimeFormatter와 LocalDate를 사용합니다. Android Developer Docs에 따르면, 날짜와 시간 형식 지정에 적합한 모바일 API를 선택하는 것은 다양한 시간대에서 성능과 표시 정확성에 직접적인 영향을 미칩니다.

핵심 요점

  • DateFormatter iOS에서 — 강력하지만 자주 생성하면 느림. 인스턴스를 캐시하거나 ISO 8601 형식에는 ISO8601DateFormatter를 사용하세요.
  • DateTimeFormatter Android에서 — java.time의 스레드 안전 포맷터. API 26부터 더 이상 사용되지 않는 SimpleDateFormat을 대체했습니다.
  • ThreeTenABP — Android API 26 미만을 위한 java.time의 백포트. 오래된 기기에 LocalDate, ZonedDateTime 및 DateTimeFormatter를 추가합니다.
  • TimeZone — UTC를 현지 시간으로 변환하는 데 매우 중요. 시간은 UTC로 저장하고 사용자의 시간대로 표시합니다.
  • Unix Timestamp — 표준 시간 저장 형식. NTP를 통한 동기화는 밀리초 단위의 정확성을 보장합니다.

iOS의 날짜와 시간: DateFormatter와 ISO8601DateFormatter

iOS에서는 날짜와 시간이 전통적으로 Foundation의 DateFormatter를 사용하여 형식이 지정됩니다. 이 클래스는 지정된 패턴, 로케일 및 시간대를 사용하여 Date를 문자열로 변환하거나 다시 변환합니다. DateFormatter의 주요 문제 — 스레드 안전하지 않고 생성 속도가 느리므로 모바일 코드에서는 인스턴스를 반드시 캐시해야 합니다. iOS의 모바일 개발에서 날짜에는 적절한 포맷터가 필요합니다.

DateFormatter와 성능

DateFormatter를 만드는 데는 dateFormat 패턴 구문 분석, 로케일 로드 및 시간대 결정으로 인해 약 1밀리초가 걸립니다. 수백 개의 날짜 목록의 형식을 지정할 때 반복적으로 생성하면 UI에 눈에 띄는 지연이 발생합니다. 해결책 — 포맷터를 전체 화면에 대해 한 번만 만들고 재사용합니다. 멀티스레드 액세스의 경우 DispatchQueue를 통한 동기화를 사용합니다.

swift
import Foundation

// 캐시된 DateFormatter — 한 번 생성됨
private let dateFormatter: DateFormatter = {
    let formatter = DateFormatter()
    formatter.dateFormat = "dd.MM.yyyy HH:mm"
    formatter.locale = Locale(identifier: "ru_RU")
    formatter.timeZone = TimeZone(identifier: "Europe/Moscow")
    return formatter
}()

// ISO8601DateFormatter — 경량 대안
private let isoFormatter: ISO8601DateFormatter = {
    let formatter = ISO8601DateFormatter()
    formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
    return formatter
}()

let now = Date()
let formattedDate = dateFormatter.string(from: now)
// "01.07.2026 14:30"
let isoDate = isoFormatter.string(from: now)
// "2026-07-01T14:30:00.000Z"

ISO 8601 형식의 경우 ISO8601DateFormatter를 사용하세요 — 패턴 지정이 필요 없고 DateFormatter보다 빠르게 작동합니다. iOS 10+에서는 이 클래스가 서버 날짜 작업에 선호됩니다. 이전 형식의 경우 DateFormatter를 계속 사용하되 인스턴스를 정적 속성 또는 싱글톤으로 캐시해야 합니다.

Android의 날짜와 시간: java.time과 DateTimeFormatter

Android에서는 날짜와 시간이 API 26부터 사용 가능한 java.time 패키지를 통해 처리됩니다. 주요 클래스: LocalDate(날짜만), LocalTime(시간만), LocalDateTime(시간대 없는 날짜와 시간) 및 ZonedDateTime(시간대 포함). DateTimeFormatter — Android 모바일 플랫폼을 위한 스레드 안전 포맷터. 모바일 애플리케이션의 날짜는 성능 저하 없이 DateTimeFormatter와 LocalDate를 통해 형식이 지정됩니다.

LocalDate, ZonedDateTime 및 형식 지정

LocalDate는 시간 없이 날짜를 저장합니다 — 생일에 이상적입니다. ZonedDateTime은 시간대와 함께 전체 정보를 저장합니다. DateTimeFormatter는 미리 정의된 패턴(ISO_LOCAL_DATE, ISO_DATE_TIME)과 ofPattern을 통한 사용자 정의 패턴을 지원합니다. 모든 java.time 클래스는 불변이며 스레드 안전하여 여러 스레드에서 작업할 때 경합 상태를 제거합니다.

kotlin
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import java.time.ZoneId

// 현재 날짜 생성 및 형식 지정
val today = LocalDate.now()
val formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy")
val formatted = today.format(formatter)

// 시간대 작업
val utcTime = ZonedDateTime.now(ZoneId.of("UTC"))
val moscowTime = utcTime.withZoneSameInstant(ZoneId.of("Europe/Moscow"))

DateTimeFormatter는 호출할 때마다 패턴을 구문 분석하지 않으므로 SimpleDateFormat보다 훨씬 효율적입니다. 클래스 또는 컴패니언 객체 수준에서 포맷터 상수를 만드는 것이 좋습니다. Unix Timestamp를 변환하려면 Instant.ofEpochSecond를 사용한 다음 시간대를 통해 LocalDateTime 또는 ZonedDateTime으로 변환합니다.

시간대: 모바일 애플리케이션의 날짜와 시간 및 TimeZone

사용자 화면에 올바른 날짜와 시간을 표시하려면 시간대를 적절히 처리해야 합니다. Android용 모바일 개발의 날짜와 시간은 기기의 시간대를 고려해야 합니다. 황금률: 시간은 UTC로 저장하고 표시용으로만 현지 시간대로 변환합니다. iOS는 Foundation의 TimeZone을 제공하고 Android는 java.time의 ZoneId를 제공합니다. 두 모바일 플랫폼 API 모두 기기의 현재 시간대 자동 감지를 지원합니다. 모바일 애플리케이션의 날짜는 ZoneId와 TimeZone에 따라 달라집니다.

일광 절약 시간과 IANA 식별자

일광 절약 시간은 모호성을 만듭니다: 하나의 시점이 두 개의 다른 현지 시간으로 표현될 수 있습니다. java.time과 Foundation은 DST를 자동으로 처리합니다. IANA 식별자(Europe/Moscow, America/New_York)를 사용하고 약어(MSK, EST)는 사용하지 마세요 — 약어는 모호하고 일광 절약 시간 전환을 무시합니다.

swift
import Foundation

// UTC를 iOS 현지 시간으로 변환
func formatToLocalTime(utcDate: Date, timeZoneId: String) -> String {
    let formatter = DateFormatter()
    formatter.dateFormat = "dd.MM.yyyy HH:mm"
    formatter.timeZone = TimeZone(identifier: timeZoneId)
    return formatter.string(from: utcDate)
}

// 기기 시간대 확인
let localTimeZone = TimeZone.current
let isDST = localTimeZone.isDaylightSavingTime()
let secondsFromGMT = localTimeZone.secondsFromGMT()

Android에서는 ZoneId.systemDefault()를 사용하여 기기의 시간대를 가져옵니다. UTC를 현지 시간으로 변환할 때 ZoneOffset.UTC로 ZonedDateTime을 만들고 withZoneSameInstant를 적용합니다. java.time이 없는 이전 API의 경우 TimeZone.getDefault()와 Calendar를 사용하지만 바로 ThreeTenABP를 추가하는 것이 좋습니다.

kotlin
import java.time.Instant
import java.time.ZonedDateTime
import java.time.ZoneId

// Unix Timestamp를 현지 시간으로 변환
fun toLocalDisplay(unixSeconds: Long): String {
    val instant = Instant.ofEpochSecond(unixSeconds)
    val local = instant.atZone(ZoneId.systemDefault())
    return local.format(DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm"))
}

ThreeTenABP — 이전 Android 버전의 날짜와 시간

ThreeTenABP — java.time을 Android API 26 미만으로 포팅하는 어댑터 라이브러리입니다. 동일한 클래스를 제공합니다: LocalDate, LocalTime, ZonedDateTime, DateTimeFormatter, Instant. 애플리케이션이 Android 5 또는 6(API 21-25)을 지원하는 경우 ThreeTenABP는 더 이상 사용되지 않는 Calendar로 전환하지 않고 최신 모바일 API를 사용하는 유일한 방법입니다. 이전 기기를 위한 모바일 개발의 날짜와 시간은 이 라이브러리를 통해 구현됩니다. 이전 기기의 경우 날짜와 시간은 ThreeTenABP를 통해 구현됩니다.

ThreeTenABP 추가 및 구성

라이브러리는 Application.onCreate() 메서드에서 AndroidThreeTen.init()을 호출하여 초기화해야 합니다. 이렇게 하면 assets에서 시간대 데이터가 로드됩니다. 초기화 후 API는 java.time과 완전히 동일합니다 — API 26+ 및 API 21+용 코드가 동일합니다. 라이브러리 크기는 약 400KB로 대부분의 모바일 애플리케이션에 적합합니다.

kotlin
import org.threeten.bp.LocalDate
import org.threeten.bp.format.DateTimeFormatter

// Application에서 초기화
class App : Application() {
    override fun onCreate() {
        super.onCreate()
        AndroidThreeTen.init(this)
    }
}

// API는 java.time과 동일
val today = LocalDate.now()
val formatted = today.format(DateTimeFormatter.ISO_LOCAL_DATE)

ThreeTenABP의 성능은 최신 기기에서 원래 java.time과 비슷합니다. 이전 기기에서는 시간대 데이터 로드로 인해 첫 번째 호출 시 지연이 발생할 수 있습니다. Calendar에서 ThreeTenABP로 기존 코드를 점진적으로 마이그레이션합니다: 새 모듈에서는 Date와 Calendar를 Instant와 LocalDate로 바꾸고 이전 코드는 그대로 둡니다.

Unix Timestamp와 NTP를 통한 시간 동기화

Unix Timestamp — 1970년 1월 1일 00:00 UTC 이후 경과한 초 수입니다. 서버와 클라이언트 간에 시간을 저장하고 교환하기 위한 범용 형식입니다. 하지만 기기 시간은 사용자 설정으로 인해 실제 시간과 다를 수 있습니다. 동기화를 위해 NTP가 사용됩니다 — UDP를 통한 정확한 시간 프로토콜입니다. Unix Timestamp는 서버에 날짜와 시간이 저장되는 형식입니다.

Unix Timestamp 가져오기 및 NTP 동기화

iOS의 Date().timeIntervalSince1970은 1970년 이후의 초를 반환합니다. Android에서 System.currentTimeMillis()는 밀리초를 반환합니다. 정확성을 위해 NTP를 사용하세요: iOS용 TrueTime 라이브러리와 Android용 AndroidNtp가 NTP 서버에 요청을 보내고 시간 오프셋을 계산합니다. NTP 정확성은 로컬 네트워크에서 1-10ms, 인터넷을 통해 10-100ms입니다.

swift
import Foundation

// iOS에서 Unix Timestamp 가져오기
let seconds = Date().timeIntervalSince1970
let milliseconds = Int64(seconds * 1000)

// TrueTime으로 NTP 동기화
TrueTime.shared.start { result in
    switch result {
    case .success:
        let ntpTime = TrueTime.shared.now()
        print("정확한 시간: \(ntpTime)")
    case .failure(let error):
        print("NTP 오류: \(error)")
    }
}

모바일 애플리케이션에서 동기화 없이 잘못된 이벤트 타임스탬프, 서버와의 비동기화 등의 오류가 발생할 수 있습니다. 모바일 개발의 시간은 애플리케이션 시작 시 NTP를 통해 한 번 동기화된 후 계산된 오프셋이 사용됩니다. 정확성이 중요한 모바일 애플리케이션(금융, 물류)의 경우 서버에 데이터를 보내기 전에 NTP 프로토콜이 필수입니다.

자주 묻는 질문

iOS에서 DateFormatter가 느린 이유는?

DateFormatter는 인스턴스가 생성될 때마다 형식 패턴을 구문 분석하고 로케일을 로드하며 시간대를 결정합니다. 포맷터를 정적 상수로 캐시하거나 ISO 8601에는 ISO8601DateFormatter를 사용하세요 — 더 가볍고 빠릅니다.

Android에서 SimpleDateFormat 대신 무엇을 사용하나요?

java.time 패키지의 DateTimeFormatter — 스레드 안전하고 효율적입니다. API 26부터 사용 가능합니다. 이전 버전에서는 동일한 API를 제공하는 ThreeTenABP를 사용하세요.

Android에서 Java 8 이전 날짜를 어떻게 처리하나요?

ThreeTenABP를 추가하세요 — Android API 21+용 java.time의 백포트입니다. Application.onCreate()에서 AndroidThreeTen.init()을 통해 초기화합니다. API는 원래 java.time과 완전히 동일합니다.

시간을 UTC로 저장해야 하나요?

네, 서버와 로컬 데이터베이스에 시간을 UTC로 저장하세요. 표시 단계에서만 사용자의 현지 시간대로 변환합니다. 이렇게 하면 시간대 변경이나 여행 시 오류가 제거됩니다.

iOS에서 Unix Timestamp를 어떻게 얻나요?

Date().timeIntervalSince1970은 1970년 1월 1일 이후의 초 수를 반환합니다. 밀리초의 경우 1000을 곱하고 Int64로 변환합니다. 정확한 동기화를 위해 NTP 서버와 함께 TrueTime 라이브러리를 사용하세요.

요약

  • iOS의 DateFormatter — 날짜와 시간 형식 지정의 주요 도구, 인스턴스 캐싱 필수. ISO8601DateFormatter는 ISO 8601을 위한 더 가벼운 대안.
  • Android의 DateTimeFormatter — API 26+용 java.time의 스레드 안전 포맷터. LocalDate와 ZonedDateTime이 날짜 작업의 주요 클래스.
  • ThreeTenABP — 모든 Android 버전을 위한 통합 API. API 21-25와의 하위 호환성을 위해 추가. 코드는 java.time과 동일.
  • TimeZone과 UTC — 시간은 UTC로 저장하고 표시용으로만 현지 시간대로 변환. IANA 식별자 사용.
  • Unix Timestamp — 서버와 클라이언트 간 시간 교환을 위한 범용 형식. iOS에서 Date().timeIntervalSince1970을 통해 가져옴.
  • NTP 동기화 — 밀리초 단위의 시간 정확성 보장. TrueTime(iOS)과 AndroidNtp(Android)가 표준 라이브러리.

턴키 방식의 모바일 애플리케이션을 개발해 드립니다

IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.

프로젝트 논의