[Java] YearMonth로 월 단위 날짜를 다루는 방법
📖 Java YearMonth로 월 단위 날짜를 다루는 방법
Java에서 날짜를 다룰 때 대부분 LocalDate를 먼저 떠올리게 된다.
LocalDate date = LocalDate.now();
하지만 모든 상황에서 일(day)까지 필요한 것은 아니다.
예를 들어 가계부에서:
2026년 8월 지출 내역
2026년 8월 수입 내역
2026년 8월 저축 내역
을 조회한다고 하면 실제로 필요한 값은:
2026-08
이라는 연도와 월이다.
이럴 때 사용할 수 있는 클래스가 YearMonth다.
🔎 YearMonth란?
YearMonth는 Java 8부터 제공되는 java.time 패키지의 날짜 타입으로,
특정 연도와 월을 표현하기 위한 객체
다.
YearMonth yearMonth = YearMonth.of(2026, 8);
위 값은:
2026년 8월
을 의미한다.
LocalDate가:
2026-08-18
처럼 연도, 월, 일을 표현한다면 YearMonth는:
2026-08
처럼 연도와 월만 표현한다.
🛠️ 기본 사용법
현재 연도와 월을 가져올 수도 있다.
YearMonth currentMonth = YearMonth.now();
특정 연도와 월을 지정할 수도 있다.
YearMonth month = YearMonth.of(2026, 8);
문자열에서 변환하는 것도 가능하다.
YearMonth month =
YearMonth.parse("2026-08");
반대로 문자열로 변환하면:
String value = month.toString();
결과:
2026-08
이처럼 YearMonth는 yyyy-MM 형태의 월 데이터를 표현하기에 적합하다.
📅 해당 월의 시작일과 마지막 날 구하기
YearMonth를 실무에서 사용할 때 가장 유용한 기능 중 하나가 특정 월의 날짜 범위를 계산하는 것이다.
예를 들어:
YearMonth ym = YearMonth.parse("2026-08");
LocalDate startDate = ym.atDay(1);
LocalDate endDate = ym.atEndOfMonth();
결과:
startDate
→ 2026-08-01
endDate
→ 2026-08-31
여기서 중요한 점은 월마다 마지막 날짜가 다르다는 것이다.
2월 → 28일 또는 29일
4월 → 30일
6월 → 30일
8월 → 31일
직접 마지막 날짜를 계산할 필요 없이 atEndOfMonth()가 해당 연도의 윤년 여부까지 고려해서 마지막 날짜를 반환한다.
🧩 LocalDate와 함께 사용하기
YearMonth 자체에는 일(day)이 없기 때문에 실제 날짜를 다뤄야 하는 시점에서는 LocalDate로 변환해서 사용할 수 있다.
YearMonth ym = YearMonth.of(2026, 8);
LocalDate firstDay = ym.atDay(1);
LocalDate lastDay = ym.atEndOfMonth();
이를 활용하면 특정 월의 검색 범위를 쉽게 만들 수 있다.
예를 들어 QueryDSL에서 가계부 데이터를 조회한다면:
YearMonth ym = YearMonth.parse(month);
LocalDate startDate = ym.atDay(1);
LocalDate endDate = ym.atEndOfMonth();
그리고:
.where(
transaction.date.between(
startDate,
endDate
)
)
처럼 사용할 수 있다.
즉,
사용자가 선택한 월
↓
YearMonth
↓
월의 시작일 / 마지막 날 계산
↓
LocalDate 범위
↓
DB 날짜 조회
라는 흐름을 만들 수 있다.
🔄 YearMonth의 장점
YearMonth를 사용하면 단순히 int year, int month를 따로 관리하는 것보다 의도가 명확해진다.
예를 들어:
int year = 2026;
int month = 8;
보다:
YearMonth month =
YearMonth.of(2026, 8);
가 **"2026년 8월이라는 하나의 월을 표현하고 있다"**는 의미가 더 명확하다.
또한 날짜 계산을 직접 구현하지 않아도 Java Time API가 제공하는 기능을 활용할 수 있다.
month.atDay(1);
month.atEndOfMonth();
month.plusMonths(1);
month.minusMonths(1);
처럼 월 단위 계산도 자연스럽게 처리할 수 있다.
🧭 월 단위 데이터에서 활용하기
특히 다음과 같은 기능에서 YearMonth를 활용하기 좋다.
월별 가계부 조회
월별 통계
월별 매출 조회
월별 정산
월별 리포트
월별 예산
월별 지출 분석
예를 들어:
YearMonth current = YearMonth.now();
YearMonth next = current.plusMonths(1);
YearMonth previous = current.minusMonths(1);
처럼 이전 달과 다음 달을 쉽게 계산할 수 있다.
⚠️ YearMonth를 사용하지 않는 것이 좋은 경우
반대로 시간까지 필요한 경우에는 YearMonth가 적합하지 않다.
예:
2026-08-18 14:30:00
처럼 날짜와 시간이 필요한 경우에는:
LocalDateTime
또는 시간대까지 고려해야 한다면:
ZonedDateTime
등을 사용하는 것이 적합하다.
즉 Java Time API에서는 표현하려는 데이터의 범위에 맞는 타입을 선택하는 것이 중요하다.
연도만
→ Year
연도 + 월
→ YearMonth
날짜
→ LocalDate
날짜 + 시간
→ LocalDateTime
시간대 포함 날짜 + 시간
→ ZonedDateTime
🎯 마무리
YearMonth는 특별히 복잡한 클래스는 아니지만, 월 단위 데이터를 다룰 때 의도를 명확하게 표현할 수 있는 유용한 타입이다.
특히:
YearMonth ym =
YearMonth.parse("2026-08");
LocalDate startDate =
ym.atDay(1);
LocalDate endDate =
ym.atEndOfMonth();
처럼 사용하면 특정 월의 날짜 범위를 간단하게 계산할 수 있다.
월별 데이터를 조회할 때:
2026 + 8
↓
YearMonth
↓
2026-08-01 ~ 2026-08-31
↓
DB 조회
와 같은 구조로 연결할 수 있기 때문에 가계부, 통계, 정산처럼 월 단위 조회가 많은 서비스에서 특히 유용하다.
결국 날짜를 다룰 때 중요한 것은 하나의 날짜 타입을 모든 상황에 사용하는 것이 아니라,
내가 표현하려는 시간의 범위에 맞는 타입을 선택하는 것
이다.v
