diff --git a/packages/common/business_components/src/ui/date_month_picker/index.tsx b/packages/common/business_components/src/ui/date_month_picker/index.tsx
new file mode 100644
index 000000000..d318b561f
--- /dev/null
+++ b/packages/common/business_components/src/ui/date_month_picker/index.tsx
@@ -0,0 +1,82 @@
+'use client';
+
+import { cn } from "../../lib/utils";
+import {
+ Popover,
+ PopoverTrigger,
+ PopoverContent,
+ Button,
+} from "@common/components/ui";
+import { ko } from "date-fns/locale";
+import { format } from "date-fns";
+import { useState } from "react";
+import { MonthPicker } from "./mothPicker";
+import { CalendarIcon } from "lucide-react";
+
+type MonthPickerProps = {
+ field: { value: string; onChange: (date: string) => void }; // yyyyMM 문자열
+ selectClass?: string;
+ readOnly?: boolean;
+};
+
+// yyyyMM → Date 객체
+const parseYYYYMM = (value: string) => {
+ const year = Number(value.substring(0, 4));
+ const month = Number(value.substring(4, 6)) - 1;
+ return new Date(year, month);
+};
+
+// Date 객체 → yyyyMM 문자열
+const formatDateToYYYYMM = (date: Date) => {
+ const year = date.getFullYear();
+ const month = String(date.getMonth() + 1).padStart(2, "0");
+ return `${year}${month}`;
+};
+
+export const DateMonthPicker = ({
+ field,
+ selectClass,
+ readOnly = false,
+}: MonthPickerProps) => {
+ const [open, setOpen] = useState(false);
+
+ const parsedDate = field?.value ? parseYYYYMM(field.value) : new Date();
+
+ const handleSelect = (
+ date: Date | undefined,
+ shouldClosePopover?: boolean
+ ) => {
+ if (!readOnly && date) {
+ field.onChange(formatDateToYYYYMM(date));
+ if (shouldClosePopover) setOpen(false);
+ }
+ };
+
+ return (
+
+
+
+ {parsedDate
+ ?format(parsedDate, "yyyy년 M월", { locale: ko })
+ : "월을 선택하세요"}
+
+
+
+
+
+
+
+ );
+};
diff --git a/packages/common/business_components/src/ui/date_month_picker/mothPicker.tsx b/packages/common/business_components/src/ui/date_month_picker/mothPicker.tsx
new file mode 100644
index 000000000..acf17fba4
--- /dev/null
+++ b/packages/common/business_components/src/ui/date_month_picker/mothPicker.tsx
@@ -0,0 +1,125 @@
+import { cn } from "../../lib/utils";
+import {
+ Select,
+ SelectContent,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@common/components/ui";
+import {
+ eachMonthOfInterval,
+ endOfYear,
+ format,
+ isEqual,
+ isFuture,
+ parse,
+ startOfMonth,
+ startOfToday,
+} from "date-fns";
+import { ko } from "date-fns/locale";
+
+function getStartOfCurrentMonth() {
+ return startOfMonth(startOfToday());
+}
+
+export type MonthPickerProps = {
+ currentMonth: Date;
+ onMonthChange: (
+ newMonth: Date | undefined,
+ shouldClosePopover?: boolean
+ ) => void;
+};
+
+export function MonthPicker({ currentMonth, onMonthChange }: MonthPickerProps) {
+
+ const today = startOfToday();
+const currentYear = today.getFullYear();
+ const yearFromProp = format(currentMonth, "yyyy");
+const selectedYear = parseInt(yearFromProp);
+
+ // 현재 월의 시작 날짜
+ const fullYearStart = parse(yearFromProp, "yyyy", new Date());
+
+ const yearEnd =
+ selectedYear === currentYear ? today : endOfYear(fullYearStart);
+
+
+
+
+ const yearRange = Array.from({ length: 21 }, (_, i) => currentYear - 20 + i);
+ const months = eachMonthOfInterval({ start: fullYearStart, end: yearEnd });
+
+ const getMonthButtonClass = (month: Date) =>
+ cn(
+ "inline-flex h-9 w-16 items-center justify-center rounded-md p-0 text-sm font-normal ring-offset-white transition-colors hover:bg-slate-100 hover:text-slate-900 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-400 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 aria-selected:opacity-100 dark:ring-offset-slate-950 dark:hover:bg-slate-800 dark:hover:text-slate-50 dark:focus-visible:ring-slate-800",
+ isEqual(month, currentMonth) &&
+ "bg-slate-900 text-slate-50 hover:bg-slate-900 hover:text-slate-50 focus:bg-slate-900 focus:text-slate-50 dark:bg-slate-50 dark:text-slate-900 dark:hover:bg-slate-50 dark:hover:text-slate-900 dark:focus:bg-slate-50 dark:focus:text-slate-900",
+ !isEqual(month, currentMonth) &&
+ isEqual(month, getStartOfCurrentMonth()) &&
+ "bg-slate-100 text-slate-900 dark:bg-slate-800 dark:text-slate-50"
+ );
+
+ return (
+
+
+
+ {/* 년도 셀렉트 */}
+
+ {
+ const selectedYearNum = parseInt(selectedYearStr);
+ const newDate = new Date(
+ selectedYearNum,
+ currentMonth.getMonth(),
+ 1
+ );
+ onMonthChange(newDate, false);
+ }}
+ >
+
+
+
+
+ {yearRange.map((year) => (
+
+ {year}년
+
+ ))}
+
+
+
+
+ {/* 월 그리드 */}
+
+ {months.map((month) => (
+
+ onMonthChange(month, true)}
+ >
+
+ {format(month, 'MMM', { locale: ko })}
+
+
+
+ ))}
+
+
+
+
+ );
+}
diff --git a/packages/common/business_components/src/ui/index.ts b/packages/common/business_components/src/ui/index.ts
index 19d966a53..fd1e6fe9e 100644
--- a/packages/common/business_components/src/ui/index.ts
+++ b/packages/common/business_components/src/ui/index.ts
@@ -20,4 +20,5 @@ export * from "./table";
export * from "./table_div";
export * from "./title";
export * from "./sdmInsertForm";
-export * from "./popover_ui"
\ No newline at end of file
+export * from "./popover_ui";
+export * from "./date_month_picker";
\ No newline at end of file