Merge branch 'iipbs/sn/dev_kic' into iipbs/sn/dev

This commit is contained in:
kiminchan
2026-07-20 15:33:27 +09:00
2 changed files with 58 additions and 1 deletions
@@ -0,0 +1,32 @@
# 시설물 레이어 트리 스크롤 유지 구현기록
## 작업 정보
- 작업일: 2026-07-20
- 모드: `quick_vibe`
- 범위: 프론트엔드
## 요구사항 및 원인
- 시설물 레이어 트리 하단의 체크박스를 변경해도 세로 스크롤이 현재 위치를 유지해야 한다.
- 기존 `GisTree`는 체크 변경 후 부모 지도 화면과 하단 레이어 설정영역이 다시 렌더되지만, 스크롤 요소의 `scrollTop`을 별도로 보존하지 않아 위치가 초기화될 수 있었다.
## 변경 내용
- `GisTree`의 실제 세로 스크롤 요소를 ref로 추적한다.
- 스크롤 이벤트에서 현재 `scrollTop`을 보관하고, 렌더 완료 직후 유효 범위 안에서 같은 위치를 복원한다.
- API, DB, 백엔드 계약은 변경하지 않았다.
## 수정 파일
- `packages/common/business_components/src/ui/map/GisTree.js`
## 검증
- 공통 비즈니스 컴포넌트 로컬 `tsup` ESM/DTS 빌드 성공
- `git diff --check` 성공
- 로컬 `/map`은 인증되지 않은 브라우저 세션에서 로그인 화면으로 전환되어 실제 레이어 체크 검증은 후속 수동 확인으로 남겼다.
## 롤백
- `GisTree.js`의 스크롤 ref, 스크롤 이벤트 핸들러, `useLayoutEffect` 복원 로직을 제거한다.
@@ -5,7 +5,7 @@ import {
DndProvider,
} from "@minoru/react-dnd-treeview";
import { ChevronLeft, ChevronRight } from "lucide-react";
import React, { useEffect, useState, useRef, useCallback } from "react";
import React, { useEffect, useLayoutEffect, useState, useRef, useCallback } from "react";
import { useGisContext } from "./Gis";
import GisApp from "./lib/gis.core";
@@ -66,6 +66,29 @@ export default React.memo(function GisTree({
const targetNodesRef = useRef([]);
const isPausedRef = useRef(false);
const timeoutIdRef = useRef(null);
// 체크 후 부모 설정영역까지 다시 렌더되어도 사용자가 보던 트리 위치를 유지한다.
const layerPanelScrollRef = useRef(null);
const layerPanelScrollTopRef = useRef(0);
const handleLayerPanelScroll = useCallback((event) => {
layerPanelScrollTopRef.current = event.currentTarget.scrollTop;
}, []);
useLayoutEffect(() => {
const scrollContainer = layerPanelScrollRef.current;
if (!scrollContainer) return;
const maxScrollTop = Math.max(
0,
scrollContainer.scrollHeight - scrollContainer.clientHeight
);
const nextScrollTop = Math.min(layerPanelScrollTopRef.current, maxScrollTop);
if (scrollContainer.scrollTop !== nextScrollTop) {
scrollContainer.scrollTop = nextScrollTop;
}
layerPanelScrollTopRef.current = nextScrollTop;
});
// =====================
// 유틸리티: 트리 탐색 관련 함수들
@@ -533,6 +556,8 @@ export default React.memo(function GisTree({
}`}
>
<div
ref={layerPanelScrollRef}
onScroll={handleLayerPanelScroll}
className={`grow overflow-y-auto border-none p-2 ${showLayerPanelTitle ? "pt-0" : "pt-2"} shadow-none ${activeTab === "layers" ? "block" : "hidden"
}`}
>