+
+```
diff --git a/packages/common/business_components/src/index.css b/packages/common/business_components/src/index.css
new file mode 100644
index 000000000..46896e552
--- /dev/null
+++ b/packages/common/business_components/src/index.css
@@ -0,0 +1,11 @@
+
+@layer base {}
+
+@layer base {
+ * {
+ @apply border-border outline-ring/50;
+ }
+ body {
+ @apply bg-background text-foreground;
+ }
+}
\ No newline at end of file
diff --git a/packages/common/business_components/src/index.ts b/packages/common/business_components/src/index.ts
new file mode 100644
index 000000000..4aedf5936
--- /dev/null
+++ b/packages/common/business_components/src/index.ts
@@ -0,0 +1 @@
+export * from "./ui";
diff --git a/packages/common/business_components/src/lib/utils.ts b/packages/common/business_components/src/lib/utils.ts
new file mode 100644
index 000000000..a5ef19350
--- /dev/null
+++ b/packages/common/business_components/src/lib/utils.ts
@@ -0,0 +1,6 @@
+import { clsx, type ClassValue } from "clsx";
+import { twMerge } from "tailwind-merge";
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs));
+}
diff --git a/packages/common/business_components/src/ui/chart/BarChart.tsx b/packages/common/business_components/src/ui/chart/BarChart.tsx
new file mode 100644
index 000000000..82499306c
--- /dev/null
+++ b/packages/common/business_components/src/ui/chart/BarChart.tsx
@@ -0,0 +1,42 @@
+"use client"
+import type { CSSProperties } from "react";
+import {
+ Card,
+ CardContent
+} from "./lib/card";
+import {
+ ChartContainer,
+ ChartTooltip,
+ ChartTooltipContent,
+ type ChartConfig
+} from "./lib/chart";
+import { Bar, BarChart, CartesianGrid, XAxis } from "recharts";
+
+export default function Chart(props: { chartConfig: ChartConfig; chartData: any[] | undefined; chartTitle: string}) {
+ return (
+
+
+ {props.chartTitle && props.chartTitle !== "" && props.chartTitle !== "undefined" ? (
+
+ {props.chartTitle}
+
): null}
+
+
+
+
+ value.slice(0, 3)}
+ />
+ }/>
+
+
+
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/packages/common/business_components/src/ui/chart/DoughnutChart.tsx b/packages/common/business_components/src/ui/chart/DoughnutChart.tsx
new file mode 100644
index 000000000..f88b35476
--- /dev/null
+++ b/packages/common/business_components/src/ui/chart/DoughnutChart.tsx
@@ -0,0 +1,47 @@
+"use client"
+
+import { Pie, PieChart } from "recharts";
+
+import {
+ Card,
+ CardContent
+} from "./lib/card";
+import {
+ ChartContainer,
+ ChartTooltip,
+ ChartTooltipContent,
+ type ChartConfig
+} from "./lib/chart";
+
+// eslint-disable-next-line react-refresh/only-export-components
+export default (props: { chartConfig: ChartConfig; chartData: never[] | undefined; chartTitle:string}) =>{
+ return (
+
+
+ {props.chartTitle && props.chartTitle !== "" && props.chartTitle !== "undefined" ? (
+
+ {props.chartTitle}
+
): null}
+
+
+
+ )
+}
diff --git a/packages/common/business_components/src/ui/chart/LineBarChart.tsx b/packages/common/business_components/src/ui/chart/LineBarChart.tsx
new file mode 100644
index 000000000..5f2ae4715
--- /dev/null
+++ b/packages/common/business_components/src/ui/chart/LineBarChart.tsx
@@ -0,0 +1,108 @@
+"use client"
+import type { CSSProperties } from "react";
+import { Bar, CartesianGrid, ComposedChart, Legend, Line, Tooltip, XAxis, YAxis } from "recharts";
+import {
+ Card,
+ CardContent
+} from "./lib/card";
+import {
+ ChartContainer,
+ type ChartConfig
+} from "./lib/chart";
+import React from "react";
+
+// 툴팁 커스텀 css
+/** 차트 기본 스타일 */
+const styles = {
+ tooltipDiv: {
+ borderRadius: "5px",
+ backgroundColor: "white",
+ padding: "10px",
+ boxShadow: "0px 2px 10px rgba(0,0,0,0.2)",
+ width: "180px", // 적절한 크기로 설정
+ } as React.CSSProperties,
+ tooltipLabel: {
+ fontWeight: "bold",
+ fontSize: "12px",
+ marginBottom: "5px",
+ borderBottom: "1px solid #ddd",
+ paddingBottom: "3px",
+ } as React.CSSProperties,
+ tooltipText: {
+ fontSize: "11px",
+ fontWeight:"bold",
+ } as React.CSSProperties,
+ legendContainer: {
+ display: "flex",
+ justifyContent: "center",
+ gap: "20px",
+ fontSize: "9px",
+ fontWeight : "bold",
+ marginTop: "10px",
+ } as CSSProperties,
+};
+
+// 커스텀 툴팁
+const CustomTooltip = ({ active, payload, label }) => {
+ if (active && payload && payload.length) {
+ return (
+
+
{label}
+ {payload.map((item, index) => (
+
+ {/* 색상 박스 추가 (범례 색상과 동일) */}
+
+
{`${item.name}: ${item.value}`}
+
+ ))}
+
+ );
+ }
+ return null;
+};
+
+// 커스텀 범례 (글씨 크기 키우기 + 스타일 추가)
+const CustomLegend = (props: any) => {
+ const { payload } = props;
+ return (
+
+ {payload.map((entry, index) => (
+
+ ))}
+
+ );
+};
+
+export default function LineBarchart(props: { chartConfig: ChartConfig; chartData: any[] | undefined; chartTitle:string }) {
+ return (
+
+
+ {props.chartTitle && props.chartTitle !== "" && props.chartTitle !== "undefined" ? (
+
+ {props.chartTitle}
+
): null}
+
+
+
+
+
+ {/* 왼쪽 Y축: lineVal (정상) */}
+
+ {/* 오른쪽 Y축: barVal (위에서 아래로 반전) */}
+
+ } />
+
+
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/packages/common/business_components/src/ui/chart/LineChart.tsx b/packages/common/business_components/src/ui/chart/LineChart.tsx
new file mode 100644
index 000000000..136034e00
--- /dev/null
+++ b/packages/common/business_components/src/ui/chart/LineChart.tsx
@@ -0,0 +1,121 @@
+"use client"
+import type { CSSProperties } from "react";
+import {
+ Card,
+ CardContent
+} from "./lib/card";
+import {
+ ChartContainer,
+ ChartTooltip,
+ ChartTooltipContent,
+ type ChartConfig
+} from "./lib/chart";
+import { CartesianGrid, Legend, Line, LineChart, Tooltip, XAxis, YAxis } from "recharts";
+
+/** 차트 기본 스타일 */
+const styles = {
+ tooltipDiv: {
+ borderRadius: "5px",
+ backgroundColor: "white",
+ padding: "10px",
+ boxShadow: "0px 2px 10px rgba(0,0,0,0.2)",
+ width: "180px", // 적절한 크기로 설정
+ } as React.CSSProperties,
+ tooltipLabel: {
+ fontWeight: "bold",
+ fontSize: "12px",
+ marginBottom: "5px",
+ borderBottom: "1px solid #ddd",
+ paddingBottom: "3px",
+ } as React.CSSProperties,
+ tooltipText: {
+ fontSize: "11px",
+ fontWeight:"bold",
+ } as React.CSSProperties,
+ legendContainer: {
+ display: "flex",
+ justifyContent: "center",
+ gap: "20px",
+ fontSize: "9px",
+ fontWeight : "bold",
+ marginTop: "10px",
+ } as CSSProperties,
+};
+
+// 커스텀 툴팁
+const CustomTooltip = ({ active, payload, label }) => {
+ if (active && payload && payload.length) {
+ return (
+
+
{label}
+ {payload.map((item, index) => (
+
+ {/* 색상 박스 추가 (범례 색상과 동일) */}
+
+
{`${item.name}: ${item.value}`}
+
+ ))}
+
+ );
+ }
+ return null;
+};
+
+// 커스텀 범례 (글씨 크기 키우기 + 스타일 추가)
+const CustomLegend = (props: any) => {
+ const { payload } = props;
+ return (
+
+ {payload.map((entry, index) => (
+
+ ))}
+
+ );
+};
+
+type DataType = {label : string; val:number};
+type ChartDataType = {
+ chartData1: DataType[];
+ chartData2: DataType[];
+};
+
+export default function Linechart(props: { chartConfig: ChartConfig; chartData: ChartDataType; chartTitle:string}) {
+ const mergedData = Object.values(props.chartData).reduce((acc, dataset) => {
+ dataset.forEach((entry, index) => {
+ if (!acc[index]) {
+ acc[index] = { label: entry.label }; // label 추가
+ }
+ const key = Object.keys(props.chartData).find(k => props.chartData[k] === dataset);
+ if (key) acc[index][key] = entry.val;
+ });
+ return acc;
+ }, [] as any[]);
+
+ return (
+
+
+ {props.chartTitle && props.chartTitle !== "" && props.chartTitle !== "undefined" ? (
+
+ {props.chartTitle}
+
): null}
+
+
+
+
+
+
+ } />
+
+
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/packages/common/business_components/src/ui/chart/index.tsx b/packages/common/business_components/src/ui/chart/index.tsx
new file mode 100644
index 000000000..fc5747f3a
--- /dev/null
+++ b/packages/common/business_components/src/ui/chart/index.tsx
@@ -0,0 +1,48 @@
+
+import React from 'react';
+import BarChart from './BarChart';
+import DoughnutChart from './DoughnutChart';
+import { type ChartConfig } from './lib/chart';
+import LineChart from './LineChart';
+import LineBarchart from './LineBarChart';
+
+/**차트 FORM */
+const CHART_FORM = {
+ /**바 차트 형태*/
+ BAR : 'bar',
+ /**라인 차트 형태*/
+ LINE:'line',
+ /**도넛 차트 형태*/
+ DN :'daughnut',
+ /**LINE,BAR차트 */
+ LINEBAR : 'linebar'
+};
+
+function MainChart(props: { chartForm: string; chartConfig: any; chartData: any; chartTitle:string; }) {
+ if( props.chartForm == CHART_FORM.BAR ){
+ return (
+
+
+ );
+ } else if( props.chartForm == CHART_FORM.LINE ){
+ return (
+
+
+ );
+ } else if( props.chartForm == CHART_FORM.DN ){
+ return (
+
+
+ );
+ } else if (props.chartForm == CHART_FORM.LINEBAR){
+ return (
+
+
+ );
+ }
+}
+
+export { MainChart };
+// eslint-disable-next-line react-refresh/only-export-components
+ export { CHART_FORM };
+ export type { ChartConfig };
diff --git a/packages/common/business_components/src/ui/chart/lib/card.tsx b/packages/common/business_components/src/ui/chart/lib/card.tsx
new file mode 100644
index 000000000..351d6566b
--- /dev/null
+++ b/packages/common/business_components/src/ui/chart/lib/card.tsx
@@ -0,0 +1,77 @@
+import * as React from "react"
+
+import { cn } from "../../../lib/utils"
+
+const Card = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+Card.displayName = "Card"
+
+const CardHeader = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardHeader.displayName = "CardHeader"
+
+const CardTitle = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardTitle.displayName = "CardTitle"
+
+const CardDescription = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardDescription.displayName = "CardDescription"
+
+const CardContent = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardContent.displayName = "CardContent"
+
+const CardFooter = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardFooter.displayName = "CardFooter"
+
+export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle }
+
diff --git a/packages/common/business_components/src/ui/chart/lib/chart.tsx b/packages/common/business_components/src/ui/chart/lib/chart.tsx
new file mode 100644
index 000000000..3a69fd454
--- /dev/null
+++ b/packages/common/business_components/src/ui/chart/lib/chart.tsx
@@ -0,0 +1,364 @@
+"use client"
+
+import * as React from "react"
+import * as RechartsPrimitive from "recharts"
+
+import { cn } from "../../../lib/utils"
+
+// Format: { THEME_NAME: CSS_SELECTOR }
+const THEMES = { light: "", dark: ".dark" } as const
+
+export type ChartConfig = {
+ [k in string]: {
+ label?: React.ReactNode
+ icon?: React.ComponentType
+ } & (
+ | { color?: string; theme?: never }
+ | { color?: never; theme: Record }
+ )
+}
+
+type ChartContextProps = {
+ config: ChartConfig
+}
+
+const ChartContext = React.createContext(null)
+
+function useChart() {
+ const context = React.useContext(ChartContext)
+
+ if (!context) {
+ throw new Error("useChart must be used within a ")
+ }
+
+ return context
+}
+
+const ChartContainer = React.forwardRef<
+ HTMLDivElement,
+ React.ComponentProps<"div"> & {
+ config: ChartConfig
+ children: React.ComponentProps<
+ typeof RechartsPrimitive.ResponsiveContainer
+ >["children"]
+ }
+>(({ id, className, children, config, ...props }, ref) => {
+ const uniqueId = React.useId()
+ const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`
+
+ return (
+
+
+
+
+ {children}
+
+
+
+ )
+})
+ChartContainer.displayName = "Chart"
+
+const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
+ const colorConfig = Object.entries(config).filter(
+ ([, config]) => config.theme || config.color
+ )
+
+ if (!colorConfig.length) {
+ return null
+ }
+
+ return (
+