10.4 KB · 수정 2026-08-05 08:31
목차

2026-08-04 세션 — PFS 사이트맵(테스트/운영 테크트리) 신규

페페 지시: "pfs의 테스트 서버, 운영 서버 사이트 맵을 각각 만들어라. 사이드 메뉴로 두 맵을 넘나들수 있게 하고 다이어그램 형식, 테크트리의 개념이다. 각 그룹별 펼침/접기 기능 달아주고 전체 펼침, 전체 접기 기능도 추가해라. 운영서버에 반영 안된 항목은 주황색 배경으로 표시해라." + 추가 지시 "만든 항목은 pfs 기획서 링크로 연결해."

🆕 2차 지시(같은 날): "가로형 트리맵 형태로 변경해줘. 큰 제목만 표기하고 상세내용은 클릭시 팝업으로 보이기. 다이어그램형태로 PFS 제목부터 관계도로 연결해줘." → 아래 «2차 — 가로형 관계도» 절.

무엇

지도의 원천 — 손으로 적은 값 0

원천 수집 방법
그룹·페이지 이름·사이드바 노출 두 RDS menu_catalog dump_menu_catalog.pyssm_run.py(EC2 경유, 운영 RDS는 로컬 직결 불가)
실제 존재하는 화면 두 브랜치 소스 git archive origin/master / origin/deploy-live → Blueprint·@route·render_template 파싱
화면이 쓰는 API api/config.py add_namespace + 컨트롤러 @api.route 템플릿·JS 에서 호출 리터럴 역추적

트리 = 그룹 → 페이지 → API 엔드포인트 3단. 실측 결과 그룹 8 · 페이지 49 · API 893 · 사이드바 노출 21.

운영 미반영 판정

커밋 수가 아니라 화면 뒷단 파일 내용 해시 비교(playbook §2 — 07-27 파일단위 포워드 탓 patch-id 비교가 28건으로 부풀려진 전례). 페이지의 뒷단 = 컨트롤러 + 템플릿(+모바일 분기) + 그 템플릿이 부르는 static js/css + 연결 API 모듈.

🔑 트리에 안 걸리는 미반영 파일은 따로 열거(화면 밖 미반영 파일 절, 24건 = 공통 유틸 리팩토링·patch44 마이그· 검증 스크립트). 이걸 안 적으면 "미반영 2"가 리포 전체 미반영으로 오독된다 — 지도가 거짓말하는 지점이었다.

화면 기능

사이드 메뉴 🧪 테스트 서버 맵 / 🚀 운영 서버 맵 전환(상단 토글과 동기) · 그룹 헤더 클릭 = 그룹 접기/펼침 · 페이지 클릭 = API 목록 접기/펼침 · 전체 펼침/전체 접기 · 미반영만 필터 · 메뉴·URL 검색. 운영 맵은 운영에 없는 화면(new)을 빼고 그리고 미반영 배지·주황을 쓰지 않는다(운영엔 미반영이라는 개념이 없다).

검증

함정 4 (다음에 또 밟는다)

  1. 라우트 URL 의 <int:no> 가 HTML 태그로 먹힌다innerHTML 에 그냥 넣으면 /api/x/<int:no>/excel/api/x//excel 로 보인다. 트리 렌더는 전부 esc() 경유.
  2. render_template 인자가 다음 줄에 있으면 줄 단위 파싱이 놓친다(견적 v2 3화면이 전부 그 꼴) → 함수 본문을 통째 이어붙여 정규식. 한 함수가 모바일/데스크톱 템플릿 2개를 렌더하는 것도 있다(omc) → 리스트로 받는다.
  3. JS 의 API 호출은 apiURL() 직호출이 아니다 — 화면마다 지역 래퍼(dcApi(path) / api(method, path))로 한 번 더 감싼다. 별칭을 안 따라가면 페이지 절반이 "API 0개"로 나온다. 메서드 인자('GET')를 경로로 오독하지 않게 앞의 대문자 문자열 하나는 건너뛴다.
  4. 🔴 별칭 정규식의 본문은 lookahead 로만 봐야 한다 — 소비하면 바깥 래퍼(function bootstrap(){ try { function api(…)가 안쪽 진짜 별칭을 통째로 먹어 한 파일에서 별칭이 하나만 잡힌다(admin JS 가 실제 그 꼴). 증상이 "이 페이지만 API 0"이라 원인이 안 보인다.

갱신 방법

cd C:\dev\pfs
python tools/sitemap/build_sitemap.py --dump   # RDS 덤프부터 새로(SSM, 배포 후엔 이걸로)
python tools/sitemap/build_sitemap.py          # 캐시된 덤프로 HTML만 재생성
python tools/sitemap/build_sitemap.py --selftest

안 한 것


2차 — 가로형 관계도로 교체 (같은 날, master ad705e3)

세로 아코디언(그룹 카드 안에 페이지 목록) → PFS 루트에서 오른쪽으로 뻗는 관계도로 전면 교체. 데이터·빌더 로직은 손대지 않았다sitemap_template.html 만 다시 썼다.

모양

PFS ─┬─ 견적서 (10) ⓘ
     ├─ 현장 (17) ● ⓘ ──┬─ AL발주서 (8)
     │                   ├─ 대화방 수집관리 (4)
     │                   └─ …
     ├─ … 8개 그룹
     ├─ 공용 API (11)
     └─ 화면 밖 미반영 파일 (28) ●

클릭 규약 (충돌을 피해 셋으로 나눴다)

대상 클릭 결과
페이지 노드 노드 상세 팝업 — URL·그룹·메뉴키·배포상태·설명·뒷단 파일·연결 API 전량
그룹 노드 노드 본체 접기/펼치기
그룹 노드 그룹 요약 팝업(페이지·사이드바·API 합계·미반영 수 + 페이지 버튼 → 상세로 이동)
루트 PFS 노드 서버 메타(브랜치·HEAD·uwsgi·menu_catalog·테이블·반대편 HEAD)

🔑클릭 하나에 기능 둘을 걸 수 없다 — "클릭=팝업"과 "클릭=접기"가 충돌해서, 접기는 노드 본체·요약은 ⓘ로 분리했다. .info 핸들러에서 stopPropagation() 안 하면 팝업과 동시에 그룹이 접힌다(실측 후 추가).

커넥터 = 순수 CSS (JS 좌표계산 0)

.tm li { display:flex; align-items:center; }      /* 노드가 자식 묶음의 세로 중앙에 온다 */
.tm ul ul > li::before { left:-22px; top:0; bottom:0; border-left }   /* 세로 트렁크 */
.tm ul ul > li:first-child::before { top:50% }    /* 위 잘라내기 */
.tm ul ul > li:last-child::before  { bottom:50% } /* 아래 잘라내기 */
.tm ul ul > li::after  { left:-22px; top:50%; width:22px; border-top } /* 가로 엘보 */
.tm ul ul::before      { left:0; top:50%; width:22px; border-top }     /* 부모→트렁크 스텁 */

align-items:center 덕에 top:50% 가 정확히 노드 중심이라 SVG·리사이즈 리스너가 필요 없다. 접기는 li.collapsed > ul { display:none } 한 줄.

🔑 기본 상태 = 전부 접힘

처음엔 전부 펼침으로 뒀더니 49개가 세로로 늘어져 뿌리(PFS)가 화면 밖으로 밀려났다 — 관계도가 아니라 긴 목록이 된다. 기본을 접힘으로 바꾸니 PFS→그룹 10개가 한 화면(다이어그램 높이 571px)에 들어온다. 「전체 펼침」은 버튼으로 남겼다.

함정

검증 (실브라우저, 콘솔 오류 0)