본문 바로가기
우아한 코딩

날짜와 시간을 다루는 자바 API 이용 시 주의 사항 👀

by 피크인사이트 2024. 2. 7.
반응형

<날짜와 시간 API&nbsp; 주의사항>

 

지난 글에 이어 "날짜와 시간을 다루는 자바 프로그램을 코딩할 때 주의해야 할 사항을 코딩 사례와 함께 하나씩 살펴보겠습니다.

잘못된 사례를 통한 주의사항 설명 순서는 다음과 같습니다.
1. 불변성(Immutability) 유지
2. 시간대(Time Zone) 고려
3. 문자열 파싱 및 형식 지정에 유의
4. 날짜와 시간 연산에 따른 적합한 클래스 선택
5. 예외 처리
6. 호환성을 고려한 적절한 자바버전 선택


1. 불변성(Immutability) 유지

불변성(Immutability)을 유지하는 것은 java.time 패키지의 클래스를 안정적으로 사용하는 핵심 원칙 중 하나입니다.
이를 위배하는 몇 가지 코딩 사례는 다음과 같습니다.


(1) 직접적인 필드 수정

LocalDate currentDate = LocalDate.now();
currentDate.plusDays(1);  // 올바르게 수정되지 않음
currentDate = currentDate.plusDays(1); // 새로운 인스턴스를 생성하여 할당해야 함

 

LocalDate, LocalTime, LocalDateTime, ZonedDateTime, Duration, Period 등의 클래스는 모두 불변 클래스이므로, 인스턴스를 수정하는 메서드를 사용하거나 필드에 직접 접근하여 수정하려고 하면 불변성이 깨집니다.
이러한 클래스의 인스턴스는 수정할 수 없으므로, 변경이 필요하다면 해당 메서드가 새로운 인스턴스를 반환하는지 확인해야 합니다.


(2) 가변 객체를 인스턴스 필드로 사용

 

public class MyClass {
    private LocalDate date;
    public MyClass(LocalDate date) {
        this.date = date;
    }
    public LocalDate getDate() {
        return date;
    }
    // setDate 메서드는 클래스의 불변성을 위배함
    public void setDate(LocalDate date) {
        this.date = date;
    }
}

java.time 패키지의 클래스를 가변 객체의 인스턴스 필드로 사용하면 해당 인스턴스의 불변성이 위협될 수 있습니다. 이를 해결하기 위해서는 불변한 복사본을 만들거나 가변 객체를 사용하는 대신 불변 객체를 사용해야 합니다.

 

(3) 가변 컬렉션 사용

List<LocalDate> dates = new ArrayList<>();
dates.add(LocalDate.now());


불변성을 유지하기 위해 java.time 패키지의 클래스를 가변 컬렉션에 저장하거나 전달하면 안 됩니다.
불변 컬렉션 또는 불변된 복사본을 사용하여 이를 방지해야 합니다.

 

2. 시간대(Time Zone) 고려

시간대(Time Zone)를 고려하는 것은 시간 정보를 처리할 때 중요한 측면으로 자칫 잘못된 결과를 얻을 수도 있습니다.
아래 코드는 시간대를 잘못 적용한 예시입니다:

import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.time.ZoneId;

public class IncorrectTimeZoneExample {
    public static void main(String[] args) {
        // 현재 시간과 기본 시간대를 사용하여 ZonedDateTime 가져오기
        ZonedDateTime currentZonedDateTime = ZonedDateTime.now();
        System.out.println("현재 시간과 기본 시간대: " + currentZonedDateTime);

        // 잘못된 시간대로 ZonedDateTime 생성하기
        LocalDateTime localDateTime = LocalDateTime.of(2023, 9, 15, 14, 30, 45);
        ZoneId zoneId = ZoneId.of("Asia/Tokyo"); // 도쿄 시간대
        ZonedDateTime incorrectZonedDateTime = ZonedDateTime.of(localDateTime, zoneId);
        System.out.println("잘못된 시간대: " + incorrectZonedDateTime);
    }
}


위 사례에서는 현재 시간과 기본 시간대를 사용하여 ZonedDateTime을 가져온 후, 잘못된 시간대로 ZonedDateTime을 생성합니다.
LocalDateTime에는 시간대 정보가 없으며, ZonedDateTime에는 시간대 정보가 필요합니다.

그러나 위 코드에서는 LocalDateTime과 ZoneId를 조합하여 ZonedDateTime을 생성하고 있지만, LocalDateTime에는 시간대 정보가 없기 때문에 잘못된 결과가 출력됩니다.


올바른 방법은 ZonedDateTime의 of() 메서드를 사용하여 시간대를 고려한 ZonedDateTime을 직접 생성하는 것입니다.


3. 문자열 파싱 및 형식 지정에 유의

java.time.format.DateTimeFormatter 클래스를 사용하여 문자열을 파싱 하거나 형식을 지정하는 경우에는 유효한 패턴을 사용해야 합니다.
다음은 잘못된 패턴을 사용하여 문자열을 파싱하는 예시 코드입니다.

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

public class DateTimeParsingExample {
    public static void main(String[] args) {
        String dateString = "2023-09-15T14:30:45";
        
        // 잘못된 날짜/시간 형식 패턴 사용
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-mm-dd");        
        try {
            LocalDateTime dateTime = LocalDateTime.parse(dateString, formatter);
            System.out.println("파싱된 날짜/시간: " + dateTime);
        } catch (Exception e) {
            System.out.println("예외 발생: " + e.getMessage());        }    }}

위 코드에서는 "yyyy-mm-dd" 패턴을 사용하여 문자열을 파싱 하려고 하지만, 실제 문자열에는 시간 정보가 포함되어 있습니다. 따라서 잘못된 패턴을 사용하고 있기 때문에 java.time.format.DateTimeParseException 예외가 발생합니다.


올바른 패턴을 사용하려면 문자열의 형식과 일치하는 패턴을 지정해야 합니다. 예를 들어, "yyyy-mm-dd'T'hh:mm:ss"와 같이 시간 정보를 포함하는 패턴을 사용해야 합니다.

 

4. 날짜와 시간 연산에 따른 적합한 클래스 선택

날짜와 시간 연산의 성격에 따라 적합한 클래스를 선택해야 합니다.

예를 들어, 특정 날짜와 시간 간의 시간 간격을 계산해야 한다면 Duration 클래스를 사용할 수 있고,

두 날짜 간의 날짜 간격을 계산해야 한다면 Period 클래스를 사용할 수 있습니다.

만약 날짜와 시간 모두를 고려해야 한다면 LocalDateTime 클래스를 사용할 수 있습니다.

 

※ 날짜와 시간 처리 클래스 종류

- LocalDate: 날짜 정보만 필요한 경우에 사용됩니다. 시간 정보를 고려하지 않으므로 시간 연산은 지원하지 않습니다.

- LocalTime: 시간 정보만 필요한 경우에 사용됩니다. 날짜 정보를 고려하지 않으므로 날짜 연산은 지원하지 않습니다.

- LocalDateTime: 날짜와 시간 모두 필요한 경우에 사용됩니다. 날짜와 시간 연산을 모두 지원합니다.

- ZonedDateTime: 특정 시간대 정보를 포함한 날짜와 시간이 필요한 경우에 사용됩니다. 지역 시간대와 관련된 연산을 지원합니다.

- Duration: 두 시간 사이의 시간 간격을 나타내는 경우에 사용됩니다. 시간 단위의 연산을 지원합니다.

- Period: 두 날짜 사이의 날짜 간격을 나타내는 경우에 사용됩니다. 일(day), 월(month), 연(year) 단위의 연산을 지원합니다

 

5. 예외 처리

java.time 패키지의 클래스를 사용할 때 예외(Exception )가 발생할 수 있습니다.

예를 들어, 잘못된 날짜나 시간을 사용하거나 시스템의 시간대를 지원하지 않는 경우에는 예외가 발생할 수 있습니다. 따라서 예외 처리를 적절하게 해주어야 합니다.

  String invalidDateString = "2023-13-32"; // 잘못된 날짜 형식


위와 같이 잘못된 날짜와 시간을 사용하면 DateTimeParseException 예외가 발생할 수 있기 때문에 다음 코드처럼 예외처리를 해주어야 합니다.

 public static void main(String[] args) {
        String invalidDateString = "2023-13-32"; // 잘못된 날짜 형식
        try {
            LocalDate date = LocalDate.parse(invalidDateString);
            System.out.println("파싱된 날짜: " + date);
        } catch (DateTimeParseException e) {
            System.out.println("잘못된 날짜 형식입니다: " + e.getMessage());
        } catch (Exception e) {
            System.out.println("예상치 못한 오류 발생: " + e.getMessage());
        }
 }

 

 

6. 호환성을 고려한 적절한 자바버전 선택

java.time 패키지는 Java 8 이상에서 사용할 수 있으므로, 이전 버전의 자바에서는 사용할 수 없습니다.

따라서 프로젝트의 호환성을 고려하여 적절한 자바 버전을 선택해야 합니다.

import java.time.LocalDate;

public class IncorrectJavaVersionExample {
    public static void main(String[] args) {
        LocalDate date = LocalDate.now();
        System.out.println("현재 날짜: " + date);
    }
}


위 코드는 java.time.LocalDate를 사용하여 현재 날짜를 가져오고 출력하는 간단한 예시입니다.

그러나 이 코드는 호환성을 고려하지 않고 자바 8 이상의 버전에서만 실행될 것으로 가정하고 작성되었습니다.
이러한 코드의 문제는 다음과 같습니다
첫 번째로 자바 8 이상의 버전에서만 실행될 수 있기 때문에 이 코드를 사용하려는 경우 자바 8 이상의 버전을 필수적으로 사용해야 합니다. 이러한 점은 프로젝트의 요구 사항이나 환경에 따라 제약이 될 수 있습니다.

 

두 번째는 자바 8 이상의 버전이 지원되지 않는 환경에서는 이 코드를 실행할 수 없습니다.

예를 들어, 일부 레거시 시스템이나 임베디드 시스템에서는 자바 8 이상의 버전을 지원하지 않을 수 있습니다.
이러한 문제를 해결하기 위해서는 호환성을 고려하여 최소한의 자바 버전을 선택해야 합니다.

자바 8 이상의 버전에서만 사용할 수 있는 기능이 필요한 경우에는 이를 명시적으로 표기하고, 가능한 경우에는 호환성을 고려하여 자바 버전을 선택해야 합니다.



이번 글에서는 java.time 패키지를 사용할 때 주의해야 할 몇 가지 중요한 사항들에 대해 살펴보았습니다.
먼저, 불변성을 유지하고 객체를 수정하지 않는 것이 중요하고, 시간대를 고려하여 적절한 클래스를 선택하는 것이 필요합니다. 또한 잘못된 패턴을 사용하지 않고 예외 처리를 적절하게 해야 하며, 코드의 호환성을 고려하여 적절한 자바 버전을 선택해야 합니다.


코드를 작성할 때 안정성과 이식성을 고려하는 것도 중요합니다.

코드를 작성하기 전에 각 클래스와 메서드의 특징을 충분히 이해하고, 적절한 예외 처리와 호환성을 고려하여 코드를 작성하는 것이 바람직합니다.

이러한 노력들은 코드의 가독성과 유지보수성을 높이는 데 도움이 될 것입니다.


앞으로도 자바의 다양한 기능을 잘 활용하여 보다 안전하고 효율적인 코드를 작성할 수 있도록 함께 공부하고 성장해 나가길 기대합니다.
감사합니다.

반응형