From 791bc20e8e24034f8849ccbc9e6bbc01da576e53 Mon Sep 17 00:00:00 2001 From: ljpark Date: Tue, 13 Oct 2026 15:22:16 +0900 Subject: [PATCH 1/3] =?UTF-8?q?sn:=20=EC=A7=80=EB=8F=84=20=EC=9C=84?= =?UTF-8?q?=EC=B9=98=20=EC=A0=95=EB=B3=B4=EA=B0=80=20=EC=97=86=EB=8A=94=20?= =?UTF-8?q?=EA=B2=BD=EC=9A=B0=20404>>=EC=9C=84=EC=B9=98=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=EA=B0=80=20=EC=97=86=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../flood-dngr-map-popup-page.tsx | 17 ++++++----- .../001-fe-SN-도시침수지도-빈목록응답-작업카드.md | 28 +++++++++++++++++++ .../lib/use-flood-prediction-map.ts | 6 ++-- .../ui/fldng-predc-prst-popup-content.tsx | 7 ++++- 4 files changed, 47 insertions(+), 11 deletions(-) create mode 100644 apps/sn/docs/작업계획/SN-도시침수지도-정보제공포털-목록보기/001-fe-SN-도시침수지도-빈목록응답-작업카드.md diff --git a/apps/sn/app/(map-layout)/map/components/flood-dngr-map/flood-dngr-map-popup-page.tsx b/apps/sn/app/(map-layout)/map/components/flood-dngr-map/flood-dngr-map-popup-page.tsx index 5474e8fad..52220d34d 100644 --- a/apps/sn/app/(map-layout)/map/components/flood-dngr-map/flood-dngr-map-popup-page.tsx +++ b/apps/sn/app/(map-layout)/map/components/flood-dngr-map/flood-dngr-map-popup-page.tsx @@ -226,7 +226,12 @@ export default function FloodDngrMapPopupPage() { const response = await getFloodDngrMapJson( `/sewerage-service/api/v1/fldng/floodDngrMap/group/extent?${params.toString()}`, ); - const payload = response as FloodDngrMapExtent; + const payload = response as FloodDngrMapExtent | null | undefined; + // 성공 응답의 null·생략된 data는 위치 부재이다. 좌표 접근과 지도 메시지를 중단한다. + if (payload == null) { + setErrorMessage("위치 정보가 없습니다"); + return; + } const extent = [ payload?.minX, payload?.minY, @@ -237,7 +242,7 @@ export default function FloodDngrMapPopupPage() { extent.length !== 4 || extent.some((value) => !Number.isFinite(value)) ) { - throw new Error("해당 도시침수지도 피처의 위치 정보가 없습니다."); + throw new Error("도시침수지도 위치 응답의 좌표가 올바르지 않습니다."); } window.opener?.postMessage( { @@ -253,11 +258,9 @@ export default function FloodDngrMapPopupPage() { } catch (error) { console.error("도시침수지도 위치 이동 중 오류:", error); const message = - error instanceof Error && error.message.includes("404") - ? "해당 도시침수지도 데이터에 위치 정보가 없어 이동할 수 없습니다." - : error instanceof Error - ? error.message - : "도시침수지도 위치 이동 중 오류가 발생했습니다."; + error instanceof Error + ? error.message + : "도시침수지도 위치 이동 중 오류가 발생했습니다."; setErrorMessage(message); } finally { setIsLoading(false); diff --git a/apps/sn/docs/작업계획/SN-도시침수지도-정보제공포털-목록보기/001-fe-SN-도시침수지도-빈목록응답-작업카드.md b/apps/sn/docs/작업계획/SN-도시침수지도-정보제공포털-목록보기/001-fe-SN-도시침수지도-빈목록응답-작업카드.md new file mode 100644 index 000000000..2fdf7daf4 --- /dev/null +++ b/apps/sn/docs/작업계획/SN-도시침수지도-정보제공포털-목록보기/001-fe-SN-도시침수지도-빈목록응답-작업카드.md @@ -0,0 +1,28 @@ +# FE 도시침수지도 빈 결과 안내 작업카드 + +- 작성일: 2026-10-13 / 상태: 구현 완료 / 실서버·브라우저 검증 대기 +- 근거: 사용자 요청. extent 위치 정보가 없으면 `위치 정보가 없습니다`로 안내한다. + +## 변경 계획 + +- 목록 200·items=[]·total=0: 총 0건과 빈 표를 표시하고 이전 행·오류·로딩 상태를 정리한다. +- 단건·그룹 extent 200 응답에 위치 데이터가 없으면 `위치 정보가 없습니다`를 표시하고 지도 이동·선택 강조를 수행하지 않는다. +- 공통 응답에서 data가 null이거나 생략된 경우를 좌표 접근 전에 처리한다. 404 문자열로 위치 부재를 판단하는 기존 분기는 제거한다. +- 위치 데이터가 있으면 기존 지도 이동을 유지한다. 실제 HTTP 오류·잘못된 좌표는 기존 오류 처리로 구분한다. + +## 수정 대상 + +- `app/(map-layout)/map/components/flood-dngr-map/flood-dngr-map-popup-page.tsx`: 목록·그룹 extent·안내 처리. +- sn 내 단건·그룹 extent 호출부(침수예측 현황·지도 포함): 검색으로 사용처를 확정하고 동일한 빈 결과 처리 적용. +- `src/shared/api/sewerage-api.ts`, `http-transport.ts`: null·data 생략 응답의 전달 방식 확인. 전역 오류 치환은 하지 않는다. + +## 검증·영향 + +- 두 extent의 위치 없음: 200, 지정 안내 문구, 지도 이동 없음, null 접근 오류 없음. +- 위치 있음: 기존 이동 정상. 실제 404·401·403·5xx·timeout: 오류 안내 유지. +- 목록은 데이터 있음 → 0건 → 데이터 있음 재검색 시 행·건수·로딩이 일치한다. +- BE 성공 JSON의 data 생략·null 처리를 연동 확인한다. 빈 본문·비정상 응답을 임의로 위치 없음으로 처리하지 않는다. +- 영향은 sn의 extent 사용 화면. UI·DB 변경 없음. 롤백은 실제 수정한 기능 파일 복원. +- 남은 확인: 전체 extent 호출부와 실제 응답 형태·브라우저 동작. + +FE 구현 및 타입 검사·클릭 처리 모의 검증 완료. 로그인 브라우저 검증은 미수행이다. diff --git a/apps/sn/src/features/fldng-predc-prst/lib/use-flood-prediction-map.ts b/apps/sn/src/features/fldng-predc-prst/lib/use-flood-prediction-map.ts index e8f0c6596..9a649e309 100644 --- a/apps/sn/src/features/fldng-predc-prst/lib/use-flood-prediction-map.ts +++ b/apps/sn/src/features/fldng-predc-prst/lib/use-flood-prediction-map.ts @@ -7,7 +7,7 @@ import Overlay from "ol/Overlay.js"; import GisApp from "@common/business_components/ui/map/lib/gis.core"; -import { getRawJson } from "@/shared/api/sewerage-api"; +import { getData } from "@/shared/api/sewerage-api"; import { WINDOW_POPUP_MESSAGE_TYPE } from "@/features/window-popup/model/types"; import { getFloodRiskGradeClassName } from "./flood-risk-grade"; @@ -251,11 +251,11 @@ export const useFloodPredictionMap = ({ removeFloodPredictionOverlay(); try { - const response = await getRawJson( + // 공통 응답의 data만 읽어 null·생략된 값을 빈 오버레이 결과로 처리한다. + const payload = await getData( `/sewerage-service/api/v1/fldng/predc/prst/gridMap?sggCd=${encodeURIComponent(sggCd)}&analysisDateTime=${encodeURIComponent(analysisDateTime)}`, ); if (!navigation?.isCurrent()) return; - const payload = response?.data ?? response; const row = payload && typeof payload === "object" && !Array.isArray(payload) ? (payload as FloodPredictionOverlayRow) diff --git a/apps/sn/src/features/fldng-predc-prst/ui/fldng-predc-prst-popup-content.tsx b/apps/sn/src/features/fldng-predc-prst/ui/fldng-predc-prst-popup-content.tsx index e5d6b98db..9f437b19e 100644 --- a/apps/sn/src/features/fldng-predc-prst/ui/fldng-predc-prst-popup-content.tsx +++ b/apps/sn/src/features/fldng-predc-prst/ui/fldng-predc-prst-popup-content.tsx @@ -367,6 +367,11 @@ export default function FldngPredcPrstPopupContent() { const extentData = await getData( `/sewerage-service/api/v1/fldng/floodDngrMap/group/extent?${params.toString()}`, ); + // null·생략된 data는 정상적인 위치 부재이며 부모 지도 이동·강조를 요청하지 않는다. + if (extentData == null) { + alert("위치 정보가 없습니다"); + return; + } const extent = [ extentData?.minX, extentData?.minY, @@ -374,7 +379,7 @@ export default function FldngPredcPrstPopupContent() { extentData?.maxY, ].map(Number); if (extent.some((value) => !Number.isFinite(value))) { - throw new Error("도시침수지도 위치 정보가 없습니다."); + throw new Error("도시침수지도 위치 응답의 좌표가 올바르지 않습니다."); } window.opener.postMessage( { From c850b9ce1effa227f9dcd1c5b0799b7ec205a7ba Mon Sep 17 00:00:00 2001 From: ljpark Date: Tue, 13 Oct 2026 15:48:24 +0900 Subject: [PATCH 2/3] =?UTF-8?q?sn:=20=ED=95=B4=EB=8B=B9=20=EB=8F=84?= =?UTF-8?q?=EC=8B=9C=EC=B9=A8=EC=88=98=EC=A7=80=EB=8F=84=EA=B0=80=20?= =?UTF-8?q?=EC=97=86=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fldng-predc-prst/ui/fldng-predc-prst-popup-content.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/sn/src/features/fldng-predc-prst/ui/fldng-predc-prst-popup-content.tsx b/apps/sn/src/features/fldng-predc-prst/ui/fldng-predc-prst-popup-content.tsx index 9f437b19e..5f213234a 100644 --- a/apps/sn/src/features/fldng-predc-prst/ui/fldng-predc-prst-popup-content.tsx +++ b/apps/sn/src/features/fldng-predc-prst/ui/fldng-predc-prst-popup-content.tsx @@ -369,7 +369,7 @@ export default function FldngPredcPrstPopupContent() { ); // null·생략된 data는 정상적인 위치 부재이며 부모 지도 이동·강조를 요청하지 않는다. if (extentData == null) { - alert("위치 정보가 없습니다"); + alert("해당 도시침수지도가 없습니다."); return; } const extent = [ From 728a66bac2b0d2eb9cf9b4e6b1763b77e5961e67 Mon Sep 17 00:00:00 2001 From: ljpark Date: Tue, 13 Oct 2026 15:55:31 +0900 Subject: [PATCH 3/3] sn: apigateway.onasys.co.kr --- apps/sn/.env.local | 2 +- apps/sn/.env.mindone | 2 +- apps/sn/src/shared/config/env.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/sn/.env.local b/apps/sn/.env.local index dce96bf40..256b4daac 100644 --- a/apps/sn/.env.local +++ b/apps/sn/.env.local @@ -11,7 +11,7 @@ NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver #NEXT_PUBLIC_NGII_URL = https://map.ngii.go.kr/openapi/Gettile.do?apiKey=04trYP9_xwLAfALjwZ-B8g&Service=WMTS&Request=GetTile&Version=1.0.0&Format=image/png&layer=korean_map&style=korean&tilematrixset=EPSG:5179&TileMatrix={z}&TileCol={x}&TileRow={y} NEXT_PUBLIC_NGII_URL = https://map.ngii.go.kr NEXT_PUBLIC_NGII_PARAM = 04trYP9_xwLAfALjwZ-B8g&service=WMTS&request=GetTile&version=1.0.0&format=image/png&layer=korean_map&style=korean&tilematrixset=korean&tilematrix={z}&tilecol={x}&tilerow={y} -SERVER_API_URL = http://dev.onasys.co.kr:8000 +SERVER_API_URL = https://apigateway.onasys.co.kr SEWERAGE_API_URL = http://localhost:8883 # SEWERAGE_API_URL = http://con.mind-one.co.kr:11083 DC_URL = https://apigateway.apps.rsonesoft.com diff --git a/apps/sn/.env.mindone b/apps/sn/.env.mindone index 84202b57b..fb477b3bb 100644 --- a/apps/sn/.env.mindone +++ b/apps/sn/.env.mindone @@ -6,7 +6,7 @@ NEXT_PUBLIC_ACCESS_TOKEN = access-token NEXT_PUBLIC_REFRESH_TOKEN = refresh-token NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11302 NEXT_PUBLIC_SUB_DOMAIN = http://con.mind-one.co.kr:13000 -SERVER_API_URL = http://dev.onasys.co.kr:8000 +SERVER_API_URL = https://apigateway.onasys.co.kr NEXT_PUBLIC_GEOSERVER_URL = https://hasudo.geo.rsonesoft.com/geoserver NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver NEXT_PUBLIC_NGII_URL = https://map.ngii.go.kr diff --git a/apps/sn/src/shared/config/env.ts b/apps/sn/src/shared/config/env.ts index 788fdf36f..0ec1c73ea 100644 --- a/apps/sn/src/shared/config/env.ts +++ b/apps/sn/src/shared/config/env.ts @@ -1,7 +1,7 @@ export const SITE_ID = process.env.NEXT_PUBLIC_SITE_ID || "SN"; export const PORT = process.env.NEXT_PUBLIC_PORT || "3000"; export const PROXY_HOST = process.env.NEXT_PUBLIC_PROXY_HOST || `http://localhost:${PORT}`; -export const SERVER_API_URL = process.env.SERVER_API_URL||'http://dev.onasys.co.kr:8000'; +export const SERVER_API_URL = process.env.SERVER_API_URL||'https://apigateway.onasys.co.kr'; export const AUTH_LOGIN_REDIRECT_URL = process.env.NEXT_PUBLIC_AUTH_LOGIN_REDIRECT_URL || "/auth/login";