고랭(Golang) 밀리초(Milliseconds) ↔ time.Time 완벽 변환 가이드 (JSON 팁 포함!)

고랭(Golang) 밀리초(Milliseconds) ↔ time.Time 완벽 변환 가이드 (JSON 팁 포함!)

안녕하세요!

 

코딩을 하다 보면 시간을 다루는 경우가 정말 많은데요.

 

특히 다른 시스템이나 데이터 형식과 정보를 주고받을 때, 시간을 '밀리초(milliseconds)' 단위로 표현하는 경우를 종종 만나게 됩니다.

 

여기서 말하는 밀리초는 보통 유닉스 시간(Unix epoch), 즉 1970년 1월 1일 0시 0분 0초 UTC를 기준으로 얼마나 많은 밀리초가 흘렀는지를 나타내는 정수 값입니다.

 

고랭(Golang)에서는 시간을 time.Time이라는 구조체 타입으로 다루는데요.

 

그래서 밀리초로 표현된 시간을 time.Time으로 바꾸거나, 반대로 time.Time 객체를 밀리초로 바꿔야 할 필요가 생깁니다.

 

오늘은 이 변환 작업을 어떻게 정확하고 쉽게 할 수 있는지, 그 방법을 속 시원하게 알려드리겠습니다! JSON 데이터를 다룰 때의 팁까지 준비했으니 끝까지 함께해주세요.

 

핵심 요약 미리보기

  • 밀리초 → time.Time 변환: time.UnixMilli(밀리초) 함수를 사용하면 아주 간편합니다. (Go 1.17 버전부터 가능) 또는 time.Unix(0, 밀리초 * int64(time.Millisecond)) 방식을 사용할 수도 있습니다.
  • time.Time → 밀리초 변환: time.Time 객체의 UnixMilli() 메서드를 호출하면 바로 밀리초 값을 얻을 수 있습니다.
  • JSON 속 밀리초 타임스탬프 처리: JSON 데이터를 파싱할 때, 타임스탬프 필드를 int64 타입으로 우선 저장한 뒤, 필요할 때 time.UnixMilli() 함수를 사용해 time.Time 객체로 변환하는 것이 일반적입니다.

1. 밀리초(Milliseconds)를 time.Time으로 변환하기

 

유닉스 시간(Unix epoch) 기준으로 주어진 밀리초(milliseconds) 값을 고랭(Go)의 time.Time 객체로 변환하는 방법을 알아보겠습니다.

 

예전 방식부터 살펴보면, time.Unix() 함수를 사용할 수 있습니다.

 

이 함수는 초(seconds)와 나노초(nanoseconds) 두 개의 파라미터(parameter)를 받습니다.

 

1 밀리초는 1,000,000 나노초와 같다는 점을 이용해서 변환할 수 있는데요.

package main

import (
    "fmt"
    "time"
)

func main() {
    // 유닉스 시간 기준 밀리초 값 (예시)
    var millis int64 = 1610000000000 // 2021년 1월 7일 정도의 시간입니다.

    // 방법 1: time.Unix() 사용 (조금 복잡한 방식)
    // 밀리초를 나노초로 변환 (millis * 1,000,000)
    nanos := millis * int64(time.Millisecond)
    t1 := time.Unix(0, nanos) // 초는 0으로 두고, 모든 시간을 나노초로 전달

    fmt.Println("time.Unix() 변환 결과:", t1)

        // --- 여기서부터 중요! ---

    // 방법 2: time.UnixMilli() 사용 (Go 1.17+ 버전부터 가능, 훨씬 간편!)
    t2 := time.UnixMilli(millis)

    fmt.Println("time.UnixMilli() 변환 결과:", t2)
}

 

코드 설명

  • millis * int64(time.Millisecond): 주어진 밀리초 값(millis)에 time.Millisecond 상수(값은 1,000,000)를 곱해서 나노초(nanoseconds) 단위로 바꿔줍니다. int64()로 타입을 맞춰주는 것도 잊지 마세요.
  • time.Unix(0, nanos): time.Unix() 함수는 첫 번째 인자로 초(sec), 두 번째 인자로 나노초(nsec)를 받습니다. 우리는 전체 시간을 나노초(nanos)로 계산했기 때문에, 초 부분은 0으로 두고 나노초 부분에 계산된 nanos 값을 넣어주면 됩니다. 이렇게 하면 유닉스 시간(Unix epoch) 기준으로 정확한 time.Time 객체가 생성됩니다.
  • time.UnixMilli(millis): 고랭(Go) 1.17 버전부터는 훨씬 더 직관적인 time.UnixMilli() 함수가 추가되었습니다. 이 함수는 밀리초 값을 직접 파라미터(parameter)로 받아서 해당 time.Time 객체를 바로 반환해줍니다. 코드가 훨씬 간결해지죠? 특별한 이유가 없다면 이 방법을 사용하는 것이 좋습니다.

2. time.Time을 밀리초(Milliseconds)로 변환하기

 

반대로, 이미 가지고 있는 time.Time 객체를 유닉스 시간(Unix epoch) 기준의 밀리초 값(정수형, int64)으로 얻고 싶을 때는 어떻게 할까요?

 

이건 정말 간단합니다.

 

time.Time 객체가 가지고 있는 UnixMilli() 메서드를 호출하기만 하면 됩니다.

package main

import (
    "fmt"
    "time"
)

func main() {
    // 현재 시간 가져오기
    t := time.Now()
    fmt.Println("현재 시간:", t)

    // time.Time 객체를 유닉스 시간 기준 밀리초로 변환
    millis := t.UnixMilli()

    fmt.Println("밀리초 변환 결과:", millis)
}

 

t.UnixMilli() 호출 한 번이면 끝! 정말 쉽죠?

 

이 메서드는 해당 time.Time 객체가 나타내는 시간을 유닉스 시간(Unix epoch) 기준으로 몇 밀리초가 지났는지를 int64 타입으로 반환해줍니다.

 

3. JSON 데이터 속 밀리초 타임스탬프 처리하기

 

실무에서는 JSON 형식의 데이터를 주고받을 때 시간 정보를 밀리초 타임스탬프(timestamp)로 포함하는 경우가 아주 흔합니다.

 

이럴 때는 JSON 데이터를 파싱(parsing)해서 고랭(Go) 구조체(struct)로 변환할 때 약간의 요령이 필요합니다.

 

가장 일반적인 방법은, JSON의 밀리초 타임스탬프 필드(field)를 구조체에서는 우선 int64 타입의 필드(field)로 받는 것입니다.

 

그리고 필요할 때 이 int64 값을 time.Time 객체로 변환해주는 헬퍼 메서드(helper method)를 구조체에 추가하는 방식입니다.

 

예시 코드를 보면서 이해해 보겠습니다.

package main

import (
    "encoding/json"
    "fmt"
    "time"
)

// JSON 데이터 구조에 대응하는 Go 구조체 정의
type Event struct {
    Name      string `json:"name"`      // 이벤트 이름
    Timestamp int64  `json:"timestamp"` // JSON의 밀리초 타임스탬프를 받을 필드 (int64 타입)
}

// Timestamp 필드(int64)를 time.Time 객체로 변환해주는 헬퍼 메서드
func (e *Event) Time() time.Time {
    // 저장된 int64 타입의 Timestamp 값을 time.UnixMilli()를 사용해 변환
    return time.UnixMilli(e.Timestamp)
}

func main() {
    // 예시 JSON 데이터 (문자열 형태)
    data := []byte(`{"name": "특별 할인 이벤트", "timestamp": 1610000000000}`)

    var event Event // JSON 데이터를 담을 Event 구조체 변수 선언

    // JSON 데이터를 Event 구조체로 언마샬링(변환)
    if err := json.Unmarshal(data, &event); err != nil {
        fmt.Println("JSON 파싱 에러:", err)
        return
    }

    // 결과 확인
    fmt.Println("이벤트 이름:", event.Name)
    fmt.Println("이벤트 시간 (int64):", event.Timestamp) // 구조체에 저장된 원시 int64 값
    fmt.Println("이벤트 시간 (time.Time):", event.Time()) // 헬퍼 메서드를 이용해 time.Time으로 변환된 값
}

 

코드 설명

  • Event 구조체: JSON 데이터의 "name" 필드(field)는 string 타입 Name 필드(field)로, "timestamp" 필드(field)(밀리초 값)는 int64 타입 Timestamp 필드(field)로 매핑(mapping)되도록 정의했습니다. json:"..." 태그(tag)를 사용해서 JSON 필드(field) 이름과 구조체 필드(field) 이름을 연결해줍니다.
  • Time() 메서드: Event 구조체에 연결된 메서드입니다. 이 메서드 안에서는 구조체가 가지고 있는 Timestamp 필드(field)(int64 타입) 값을 time.UnixMilli() 함수에 넣어 time.Time 객체로 변환한 뒤 반환합니다. 이렇게 하면 Event 객체를 사용하는 쪽에서는 단순히 event.Time()을 호출하는 것만으로 편리하게 time.Time 값을 얻을 수 있습니다.
  • json.Unmarshal(): 바이트 슬라이스(byte slice) 형태의 JSON 데이터를 두 번째 인자로 전달된 구조체 포인터(&event)가 가리키는 구조체 변수에 채워 넣는 역할을 합니다. 이 과정에서 JSON의 숫자 값인 1610000000000event.Timestamp 필드(field)에 int64 타입으로 저장됩니다.
  • 결과 출력: 파싱된 eventName과 원시 Timestamp 값을 출력하고, 추가로 event.Time() 메서드를 호출해서 변환된 time.Time 값도 함께 출력하여 확인합니다.

마무리하며

 

고랭(Golang)에서 밀리초(milliseconds)와 time.Time 사이의 변환은 생각보다 간단합니다.

 

특히 Go 1.17 버전 이후에 추가된 time.UnixMilli() 함수와 UnixMilli() 메서드 덕분에 더욱 편리해졌는데요.

 

오늘 배운 내용을 잘 활용하시면 시간 관련 데이터를 다룰 때 훨씬 효율적이고 정확하게 작업을 처리하실 수 있을 겁니다.