Brolog
Spring

[Java] YearMonth로 월 단위 날짜를 다루는 방법

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

Copyright © 2026 Brolog. All rights reserved.