데이터 엔지니어링

패스트캠퍼스 환급챌린지 30일차: 데이터엔지니어링 초격차 강의 후기

Big Byte 2025. 4. 30. 23:08

본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성하였습니다.

 

날짜/시간 마스터하기! 📅⏰ 

 

 

안녕하세요, 여러분! 

지난번에는 예외 처리의 심화 기술들을 배우면서 어떤 위기 상황에서도 우리 코드를 굳건히 지켜내는 방법을 익혔었죠! 마치 타임머신을 조종하다 예상치 못한 시간 왜곡(예외)을 만나도 능숙하게 대처하는 베테랑 시간 여행자처럼요! 🚀🔧

 

덕분에 프로그램이 시간의 미아가 되는(?) 불상사를 막을 수 있게 되었습니다! 👍

 

하지만 시간 여행자의 여정은 여기서 멈추지 않죠! 😉 프로그래밍 세계에서 '시간'을 다루는 것은 정말 중요하면서도... 솔직히 좀 까다로울 때가 많아요. 특히 자바 초창기부터 함께 해온 java.util.Date 클래스는 여러 가지 함정(?)과 불편함으로 많은 개발자들을 눈물짓게 했답니다. 😭

 

"분명 날짜만 저장했는데 왜 시간까지 나오지?", "이 달은 왜 0부터 시작하는 거야?", "이 객체, 누가 중간에 바꿔버리면 어떡하지?" 🤯 이런 고민들, 한 번쯤 해보셨을 거예요!

 

그래서 오늘은! 이런 시간 여행의 어려움을 해결해 줄 자바의 새롭고 강력한 날짜와 시간 API (java.time 패키지)에 대해 알아볼 거예요! 구닥다리 DateCalendar는 잠시 잊고, 더 직관적이고, 안전하고, 편리한 방법으로 시간 여행을 떠나봅시다!

오늘 우리가 탐험할 내용들은 다음과 같아요:

  1. 과거의 유물: Date 클래스와 그 한계점들 😢
  2. 새 시대의 개막: LocalDate, LocalTime, LocalDateTime 삼총사! ✨
  3. 시간의 간격 측정: PeriodDuration ⏳📏
  4. 과거와의 조우: Date, Calendar 와의 호환성 🤝🕰️
  5. 시간을 내 맘대로! 날짜/시간 형식화 (Formatting & Parsing) 🎨✍️

자, 타임머신에 탑승할 준비되셨나요? 최신 시간 여행 기술을 배우러 출발! 슝~! 💨

 

1. 과거의 유물: Date 클래스와 그 한계점들 😢🏛️

먼저, 우리가 오랫동안 사용해왔던 java.util.Date 클래스를 잠깐 돌아봅시다. 특정 시점의 날짜와 시간을 나타내기 위해 만들어졌죠.

import java.util.Date;

public class OldDateExample {
    public static void main(String[] args) {
        Date now = new Date(); // 현재 시점의 Date 객체 생성
        System.out.println("현재 시간 (Date): " + now); // 뭔가 복잡하게 나와요 🤔

        // 특정 날짜를 만들려면? (Deprecated된 방법들...)
        // Date specificDate = new Date(2023 - 1900, 4 - 1, 30); // 연도는 1900 빼고, 월은 0부터 시작... 🤯
        // System.out.println("특정 날짜 (Deprecated): " + specificDate);

        // Date 객체는 변경 가능 (Mutable) 해요!
        long currentTimeMillis = now.getTime();
        now.setTime(currentTimeMillis + 10000); // 10초 뒤로 변경! 😱
        System.out.println("10초 뒤 시간: " + now);
    }
}

Date 클래스는 몇 가지 치명적인 단점들을 가지고 있었어요:

  • 변경 가능성 (Mutable): 생성된 Date 객체의 값을 나중에 변경할 수 있어서, 여러 곳에서 참조할 때 예상치 못한 문제를 일으킬 수 있었어요. (방금 예제에서 setTime으로 바뀐 것처럼요!)
  • 혼란스러운 설계: 이름은 Date인데 실제로는 특정 시점(타임스탬프)을 나타내고, toString() 결과는 기본 타임존을 포함해서 복잡해요. 연도는 1900년부터, 월은 0부터 시작하는 등 직관적이지 않은 부분도 많았죠. 😵‍💫
  • 부족한 기능: 날짜나 시간을 더하거나 빼는 등의 연산 기능이 매우 부족했고, 대부분의 유용한 메소드들은 사용이 권장되지 않는 상태(Deprecated)가 되었습니다.
  • 타임존 처리의 어려움: 타임존 관련 처리가 명확하지 않았어요.

이런 문제들을 해결하기 위해 java.util.Calendar 클래스가 등장했지만, 이 역시 사용법이 다소 복잡하고 여전히 변경 가능하다는 단점을 가지고 있었습니다. 😥

2. 새 시대의 개막: LocalDate, LocalTime, LocalDateTime 삼총사! ✨🚀 (java.time 패키지)

드디어 구세주 등장! 🎉 Java 8부터는 이런 문제점들을 말끔히 해결한 java.time 패키지가 도입되었습니다! 이 API의 가장 큰 특징은 불변성(Immutable) 이에요. 한 번 만들어진 객체는 절대 변하지 않아서 훨씬 안전하게 사용할 수 있답니다! 마치 역사 기록처럼, 한 번 정해진 시간은 바뀌지 않는 거죠! 📜

2.1 LocalDate - 날짜만 깔끔하게! 📅

이름 그대로, 시간 정보 없이 날짜(년-월-일) 정보만을 다루는 클래스예요.

import java.time.LocalDate;

public class LocalDateExample {
    public static void main(String[] args) {
        LocalDate today = LocalDate.now(); // 오늘 날짜
        System.out.println("오늘 날짜: " + today); // yyyy-MM-dd 형식으로 깔끔하게!

        LocalDate specificDate = LocalDate.of(2024, 5, 1); // 특정 날짜 생성 (월은 1부터!)
        System.out.println("특정 날짜: " + specificDate);

        System.out.println("연도: " + today.getYear());
        System.out.println("월: " + today.getMonthValue()); // getMonth()는 Month 열거형 반환
        System.out.println("일: " + today.getDayOfMonth());

        // 날짜 계산도 쉬워요! (새로운 객체를 반환 - 불변!)
        LocalDate tomorrow = today.plusDays(1);
        System.out.println("내일 날짜: " + tomorrow);
        LocalDate oneMonthAgo = today.minusMonths(1);
        System.out.println("한 달 전 날짜: " + oneMonthAgo);
    }
}

핵심:

  • now(): 현재 날짜를 가져옵니다.
  • of(...): 특정 년, 월, 일로 날짜를 생성합니다. (월은 1부터 12까지!)
  • getYear(), getMonthValue(), getDayOfMonth() 등: 날짜 구성 요소를 가져옵니다.
  • plusDays(), minusMonths() 등: 날짜를 계산합니다. (주의! 기존 객체가 변하는 게 아니라 새 객체가 반환됩니다!)

 

2.2 LocalTime - 시간만 명확하게! ⏰

 

날짜 정보 없이 시간(시-분-초-나노초) 정보만을 다루는 클래스입니다.

import java.time.LocalTime;

public class LocalTimeExample {
    public static void main(String[] args) {
        LocalTime now = LocalTime.now(); // 현재 시간
        System.out.println("현재 시간: " + now); // HH:mm:ss.SSSSSSSSS 형식

        LocalTime specificTime = LocalTime.of(13, 30, 0); // 오후 1시 30분 0초
        System.out.println("특정 시간: " + specificTime);

        System.out.println("시: " + now.getHour());
        System.out.println("분: " + now.getMinute());
        System.out.println("초: " + now.getSecond());

        // 시간 계산도 간편! (역시 불변!)
        LocalTime oneHourLater = now.plusHours(1);
        System.out.println("1시간 뒤: " + oneHourLater);
    }
}

 

2.3 LocalDateTime - 날짜와 시간, 환상의 짝꿍! 🤝

LocalDateLocalTime을 합쳐놓은 클래스로, 날짜와 시간 정보를 모두 다룹니다. 가장 많이 사용될 만능 엔터테이너죠! 🌟

      import java.time.LocalDateTime;
import java.time.Month;

public class LocalDateTimeExample {
    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now(); // 현재 날짜와 시간
        System.out.println("현재 날짜와 시간: " + now);

        LocalDateTime specificDateTime = LocalDateTime.of(2024, Month.MAY, 1, 10, 0, 0); // 2024년 5월 1일 오전 10시
        System.out.println("특정 날짜와 시간: " + specificDateTime);

        // LocalDate와 LocalTime으로 조합 가능
        LocalDate datePart = LocalDate.of(2025, 1, 1);
        LocalTime timePart = LocalTime.of(0, 0);
        LocalDateTime newYear = LocalDateTime.of(datePart, timePart);
        System.out.println("새해 첫 순간: " + newYear);

        // 날짜/시간 계산
        LocalDateTime twoWeeksLater = now.plusWeeks(2);
        System.out.println("2주 뒤: " + twoWeeksLater);
    }
}
    

어때요? Date보다 훨씬 직관적이고 사용하기 편리해 보이죠? 게다가 불변(Immutable) 이라서 더 이상 값이 멋대로 바뀌는 걱정은 안 해도 된답니다! 😄

 

3. 시간의 간격을 재다! Period vs Duration ⏳📏

두 날짜 또는 시간 사이의 간격을 나타내는 방법도 새로워졌어요!

  • Period: 날짜 기반의 간격 (년, 월, 일 단위). 주로 LocalDate와 함께 사용해요.
  •  
  • import java.time.LocalDate;
    import java.time.Period;
    
    LocalDate startDate = LocalDate.of(2024, 1, 1);
    LocalDate endDate = LocalDate.of(2024, 4, 30); // 오늘 (가정)
    
    Period period = Period.between(startDate, endDate);
    System.out.println("기간: " + period); // P3M29D (3개월 29일)
    System.out.println("개월 차이: " + period.getMonths());
    System.out.println("일 차이: " + period.getDays());
  • Duration: 시간 기반의 간격 (일, 시, 분, 초, 나노초 단위). 주로 LocalTime, LocalDateTime, Instant와 함께 사용해요. (주의: Duration으로 날짜 간격을 계산하면 24시간 기준으로 변환됩니다)
  • import java.time.Duration;
    import java.time.LocalTime;
    
    LocalTime startTime = LocalTime.of(9, 0);
    LocalTime endTime = LocalTime.of(10, 30);
    
    Duration duration = Duration.between(startTime, endTime);
    System.out.println("소요 시간: " + duration); // PT1H30M (1시간 30분)
    System.out.println("총 분 단위: " + duration.toMinutes()); // 90

이제 D-day 계산이나 작업 소요 시간 측정 등이 훨씬 명확하고 쉬워졌어요! 🎉

 

4. 과거와의 조우: Date, Calendar 와의 호환성 🤝🕰️

"새로운 API가 좋은 건 알겠는데, 기존에 DateCalendar를 쓰는 라이브러리나 코드는 어떡하죠?" 😥 걱정 마세요! 자바는 과거와의 호환성을 위한 다리도 마련해 두었습니다.

java.time.Instant 클래스가 핵심적인 역할을 해요. Instant는 1970년 1월 1일 0시 0분 0초(UTC 기준)부터 경과한 시간을 나노초 단위로 표현하는, 기계적인 시간 표현입니다. Date와 가장 유사한 개념이죠.

      import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.Calendar;
import java.util.TimeZone;

// Date <-> Instant <-> LocalDateTime
Date oldDate = new Date();
System.out.println("Old Date: " + oldDate);

// Date -> Instant
Instant instant = oldDate.toInstant();
System.out.println("Instant: " + instant);

// Instant -> LocalDateTime (시스템 기본 타임존 사용)
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
System.out.println("LocalDateTime: " + localDateTime);

// LocalDateTime -> Instant
Instant backToInstant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
System.out.println("Back to Instant: " + backToInstant);

// Instant -> Date
Date backToDate = Date.from(backToInstant);
System.out.println("Back to Date: " + backToDate);

// Calendar 와의 변환도 Instant를 통해 유사하게 가능합니다.
Calendar calendar = Calendar.getInstance();
Instant calInstant = calendar.toInstant();
LocalDateTime ldtFromCal = LocalDateTime.ofInstant(calInstant, ZoneId.systemDefault());

System.out.println("From Calendar: " + ldtFromCal);
    

Instant를 중간 다리로 사용하면 Date/Calendar와 새로운 API (LocalDateTime 등) 사이를 비교적 쉽게 오갈 수 있어요. 레거시 코드와의 연동도 문제없겠죠? 😉

5. 시간을 내 맘대로! 날짜/시간 형식화 (Formatting & Parsing) 🎨✍️

마지막으로, 날짜와 시간을 우리가 원하는 형식의 문자열로 바꾸거나(Formatting), 특정 형식의 문자열을 날짜/시간 객체로 변환하는(Parsing) 방법을 알아볼게요. DateTimeFormatter 클래스가 이 역할을 담당합니다!

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;

LocalDateTime now = LocalDateTime.now();

// 1. 미리 정의된 표준 형식 사용
DateTimeFormatter isoDateTime = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
System.out.println("ISO 형식: " + now.format(isoDateTime)); // 2024-04-30T11:23:45.678

DateTimeFormatter shortFormat = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);
// System.out.println("SHORT 형식: " + now.format(shortFormat)); // OS/Locale 설정에 따라 다름 (예: 24. 4. 30. 오전 11:23)

// 2. 원하는 패턴 직접 지정! (가장 많이 사용됨)
DateTimeFormatter myPattern = DateTimeFormatter.ofPattern("yyyy년 MM월 dd일 HH시 mm분 ss초");
System.out.println("내 패턴: " + now.format(myPattern)); // 2024년 04월 30일 11시 23분 45초

DateTimeFormatter anotherPattern = DateTimeFormatter.ofPattern("yyyy-MM-dd a hh:mm"); // a는 오전/오후
System.out.println("다른 패턴: " + now.format(anotherPattern)); // 2024-04-30 오후 11:23

// 3. 문자열 -> 날짜/시간 객체로 변환 (Parsing)
String dateString = "2024-05-01 12:00:00";
DateTimeFormatter parserPattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime parsedDateTime = LocalDateTime.parse(dateString, parserPattern);
System.out.println("파싱 결과: " + parsedDateTime);

ofPattern() 메소드에 원하는 형식을 지정하면 자유자재로 날짜/시간을 문자열로, 또는 문자열을 날짜/시간 객체로 변환할 수 있어요. 정말 편리하죠? 🥳

6. 정리하며 📝

오늘은 자바의 현대적인 날짜와 시간 API (java.time)에 대해 깊이 알아보았습니다! ✨

  • Date의 시대는 갔다!: 변경 가능성, 혼란스러운 설계 등 DateCalendar의 문제점을 인식했습니다.
  • java.time 패키지 만세!: 불변(Immutable)하고, 직관적이며, 풍부한 기능을 제공하는 LocalDate, LocalTime, LocalDateTime을 만났습니다.
  • 시간 간격 측정: Period (날짜 기반)와 Duration (시간 기반)으로 시간 차이를 명확하게 계산할 수 있게 되었어요.
  • 과거와의 호환: Instant를 이용해 기존 Date/Calendar와 매끄럽게 연동하는 방법을 배웠습니다.
  • 자유로운 형식 변환: DateTimeFormatter로 원하는 어떤 형식으로든 날짜/시간을 표현하고 해석할 수 있게 되었습니다.

이제 여러분은 자바에서 시간을 훨씬 더 우아하고 안전하게 다룰 수 있는 강력한 도구를 손에 넣으셨습니다! 💪 이 새로운 API를 적극적으로 활용해서 시간 여행의 달인이 되어보세요! 꾸준한 연습만이 살길입니다! 💻

 

이야~ 오늘도 정말 알찬 내용을 배우며 시간 가는 줄 몰랐네요! 벌써 화요일 밤이 깊어가고 있습니다. 🌃 로운 지식을 머릿속에 채우느라 정말 고생 많으셨어요! 👏

 

이 내용들이 여러분의 코딩 실력 향상에 큰 도움이 되기를 진심으로 바랍니다! 😊

 

 

그리고 여러분!!! 내일이 무슨 날인지 아세요? 바로바로 근로자의 날입니다!!! 🎉🎉🎉 빨간 날은 아니지만 많은 직장인들에게는 꿀 같은 휴일이죠! (물론 모든 분들이 쉬시는 건 아니지만요 😢)

 

저는 내일 푹~ 쉴 생각을 하니 벌써부터 너무너무 신나요! 😄 코딩도 좋지만, 가끔은 이렇게 재충전의 시간을 갖는 것도 중요하잖아요? 여러분도 내일 푹 쉬시면서 에너지 충전하시길 바랍니다!

 

오늘 하루도 정말 정말 수고 많으셨습니다! 푹 주무시고, 즐거운 휴일 보내세요! 우리는 다음 시간에 더 유익하고 재미있는 내용으로 다시 만나요! 👋 안녕~!

 

 

https://abit.ly/lisbva