# 화면설계서: 이전기본계획조회 (기본 계획 찾기) ## 1. 기본 정보 | 항목 | 내용 | | ---------- | --------------------------------------------------------------- | | 버전 | 0.2 | | 프로세스명 | UI설계 | | 화면명 | 이전기본계획조회 (기본 계획 찾기) | | 화면 유형 | [v] 조회 [ ] 입력 [ ] 수정 [ ] 삭제 [ ] 출력 | | 메뉴 경로 | 하수도기본계획 등록·수정 > 사업개요 > [이전기본계획조회] Dialog | --- ## 2. 화면 목적 하수도기본계획 등록·수정 화면에서 **이전(기수립) 기본계획** 수치와 관련 보고서를 **조회·다운로드**한다. 시도·구군·연도·처리시설을 선택한 뒤 총설·처리구역별 현황을 표시하고, 분류 트리에서 기본계획 파일을 내려받는다. **부모 사업개요 폼에는 수치를 반영하지 않는다**(레거시 `bscPlnPopup.jsp`와 동일). --- ## 3. 화면 구성 ### 3-1. 전체 레이아웃 부모: 하수도기본계획 등록/수정 폼 → 사업개요 섹션의 `[이전기본계획조회]` 버튼으로 Dialog 오픈. ``` ┌─────────────────────────────────────────────────────────────────────────────────┐ │ Dialog 타이틀: 기본 계획 찾기 [닫기] │ ├─────────────────────────────────────────────────────────────────────────────────┤ │ [영역 A] 검색 필터 │ │ 시도 ▼ 구군 ▼ 연도 ▼ 처리시설 ▼ [조회] │ ├─────────────────────────────────────────────────────────────────────────────────┤ │ [영역 B] 기본계획파일 │ │ ┌──────────────────────┬────────────────────────────────────────────────────┐ │ │ │ [영역 B-1] 분류 트리 │ [영역 B-2] 파일 목록 │ │ │ │ (약 40%) │ (약 60%) │ │ │ │ └ 노드… │ 파일명 / 다운로드 │ │ │ └──────────────────────┴────────────────────────────────────────────────────┘ │ ├─────────────────────────────────────────────────────────────────────────────────┤ │ [영역 C] 총설 │ │ ┌────────┬──────────────당초──────────────┬──기준──┬──────────────변경──────────────┐ │ │ │ 구분 │ 1단계 │ 2단계 │ 3단계 │ 4단계 │ 기준 │ 1단계 │ 2단계 │ 3단계 │ 4단계 │ │ │ ├────────┼───────┼───────┼───────┼───────┼────────┼───────┼───────┼───────┼───────┤ │ │ │계획목표│ 년 │ 년 │ 년 │ 년 │ 년 │ 년 │ 년 │ 년 │ 년 │ │ │ │년도 │ │ │ │ │ │ │ │ │ │ │ │ └────────┴───────┴───────┴───────┴───────┴────────┴───────┴───────┴───────┴───────┘ │ ├─────────────────────────────────────────────────────────────────────────────────┤ │ [영역 D] 처리구역별 현황 │ │ ┌────────┬──────────────당초──────────────┬──기준──┬──────────────변경──────────────┐ │ │ │ 구분 │ 1~4단계(+연도헤더) │ 기준 │ 1~4단계(+연도헤더) │ │ │ ├────────┼────────────────────────────────┼────────┼────────────────────────────────┤ │ │ │ 하수처리인구 … 배제방식 (읽기 전용 행) │ │ │ └────────┴────────────────────────────────┴────────┴────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────────────────┘ ``` ### 3-2. 화면 데이터 흐름 ``` BEGIN // 부모 폼 — 사업개요 ON [이전기본계획조회] 버튼 CLICK DO OPEN PreviousPlanLookupDialog // 프리필: 부모 폼 sewerBscPlan.sido / gugun / admdstCd CALL findSidoCombo() DISPLAY 시도 옵션 (영역 A) IF 시도 프리필 THEN CALL findGugunCombo(sidoCd) DISPLAY 구군 옵션 (영역 A) CALL getLvNowDmgMtncGnsvy({ level: "1", ctpvNm }) // TBD: useLvNowDmgMtncGnsvy enabled — level별 필수 파라미터만 검사하도록 조정 IF 구군 프리필 THEN CALL getLvNowDmgMtncGnsvy({ level: "2", ctpvNm, sggNm }) DISPLAY 연도 옵션 (영역 A) // children 중 level=3 노드의 gnsvyYr CALL getClsfSystm({ clsfSystmNm: gugunNm }) DISPLAY 분류 트리 (영역 B-1) END IF END IF END ON // 영역 A: 시도 변경 ON 영역 A 시도 CHANGE DO RESET 구군 / 연도 / 처리시설 CALL findGugunCombo(sidoCd) CALL getLvNowDmgMtncGnsvy({ level: "1", ctpvNm }) // 구군 미선택 → 연도·처리시설 옵션 비움, 트리 빈 안내 END ON // 영역 A: 구군 변경 ON 영역 A 구군 CHANGE DO RESET 연도 / 처리시설 CALL getLvNowDmgMtncGnsvy({ level: "2", ctpvNm, sggNm }) DISPLAY 연도 옵션 (영역 A) // level=3 노드 → gnsvyYr CALL getClsfSystm({ clsfSystmNm: sggNm }) DISPLAY 분류 트리 (영역 B-1) END ON // 영역 A: 연도 변경 ON 영역 A 연도 CHANGE DO RESET 처리시설 CALL getLvNowDmgMtncGnsvy({ level: "3", ctpvNm, sggNm, gnsvyYr }) DISPLAY 처리시설 옵션 (영역 A) // level=3 노드 children → swtrmtFcltCd / swtrmtFcltNm END ON // 영역 A: 조회 ON [조회] 버튼 CLICK DO VALIDATE 시도, 구군, 연도(targetYear), 처리시설(swtrmtFcltCd) CALL getNowDmgMtncGnsvy({ swtrmtFcltCd, ctpvNm, sggNm, targetYear }) DISPLAY 총설 (영역 C) // 응답[0]의 planYr / planYrDt* / planYrDc* DISPLAY 처리구역별 현황 (영역 D) // 응답[0]의 지표 Dt1~4 / base / Dc1~4 END ON // 영역 B: 트리 노드 선택 ON 영역 B-1 노드 CLICK DO CALL getFile({ clsfSystmSn, sort, vetPrcsYn }) // Response DTO TBD DISPLAY 파일 목록 (영역 B-2) END ON // 영역 B: 파일 다운로드 ON 영역 B-2 파일 CLICK DO CALL getFilePrcs(fileSn) // 파일 메타(경로·제목) — Response TBD CALL fileDownload({ filePath, fileName }) // 브라우저 다운로드 트리거 END ON ON [닫기] DO CLOSE PreviousPlanLookupDialog // 부모 폼 값 변경 없음 END ON END ``` --- ## 4. 영역 A — 검색 필터 구성: **시도 · 구군 · 연도 · 처리시설** (+ 조회). - 시도·구군: `adstdstr` 콤보 (기존 스펙 유지) - 연도·처리시설: 각각 `useLvNowDmgMtncGnsvy`를 **별도 호출**. `level`에 따라 반환 계층이 달라진다. ### 4-1. 필드 정의 | 표시명 | 입력 유형 | 필수 | 기본값 | API 파라미터 매핑 | 비고 | | -------- | --------- | ---- | ------------------------- | ------------------------------------------------ | -------------------------------------------------------------- | | 시도 | Select | Y | 부모 `sewerBscPlan.sido` | `ctpvNm`(표시명), 코드는 `adstDstrCd` | `useFindSidoCombo` | | 구군 | Select | Y | 부모 `sewerBscPlan.gugun` | `sggNm`(표시명), 코드는 `adstDstrCd` | `useFindGugunCombo(sidoCd)` | | 연도 | Select | Y | 없음 | `gnsvyYr` / 조회 시 `targetYear` | `useLvNowDmgMtncGnsvy({ level: "2", ctpvNm, sggNm })` | | 처리시설 | Select | Y | 없음 | `swtrmtFcltCd` ← 옵션 value, 라벨 `swtrmtFcltNm` | `useLvNowDmgMtncGnsvy({ level: "3", ctpvNm, sggNm, gnsvyYr })` | > 처리시설은 `bns-if` `useFacilityList`를 **사용하지 않는다**. ### 4-2. 버튼 | 버튼명 | 동작 | | ------ | -------------------------------------------------------- | | 조회 | 필수값 검증 후 `getNowDmgMtncGnsvy` 호출 → 영역 C·D 갱신 | | 닫기 | Dialog 종료 (부모 미반영) | ### 4-3. `lvNowDmgMtncGnsvy` level 캐스케이드 | 트리거 | Request `level` | Request 파라미터 | UI에 쓰는 응답 | 옵션 추출 | | --------- | --------------- | ---------------------------- | --------------- | ------------------------------------------------------------------------------ | | 시도 선택 | `"1"` | `ctpvNm` | (하위 초기화용) | 연도·처리시설 Select 리셋. 구군은 `findGugunCombo` | | 구군 선택 | `"2"` | `ctpvNm`, `sggNm` | 연도 Select | 트리에서 `level === 3` 노드의 `gnsvyYr` | | 연도 선택 | `"3"` | `ctpvNm`, `sggNm`, `gnsvyYr` | 처리시설 Select | 선택 연도(`level === 3`) 노드의 `children[]` → `swtrmtFcltCd` / `swtrmtFcltNm` | 상위 변경 시 하위 선택값·옵션을 RESET한다 (시도→구군·연도·시설 / 구군→연도·시설 / 연도→시설). --- ## 5. 영역 B — 기본계획파일 ### 5-1. 트리 (B-1) | 표시명 | Field | 비고 | | ------ | --------------- | ------------------------ | | 분류명 | `clsfSystmNm` | `ClsfSystmResponseDto` | | 노드키 | `clsfSystmSn` | 선택 시 파일 목록 조회 | | 상위키 | `upClsfSystmSn` | 클라이언트에서 트리 조립 | | 정렬 | `sortSeq` | | | 경로 | `path` | | - 조회 파라미터: `clsfSystmNm` = 선택 구군명(레거시와 동일). `upClsfSystmSn`은 하위 전개 시 TBD. - 시도·구군 미선택 시: 「시도와 구군을 선택하세요.」 안내. ### 5-2. 파일 목록 (B-2) | 표시명 | Field | 비고 | | ------ | ----- | ------------------------------------------------------------------- | | 파일명 | TBD | `getFile` Response DTO가 `unknown` — 백엔드 스키마 확정 후 매핑 | | (기타) | TBD | 레거시: 트리 선택 후 목록 표시, 클릭 시 `fileprcs` → `fileDownload` | ### 5-3. 버튼·상호작용 | 동작 | 설명 | | -------------- | -------------------------------------------------------------- | | 트리 노드 클릭 | `getFile({ clsfSystmSn, … })` → B-2 목록 | | 파일 클릭 | `getFilePrcs(fileSn)` → `fileDownload({ filePath, fileName })` | | 빈 목록 | 「트리에서 항목을 선택하세요.」 / 「파일이 없습니다.」 | --- ## 6. 영역 C — 총설 ### 6-1. 테이블 구조 | 행(구분) | 열 매핑 (당초1~~4 / 기준 / 변경1~~4) | | ------------ | ------------------------------------------------------------------------------ | | 계획목표년도 | `planYrDt1planYrDt4` ~~/~~ `planYr` ~~/~~ `planYrDc1planYrDc4` (+ `년` 접미사) | - 헤더: 당초(1~~4단계) · 기준 · 변경(1~~4단계) - 데이터 소스: `getNowDmgMtncGnsvy` 응답 배열의 **첫 번째** 요소 - 읽기 전용 --- ## 7. 영역 D — 처리구역별 현황 ### 7-1. 행 정의 (표시명 → Field 접두사) 각 행은 `Dt1Dt4` ~~/ (접미사 없음=기준) /~~ `Dc1Dc4` 셀로 표시한다. 숫자는 천단위 콤마, 없으면 `-`. | 표시명 | Field 접두사 | 비고 | | ------------------------ | -------------------- | ---------------------------------------------- | | 하수처리인구(인) | `swtrmtPpltnCnt` | | | 자연적하수처리인구수(인) | `natrSwtrmtPpltnCnt` | | | 사회적하수처리인구수(인) | `scilSwtrmtPpltnCnt` | | | 하수처리구역면적 | `swtrmtZoneArea` | | | 물사용량원단위 | `wtrUsqtyOrgnUnit` | | | 오수전환율(%) | `drtwSwtcRt` | | | 변동부하율(%) | `flctnLodRt` | | | 오수원단위 | `drtwOrgnUnit` | | | 계획하수량합계(㎥/일) | `planSwageQntSum` | | | 생활오수(㎥/일) | `lvngDrtwSum` | | | 지하수(㎥/일) | `ugwtSum` | | | 공장폐수(㎥/일) | `fctryWwtSum` | | | 관광오수(㎥/일) | `toursmDrtwSum` | | | 군부대(㎥/일) | `mtbsSum` | | | 연계처리수(㎥/일) | `linkPrcsCntSum` | | | 기타오수(㎥/일) | `etcDrtwSum` | | | 지하수사용량(㎥/일) | `ugwtUseSum` | | | 시설용량(㎥/일) | `fcltCpctSum` | | | 배제방식 | `exclsMethExpln` | 문자열; 단계별 `*Dt*`/`*Dc*` 존재 시 동일 규칙 | 헤더 3행째 연도: 영역 C와 동일하게 `planYrDt*` / `planYr` / `planYrDc*` 표시. --- ## 8. API/DTO 명세 ### 8-1. 공통 | 항목 | 값 | | --------------- | ---------------------------------------------------- | | DC Base | `/dc-service/api/v1` (`ENDPOINT.DC_SERVICE`) | | AS adstdstr | `/as-service/api/v1/adstdstr` | | 클라이언트 모듈 | `@/entities/dc` (`dcService`), `@/entities/adstdstr` | > 영역 A 처리시설은 `bns-if`를 사용하지 않음. ### 8-2. 시도·구군 콤보 (non-DC) | 기능 | Method | URL | Request DTO | Response DTO | API | | -------- | ------ | ----------------------------------- | ------------------------ | -------------------------------- | ---------------------------------------------------------- | | 시도목록 | GET | `/as-service/api/v1/adstdstr/sido` | — | `CmCdAdstDstrComboResponseDto[]` | `cmCdAdstDstrService.findSidoCombo` / `useFindSidoCombo` | | 구군목록 | GET | `/as-service/api/v1/adstdstr/gugun` | Query: `sido` (시도코드) | `CmCdAdstDstrComboResponseDto[]` | `cmCdAdstDstrService.findGugunCombo` / `useFindGugunCombo` | ### 8-3. 연도·처리시설 계층 조회 — DC | 기능 | Method | URL | Request DTO | Response DTO | API | | --------------- | ------ | -------------------------------------- | ---------------------------- | -------------------------------- | --------------------------------------------------------- | | 계층형 계획목록 | GET | `/dc-service/api/v1/lvNowDmgMtncGnsvy` | `LvNowDmgMtncGnsvySearchDto` | `LvNowDmgMtncGnsvyResponseDto[]` | `dcService.getLvNowDmgMtncGnsvy` / `useLvNowDmgMtncGnsvy` | 연도 Select·처리시설 Select는 **각각** `useLvNowDmgMtncGnsvy`를 호출한다 (`level`만 다르게). **Request (**`LvNowDmgMtncGnsvySearchDto`**)** | 필드 | 시도(`level=1`) | 구군→연도(`level=2`) | 연도→시설(`level=3`) | | --------- | --------------- | -------------------- | -------------------- | | `level` | `"1"` | `"2"` | `"3"` | | `ctpvNm` | 필수 | 필수 | 필수 | | `sggNm` | — | 필수 | 필수 | | `gnsvyYr` | — | — | 필수 | **Response 노드 필드 (**`LvNowDmgMtncGnsvyResponseDto`**, 부분 optional)** | 필드 | 등장 level | 설명 | | -------------- | ---------- | ------------------------ | | `level` | 1~3 | 계층 깊이 | | `ctpvNm` | 1 | 시도명 | | `sggNm` | 2 | 구군명 | | `gnsvyYr` | 3 | 연도 → 연도 Select value | | `swtrmtFcltCd` | 시설(리프) | 처리시설 코드 | | `swtrmtFcltNm` | 시설(리프) | 처리시설명 | | `children` | 1~3 | 하위 노드 배열 | > **TBD**: 현재 `useLvNowDmgMtncGnsvy` `enabled`가 `level && ctpvNm && sggNm && gnsvyYr`로 고정되어 `level=1`/`2` 호출이 막힘. level별 필수 파라미터만 검사하도록 수정 필요. > > 예: `level=1` → `ctpvNm` / `level=2` → `ctpvNm && sggNm` / `level=3` → `ctpvNm && sggNm && gnsvyYr` ### 8-4. 기본계획 수치 조회 — DC | 기능 | Method | URL | Request DTO | Response DTO | API | | ---------------- | ------ | ------------------------------------ | -------------------------- | ------------------------------ | ----------------------------------------------------- | | 현재·단계별 수치 | GET | `/dc-service/api/v1/nowDmgMtncGnsvy` | `NowDmgMtncGnsvySearchDto` | `NowDmgMtncGnsvyResponseDto[]` | `dcService.getNowDmgMtncGnsvy` / `useNowDmgMtncGnsvy` | **Request (**`NowDmgMtncGnsvySearchDto`**)** | 필드 | 매핑 | | -------------- | ----------------------- | | `swtrmtFcltCd` | 영역 A 처리시설 | | `ctpvNm` | 영역 A 시도 표시명 | | `sggNm` | 영역 A 구군 표시명 | | `targetYear` | 영역 A 연도 (`gnsvyYr`) | **Response**: 지표 필드 + `Dt1Dt4` ~~/~~ `Dc1Dc4` 접미사 스테이지 필드 (`NowDmgMtncGnsvyResponseDto`). UI는 `data[0]` 사용. ### 8-5. 분류체계 — DC | 기능 | Method | URL | Request DTO | Response DTO | API | | ------------ | ------ | ------------------------------ | -------------------- | ------------------------ | ----------------------------------------- | | 분류트리조회 | GET | `/dc-service/api/v1/clsfSystm` | `ClsfSystmParamsDto` | `ClsfSystmResponseDto[]` | `dcService.getClsfSystm` / `useClsfSystm` | **Request**: `clsfSystmNm?`, `upClsfSystmSn?` **Response**: `clsfSystmSn`, `upClsfSystmSn`, `clsfSystmNm`, `sortSeq`, `droppAble`, `path` > 레거시 경로 `/clsf` → 현재 클라이언트는 `/clsfSystm`. ### 8-6. 파일 목록·처리·다운로드 — DC | 기능 | Method | URL | Request DTO / Params | Response DTO | API | | ------------ | ------ | --------------------------------- | ------------------------------------------------------- | ----------------- | -------------------------------------------- | | 파일목록 | GET | `/dc-service/api/v1/file` | `FileParamsDto` (`sort?`, `clsfSystmSn?`, `vetPrcsYn?`) | `unknown` **TBD** | `dcService.getFile` / `useFile` | | 파일처리정보 | GET | `/dc-service/api/v1/fileprcs` | Query: `fileSn` | `unknown` **TBD** | `dcService.getFilePrcs` / `useFilePrcs` | | 파일다운로드 | POST | `/dc-service/api/v1/fileDownload` | `FileDownloadParamsDto` (`filePath?`, `fileName?`) | `unknown` **TBD** | `dcService.fileDownload` / `useFileDownload` | > **TBD**: 파일 관련 Response 스키마·다운로드 blob/헤더 처리·`fileDownload` POST body vs query 전달 방식은 백엔드/게이트웨이 확인 후 확정. --- ## 9. UI 구현 가이드 ### 9-1. 기술 스택·원칙 - UI: `@common/components` — `Dialog`, `Select`, `Button`, `Table`, `Skeleton` - 상태: Dialog 로컬 state + React Query (`entities/dc`, `adstdstr`) - 영역 A 연도·처리시설: `useLvNowDmgMtncGnsvy`를 level별 **두 번**(또는 시도 포함 시 세 번) 호출 - 테이블: 읽기 전용 고정 행 → `@tanstack/react-table` / `DataTable` **불필요** - 트리: jsTree 미사용 — 재귀 들여쓰기 트리 - 번들: `PreviousPlanLookupDialog`는 outline에서 `next/dynamic` 로드 권장 - 부모 폼: **수치 미반영** (조회·다운로드 only) - 1차 구현 시 DC 미연동이면 `@faker-js/faker` mock + TODO → 이후 `dcService` 훅으로 교체 ### 9-2. 앱·파일 배치 | 구분 | 경로 | | ------------ | ------------------------------------------------------------------------ | | 진입 버튼 | `pages/sewer-bsc-plan/ui/sections/outline-form-section.tsx` | | Dialog | `pages/sewer-bsc-plan/ui/previous-plan-lookup-dialog.tsx` | | 필터 | `pages/sewer-bsc-plan/ui/previous-plan/previous-plan-search-filters.tsx` | | 파일 | `pages/sewer-bsc-plan/ui/previous-plan/previous-plan-file-section.tsx` | | 총설 | `pages/sewer-bsc-plan/ui/previous-plan/previous-plan-summary-table.tsx` | | 처리구역 | `pages/sewer-bsc-plan/ui/previous-plan/previous-plan-area-table.tsx` | | 셀 매핑 유틸 | `pages/sewer-bsc-plan/lib/previous-plan-table-utils.ts` | | mock(선택) | `pages/sewer-bsc-plan/lib/previous-plan-mock.ts` | | DC entity | `entities/dc/api/dc-service.ts`, `queries.ts`, `model/dc-interface.ts` | | 레거시 참조 | `adssNewOld/.../cmmn/bscPlnPopup.jsp` | ### 9-3. 영역별 UI 매핑 | 영역 | 컴포넌트 | 데이터 | | ---- | ------------------------------ | -------------------------------------------------------------- | | A | `previous-plan-search-filters` | adstdstr + `useLvNowDmgMtncGnsvy`(level 1·2·3) | | B | `previous-plan-file-section` | `useClsfSystm` + `useFile` + `useFilePrcs` + `useFileDownload` | | C | `previous-plan-summary-table` | `useNowDmgMtncGnsvy` / 조회 결과 state | | D | `previous-plan-area-table` | 동일 | ### 9-4. 다이얼로그·라우팅 | 항목 | 내용 | | ------------ | ------------------------------------------------------------------------ | | 다이얼로그명 | `PreviousPlanLookupDialog` / 타이틀 `기본 계획 찾기` | | 오픈 | 사업개요 `[이전기본계획조회]` | | 라우트 | 없음 (모달). 부모: `/sewer-bsc-plan/regist`, `/sewer-bsc-plan/[id]/edit` | | 선택 반영 | 없음 | ### 9-5. 데이터 흐름 (구현 요약) ``` BEGIN ON [이전기본계획조회] CLICK DO OPEN PreviousPlanLookupDialog (sido/gugun 프리필) END ON ON 시도 CHANGE DO CALL findGugunCombo CALL getLvNowDmgMtncGnsvy(level=1) RESET 연도·처리시설 END ON ON 구군 CHANGE DO CALL getLvNowDmgMtncGnsvy(level=2) // → 연도 옵션 CALL getClsfSystm RESET 처리시설 END ON ON 연도 CHANGE DO CALL getLvNowDmgMtncGnsvy(level=3) // → 처리시설 옵션 END ON ON [조회] CLICK DO VALIDATE CALL getNowDmgMtncGnsvy DISPLAY 영역 C · 영역 D END ON ON 트리 노드 / 파일 CLICK DO CALL getFile → getFilePrcs → fileDownload // Response TBD END ON END ``` --- ## 10. 미확정 (TBD) 추적 | ID | 항목 | 비고 | | --- | -------------------------------------------------------- | -------------------------------------------------------------------- | | T1 | `useLvNowDmgMtncGnsvy` enabled을 level별 필수값으로 분기 | `1`: ctpvNm / `2`: +sggNm / `3`: +gnsvyYr | | T2 | `getFile` / `getFilePrcs` / `fileDownload` Response DTO | 현재 `unknown` | | T3 | 파일 다운로드 UX (blob, Content-Disposition, 게이트웨이) | 레거시 apigateway 직접 호출과 차이 | | T4 | `clsfSystm`의 `upClsfSystmSn` 점진 로드 여부 | flat 목록 vs 계층 API | | T5 | 1차 mock vs 즉시 `dcService` 실연동 | 마이그레이션 플랜은 mock 우선, entity는 준비됨 | | T6 | 부모 폼 수치 반영 | 요구 없음(레거시 동일). 요청 시 별도 스펙 | | T7 | `level=1` 응답 UI 활용 여부 | 시도 선택 시 호출하나 구군은 adstdstr — 응답은 캐시·검증용일 수 있음 |