From c9169772922b9ad3046b894b4375f3983779a1bd Mon Sep 17 00:00:00 2001 From: leedj312 Date: Mon, 8 Sep 2025 17:42:50 +0900 Subject: [PATCH] =?UTF-8?q?=EB=8C=80=EB=AF=BC=20=EB=AC=BC=EC=9E=AC?= =?UTF-8?q?=EC=9D=B4=EC=9A=A9=20=ED=98=84=ED=99=A9=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=EB=B0=9B=EB=8A=94=EA=B1=B8=EB=A1=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/(base-layout)/pages/wrStatus/page.tsx | 335 +++++------------- apps/dm/app/common/comFunction.ts | 74 ++++ apps/dm/app/store/store.tsx | 57 ++- apps/dm/app/store/wrStatus/index.tsx | 63 ++++ apps/dm/app/store/wrStatus/type.ts | 32 ++ apps/dm/public/data/wrStatusData.json | 20 ++ 6 files changed, 309 insertions(+), 272 deletions(-) create mode 100644 apps/dm/app/common/comFunction.ts create mode 100644 apps/dm/app/store/wrStatus/index.tsx create mode 100644 apps/dm/app/store/wrStatus/type.ts create mode 100644 apps/dm/public/data/wrStatusData.json diff --git a/apps/dm/app/(base-layout)/pages/wrStatus/page.tsx b/apps/dm/app/(base-layout)/pages/wrStatus/page.tsx index 826ab3222..263d9e42e 100644 --- a/apps/dm/app/(base-layout)/pages/wrStatus/page.tsx +++ b/apps/dm/app/(base-layout)/pages/wrStatus/page.tsx @@ -1,237 +1,43 @@ 'use client'; +import { regionData, regionIdMap } from '@/app/common/comFunction'; +import { useDmStore } from '@/app/store'; +import type { DmStatusDataType } from '@/app/store/wrStatus/type'; import { CHART_FORM, MainChart, type ChartConfig } from '@common/business_components'; -import React, { useEffect, useRef, useState, useMemo, useCallback } from 'react'; +import React, { useEffect, useRef, useState, useCallback } from 'react'; -interface RegionData { - name: string; - x: number; - y: number; - values: number[]; + +interface WrStatusChartProps { + chartForm: string; + chartConfig: ChartConfig; + chartData: any; + chartTitle: string; + chartClassName?: string; + graphSize?: number; + yFieldText? : string | undefined; + yFieldText2? : string | undefined; + showLegend? : boolean; + setXAxisYearTick ?: boolean; } -interface TableData { - region: string; - sewage: string; - rainwater: string; - reclaimed: string; - thermal: string; -} +export default function WrStatusPage() { - -const WrStatusPage: React.FC = () => { + const { dmStatus, getDmStatusData} = useDmStore((state) => state); + const { statusData,facilityTotals ,chartData} = dmStatus; const [selectedRegion, setSelectedRegion] = useState(null); const [hoveredRegion, setHoveredRegion] = useState(null); const [tooltipPosition, setTooltipPosition] = useState<{ x: number; y: number } | null>(null); + const [chartOption, setChartOption] = useState({} as WrStatusChartProps) const svgContainerRef = useRef(null); - const [chartData] = useState([ - { - label : '서울', - 하수 : 4, - 빗물 : 816, - 중수도 : 371, - 온배수 : 0 - }, - { - label : '부산', - 하수 : 13, - 빗물 : 68, - 중수도 : 20, - 온배수 : 1 - }, - { - label : '대구', - 하수 : 9, - 빗물 : 294, - 중수도 : 14, - 온배수 : 2 - }, - { - label : '인천', - 하수 : 17, - 빗물 : 165, - 중수도 : 35, - 온배수 : 15 - }, - { - label : '광주', - 하수 : 3, - 빗물 : 74, - 중수도 : 15, - 온배수 : 15 - }, - { - label : '대전', - 하수 : 2, - 빗물 : 52, - 중수도 : 11, - 온배수 : 20 - }, - { - label : '울산', - 하수 : 8, - 빗물 : 111, - 중수도 : 19, - 온배수 : 30 - }, - { - label : '세종', - 하수 : 9, - 빗물 : 65, - 중수도 : 0, - 온배수 : 0 - }, - { - label : '경기', - 하수 : 176, - 빗물 : 1009, - 중수도 : 252, - 온배수 : 40 - }, - { - label : '강원', - 하수 : 69, - 빗물 : 69, - 중수도 : 22, - 온배수 : 0 - }, - { - label : '충북', - 하수 : 38, - 빗물 : 17, - 중수도 : 91, - 온배수 : 0 - }, - { - label : '충남', - 하수 : 67, - 빗물 : 54, - 중수도 : 188, - 온배수 : 0 - }, - { - label : '전북', - 하수 : 55, - 빗물 : 33, - 중수도 : 220, - 온배수 : 0 - }, - { - label : '전남', - 하수 : 83, - 빗물 : 16, - 중수도 : 75, - 온배수 : 0 - }, - { - label : '경북', - 하수 : 81, - 빗물 : 37, - 중수도 : 70, - 온배수 : 0 - }, - { - label : '경남', - 하수 : 75, - 빗물 : 27, - 중수도 : 140, - 온배수 : 0 - }, - { - label : '제주', - 하수 : 8, - 빗물 : 47, - 중수도 : 64, - 온배수 : 0 - } - ]); - - const chartConfig = chartData.reduce((config, element) => { - config[element.label] = { - label: element.label, - color : "hsl(var(--chart-1))" - }; - return config; - }, {} as Record) satisfies ChartConfig; - - const chartOption = { - chartForm : CHART_FORM.BAR, - chartConfig : chartConfig, - chartData : chartData, - chartTitle : '', - chartClassName : "h-[300px] w-full", - graphSize : 40, - yFieldText : '시설(개소)', - showLegend : true - } - const colorLegend = [ { label: '하수', color: '#FF6B6B', key: 'sewage' }, { label: '빗물', color: '#4ECDC4', key: 'rainwater' }, { label: '중수도', color: '#45B7D1', key: 'reclaimed' }, { label: '온배수', color: '#FED16A', key: 'thermal' }, ]; + const facilityTotalsColor = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#FED16A']; - const regionIdMap: Record = { - 서울: '서울특별시', - 부산: '부산광역시', - 대구: '대구광역시', - 인천: '인천광역시', - 광주: '광주광역시', - 대전: '대전광역시', - 울산: '울산광역시', - 세종: '세종특별자치시', - 경기: '경기도', - 강원: '강원특별자치도', - 충북: '충청북도', - 충남: '충청남도', - 전북: '전라북도', - 전남: '전라남도', - 경북: '경상북도', - 경남: '경상남도', - 제주: '제주특별자치도' - }; - const tableData: TableData[] = [ - { region: '전국', sewage: '717(1,137,538)', rainwater: '3544(13,945)', reclaimed: '1018(222,476)', thermal: '123(492)' }, - { region: '서울특별시', sewage: '4(114,908)', rainwater: '816(430)', reclaimed: '371(341)', thermal: '0' }, - { region: '부산광역시', sewage: '13(146,197)', rainwater: '68(335)', reclaimed: '20(512)', thermal: '1(18)' }, - { region: '대구광역시', sewage: '9(102,380)', rainwater: '294(133)', reclaimed: '14(44)', thermal: '2(12)' }, - { region: '인천광역시', sewage: '17(57,691)', rainwater: '165(642)', reclaimed: '35(7,859)', thermal: '15(32)' }, - { region: '광주광역시', sewage: '3(28,738)', rainwater: '74(23)', reclaimed: '15(450)', thermal: '15(6)' }, - { region: '대전광역시', sewage: '2(11,966)', rainwater: '52(2)', reclaimed: '11(492)', thermal: '20(100)' }, - { region: '울산광역시', sewage: '8(36,076)', rainwater: '111(39)', reclaimed: '19(28,904)', thermal: '30(130)' }, - { region: '세종특별자치시', sewage: '9(2,555)', rainwater: '65(16)', reclaimed: '0(0)', thermal: '0' }, - { region: '경기도', sewage: '176(313,298)', rainwater: '1009(4,735)', reclaimed: '252(77,096)', thermal: '40(143)' }, - { region: '강원특별자치도', sewage: '69(19,677)', rainwater: '69(4)', reclaimed: '22(447)', thermal: '0' }, - { region: '충청북도', sewage: '38(15,607)', rainwater: '17(91)', reclaimed: '91(2,211)', thermal: '0' }, - { region: '충청남도', sewage: '67(41,368)', rainwater: '54(77)', reclaimed: '188(50,434)', thermal: '0' }, - { region: '전라북도', sewage: '55(42,671)', rainwater: '33(199)', reclaimed: '220(9,453)', thermal: '0' }, - { region: '전라남도', sewage: '83(23,560)', rainwater: '16(885)', reclaimed: '75(15,412)', thermal: '0' }, - { region: '경상북도', sewage: '81(129,081)', rainwater: '37(341)', reclaimed: '70(27,818)', thermal: '0' }, - { region: '경상남도', sewage: '75(50,101)', rainwater: '27(244)', reclaimed: '140(343)', thermal: '0' }, - { region: '제주특별자치도', sewage: '8(1,666)', rainwater: '47(5,746)', reclaimed: '64(660)', thermal: '0' }, - ]; - - const regionData: RegionData[] = useMemo(() => [ - { name: '서울', x: 170, y: 140, values: [0.3, 0.3, 0.2, 0.2] }, - { name: '인천', x: 120, y: 150, values: [0.3, 0.3, 0.2, 0.2] }, - { name: '경기', x: 210, y: 210, values: [0.3, 0.3, 0.2, 0.2] }, - { name: '강원', x: 330, y: 120, values: [0.3, 0.3, 0.2, 0.2] }, - { name: '충북', x: 260, y: 280, values: [0.3, 0.3, 0.2, 0.2] }, - { name: '충남', x: 100, y: 320, values: [0.3, 0.3, 0.2, 0.2] }, - { name: '세종', x: 180, y: 305, values: [0.3, 0.3, 0.2, 0.2] }, - { name: '대전', x: 195, y: 360, values: [0.3, 0.3, 0.2, 0.2] }, - { name: '전북', x: 170, y: 450, values: [0.3, 0.3, 0.2, 0.2] }, - { name: '전남', x: 160, y: 600, values: [0.3, 0.3, 0.2, 0.2] }, - { name: '광주', x: 120, y: 530, values: [0.3, 0.3, 0.2, 0.2] }, - { name: '경북', x: 400, y: 320, values: [0.3, 0.3, 0.2, 0.2] }, - { name: '경남', x: 310, y: 530, values: [0.3, 0.3, 0.2, 0.2] }, - { name: '대구', x: 350, y: 450, values: [0.3, 0.3, 0.2, 0.2] }, - { name: '울산', x: 450, y: 500, values: [0.3, 0.3, 0.2, 0.2] }, - { name: '부산', x: 420, y: 550, values: [0.3, 0.3, 0.2, 0.2] }, - { name: '제주', x: 60, y: 750, values: [0.3, 0.3, 0.2, 0.2] }, - ], []); const handleMarkerClick = (regionId: string) => { if (selectedRegion === regionId) { @@ -241,7 +47,6 @@ const WrStatusPage: React.FC = () => { } }; - const createDonutMarker = useCallback((svg: SVGSVGElement, x: number, y: number, name: string, values: number[]) => { const colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#FED16A']; const radius = 26; @@ -252,7 +57,6 @@ const WrStatusPage: React.FC = () => { console.warn(`Invalid region name: ${name}`); return; } - const g = document.createElementNS('http://www.w3.org/2000/svg', 'g'); g.setAttribute('transform', `translate(${x}, ${y})`); g.setAttribute('id', `marker-${name}`); @@ -336,6 +140,13 @@ const WrStatusPage: React.FC = () => { svg.appendChild(g); }, [handleMarkerClick, regionIdMap]); + + useEffect(() => { + getDmStatusData('2023'); + },[]) + + + useEffect(() => { const loadSVG = async () => { try { @@ -393,6 +204,31 @@ const WrStatusPage: React.FC = () => { }); } }, [selectedRegion]); + useEffect(() => { + if(chartData.length>0){ + const chartConfig = chartData.reduce((config, element) => { + config[element.label] = { + label: element.label, + color : "hsl(var(--chart-1))" + }; + return config; + }, {} as Record) satisfies ChartConfig; + + const Option = { + chartForm : CHART_FORM.BAR, + chartConfig : chartConfig, + chartData : chartData, + chartTitle : '', + chartClassName : "h-[300px] w-full", + graphSize : 40, + yFieldText : '시설(개소)', + showLegend : true + } + setChartOption(Option) + }else{ + setChartOption({} as WrStatusChartProps) + } + }, [chartData]); return (
@@ -401,7 +237,6 @@ const WrStatusPage: React.FC = () => { {/* 상단 제목 */}

물재이용 현황

-
관리자 ▼
{/* 콘텐츠 본문 */} @@ -439,11 +274,11 @@ const WrStatusPage: React.FC = () => {
{hoveredRegion}
{colorLegend.map(({ label, color, key }) => ( -
+
{label}:{' '} - {tableData.find(d => d.region === hoveredRegion)?.[key as keyof TableData] ?? '-'} + {statusData?.find(d => d.region === hoveredRegion)?.[key as keyof DmStatusDataType] || '-'}
))} @@ -453,22 +288,12 @@ const WrStatusPage: React.FC = () => { {/* 범례 */}
-
- - 하수재이용시설 (총 717개소) -
-
- - 빗물이용시설 (총 3,730개소) -
-
- - 중수도시설 (총 1,074개소) -
-
- - 온배수시설 (총 201개소) -
+ {facilityTotals?.map((item, index) => ( +
+ + {item} +
+ )) }
@@ -479,10 +304,10 @@ const WrStatusPage: React.FC = () => { {/* 재이용시설현황 표 */}
{/* 타이틀 + 버튼 영역 */} -
+

재이용시설현황(2023)

-

행정구역별 재이용시설현황(개소)

+

행정구역별 재이용시설현황[개소(천m³/년)]

@@ -493,14 +318,18 @@ const WrStatusPage: React.FC = () => { 번호 시도 - 하수(이용량,천𝓂³/년) + 하수재이용시설 + 빗물이용시설 + 중수도시설 + 온배수시설 + {/* 하수(이용량,천𝓂³/년) 빗물(이용량,천𝓂³/년) 중수도(이용량,천𝓂³/년) - 온배수(이용량,천𝓂³/년) + 온배수(이용량,천𝓂³/년) */} - {tableData.map((row, index) => ( + {statusData?.map((row, index) => ( {index+1} @@ -526,16 +355,18 @@ const WrStatusPage: React.FC = () => {
- + {chartOption? + + :<>}
@@ -545,5 +376,3 @@ const WrStatusPage: React.FC = () => {
); }; - -export default WrStatusPage; \ No newline at end of file diff --git a/apps/dm/app/common/comFunction.ts b/apps/dm/app/common/comFunction.ts new file mode 100644 index 000000000..6d7274b95 --- /dev/null +++ b/apps/dm/app/common/comFunction.ts @@ -0,0 +1,74 @@ +import type { DmStatusChartType, DmStatusDataType, RegionData, } from "../store/wrStatus/type"; + + + +export const regionData:RegionData[] = [ + { name: '서울', x: 170, y: 140, values: [0.3, 0.3, 0.2, 0.2] }, + { name: '인천', x: 120, y: 150, values: [0.3, 0.3, 0.2, 0.2] }, + { name: '경기', x: 210, y: 210, values: [0.3, 0.3, 0.2, 0.2] }, + { name: '강원', x: 330, y: 120, values: [0.3, 0.3, 0.2, 0.2] }, + { name: '충북', x: 260, y: 280, values: [0.3, 0.3, 0.2, 0.2] }, + { name: '충남', x: 100, y: 320, values: [0.3, 0.3, 0.2, 0.2] }, + { name: '세종', x: 180, y: 305, values: [0.3, 0.3, 0.2, 0.2] }, + { name: '대전', x: 195, y: 360, values: [0.3, 0.3, 0.2, 0.2] }, + { name: '전북', x: 170, y: 450, values: [0.3, 0.3, 0.2, 0.2] }, + { name: '전남', x: 160, y: 600, values: [0.3, 0.3, 0.2, 0.2] }, + { name: '광주', x: 120, y: 530, values: [0.3, 0.3, 0.2, 0.2] }, + { name: '경북', x: 400, y: 320, values: [0.3, 0.3, 0.2, 0.2] }, + { name: '경남', x: 310, y: 530, values: [0.3, 0.3, 0.2, 0.2] }, + { name: '대구', x: 350, y: 450, values: [0.3, 0.3, 0.2, 0.2] }, + { name: '울산', x: 450, y: 500, values: [0.3, 0.3, 0.2, 0.2] }, + { name: '부산', x: 420, y: 550, values: [0.3, 0.3, 0.2, 0.2] }, + { name: '제주', x: 60, y: 750, values: [0.3, 0.3, 0.2, 0.2] }, + ] + +export const regionIdMap: Record = { + 서울: '서울특별시', + 부산: '부산광역시', + 대구: '대구광역시', + 인천: '인천광역시', + 광주: '광주광역시', + 대전: '대전광역시', + 울산: '울산광역시', + 세종: '세종특별자치시', + 경기: '경기도', + 강원: '강원특별자치도', + 충북: '충청북도', + 충남: '충청남도', + 전북: '전라북도', + 전남: '전라남도', + 경북: '경상북도', + 경남: '경상남도', + 제주: '제주특별자치도' + }; + + +const makeRegion = (region: string) => { + if (region === '서울특별시') return '서울' + if (region === '부산광역시') return '부산' + if (region === '대구광역시') return '대구' + if (region === '인천광역시') return '인천' + if (region === '광주광역시') return '광주' + if (region === '대전광역시') return '대전' + if (region === '울산광역시') return '울산' + if (region === '세종특별자치시') return '세종' + if (region === '경기도') return '경기' + if (region === '강원특별자치도') return '강원' + if (region === '충청북도') return '충북' + if (region === '충청남도') return '충남' + if (region === '전라북도') return '전북' + if (region === '전라남도') return '전남' + if (region === '경상북도') return '경북' + if (region === '경상남도') return '경남' + if (region === '제주특별자치도') return '제주' + return region; +} +export const changeStatusMapData= (data: DmStatusDataType[]) : DmStatusChartType[]=> { + return data.map((item) => ({ + label: makeRegion(item.region??''), + 하수: item.sewage.split('(')[0]??'', + 빗물: item.rainwater.split('(')[0]??'', + 중수도: item.reclaimed.split('(')[0] ??'', + 온배수: item.thermal.split('(')[0] ??'', + })); +} \ No newline at end of file diff --git a/apps/dm/app/store/store.tsx b/apps/dm/app/store/store.tsx index be6a26475..f885a3bd0 100644 --- a/apps/dm/app/store/store.tsx +++ b/apps/dm/app/store/store.tsx @@ -1,29 +1,48 @@ -import { createStore } from 'zustand/vanilla'; -import { CommonReducer, CommonState, type CommonStore, type CommonType } from './common'; -import { SdmReducer, SdmState, type SdmStore, type SdmType } from './sdmMng'; -import { dmMapState, type DmMapType, type DmMapStore, DmMapReducer } from './map'; -import { tokenManager } from '@/src/entities/auth/lib/token-manager'; +import { createStore } from "zustand/vanilla"; +import { + CommonReducer, + CommonState, + type CommonStore, + type CommonType, +} from "./common"; +import { SdmReducer, SdmState, type SdmStore, type SdmType } from "./sdmMng"; +import { + dmMapState, + type DmMapType, + type DmMapStore, + DmMapReducer, +} from "./map"; +import { tokenManager } from "@/src/entities/auth/lib/token-manager"; +import { + DmStatusReducer, + dmStatusState, + type DmStatusStore, + type DmStatusType, +} from "./wrStatus"; -export type DmStore = CommonStore & SdmStore &DmMapStore ; -export type DmState = CommonType & SdmType &DmMapType; +export type DmStore = CommonStore & SdmStore & DmMapStore & DmStatusStore; +export type DmState = CommonType & SdmType & DmMapType & DmStatusType; -export const StoreZus = (initState: DmState= { - ...CommonState, - ...SdmState, - ...dmMapState, -}) => { +export const StoreZus = ( + initState: DmState = { + ...CommonState, + ...SdmState, + ...dmMapState, + ...dmStatusState, + } +) => { return createStore()((set) => { if (typeof window !== "undefined") { - tokenManager.setToken("site-id-key", 'DM'); - tokenManager.setToken("site-theme-key", 'green'); + tokenManager.setToken("site-id-key", "DM"); + tokenManager.setToken("site-theme-key", "green"); } - return { ...initState, ...CommonReducer(set), ...SdmReducer(set), - ...DmMapReducer(set) - } - }) -} \ No newline at end of file + ...DmMapReducer(set), + ...DmStatusReducer(set), + }; + }); +}; diff --git a/apps/dm/app/store/wrStatus/index.tsx b/apps/dm/app/store/wrStatus/index.tsx new file mode 100644 index 000000000..417bfab6c --- /dev/null +++ b/apps/dm/app/store/wrStatus/index.tsx @@ -0,0 +1,63 @@ +import { changeStatusMapData } from "@/app/common/comFunction"; +import { fetchType, getFetch } from "@/components/ui/api"; +import type { + DmStatusDataType, + DmStatusChartType, +} from "./type"; + +export type DmStatusActions = { + getDmStatusData(year: string): void; +}; + +export type DmStatusType = { + dmStatus: { + statusData: DmStatusDataType[]; + facilityTotals: string[]; + chartData: DmStatusChartType[]; + }; +}; + +export const dmStatusState: DmStatusType = { + dmStatus: { + statusData: [], + facilityTotals: [], + chartData: [], + }, +}; +export type DmStatusStore = DmStatusType & DmStatusActions; + +export const DmStatusReducer = (set: any): DmStatusActions => { + return { + getDmStatusData: async (year: string) => { + const data = await getFetch(fetchType.WR, "/daemin/" + year); + let isData:DmStatusDataType[] =[] + if(data.data&&data.data.length>0){ + isData=data.data + }else{ + fetch(`data/wrStatusData.json`).then((res) => res.json()).then((json) => isData=json)//만약 백엔드에서 못가져올경우 방어책 + } + + const orgin: DmStatusDataType[] = isData; + const chartData = changeStatusMapData(orgin); + const facilityTotals = [ + "하수재이용시설" + "(총" + orgin[0]?.sewage.split("(")[0] + "개소)", + "빗물재이용시설" + "(총" + orgin[0]?.rainwater.split("(")[0] + "개소)", + "중수도재이용시설" + + "(총" + + orgin[0]?.reclaimed.split("(")[0] + + "개소)", + "온배수재이용시설" + "(총" + orgin[0]?.thermal.split("(")[0] + "개소)", + ]; + + set((state: DmStatusType) => ({ + ...state, + dmStatus: { + ...state.dmStatus, + statusData: data.data, + chartData: chartData, + facilityTotals: facilityTotals, + }, + })); + }, + }; +}; diff --git a/apps/dm/app/store/wrStatus/type.ts b/apps/dm/app/store/wrStatus/type.ts new file mode 100644 index 000000000..3e674227b --- /dev/null +++ b/apps/dm/app/store/wrStatus/type.ts @@ -0,0 +1,32 @@ +export type DmStatusDataType = { + region: string; + sewage: string; + rainwater: string; + reclaimed: string; + thermal: string; +}; + + +export type DmStatusFcltType = { + sewageFclt: string; + rainwaterFclt: string; + reclaimedFclt: string; + thermalFclt: string; + }; + + + +export type DmStatusChartType = { + label: string, + 하수: string, + 빗물: string, + 중수도: string, + 온배수: string, +} + +export type RegionData = { + name: string; + x: number; + y: number; + values: number[]; + } \ No newline at end of file diff --git a/apps/dm/public/data/wrStatusData.json b/apps/dm/public/data/wrStatusData.json new file mode 100644 index 000000000..334b521c1 --- /dev/null +++ b/apps/dm/public/data/wrStatusData.json @@ -0,0 +1,20 @@ +[ + { "region": "전국", "sewage": "717(1,137,538)", "rainwater": "3544(13,945)", "reclaimed": "1018(222,476)", "thermal": "123(492)" }, + { "region": "서울특별시", "sewage": "4(114,908)", "rainwater": "816(430)", "reclaimed": "371(341)", "thermal": "0" }, + { "region": "부산광역시", "sewage": "13(146,197)", "rainwater": "68(335)", "reclaimed": "20(512)", "thermal": "1(18)" }, + { "region": "대구광역시", "sewage": "9(102,380)", "rainwater": "294(133)", "reclaimed": "14(44)", "thermal": "2(12)" }, + { "region": "인천광역시", "sewage": "17(57,691)", "rainwater": "165(642)", "reclaimed": "35(7,859)", "thermal": "15(32)" }, + { "region": "광주광역시", "sewage": "3(28,738)", "rainwater": "74(23)", "reclaimed": "15(450)", "thermal": "15(6)" }, + { "region": "대전광역시", "sewage": "2(11,966)", "rainwater": "52(2)", "reclaimed": "11(492)", "thermal": "20(100)" }, + { "region": "울산광역시", "sewage": "8(36,076)", "rainwater": "111(39)", "reclaimed": "19(28,904)", "thermal": "30(130)" }, + { "region": "세종특별자치시", "sewage": "9(2,555)", "rainwater": "65(16)", "reclaimed": "0(0)", "thermal": "0" }, + { "region": "경기도", "sewage": "176(313,298)", "rainwater": "1009(4,735)", "reclaimed": "252(77,096)", "thermal": "40(143)" }, + { "region": "강원특별자치도", "sewage": "69(19,677)", "rainwater": "69(4)", "reclaimed": "22(447)", "thermal": "0" }, + { "region": "충청북도", "sewage": "38(15,607)", "rainwater": "17(91)", "reclaimed": "91(2,211)", "thermal": "0" }, + { "region": "충청남도", "sewage": "67(41,368)", "rainwater": "54(77)", "reclaimed": "188(50,434)", "thermal": "0" }, + { "region": "전라북도", "sewage": "55(42,671)", "rainwater": "33(199)", "reclaimed": "220(9,453)", "thermal": "0" }, + { "region": "전라남도", "sewage": "83(23,560)", "rainwater": "16(885)", "reclaimed": "75(15,412)", "thermal": "0" }, + { "region": "경상북도", "sewage": "81(129,081)", "rainwater": "37(341)", "reclaimed": "70(27,818)", "thermal": "0" }, + { "region": "경상남도", "sewage": "75(50,101)", "rainwater": "27(244)", "reclaimed": "140(343)", "thermal": "0" }, + { "region": "제주특별자치도", "sewage": "8(1,666)", "rainwater": "47(5,746)", "reclaimed": "64(660)", "thermal": "0" } + ] \ No newline at end of file