[{"data":1,"prerenderedAt":43907},["ShallowReactive",2],{"docs:all":3},[4,4346,4909,5764,9024,9194,9913,12024,15233,15526,15999,16294,16704,17369,17644,19552,22257,22794,24055,26817,28156,28967,30124,30346,31985,32517,35253],{"id":5,"title":6,"body":7,"description":423,"extension":4340,"meta":4341,"navigation":3338,"path":4342,"seo":4343,"stem":4344,"__hash__":4345},"docs\u002FADMIN-PLAN.md","관리자(malgn-helper-admin) 기획서",{"type":8,"value":9,"toc":4261},"minimark",[10,20,32,35,40,53,97,114,116,120,134,214,219,369,378,382,401,408,410,414,424,428,454,458,481,486,489,657,661,664,796,800,903,907,1025,1029,1032,1136,1140,1146,1150,1184,1191,1194,1200,1202,1206,1212,1218,1223,1240,1245,1256,1262,1268,1270,1276,1281,1339,1344,1386,1396,1401,1444,1449,1493,1498,1506,1508,1514,1518,1529,1612,1621,1789,1798,1801,1907,1919,1924,1963,1967,1974,1980,1988,2018,2025,2034,2039,2100,2105,2119,2126,2129,2181,2184,2201,2205,2262,2264,2270,2274,2311,2316,2329,2333,2359,2361,2372,2376,2387,2395,2397,2406,2418,2422,2489,2494,2500,2505,2513,2518,2544,2546,2550,2564,2569,2598,2603,2609,2614,2625,2630,2650,2655,2679,2681,2689,2693,2707,2711,2719,2721,2729,2741,2744,2752,2754,2760,2765,2802,2812,2818,2820,2826,2840,2842,2848,2871,2873,2879,2905,2907,2913,2917,2931,2935,2949,2955,2957,2961,2965,3117,3121,3154,3158,3234,3241,3243,3247,3251,3262,3285,3289,3292,3560,3563,3674,3676,3680,3685,3689,3722,3728,3732,3759,3769,3773,3788,3796,3800,3829,3834,3838,3863,3868,3870,3874,3912,3914,3918,4131,4135,4248,4250,4254,4257],[11,12,14,15,19],"h1",{"id":13},"관리자malgn-helper-admin-기획서","관리자(",[16,17,18],"code",{},"malgn-helper-admin",") 기획서",[21,22,23],"blockquote",{},[24,25,26,27,31],"p",{},"최종 현행화 — 2026-06-08 · ",[28,29,30],"strong",{},"맑은소프트 직원 전용"," (협력사 미고려) · 3 역할(관리자·개발자·상담사) · 챗봇 도입 전 필요한 전부 + 설정·계정 포함 MVP",[33,34],"hr",{},[36,37,39],"h2",{"id":38},"_1-목적","1. 목적",[24,41,42,44,45,48,49,52],{},[16,43,18],{},"은 CS 챗봇(",[16,46,47],{},"malgn-helper",")이 정상 동작하기 위한 ",[28,50,51],{},"자산 큐레이션과 운영 도구","를 담는다.",[54,55,56,63,69,79,85,91],"ul",{},[57,58,59,62],"li",{},[28,60,61],{},"자료 자산",": 매뉴얼·PDF·동영상 등 챗봇이 답변 근거로 삼을 원본 문서",[57,64,65,68],{},[28,66,67],{},"표준답변 자산",": 검증된 한국어 답변(1순위 소스)",[57,70,71,74,75,78],{},[28,72,73],{},"이미지 자산",": 게시물·답변에서 추출되어 자동 캡션된 화면 자산 (",[16,76,77],{},"hp_image_asset",")",[57,80,81,84],{},[28,82,83],{},"운영 모니터링",": LLM 비용·Q&A 평가·챗 로그·에스컬레이션",[57,86,87,90],{},[28,88,89],{},"설정",": 모델·시스템 프롬프트·캐싱·안전 가드",[57,92,93,96],{},[28,94,95],{},"계정·권한",": 운영자\u002F상담사 분리",[21,98,99],{},[24,100,101,102,105,106,109,110,113],{},"기존 PMS의 ",[16,103,104],{},"\u002Fadmin\u002Fcost",", ",[16,107,108],{},"\u002Fadmin\u002Fevals"," 페이지는 ",[28,111,112],{},"유지"," — 상담사가 PMS 흐름 안에서 보던 경험을 끊지 않는다. admin은 같은 데이터를 운영자 관점으로 재구성해 제공.",[33,115],{},[36,117,119],{"id":118},"_2-사용자역할","2. 사용자·역할",[24,121,122,125,126,129,130,133],{},[28,123,124],{},"전제"," — 맑은소프트 직원 전용. 협력사·고객사는 admin 접근 불가. 식별은 ",[16,127,128],{},"@malgnsoft.com"," 이메일 + 메모리에 등록된 직원 룰(",[16,131,132],{},"tb_user.company='맑은소프트'",").",[135,136,137,156],"table",{},[138,139,140],"thead",{},[141,142,143,147,150,153],"tr",{},[144,145,146],"th",{},"역할",[144,148,149],{},"약자",[144,151,152],{},"주요 책임",[144,154,155],{},"핵심 화면",[157,158,159,178,196],"tbody",{},[141,160,161,167,172,175],{},[162,163,164],"td",{},[28,165,166],{},"관리자",[162,168,169],{},[16,170,171],{},"admin",[162,173,174],{},"시스템 전반 책임, 계정·예산·정책 결정",[162,176,177],{},"모든 화면",[141,179,180,185,190,193],{},[162,181,182],{},[28,183,184],{},"개발자(기술 지원)",[162,186,187],{},[16,188,189],{},"developer",[162,191,192],{},"자료 인덱싱·AI 설정·캐싱·연동·이미지 큐레이션",[162,194,195],{},"자료·이미지·설정·로그·통계",[141,197,198,203,208,211],{},[162,199,200],{},[28,201,202],{},"상담사",[162,204,205],{},[16,206,207],{},"agent",[162,209,210],{},"표준답변 제안·에스컬레이션 처리·챗 로그 검토",[162,212,213],{},"표준답변·에스컬레이션·챗 로그·이미지 조회",[215,216,218],"h3",{"id":217},"_2-1-권한-매트릭스","2-1. 권한 매트릭스",[135,220,221,236],{},[138,222,223],{},[141,224,225,228,231,234],{},[144,226,227],{},"액션",[144,229,166],{"align":230},"center",[144,232,233],{"align":230},"개발자",[144,235,202],{"align":230},[157,237,238,251,262,274,289,301,312,323,334,345,356],{},[141,239,240,243,246,248],{},[162,241,242],{},"자료 업로드·재인덱싱·삭제",[162,244,245],{"align":230},"✅",[162,247,245],{"align":230},[162,249,250],{"align":230},"❌",[141,252,253,256,258,260],{},[162,254,255],{},"자료 조회",[162,257,245],{"align":230},[162,259,245],{"align":230},[162,261,245],{"align":230},[141,263,264,267,269,271],{},[162,265,266],{},"표준답변 등록·편집",[162,268,245],{"align":230},[162,270,245],{"align":230},[162,272,273],{"align":230},"✅ (제안)",[141,275,276,283,285,287],{},[162,277,278,279,282],{},"표준답변 ",[28,280,281],{},"승인","·반려·삭제",[162,284,245],{"align":230},[162,286,245],{"align":230},[162,288,250],{"align":230},[141,290,291,294,296,298],{},[162,292,293],{},"이미지 카탈로그 편집·태깅·숨김",[162,295,245],{"align":230},[162,297,245],{"align":230},[162,299,300],{"align":230},"❌ (조회만)",[141,302,303,306,308,310],{},[162,304,305],{},"챗 로그 열람",[162,307,245],{"align":230},[162,309,245],{"align":230},[162,311,245],{"align":230},[141,313,314,317,319,321],{},[162,315,316],{},"에스컬레이션 처리",[162,318,245],{"align":230},[162,320,245],{"align":230},[162,322,245],{"align":230},[141,324,325,328,330,332],{},[162,326,327],{},"AI 설정·안전 가드·캐싱",[162,329,245],{"align":230},[162,331,245],{"align":230},[162,333,250],{"align":230},[141,335,336,339,341,343],{},[162,337,338],{},"외부 연동(Slack·이메일)",[162,340,245],{"align":230},[162,342,245],{"align":230},[162,344,250],{"align":230},[141,346,347,350,352,354],{},[162,348,349],{},"계정 초대·역할 변경·비활성",[162,351,245],{"align":230},[162,353,250],{"align":230},[162,355,250],{"align":230},[141,357,358,361,363,366],{},[162,359,360],{},"감사 로그 열람",[162,362,245],{"align":230},[162,364,365],{"align":230},"✅ (자기 + 시스템)",[162,367,368],{"align":230},"❌ (자기 것만)",[21,370,371],{},[24,372,373,374,377],{},"개발자와 관리자는 운영 책임을 공유한다. 차이는 ",[28,375,376],{},"계정 관리·예산 정책"," 한정.",[215,379,381],{"id":380},"_2-2-역할-결정-흐름","2-2. 역할 결정 흐름",[54,383,384,389,398],{},[57,385,386,387],{},"가입 시 기본 ",[16,388,207],{},[57,390,391,392,394,395,397],{},"관리자가 ",[16,393,189],{}," 또는 ",[16,396,171],{},"으로 승격",[57,399,400],{},"초대 링크에는 역할 미리 지정 가능 (관리자만 발급)",[24,402,403,404,407],{},"API 측 미들웨어: ",[16,405,406],{},"requireRole('admin' | 'developer' | 'agent' | { any: [...] })",".",[33,409],{},[36,411,413],{"id":412},"_3-정보-구조-ia","3. 정보 구조 (IA)",[415,416,421],"pre",{"className":417,"code":419,"language":420},[418],"language-text","malgn-helper-admin.pages.dev\n├─ \u002F                          홈 · 전체 KPI 대시보드 · 최근 활동\n├─ \u002Flogin                     로그인 (구글 OAuth 또는 자체)\n│\n├─ \u002Fmaterials                 자료 ───────────────────────────────────\n│  ├─ \u002Fmaterials              목록 (검색·필터·인덱싱 상태)\n│  ├─ \u002Fmaterials\u002Fupload       업로드 (드래그앤드롭 + 메타 입력)\n│  └─ \u002Fmaterials\u002F:id          상세 (원본 다운로드·재인덱싱·삭제)\n│\n├─ \u002Fstandard-answers          표준답변 ─────────────────────────────────\n│  ├─ \u002Fstandard-answers       목록 (검색·태그·사용량·승인 상태)\n│  ├─ \u002Fstandard-answers\u002F:id   상세·편집 (질문 패턴 \u002F 답변 HTML \u002F 사용량)\n│  └─ \u002Fstandard-answers\u002Fsuggestions  자동 추출 후보 (LLM이 제안)\n│\n├─ \u002Fimages                    이미지 카탈로그 ─────────────────────────\n│  ├─ \u002Fimages                 목록 (썸네일 그리드, title·description 검색)\n│  └─ \u002Fimages\u002F:id             상세 (메타·사용 게시물 역추적·태그·숨김)\n│\n├─ \u002Fchat-logs                 챗봇 응답 로그 ──────────────────────────  (Phase 2 준비)\n│  ├─ \u002Fchat-logs              세션 목록 (사용자·시각·답변 수·만족도)\n│  └─ \u002Fchat-logs\u002F:sessionId   세션 상세 (메시지 흐름·인용 출처·피드백)\n│\n├─ \u002Funcovered                 미커버 질문 큐 ──────────────────────────  (Phase 2 준비, 별도 페이지)\n│  └─ \u002Funcovered\u002F:id          상세 + AI 초안 생성 + 표준답변·자료 연결\n│\n├─ \u002Fescalations               에스컬레이션 큐 ────────────────────────  (Phase 2 준비)\n│  ├─ \u002Fescalations            대기 큐 (질문·신뢰도·우선순위)\n│  └─ \u002Fescalations\u002F:id        처리 (상담사 답변 작성·표준답변 등록)\n│\n├─ \u002Fqa-evals                  Q&A 평가 (PMS와 병행) ──────────────────\n│  ├─ \u002Fqa-evals               목록 (= PMS \u002Fadmin\u002Fevals 동일)\n│  └─ \u002Fqa-evals\u002F:id           상세 (= QaEvalCard 모달)\n│\n├─ \u002Fcost                      LLM 비용 (PMS와 병행) ──────────────────\n│  └─ \u002Fcost                   대시보드 (= PMS \u002Fadmin\u002Fcost 동일)\n│\n├─ \u002Fsettings                  설정 ─────────────────────────────────────\n│  ├─ \u002Fsettings\u002Fai            AI 설정 (모델·온도·맥스토큰·시스템 프롬프트)\n│  ├─ \u002Fsettings\u002Fsafety        안전 가드 (PII·금칙어·\"모름\" 임계값)\n│  ├─ \u002Fsettings\u002Fcache         캐싱 (TTL·invalidation 규칙)\n│  └─ \u002Fsettings\u002Fintegrations  외부 연동 (Slack·이메일·티켓)\n│\n└─ \u002Faccounts                  계정·권한 ───────────────────────────────\n   ├─ \u002Faccounts               사용자 목록\n   └─ \u002Faccounts\u002F:id           역할·활성\u002F비활성·감사 로그\n","text",[16,422,419],{"__ignoreMap":423},"",[215,425,427],{"id":426},"_3-1-글로벌-레이아웃","3-1. 글로벌 레이아웃",[54,429,430,436,442,448],{},[57,431,432,435],{},[28,433,434],{},"좌측 사이드바",": 5개 그룹 × 메뉴 (§3-2 참조)",[57,437,438,441],{},[28,439,440],{},"상단바",": 검색 입력 \u002F 환경 토글(개발\u002F운영) \u002F 사용자 메뉴(역할·로그아웃)",[57,443,444,447],{},[28,445,446],{},"본문",": 좌측 패널 240px + 본문, 모바일은 hamburger",[57,449,450,453],{},[28,451,452],{},"디자인 톤",": PMS와 일관 (Tailwind v4 + Pretendard + Notion-clean 라이트 모드 고정)",[215,455,457],{"id":456},"_3-2-사이드바-메뉴-정의","3-2. 사이드바 메뉴 정의",[24,459,460,461,464,465,467,468,471,472,467,474,477,478,480],{},"권한별 가시성 — ",[16,462,463],{},"A","=관리자(",[16,466,171],{},") · ",[16,469,470],{},"D","=개발자(",[16,473,189],{},[16,475,476],{},"S","=상담사(",[16,479,207],{},").\n배지(badge)는 대기·미처리 카운트 등 운영자 주의 환기용. 아이콘은 heroicons 24-outline 기준.",[482,483,485],"h4",{"id":484},"그룹-1-운영-보드","그룹 1. 운영 보드",[24,487,488],{},"가장 자주 보는 작업 큐 — 사이드바 최상단.",[135,490,491,516],{},[138,492,493],{},[141,494,495,498,501,504,507,510,512,514],{},[144,496,497],{},"#",[144,499,500],{},"라벨",[144,502,503],{},"경로",[144,505,506],{},"아이콘",[144,508,509],{},"배지",[144,511,463],{"align":230},[144,513,470],{"align":230},[144,515,476],{"align":230},[157,517,518,545,576,603,630],{},[141,519,520,523,526,531,536,539,541,543],{},[162,521,522],{},"1.1",[162,524,525],{},"홈",[162,527,528],{},[16,529,530],{},"\u002F",[162,532,533],{},[16,534,535],{},"i-heroicons-home",[162,537,538],{},"—",[162,540,245],{"align":230},[162,542,245],{"align":230},[162,544,245],{"align":230},[141,546,547,550,553,558,563,570,572,574],{},[162,548,549],{},"1.2",[162,551,552],{},"미커버 질문",[162,554,555],{},[16,556,557],{},"\u002Funcovered",[162,559,560],{},[16,561,562],{},"i-heroicons-question-mark-circle",[162,564,565,566,569],{},"대기 N건 (",[16,567,568],{},"pending"," 빈도≥3)",[162,571,245],{"align":230},[162,573,245],{"align":230},[162,575,245],{"align":230},[141,577,578,581,584,589,594,597,599,601],{},[162,579,580],{},"1.3",[162,582,583],{},"에스컬레이션",[162,585,586],{},[16,587,588],{},"\u002Fescalations",[162,590,591],{},[16,592,593],{},"i-heroicons-bell-alert",[162,595,596],{},"대기 N건",[162,598,245],{"align":230},[162,600,245],{"align":230},[162,602,245],{"align":230},[141,604,605,608,611,616,621,624,626,628],{},[162,606,607],{},"1.4",[162,609,610],{},"챗봇 로그",[162,612,613],{},[16,614,615],{},"\u002Fchat-logs",[162,617,618],{},[16,619,620],{},"i-heroicons-chat-bubble-left-right",[162,622,623],{},"24h 부정 피드백 N",[162,625,245],{"align":230},[162,627,245],{"align":230},[162,629,245],{"align":230},[141,631,632,635,638,643,648,651,653,655],{},[162,633,634],{},"1.5",[162,636,637],{},"Q&A 평가",[162,639,640],{},[16,641,642],{},"\u002Fqa-evals",[162,644,645],{},[16,646,647],{},"i-heroicons-clipboard-document-check",[162,649,650],{},"점수\u003C3 N건",[162,652,245],{"align":230},[162,654,245],{"align":230},[162,656,245],{"align":230},[482,658,660],{"id":659},"그룹-2-지식-자산","그룹 2. 지식 자산",[24,662,663],{},"챗봇 답변의 근거가 되는 데이터.",[135,665,666,686],{},[138,667,668],{},[141,669,670,672,674,676,678,680,682,684],{},[144,671,497],{},[144,673,500],{},[144,675,503],{},[144,677,506],{},[144,679,509],{},[144,681,463],{"align":230},[144,683,470],{"align":230},[144,685,476],{"align":230},[157,687,688,715,742,770],{},[141,689,690,693,696,701,706,709,711,713],{},[162,691,692],{},"2.1",[162,694,695],{},"표준답변",[162,697,698],{},[16,699,700],{},"\u002Fstandard-answers",[162,702,703],{},[16,704,705],{},"i-heroicons-bookmark-square",[162,707,708],{},"승인 대기 N",[162,710,245],{"align":230},[162,712,245],{"align":230},[162,714,245],{"align":230},[141,716,717,720,723,728,733,736,738,740],{},[162,718,719],{},"2.2",[162,721,722],{},"자료",[162,724,725],{},[16,726,727],{},"\u002Fmaterials",[162,729,730],{},[16,731,732],{},"i-heroicons-document-text",[162,734,735],{},"인덱싱 실패 N",[162,737,245],{"align":230},[162,739,245],{"align":230},[162,741,245],{"align":230},[141,743,744,747,750,755,760,763,765,767],{},[162,745,746],{},"2.3",[162,748,749],{},"이미지 카탈로그",[162,751,752],{},[16,753,754],{},"\u002Fimages",[162,756,757],{},[16,758,759],{},"i-heroicons-photo",[162,761,762],{},"미큐레이션 N",[162,764,245],{"align":230},[162,766,245],{"align":230},[162,768,769],{"align":230},"✅ (조회만)",[141,771,772,775,778,783,788,790,792,794],{},[162,773,774],{},"2.4",[162,776,777],{},"토픽·서비스 카탈로그",[162,779,780],{},[16,781,782],{},"\u002Fcatalog",[162,784,785],{},[16,786,787],{},"i-heroicons-tag",[162,789,538],{},[162,791,245],{"align":230},[162,793,245],{"align":230},[162,795,538],{"align":230},[482,797,799],{"id":798},"그룹-3-분석비용","그룹 3. 분석·비용",[135,801,802,822],{},[138,803,804],{},[141,805,806,808,810,812,814,816,818,820],{},[144,807,497],{},[144,809,500],{},[144,811,503],{},[144,813,506],{},[144,815,509],{},[144,817,463],{"align":230},[144,819,470],{"align":230},[144,821,476],{"align":230},[157,823,824,851,877],{},[141,825,826,829,832,837,842,845,847,849],{},[162,827,828],{},"3.1",[162,830,831],{},"LLM 비용",[162,833,834],{},[16,835,836],{},"\u002Fcost",[162,838,839],{},[16,840,841],{},"i-heroicons-currency-dollar",[162,843,844],{},"예산 ≥80% 시 경고",[162,846,245],{"align":230},[162,848,245],{"align":230},[162,850,538],{"align":230},[141,852,853,856,859,864,869,871,873,875],{},[162,854,855],{},"3.2",[162,857,858],{},"응답 품질 통계",[162,860,861],{},[16,862,863],{},"\u002Fanalytics\u002Fquality",[162,865,866],{},[16,867,868],{},"i-heroicons-chart-bar",[162,870,538],{},[162,872,245],{"align":230},[162,874,245],{"align":230},[162,876,538],{"align":230},[141,878,879,882,885,890,895,897,899,901],{},[162,880,881],{},"3.3",[162,883,884],{},"사용량 통계",[162,886,887],{},[16,888,889],{},"\u002Fanalytics\u002Fusage",[162,891,892],{},[16,893,894],{},"i-heroicons-chart-pie",[162,896,538],{},[162,898,245],{"align":230},[162,900,245],{"align":230},[162,902,538],{"align":230},[482,904,906],{"id":905},"그룹-4-설정","그룹 4. 설정",[135,908,909,927],{},[138,910,911],{},[141,912,913,915,917,919,921,923,925],{},[144,914,497],{},[144,916,500],{},[144,918,503],{},[144,920,506],{},[144,922,463],{"align":230},[144,924,470],{"align":230},[144,926,476],{"align":230},[157,928,929,953,977,1001],{},[141,930,931,934,937,942,947,949,951],{},[162,932,933],{},"4.1",[162,935,936],{},"AI 설정",[162,938,939],{},[16,940,941],{},"\u002Fsettings\u002Fai",[162,943,944],{},[16,945,946],{},"i-heroicons-sparkles",[162,948,245],{"align":230},[162,950,245],{"align":230},[162,952,538],{"align":230},[141,954,955,958,961,966,971,973,975],{},[162,956,957],{},"4.2",[162,959,960],{},"안전 가드",[162,962,963],{},[16,964,965],{},"\u002Fsettings\u002Fsafety",[162,967,968],{},[16,969,970],{},"i-heroicons-shield-check",[162,972,245],{"align":230},[162,974,245],{"align":230},[162,976,538],{"align":230},[141,978,979,982,985,990,995,997,999],{},[162,980,981],{},"4.3",[162,983,984],{},"캐싱",[162,986,987],{},[16,988,989],{},"\u002Fsettings\u002Fcache",[162,991,992],{},[16,993,994],{},"i-heroicons-circle-stack",[162,996,245],{"align":230},[162,998,245],{"align":230},[162,1000,538],{"align":230},[141,1002,1003,1006,1009,1014,1019,1021,1023],{},[162,1004,1005],{},"4.4",[162,1007,1008],{},"외부 연동",[162,1010,1011],{},[16,1012,1013],{},"\u002Fsettings\u002Fintegrations",[162,1015,1016],{},[16,1017,1018],{},"i-heroicons-link",[162,1020,245],{"align":230},[162,1022,245],{"align":230},[162,1024,538],{"align":230},[482,1026,1028],{"id":1027},"그룹-5-시스템","그룹 5. 시스템",[24,1030,1031],{},"사이드바 하단 — 자주 안 쓰는 관리.",[135,1033,1034,1054],{},[138,1035,1036],{},[141,1037,1038,1040,1042,1044,1046,1048,1050,1052],{},[144,1039,497],{},[144,1041,500],{},[144,1043,503],{},[144,1045,506],{},[144,1047,509],{},[144,1049,463],{"align":230},[144,1051,470],{"align":230},[144,1053,476],{"align":230},[157,1055,1056,1083,1109],{},[141,1057,1058,1061,1064,1069,1074,1077,1079,1081],{},[162,1059,1060],{},"5.1",[162,1062,1063],{},"계정",[162,1065,1066],{},[16,1067,1068],{},"\u002Faccounts",[162,1070,1071],{},[16,1072,1073],{},"i-heroicons-users",[162,1075,1076],{},"초대 대기 N",[162,1078,245],{"align":230},[162,1080,538],{"align":230},[162,1082,538],{"align":230},[141,1084,1085,1088,1091,1096,1101,1103,1105,1107],{},[162,1086,1087],{},"5.2",[162,1089,1090],{},"감사 로그",[162,1092,1093],{},[16,1094,1095],{},"\u002Faudit-logs",[162,1097,1098],{},[16,1099,1100],{},"i-heroicons-clipboard-document-list",[162,1102,538],{},[162,1104,245],{"align":230},[162,1106,245],{"align":230},[162,1108,538],{"align":230},[141,1110,1111,1114,1117,1123,1128,1130,1132,1134],{},[162,1112,1113],{},"5.3",[162,1115,1116],{},"API 문서",[162,1118,1119,1122],{},[16,1120,1121],{},"https:\u002F\u002Fmalgn-helper-api.malgnsoft.workers.dev\u002Fdoc"," (외부)",[162,1124,1125],{},[16,1126,1127],{},"i-heroicons-code-bracket",[162,1129,538],{},[162,1131,245],{"align":230},[162,1133,245],{"align":230},[162,1135,538],{"align":230},[215,1137,1139],{"id":1138},"_3-3-사이드바-시각-구조","3-3. 사이드바 시각 구조",[415,1141,1144],{"className":1142,"code":1143,"language":420},[418],"┌─────────────────────────┐\n│  🟢 맑은도우미 관리자       │ ← 로고 + 환경 토글(dev\u002Fprod)\n├─────────────────────────┤\n│  ━━ 운영 보드 ━━━━━━━━━━│\n│  🏠 홈                   │\n│  ❓ 미커버 질문        [12]│ ← 빨강 배지 (pending 큐)\n│  🔔 에스컬레이션        [3]│ ← 노랑 배지\n│  💬 챗봇 로그           [5]│ ← 회색 배지 (24h 부정 피드백)\n│  📋 Q&A 평가            [2]│\n│                          │\n│  ━━ 지식 자산 ━━━━━━━━━━│\n│  🔖 표준답변            [4]│ ← 노랑 (승인 대기)\n│  📄 자료                 │\n│  🖼  이미지 카탈로그     │\n│  🏷  토픽·서비스           │\n│                          │\n│  ━━ 분석·비용 ━━━━━━━━━│\n│  💲 LLM 비용             │\n│  📊 응답 품질            │\n│  🥧 사용량               │\n│                          │\n│  ━━ 설정 ━━━━━━━━━━━━━│\n│  ✨ AI 설정              │\n│  🛡  안전 가드            │\n│  🗄  캐싱                │\n│  🔗 외부 연동            │\n│                          │\n│  ━━ 시스템 ━━━━━━━━━━━│\n│  👥 계정                 │\n│  📜 감사 로그            │\n│  \u003C\u002F> API 문서 ↗         │\n├─────────────────────────┤\n│  👤 김현희 (개발자)        │ ← 사용자 메뉴 (역할·로그아웃)\n└─────────────────────────┘\n",[16,1145,1143],{"__ignoreMap":423},[215,1147,1149],{"id":1148},"_3-4-메뉴-가시성접근-제어-규칙","3-4. 메뉴 가시성·접근 제어 규칙",[54,1151,1152,1162,1172,1178],{},[57,1153,1154,1157,1158,1161],{},[28,1155,1156],{},"숨김 vs 비활성"," — 권한 없는 메뉴는 사이드바에서 ",[28,1159,1160],{},"완전히 숨김"," (메뉴 표 X 표시 항목). 직접 URL 접근 시 API가 403 반환 → admin은 \"권한 없음\" 안내 페이지",[57,1163,1164,1167,1168,1171],{},[28,1165,1166],{},"배지 새로고침"," — 5분마다 폴링 (",[16,1169,1170],{},"GET \u002Fadmin\u002Fbadges"," 응답을 reactive ref에 반영) 또는 라우트 변경 시 갱신",[57,1173,1174,1177],{},[28,1175,1176],{},"그룹 헤더 클릭"," — 그룹 접기\u002F펼치기. 사용자 preference는 localStorage 저장",[57,1179,1180,1183],{},[28,1181,1182],{},"검색"," — 상단바 검색은 전역 검색 (표준답변·자료·이미지·미커버 전체 LIKE) → 결과 페이지에서 카테고리별 필터",[215,1185,1187,1188,1190],{"id":1186},"_3-5-신규-카탈로그-페이지-catalog-그룹-24","3-5. 신규 카탈로그 페이지 — ",[16,1189,782],{}," (그룹 2.4)",[24,1192,1193],{},"토픽·서비스 카탈로그 한 페이지에서 통합 관리. 운영자가 자주 추가하지는 않지만 잘못된 분류 정정용으로 진입.",[415,1195,1198],{"className":1196,"code":1197,"language":420},[418],"[탭] 토픽(11) | 서비스(6)\n\n토픽 탭:\n[+ 새 토픽]\nslug         scope    label        설명                          정렬   상태\ndomain       common   도메인        DNS·SSL 등                   1      활성\nseo          common   SEO          ...                          2      활성\nfeature      service  기능          제품 기능 관련                10     활성\n...\n\n서비스 탭:\n[+ 새 서비스]\nslug          이름          비고                              정렬   상태\nlms-general   범용 LMS       일반 학습관리                       1      활성\nlms-refund    환급 LMS       고용보험 환급                       2      활성\n...\n",[16,1199,1197],{"__ignoreMap":423},[33,1201],{},[36,1203,1205],{"id":1204},"_4-화면-명세","4. 화면 명세",[215,1207,1209,1210],{"id":1208},"_4-1-홈","4-1. 홈 — ",[16,1211,530],{},[24,1213,1214,1217],{},[28,1215,1216],{},"목적",": 운영 상태 한눈에. 상담사는 자기 작업, 운영자는 시스템 전체.",[24,1219,1220],{},[28,1221,1222],{},"KPI 카드 (운영자)",[54,1224,1225,1228,1231,1234,1237],{},[57,1226,1227],{},"자료 총 N건 · 인덱싱 완료 X% · 미처리 N건",[57,1229,1230],{},"표준답변 N건 · 승인 대기 N건 · 이번 주 신규 N건",[57,1232,1233],{},"챗봇 응답 N건 (Phase 2) · 평균 신뢰도 X%",[57,1235,1236],{},"에스컬레이션 N건 대기 · 평균 처리 시간 X시간",[57,1238,1239],{},"이번 달 LLM 비용 $X.XX · 예산 대비 X%",[24,1241,1242],{},[28,1243,1244],{},"KPI 카드 (상담사)",[54,1246,1247,1250,1253],{},[57,1248,1249],{},"내가 등록한 표준답변 N건",[57,1251,1252],{},"내가 처리한 에스컬레이션 N건",[57,1254,1255],{},"최근 7일 평가 점수 평균",[24,1257,1258,1261],{},[28,1259,1260],{},"최근 활동 피드"," — 시간순 (자료 업로드·표준답변 추가·평가 등록·에스컬레이션 해결)",[415,1263,1266],{"className":1264,"code":1265,"language":420},[418],"┌────────────────────────────────────────────────────────┐\n│  📊 시스템 현황                       [상담사 모드 보기 ↗]│\n├──────────────┬──────────────┬──────────────┬───────────│\n│ 자료         │ 표준답변      │ 이번 달 비용  │ 에스컬레이션│\n│ 142건        │ 87건         │ $12.45       │ 3건 대기   │\n│ 인덱싱 96%   │ 승인대기 4    │ 예산 25%     │ 평균 2h 처리│\n└──────────────┴──────────────┴──────────────┴───────────┘\n┌────────────────────────────────────────────────────────┐\n│  📜 최근 활동                                            │\n│  ─ 09:14  표준답변 #88 등록 — \"알림톡 비용 안내\" (장지혜)  │\n│  ─ 09:02  자료 인덱싱 완료 — manual-v2.3.pdf (32 청크)    │\n│  ─ 08:51  에스컬레이션 해결 — \"비밀번호 변경\" (김현희)     │\n└────────────────────────────────────────────────────────┘\n",[16,1267,1265],{"__ignoreMap":423},[33,1269],{},[215,1271,1273,1274],{"id":1272},"_4-2-자료-관리-materials","4-2. 자료 관리 — ",[16,1275,727],{},[24,1277,1278],{},[28,1279,1280],{},"자산 종류 2가지",[135,1282,1283,1296],{},[138,1284,1285],{},[141,1286,1287,1290,1293],{},[144,1288,1289],{},"종류",[144,1291,1292],{},"설명",[144,1294,1295],{},"인덱싱",[157,1297,1298,1315],{},[141,1299,1300,1309,1312],{},[162,1301,1302,1305,1306,78],{},[28,1303,1304],{},"파일 자산"," (",[16,1307,1308],{},"file",[162,1310,1311],{},"PDF·MD·HTML·DOCX 직접 업로드 → R2 저장",[162,1313,1314],{},"텍스트 추출 → 청크 → 임베딩 → OpenSearch",[141,1316,1317,1325,1332],{},[162,1318,1319,1305,1322,78],{},[28,1320,1321],{},"URL 자산",[16,1323,1324],{},"url",[162,1326,1327,1328,1331],{},"외부\u002F사내 페이지·",[28,1329,1330],{},"동영상 URL"," 등록만",[162,1333,1334,1335,1338],{},"URL 페이지는 크롤링 후 텍스트 청크화. 동영상은 메타(제목·설명·태그)만 인덱싱하고, ",[28,1336,1337],{},"필요시 Whisper로 자막 추출 트리거","(별도 액션)",[24,1340,1341],{},[28,1342,1343],{},"핵심 기능",[54,1345,1346,1353,1369,1376,1383],{},[57,1347,1348,1349,1352],{},"파일 드래그앤드롭 또는 ",[28,1350,1351],{},"URL 입력 폼"," (제목·설명·태그)",[57,1354,1355,1356,1358,1359,1358,1362,1365,1366],{},"자동 인덱싱 — ",[16,1357,568],{}," → ",[16,1360,1361],{},"processing",[16,1363,1364],{},"indexed"," \u002F ",[16,1367,1368],{},"failed",[57,1370,1371,1372,1375],{},"재인덱싱(",[16,1373,1374],{},"reindex",") · 삭제(soft delete)",[57,1377,1378,1379,1382],{},"동영상 URL 자산은 ",[28,1380,1381],{},"\"자막 추출(Whisper)\" 액션 버튼"," — 누르면 비동기 Whisper 호출 후 텍스트 청크에 합산. 기본 비활성, 필요할 때만",[57,1384,1385],{},"검색은 메타·본문 LIKE(MVP), 추후 OpenSearch full-text",[24,1387,1388,1391,1392,1395],{},[28,1389,1390],{},"목록 표 컬럼",": 제목 · 종류(파일\u002FURL) · 형식 · 인덱싱 상태 · 청크 수 · 업로더 · 등록일 · 액션\n",[28,1393,1394],{},"상세 페이지",": 메타데이터, 원본(파일은 다운로드\u002FURL은 새 탭), 청크 미리보기(처음 5개), \"재인덱싱\"·\"자막 추출\"(동영상만)·\"삭제\"·\"태그 편집\" 액션",[24,1397,1398],{},[28,1399,1400],{},"필요 테이블 (신규)",[54,1402,1403,1431],{},[57,1404,1405,1408,1409,1305,1412,530,1414,530,1416,1419,1420,530,1423,530,1425,530,1428,1430],{},[16,1406,1407],{},"hp_material"," — id, title, ",[28,1410,1411],{},"kind",[16,1413,1308],{},[16,1415,1324],{},[16,1417,1418],{},"video_url","), file_path(R2 key, file·video일 때만), source_url(url·video_url일 때만), mime, size, description, tags(JSON), uploader_id, project_id(NULL = 전사), indexing_status(pending\u002Fprocessing\u002Findexed\u002Ffailed), chunk_count, indexed_at, transcript_status(",[16,1421,1422],{},"none",[16,1424,568],{},[16,1426,1427],{},"done",[16,1429,1368],{},", video_url 전용), status(1\u002F-1), created_at",[57,1432,1433,1436,1437,530,1440,1443],{},[16,1434,1435],{},"hp_material_chunk"," — id, material_id, chunk_idx, body(TEXT), token_count, embedding(LONGBLOB or OpenSearch only), source(",[16,1438,1439],{},"body",[16,1441,1442],{},"transcript","), created_at",[24,1445,1446],{},[28,1447,1448],{},"필요 API (신규)",[54,1450,1451,1457,1463,1469,1475,1481,1487],{},[57,1452,1453,1456],{},[16,1454,1455],{},"POST \u002Fmaterials\u002Ffile"," (multipart) — 파일 업로드 + 인덱싱 시작",[57,1458,1459,1462],{},[16,1460,1461],{},"POST \u002Fmaterials\u002Furl"," (JSON) — URL\u002F동영상 URL 등록",[57,1464,1465,1468],{},[16,1466,1467],{},"GET \u002Fmaterials"," — 목록·필터 (kind, indexing_status, search)",[57,1470,1471,1474],{},[16,1472,1473],{},"GET \u002Fmaterials\u002F:id"," — 상세 (청크 포함)",[57,1476,1477,1480],{},[16,1478,1479],{},"POST \u002Fmaterials\u002F:id\u002Freindex"," — 재인덱싱",[57,1482,1483,1486],{},[16,1484,1485],{},"POST \u002Fmaterials\u002F:id\u002Ftranscribe"," — Whisper 자막 추출 (video_url만)",[57,1488,1489,1492],{},[16,1490,1491],{},"DELETE \u002Fmaterials\u002F:id"," — soft delete",[24,1494,1495],{},[28,1496,1497],{},"의존",[54,1499,1500,1503],{},[57,1501,1502],{},"OpenSearch 셋업 (Phase 1 후반)",[57,1504,1505],{},"Whisper API 키 (선택, 동영상 자막 필요할 때)",[33,1507],{},[215,1509,1511,1512],{"id":1510},"_4-3-표준답변-관리-standard-answers","4-3. 표준답변 관리 — ",[16,1513,700],{},[482,1515,1517],{"id":1516},"_4-3-1-분류-체계-scope-topic-service","4-3-1. 분류 체계 (Scope · Topic · Service)",[24,1519,1520,1521,1524,1525,1528],{},"표준답변은 ",[28,1522,1523],{},"2축 분류"," + ",[28,1526,1527],{},"태그","로 관리:",[135,1530,1531,1544],{},[138,1532,1533],{},[141,1534,1535,1538,1541],{},[144,1536,1537],{},"축",[144,1539,1540],{},"값",[144,1542,1543],{},"의미",[157,1545,1546,1561,1573,1586,1599],{},[141,1547,1548,1553,1558],{},[162,1549,1550],{},[28,1551,1552],{},"scope",[162,1554,1555],{},[16,1556,1557],{},"common",[162,1559,1560],{},"어떤 솔루션이든 동일하게 적용되는 답변 (도메인·SEO·일반 IT 등)",[141,1562,1563,1565,1570],{},[162,1564],{},[162,1566,1567],{},[16,1568,1569],{},"service",[162,1571,1572],{},"특정 솔루션에만 적용되는 답변 (기능·법령·정책 등)",[141,1574,1575,1580,1583],{},[162,1576,1577],{},[28,1578,1579],{},"topic",[162,1581,1582],{},"슬러그 코드",[162,1584,1585],{},"주제 — 검색·필터·자동 추천에 사용",[141,1587,1588,1593,1596],{},[162,1589,1590],{},[28,1591,1592],{},"service_tag",[162,1594,1595],{},"솔루션 슬러그 (NULL = scope=common)",[162,1597,1598],{},"어느 서비스의 답변인지",[141,1600,1601,1606,1609],{},[162,1602,1603],{},[28,1604,1605],{},"tags",[162,1607,1608],{},"JSON 배열",[162,1610,1611],{},"자유 태그 (운영자 큐레이션)",[24,1613,1614,1305,1617,1620],{},[28,1615,1616],{},"기본 topic 카탈로그",[16,1618,1619],{},"hp_topic"," 테이블로 관리, 운영자가 추가 가능):",[135,1622,1623,1637],{},[138,1624,1625],{},[141,1626,1627,1629,1632,1634],{},[144,1628,1552],{},[144,1630,1631],{},"topic 슬러그",[144,1633,500],{},[144,1635,1636],{},"예시",[157,1638,1639,1654,1669,1684,1699,1714,1729,1744,1759,1774],{},[141,1640,1641,1643,1648,1651],{},[162,1642,1557],{},[162,1644,1645],{},[16,1646,1647],{},"domain",[162,1649,1650],{},"도메인",[162,1652,1653],{},"도메인 연결·DNS·SSL",[141,1655,1656,1658,1663,1666],{},[162,1657,1557],{},[162,1659,1660],{},[16,1661,1662],{},"seo",[162,1664,1665],{},"SEO",[162,1667,1668],{},"메타·sitemap·robots.txt",[141,1670,1671,1673,1678,1681],{},[162,1672,1557],{},[162,1674,1675],{},[16,1676,1677],{},"it-general",[162,1679,1680],{},"일반 IT",[162,1682,1683],{},"브라우저 캐시·쿠키·HTTPS",[141,1685,1686,1688,1693,1696],{},[162,1687,1557],{},[162,1689,1690],{},[16,1691,1692],{},"account",[162,1694,1695],{},"계정·로그인",[162,1697,1698],{},"비밀번호·OTP·세션",[141,1700,1701,1703,1708,1711],{},[162,1702,1557],{},[162,1704,1705],{},[16,1706,1707],{},"payment",[162,1709,1710],{},"결제 일반",[162,1712,1713],{},"카드·세금계산서·환불 절차",[141,1715,1716,1718,1723,1726],{},[162,1717,1569],{},[162,1719,1720],{},[16,1721,1722],{},"feature",[162,1724,1725],{},"기능",[162,1727,1728],{},"알림톡·SMS·게시판·LMS 등",[141,1730,1731,1733,1738,1741],{},[162,1732,1569],{},[162,1734,1735],{},[16,1736,1737],{},"legal",[162,1739,1740],{},"법령·약관",[162,1742,1743],{},"개인정보·전자상거래·교육법",[141,1745,1746,1748,1753,1756],{},[162,1747,1569],{},[162,1749,1750],{},[16,1751,1752],{},"policy",[162,1754,1755],{},"정책",[162,1757,1758],{},"사용·요금·약관 정책",[141,1760,1761,1763,1768,1771],{},[162,1762,1569],{},[162,1764,1765],{},[16,1766,1767],{},"pricing",[162,1769,1770],{},"요금·계약",[162,1772,1773],{},"단가표·계약 조건",[141,1775,1776,1778,1783,1786],{},[162,1777,1569],{},[162,1779,1780],{},[16,1781,1782],{},"integration",[162,1784,1785],{},"연동·API",[162,1787,1788],{},"외부 API·웹훅",[24,1790,1791,1305,1794,1797],{},[28,1792,1793],{},"기본 service_tag 카탈로그",[16,1795,1796],{},"hp_service"," 테이블, 운영자가 추가)",[24,1799,1800],{},"맑은소프트 LMS 패밀리 — 같은 LMS라도 도메인 규정·법령·기능 옵션이 달라서 표준답변을 분리해야 함:",[135,1802,1803,1816],{},[138,1804,1805],{},[141,1806,1807,1810,1813],{},[144,1808,1809],{},"slug",[144,1811,1812],{},"이름",[144,1814,1815],{},"도메인·특수성",[157,1817,1818,1831,1844,1857,1870,1883,1896],{},[141,1819,1820,1825,1828],{},[162,1821,1822],{},[16,1823,1824],{},"lms-general",[162,1826,1827],{},"범용 LMS",[162,1829,1830],{},"일반 학습관리 (베이스 라인)",[141,1832,1833,1838,1841],{},[162,1834,1835],{},[16,1836,1837],{},"lms-refund",[162,1839,1840],{},"환급 LMS",[162,1842,1843],{},"고용보험 환급 과정 — 환급법령·증빙·이수율 룰",[141,1845,1846,1851,1854],{},[162,1847,1848],{},[16,1849,1850],{},"lms-public",[162,1852,1853],{},"공공 LMS",[162,1855,1856],{},"공공기관 — 입찰·관급·법정 의무교육·접근성(WCAG)",[141,1858,1859,1864,1867],{},[162,1860,1861],{},[16,1862,1863],{},"lms-security",[162,1865,1866],{},"민간보안 LMS",[162,1868,1869],{},"정보보호 의무교육(개인정보보호법·정보통신망법) · ISMS-P 컴플라이언스 · 보안등급별 컨텐츠 분리 · 접근 로그·이수 증명",[141,1871,1872,1877,1880],{},[162,1873,1874],{},[16,1875,1876],{},"lms-hybrid",[162,1878,1879],{},"혼합 LMS",[162,1881,1882],{},"환급+민간 등 복합 — 두 도메인 룰 동시 적용",[141,1884,1885,1890,1893],{},[162,1886,1887],{},[16,1888,1889],{},"lms-global",[162,1891,1892],{},"글로벌 LMS",[162,1894,1895],{},"다국어·다지역 — i18n·결제·세금·시간대·법령",[141,1897,1898,1901,1904],{},[162,1899,1900],{},"...",[162,1902,1903],{},"(운영자 추가)",[162,1905,1906],{},"LMS 외 솔루션이 도입되면 추가",[21,1908,1909],{},[24,1910,1911,1912,1915,1916,1918],{},"분류 효과: 같은 ",[16,1913,1914],{},"topic=legal"," 문의여도 환급(고용보험법) vs 공공(전자정부법) vs 글로벌(GDPR)이 전혀 다른 답변. ",[16,1917,1592],{}," 일치를 우선 매칭하여 정답률 확보.",[24,1920,1921],{},[28,1922,1923],{},"매칭 규칙 (챗봇 응답·표준답변 추천)",[1925,1926,1927,1935,1944,1950,1960],"ol",{},[57,1928,1929,1930,1524,1932,1934],{},"사용자 질문 → LLM이 ",[16,1931,1552],{},[16,1933,1579],{}," 추론",[57,1936,1937,1940,1941,1943],{},[16,1938,1939],{},"scope=service","이면 사용자가 사용 중인 서비스(",[16,1942,1592],{},")로 필터",[57,1945,1946,1949],{},[16,1947,1948],{},"scope=common","이면 service 무관하게 매칭",[57,1951,1952,1953,1955,1956,1959],{},"동점 시 ",[16,1954,1605],{}," 매치 수 + ",[16,1957,1958],{},"usage_count"," 우선순위",[57,1961,1962],{},"매칭 결과 N개를 LLM 컨텍스트에 첨부",[482,1964,1966],{"id":1965},"_4-3-2-화면","4-3-2. 화면",[24,1968,1969],{},[28,1970,1971,1972],{},"목록 — ",[16,1973,700],{},[415,1975,1978],{"className":1976,"code":1977,"language":420},[418],"[🔍 검색]  [scope: common\u002Fservice ▾]  [topic ▾]  [service ▾]  [상태 ▾]    [+ 새 표준답변]\n\n#   label              scope    topic        service     사용  업데이트       상태       \n84  환급 이수율 기준        service  legal        lms-refund    42회  06-07 14:21   ● 승인됨   \n83  비밀번호 변경           common   account      —             12회  06-06 09:10   ◯ 대기     \n82  도메인 SSL 갱신         common   domain       —             28회  06-05 11:00   ● 승인됨   \n81  공공기관 접근성 인증    service  legal        lms-public     5회  06-05 09:00   ● 승인됨   \n80  LMS 수료증 출력         service  feature      lms-general    7회  06-04 17:45   ● 승인됨   \n79  다국어 결제 통화        service  pricing      lms-global     3회  06-03 11:00   ◯ 대기     \n",[16,1979,1977],{"__ignoreMap":423},[24,1981,1982],{},[28,1983,1984,1985],{},"상세·편집 — ",[16,1986,1987],{},"\u002Fstandard-answers\u002F:id",[54,1989,1990,2002,2005,2011],{},[57,1991,1992,1993,530,1995,530,1997,530,1999,2001],{},"좌측: 메타 (",[16,1994,1552],{},[16,1996,1579],{},[16,1998,1569],{},[16,2000,1605],{},") + 사용 통계 + 출처 역추적",[57,2003,2004],{},"우측: HTML 답변 에디터 (Rich text, Tailwind prose preview)",[57,2006,2007,2010],{},[28,2008,2009],{},"하단: 이미지 자동 추천 패널"," (다음 §4-3-3 참조)",[57,2012,2013,2014,2017],{},"액션: 저장 · 승인 · 반려 · 영구 삭제(",[16,2015,2016],{},"status=-2",", 매우 드물게)",[482,2019,2021,2022,2024],{"id":2020},"_4-3-3-이미지-자동-배치-hp_image_asset-활용","4-3-3. 이미지 자동 배치 (",[16,2023,77],{}," 활용)",[24,2026,2027,2030,2031,2033],{},[28,2028,2029],{},"기획 의도",": 표준답변 작성 시 ",[16,2032,77],{},"의 캡션·설명으로 적절한 이미지를 자동 매칭·삽입. 운영자가 일일이 src를 찾을 필요 없음.",[24,2035,2036],{},[28,2037,2038],{},"3가지 동작 방식",[1925,2040,2041,2064,2080],{},[57,2042,2043,2046],{},[28,2044,2045],{},"에디터 사이드 패널 — 추천 이미지 그리드",[54,2047,2048,2054,2057],{},[57,2049,2050,2051,2053],{},"현재 입력 중인 답변 본문에서 LLM이 키워드 추출 → ",[16,2052,77],{}," 검색 (title·description LIKE 또는 임베딩 유사도)",[57,2055,2056],{},"썸네일 + title 표시",[57,2058,2059,2060,2063],{},"클릭 → 커서 위치에 ",[16,2061,2062],{},"\u003Cfigure>\u003Cimg src=...>\u003Cfigcaption>{title}\u003C\u002Ffigcaption>\u003C\u002Ffigure>"," 삽입",[57,2065,2066,2069],{},[28,2067,2068],{},"\"AI 자동 삽입\" 버튼",[54,2070,2071,2074,2077],{},[57,2072,2073],{},"LLM이 답변 전체를 읽고 적절한 위치에 자동으로 이미지 + 캡션 삽입",[57,2075,2076],{},"미리보기 → 운영자 승인 → 적용",[57,2078,2079],{},"이미 PMS Q&A 분석에서 D축 templates 생성 시 같은 흐름 동작 중 — 그 로직 재사용",[57,2081,2082,2085,2086],{},[28,2083,2084],{},"이미지 추출 후 자동 표준답변화"," (반대 흐름)",[54,2087,2088,2094,2097],{},[57,2089,2090,2093],{},[16,2091,2092],{},"\u002Fimages\u002F:id"," 상세 화면에 \"이 이미지를 사용하는 표준답변 만들기\" 액션",[57,2095,2096],{},"이미지의 title·description을 시작점으로 LLM이 표준답변 초안 생성",[57,2098,2099],{},"운영자 검토 후 저장",[24,2101,2102],{},[28,2103,2104],{},"필요 보강",[54,2106,2107,2112],{},[57,2108,2109,2111],{},[16,2110,77],{},"에 임베딩(embedding) 컬럼 추가 또는 OpenSearch 색인 (이미지 의미 검색용)",[57,2113,2114,2115,2118],{},"표준답변 ↔ 이미지 다대다 관계 추적: ",[16,2116,2117],{},"hp_standard_answer_image"," (sa_id, image_id, position) — 어느 표준답변이 어느 이미지를 인용하는지 역추적용",[482,2120,2122,2123,78],{"id":2121},"_4-3-4-스키마-보강-hp_standard_answer","4-3-4. 스키마 보강 (",[16,2124,2125],{},"hp_standard_answer",[24,2127,2128],{},"추가 컬럼:",[54,2130,2131,2136,2145,2154,2160,2169,2175],{},[57,2132,2133,2135],{},[16,2134,1552],{}," ENUM('common', 'service') NOT NULL DEFAULT 'service'",[57,2137,2138,2140,2141,2144],{},[16,2139,1579],{}," VARCHAR(50) NOT NULL — ",[16,2142,2143],{},"hp_topic.slug","와 매칭",[57,2146,2147,2149,2150,2153],{},[16,2148,1592],{}," VARCHAR(50) NULL — ",[16,2151,2152],{},"hp_service.slug","와 매칭 (scope=service일 때만 필수)",[57,2155,2156,2159],{},[16,2157,2158],{},"approval_status"," ENUM('pending','approved','rejected') NOT NULL DEFAULT 'pending'",[57,2161,2162,2164,2165,2168],{},[16,2163,1605],{}," JSON DEFAULT '",[2166,2167],"span",{},"'",[57,2170,2171,2174],{},[16,2172,2173],{},"approved_by"," VARCHAR(100) NULL",[57,2176,2177,2180],{},[16,2178,2179],{},"approved_at"," DATETIME NULL",[24,2182,2183],{},"신규 테이블 2종:",[54,2185,2186,2191,2196],{},[57,2187,2188,2190],{},[16,2189,1619],{}," — slug PK, scope, label, description, sort_order, status",[57,2192,2193,2195],{},[16,2194,1796],{}," — slug PK, name, description, sort_order, status",[57,2197,2198,2200],{},[16,2199,2117],{}," — sa_id, image_id, position (FK), PRIMARY KEY (sa_id, image_id)",[482,2202,2204],{"id":2203},"_4-3-5-필요-api-보강","4-3-5. 필요 API (보강)",[54,2206,2207,2220,2232,2238,2244,2250,2256],{},[57,2208,2209,2212,2213,2212,2216,2219],{},[16,2210,2211],{},"GET \u002Ftopics"," · ",[16,2214,2215],{},"POST \u002Ftopics",[16,2217,2218],{},"PATCH \u002Ftopics\u002F:slug"," — 토픽 카탈로그 CRUD",[57,2221,2222,2212,2225,2212,2228,2231],{},[16,2223,2224],{},"GET \u002Fservices",[16,2226,2227],{},"POST \u002Fservices",[16,2229,2230],{},"PATCH \u002Fservices\u002F:slug"," — 서비스 카탈로그 CRUD",[57,2233,2234,2237],{},[16,2235,2236],{},"GET \u002Fstandard-answers?scope=&topic=&service_tag=&search="," — 필터 보강",[57,2239,2240,2243],{},[16,2241,2242],{},"PATCH \u002Fstandard-answers\u002F:id\u002Fapprove"," — 승인",[57,2245,2246,2249],{},[16,2247,2248],{},"POST \u002Fstandard-answers\u002F:id\u002Fimages"," — 이미지 연결",[57,2251,2252,2255],{},[16,2253,2254],{},"POST \u002Fstandard-answers\u002F:id\u002Fsuggest-images"," — LLM이 이미지 자동 추천 (top N)",[57,2257,2258,2261],{},[16,2259,2260],{},"POST \u002Fstandard-answers\u002Fdraft"," — 이미지 → 표준답변 초안 생성",[33,2263],{},[215,2265,2267,2268],{"id":2266},"_4-4-이미지-카탈로그-images","4-4. 이미지 카탈로그 — ",[16,2269,754],{},[24,2271,2272],{},[28,2273,1343],{},[54,2275,2276,2281,2291,2298,2308],{},[57,2277,2278,2280],{},[16,2279,77],{}," 전체 시각화 — 썸네일 그리드",[57,2282,2283,2284,2212,2287,2290],{},"검색 — ",[16,2285,2286],{},"title",[16,2288,2289],{},"description"," LIKE",[57,2292,2293,2294,2297],{},"필터 — ",[16,2295,2296],{},"source"," (inquiry\u002Freply) · 프로젝트 · 사용 횟수",[57,2299,2300,2301,2304,2305,78],{},"상세 — 메타 · ",[16,2302,2303],{},"first_seen_post_id"," 역추적 · 태그 편집 · 숨김(",[16,2306,2307],{},"status=-1",[57,2309,2310],{},"챗봇 컨텍스트 활용 미리보기 — \"이 이미지 설명이 답변에 인용될 때 모습\"",[24,2312,2313],{},[28,2314,2315],{},"필요 컬럼 보강",[54,2317,2318,2323],{},[57,2319,2320,2322],{},[16,2321,1605],{}," (JSON) — 운영자가 큐레이션",[57,2324,2325,2328],{},[16,2326,2327],{},"is_curated"," (TINYINT) — 운영자가 검토 완료 표시",[24,2330,2331],{},[28,2332,1448],{},[54,2334,2335,2341,2347,2353],{},[57,2336,2337,2340],{},[16,2338,2339],{},"GET \u002Fimage-assets"," — 목록·검색·페이지네이션",[57,2342,2343,2346],{},[16,2344,2345],{},"GET \u002Fimage-assets\u002F:id"," — 상세",[57,2348,2349,2352],{},[16,2350,2351],{},"PATCH \u002Fimage-assets\u002F:id"," — title·description·tags 편집",[57,2354,2355,2358],{},[16,2356,2357],{},"DELETE \u002Fimage-assets\u002F:id"," — soft hide",[33,2360],{},[215,2362,2364,2365,2367,2368],{"id":2363},"_4-5-챗봇-응답-로그-chat-logs-phase-2-준비","4-5. 챗봇 응답 로그 — ",[16,2366,615],{}," ",[2369,2370,2371],"em",{},"(Phase 2 준비)",[24,2373,2374],{},[28,2375,1343],{},[54,2377,2378,2381,2384],{},[57,2379,2380],{},"세션 단위 목록 — 사용자·시작 시각·메시지 수·평균 신뢰도·만족도(👍\u002F👎)",[57,2382,2383],{},"세션 상세 — 메시지 흐름 (질문·답변·인용 출처·신뢰도) + 사용자 피드백 + 처리 시간",[57,2385,2386],{},"필터 — 일자·만족도·신뢰도",[21,2388,2389],{},[24,2390,2391,2394],{},[28,2392,2393],{},"참고",": \"답변 없는 PMS 게시물\"과는 다른 개념. 게시물은 상담사가 직접 PMS에서 답변하고, 미커버 질문은 챗봇 → 자료\u002F표준답변으로 흐름이 다름.",[33,2396],{},[215,2398,2400,2401,2367,2403],{"id":2399},"_4-5-1-미커버-질문-uncovered-phase-2-준비-별도-전용-페이지","4-5-1. 미커버 질문 — ",[16,2402,557],{},[2369,2404,2405],{},"(Phase 2 준비, 별도 전용 페이지)",[24,2407,2408,2410,2411,2414,2415,2417],{},[28,2409,2029],{},": 챗봇이 답을 못 한 질문을 챗 로그에서 따로 모아 ",[28,2412,2413],{},"자료·표준답변 보강 작업 큐","로 운영. ",[16,2416,615],{},"와 분리해 운영자·개발자가 한눈에 누락된 지식 영역을 본다.",[24,2419,2420],{},[28,2421,1343],{},[54,2423,2424,2437,2443,2464,2470,2480],{},[57,2425,2426,2429,2430,394,2433,2436],{},[28,2427,2428],{},"누적 큐",": 챗봇이 ",[16,2431,2432],{},"is_unknown=true",[16,2434,2435],{},"confidence \u003C 0.5","로 분기한 질문을 모음",[57,2438,2439,2442],{},[28,2440,2441],{},"자동 클러스터링",": 의미 유사 질문 묶음 (임베딩 cosine ≥ 0.8). 같은 의미면 묶어서 \"주 5건\" 같은 빈도 표시",[57,2444,2445,2448,2449,2451,2452,2455,2456,2459,2460,2463],{},[28,2446,2447],{},"상태 관리"," — ",[16,2450,568],{},"(대기) \u002F ",[16,2453,2454],{},"working","(작업 중) \u002F ",[16,2457,2458],{},"resolved","(표준답변\u002F자료 추가됨) \u002F ",[16,2461,2462],{},"wont_fix","(범위 외)",[57,2465,2466,2469],{},[28,2467,2468],{},"표준답변 등록 트리거"," — 큐 항목 클릭 → 답변 초안 작성 모달 (§4-5-2 참조)",[57,2471,2472,2475,2476,2479],{},[28,2473,2474],{},"자료 업로드 트리거"," — 큐 항목에 \"관련 매뉴얼 추가\" 액션 → ",[16,2477,2478],{},"\u002Fmaterials\u002Fupload","로 미리 채워서 이동",[57,2481,2482,2485,2486,2488],{},[28,2483,2484],{},"필터·정렬"," — 빈도 ↓ \u002F 최근 \u002F ",[16,2487,1552],{}," 추정 \u002F 상태별",[24,2490,2491],{},[28,2492,2493],{},"화면 구조 (목록)",[415,2495,2498],{"className":2496,"code":2497,"language":420},[418],"[🔍 검색]  [상태 ▾]  [scope ▾]  [빈도 ▾]                          [정렬: 빈도 ↓]\n\n#   대표 질문                              빈도  마지막 발생      추정 scope\u002Ftopic   상태       액션\n148 알림톡 발신 프로필 등록 어떻게?           12   06-08 09:14    service\u002Ffeature   ◯ 대기     [답변 작성][자료 추가]\n147 SSL 인증서 갱신 절차                       8   06-07 17:00    common\u002Fdomain     ◯ 대기     [답변 작성]\n146 LMS 수강 이력 엑셀 추출                   6   06-07 11:23    service\u002Ffeature   ● 작업중  \n145 결제 영수증 발급                          15   06-06 14:00    common\u002Fpayment    ✓ 해결됨   [표준답변 #88 보기]\n",[16,2499,2497],{"__ignoreMap":423},[24,2501,2502],{},[28,2503,2504],{},"필요 테이블",[54,2506,2507],{},[57,2508,2509,2512],{},[16,2510,2511],{},"hp_uncovered_question"," — id, sample_question(대표 질문), cluster_id(같은 의미 묶음 키), occurrence_count, last_seen_at, estimated_scope, estimated_topic, estimated_service_tag, status, resolved_by_sa_id(FK to hp_standard_answer), resolved_by_material_id(FK to hp_material), assigned_to, created_at",[24,2514,2515],{},[28,2516,2517],{},"필요 API",[54,2519,2520,2526,2532,2538],{},[57,2521,2522,2525],{},[16,2523,2524],{},"GET \u002Funcovered"," — 목록·필터",[57,2527,2528,2531],{},[16,2529,2530],{},"PATCH \u002Funcovered\u002F:id\u002Fassign"," — 담당자 지정",[57,2533,2534,2537],{},[16,2535,2536],{},"POST \u002Funcovered\u002F:id\u002Fdraft-sa"," — 미커버 질문을 시드로 표준답변 초안 생성 (§4-5-2)",[57,2539,2540,2543],{},[16,2541,2542],{},"POST \u002Funcovered\u002F:id\u002Fresolve"," — 표준답변·자료 연결하여 해결 처리",[33,2545],{},[215,2547,2549],{"id":2548},"_4-5-2-ai-초안-생성-챗봇-응답-로직-그대로-재사용","4-5-2. AI 초안 생성 — 챗봇 응답 로직 그대로 재사용",[24,2551,2552,2555,2556,2563],{},[28,2553,2554],{},"기획 결정",": 별도 prompt를 만들지 않는다. ",[28,2557,2558,2559,2562],{},"챗봇 응답 파이프라인(",[16,2560,2561],{},"POST \u002Fchat",")을 그대로 호출","하여 응답을 받고, 운영자가 검토·편집해 표준답변으로 저장한다.",[24,2565,2566],{},[28,2567,2568],{},"진입점",[1925,2570,2571,2580,2589],{},[57,2572,2573,1305,2576,2579],{},[28,2574,2575],{},"에스컬레이션 처리 화면",[16,2577,2578],{},"\u002Fescalations\u002F:id",") — \"AI 초안 생성\" 버튼",[57,2581,2582,1305,2585,2588],{},[28,2583,2584],{},"미커버 질문 큐",[16,2586,2587],{},"\u002Funcovered\u002F:id",") — \"답변 작성\" 클릭 시 자동으로 초안 생성",[57,2590,2591,1305,2594,2597],{},[28,2592,2593],{},"표준답변 신규 등록",[16,2595,2596],{},"\u002Fstandard-answers\u002Fnew",") — 질문 입력 후 \"AI 초안 받기\" 옵션",[24,2599,2600],{},[28,2601,2602],{},"동작 흐름",[415,2604,2607],{"className":2605,"code":2606,"language":420},[418],"운영자: 질문 입력 (또는 미커버 항목 클릭)\n   ↓\nAPI: POST \u002Fchat (Phase 2 챗봇 응답 API 그대로)\n   - 표준답변 매칭 우선 → 하이브리드 검색 → LLM 답변 + 출처 + 신뢰도\n   ↓\n응답: 답변 본문 + 인용 출처(표준답변 id, 자료 청크 id, 이미지 id)\n   ↓\n화면: HTML 에디터에 본문 자동 채움 + 우측에 출처 패널\n   ↓\n운영자: 편집 → scope\u002Ftopic\u002Fservice 분류 지정 → 저장\n   ↓\n승인 후 → 챗봇이 이후 매칭에 사용\n",[16,2608,2606],{"__ignoreMap":423},[24,2610,2611],{},[28,2612,2613],{},"장점",[54,2615,2616,2619,2622],{},[57,2617,2618],{},"별도 prompt 관리 부담 없음 (한 모델·한 prompt 유지)",[57,2620,2621],{},"챗봇 응답 품질이 곧 초안 품질 — 챗봇 개선 = 초안 개선",[57,2623,2624],{},"출처 인용이 자동으로 따라옴 → 표준답변 저장 시 출처 메타데이터 함께 저장",[24,2626,2627],{},[28,2628,2629],{},"필요 테이블 (신규, Phase 2)",[54,2631,2632,2638,2644],{},[57,2633,2634,2637],{},[16,2635,2636],{},"hp_chat_session"," — id, user_id(익명 hash 가능), started_at, ended_at, message_count, status",[57,2639,2640,2643],{},[16,2641,2642],{},"hp_chat_message"," — id, session_id, role(user\u002Fassistant), content, citations(JSON, hp_standard_answer.id 또는 hp_material_chunk.id), confidence, latency_ms, model, created_at",[57,2645,2646,2649],{},[16,2647,2648],{},"hp_chat_feedback"," — session_id, message_id, rating(1\u002F-1), comment, created_at",[24,2651,2652],{},[28,2653,2654],{},"필요 API (신규, Phase 2)",[54,2656,2657,2662,2668,2673],{},[57,2658,2659,2661],{},[16,2660,2561],{}," — 응답 생성 (스트리밍)",[57,2663,2664,2667],{},[16,2665,2666],{},"GET \u002Fchat-sessions"," — 목록",[57,2669,2670,2346],{},[16,2671,2672],{},"GET \u002Fchat-sessions\u002F:id",[57,2674,2675,2678],{},[16,2676,2677],{},"POST \u002Fchat-feedback"," — 피드백",[33,2680],{},[215,2682,2684,2685,2367,2687],{"id":2683},"_4-6-에스컬레이션-큐-escalations-phase-2-준비","4-6. 에스컬레이션 큐 — ",[16,2686,588],{},[2369,2688,2371],{},[24,2690,2691],{},[28,2692,1343],{},[54,2694,2695,2698,2701,2704],{},[57,2696,2697],{},"챗봇이 \"모름\" 또는 신뢰도 임계값 미만으로 분기한 질문 큐",[57,2699,2700],{},"대기·진행·완료 탭",[57,2702,2703],{},"상담사 답변 작성 → 사용자 알림 + 표준답변 등록 옵션",[57,2705,2706],{},"우선순위 (사용자 만족도·VIP·신뢰도·반복 횟수)",[24,2708,2709],{},[28,2710,1400],{},[54,2712,2713],{},[57,2714,2715,2718],{},[16,2716,2717],{},"hp_escalation"," — id, session_id, message_id, question, status(pending\u002Fin_progress\u002Fresolved), assigned_to, priority, created_at, resolved_at, resolution",[33,2720],{},[215,2722,2724,2725,2212,2727],{"id":2723},"_4-7-qa-평가-llm-비용-qa-evals-cost","4-7. Q&A 평가 \u002F LLM 비용 — ",[16,2726,642],{},[16,2728,836],{},[24,2730,2731,2732,105,2734,2736,2737,2740],{},"PMS의 ",[16,2733,108],{},[16,2735,104],{},"와 동일 데이터·UI. 동일 컴포넌트(",[16,2738,2739],{},"QaEvalCard"," 등) 재사용. 운영자가 PMS를 안 켜고도 모니터링 가능.",[24,2742,2743],{},"추후 admin 전용 부가 기능:",[54,2745,2746,2749],{},[57,2747,2748],{},"평가 기준선(score \u003C 3) 알림",[57,2750,2751],{},"비용 예산 알림 (월 한도 임박 시 Slack)",[33,2753],{},[215,2755,2757,2758],{"id":2756},"_4-8-ai-설정-settingsai","4-8. AI 설정 — ",[16,2759,941],{},[24,2761,2762],{},[28,2763,2764],{},"관리 항목",[54,2766,2767,2774,2777,2784,2795],{},[57,2768,2769,2770,2773],{},"기본 모델 (",[16,2771,2772],{},"gpt-4.1-mini"," · 다른 모델 선택)",[57,2775,2776],{},"Vision 모델 (이미지 있을 때 자동 업그레이드 여부)",[57,2778,2779,2780,2783],{},"시스템 프롬프트 — 챗봇 (",[16,2781,2782],{},"PHASE2_CHAT_SYSTEM_PROMPT",") · 평가 · 추천답변 별도 편집",[57,2785,2786,2212,2789,2212,2792],{},[16,2787,2788],{},"temperature",[16,2790,2791],{},"max_tokens",[16,2793,2794],{},"timeout",[57,2796,2797,2798,2801],{},"LLM 캐싱 TTL (",[16,2799,2800],{},"llm_input_hash"," 24h 등)",[24,2803,2804,2807,2808,2811],{},[28,2805,2806],{},"저장 위치",": 신규 ",[16,2809,2810],{},"hp_setting"," (key\u002Fvalue JSON) 또는 단순 KV 바인딩",[24,2813,2814,2817],{},[28,2815,2816],{},"Diff 미리보기"," — 변경 적용 전 영향 받을 엔드포인트 명시",[33,2819],{},[215,2821,2823,2824],{"id":2822},"_4-9-안전-가드-settingssafety","4-9. 안전 가드 — ",[16,2825,965],{},[54,2827,2828,2831,2834,2837],{},[57,2829,2830],{},"\"모름\" 분기 임계값 (confidence \u003C X)",[57,2832,2833],{},"PII 마스킹 패턴 (이메일·전화·계좌 등 정규식 목록)",[57,2835,2836],{},"금칙어 사전 (정치·종교·욕설)",[57,2838,2839],{},"응답 길이 제한·언어 제한",[33,2841],{},[215,2843,2845,2846],{"id":2844},"_4-10-캐싱-settingscache","4-10. 캐싱 — ",[16,2847,989],{},[54,2849,2850,2860,2865,2868],{},[57,2851,2852,2855,2856,2859],{},[16,2853,2854],{},"hp_briefing","·",[16,2857,2858],{},"hp_qa_eval"," 캐시 TTL",[57,2861,2862,2864],{},[16,2863,2125],{}," 자주 묻는 답변 in-memory 캐시 크기",[57,2866,2867],{},"캐시 무효화 트리거 (자료 업로드 시 등)",[57,2869,2870],{},"수동 캐시 비우기 액션",[33,2872],{},[215,2874,2876,2877],{"id":2875},"_4-11-외부-연동-settingsintegrations","4-11. 외부 연동 — ",[16,2878,1013],{},[54,2880,2881,2887,2893,2899],{},[57,2882,2883,2886],{},[28,2884,2885],{},"Slack"," — 에스컬레이션·비용 임계 알림 (Webhook URL 등록)",[57,2888,2889,2892],{},[28,2890,2891],{},"이메일"," — SendGrid·SMTP (선택)",[57,2894,2895,2898],{},[28,2896,2897],{},"티켓 시스템"," — Jira·Zendesk·기존 CS (Phase 2 후반)",[57,2900,2901,2904],{},[28,2902,2903],{},"SSO"," — Google OAuth (Phase 1 후반)",[33,2906],{},[215,2908,2910,2911],{"id":2909},"_4-12-계정권한-accounts","4-12. 계정·권한 — ",[16,2912,1068],{},[24,2914,2915],{},[28,2916,1343],{},[54,2918,2919,2922,2925,2928],{},[57,2920,2921],{},"사용자 목록 — 이메일 · 역할(admin\u002Fagent) · 마지막 로그인 · 활성 여부",[57,2923,2924],{},"초대 — 이메일 invite + 역할 지정 (운영자만)",[57,2926,2927],{},"역할 변경 · 비활성화",[57,2929,2930],{},"감사 로그 — 각 계정의 액션 시간순 (자료 업로드, 표준답변 승인 등)",[24,2932,2933],{},[28,2934,1400],{},[54,2936,2937,2943],{},[57,2938,2939,2942],{},[16,2940,2941],{},"hp_account"," — id, email, name, role(admin\u002Fagent), status, last_login_at, created_at",[57,2944,2945,2948],{},[16,2946,2947],{},"hp_audit_log"," — id, account_id, action(material.upload, sa.approve 등), entity_type, entity_id, payload(JSON), created_at",[24,2950,2951,2954],{},[28,2952,2953],{},"인증 방식",": Cloudflare Access SSO 또는 자체 비밀번호 + JWT. 1차는 Cloudflare Access(이미 가이드 있음).",[33,2956],{},[36,2958,2960],{"id":2959},"_5-데이터api-종합-추가-사항","5. 데이터·API 종합 추가 사항",[215,2962,2964],{"id":2963},"_5-1-신규-테이블-총-11종","5-1. 신규 테이블 (총 11종)",[135,2966,2967,2980],{},[138,2968,2969],{},[141,2970,2971,2974,2977],{},[144,2972,2973],{},"테이블",[144,2975,2976],{},"단계",[144,2978,2979],{},"비고",[157,2981,2982,3005,3023,3039,3050,3061,3074,3091,3104],{},[141,2983,2984,2990,2993],{},[162,2985,2986,2212,2988],{},[16,2987,1407],{},[16,2989,1435],{},[162,2991,2992],{},"Phase 1 후반",[162,2994,2995,2996,2998,2999,530,3001,530,3003],{},"자료 업로드·인덱싱. ",[16,2997,1411],{},"=",[16,3000,1308],{},[16,3002,1324],{},[16,3004,1418],{},[141,3006,3007,3011,3013],{},[162,3008,3009],{},[16,3010,1619],{},[162,3012,2992],{},[162,3014,3015,3016,1524,3018,1524,3020,78],{},"표준답변 토픽 카탈로그 (",[16,3017,1552],{},[16,3019,1809],{},[16,3021,3022],{},"label",[141,3024,3025,3029,3031],{},[162,3026,3027],{},[16,3028,1796],{},[162,3030,2992],{},[162,3032,3033,3034,1524,3036,78],{},"솔루션 카탈로그 (",[16,3035,1809],{},[16,3037,3038],{},"name",[141,3040,3041,3045,3047],{},[162,3042,3043],{},[16,3044,2117],{},[162,3046,2992],{},[162,3048,3049],{},"표준답변 ↔ 이미지 다대다 (역추적·자동 삽입)",[141,3051,3052,3056,3058],{},[162,3053,3054],{},[16,3055,2810],{},[162,3057,2992],{},[162,3059,3060],{},"키\u002F값 JSON 설정",[141,3062,3063,3069,3071],{},[162,3064,3065,2212,3067],{},[16,3066,2941],{},[16,3068,2947],{},[162,3070,2992],{},[162,3072,3073],{},"계정·감사",[141,3075,3076,3084,3089],{},[162,3077,3078,2212,3080,2212,3082],{},[16,3079,2636],{},[16,3081,2642],{},[16,3083,2648],{},[162,3085,3086],{},[28,3087,3088],{},"Phase 2",[162,3090,610],{},[141,3092,3093,3097,3101],{},[162,3094,3095],{},[16,3096,2717],{},[162,3098,3099],{},[28,3100,3088],{},[162,3102,3103],{},"에스컬레이션 큐",[141,3105,3106,3110,3114],{},[162,3107,3108],{},[16,3109,2511],{},[162,3111,3112],{},[28,3113,3088],{},[162,3115,3116],{},"미커버 질문 작업 큐 (클러스터링 포함)",[215,3118,3120],{"id":3119},"_5-2-기존-테이블-보강","5-2. 기존 테이블 보강",[54,3122,3123,3142],{},[57,3124,3125,2448,3127,105,3129,105,3131,105,3133,105,3135,105,3137,105,3139,3141],{},[16,3126,2125],{},[16,3128,1552],{},[16,3130,1579],{},[16,3132,1592],{},[16,3134,2158],{},[16,3136,1605],{},[16,3138,2173],{},[16,3140,2179],{}," 추가",[57,3143,3144,2448,3146,105,3148,3150,3151,3141],{},[16,3145,77],{},[16,3147,1605],{},[16,3149,2327],{},", (선택) ",[16,3152,3153],{},"embedding",[215,3155,3157],{"id":3156},"_5-3-신규-api-그룹","5-3. 신규 API 그룹",[135,3159,3160,3168],{},[138,3161,3162],{},[141,3163,3164,3166],{},[144,3165,503],{},[144,3167,1216],{},[157,3169,3170,3183,3193,3206,3216,3225],{},[141,3171,3172,3180],{},[162,3173,3174,3176,3177,78],{},[16,3175,727],{}," (CRUD + ",[16,3178,3179],{},"\u002Freindex",[162,3181,3182],{},"자료 관리",[141,3184,3185,3191],{},[162,3186,3187,3190],{},[16,3188,3189],{},"\u002Fimage-assets"," (CRUD)",[162,3192,749],{},[141,3194,3195,3203],{},[162,3196,3197,2212,3200],{},[16,3198,3199],{},"\u002Fstandard-answers\u002F:id\u002Fapprove",[16,3201,3202],{},"\u002Freject",[162,3204,3205],{},"승인 워크플로",[141,3207,3208,3213],{},[162,3209,3210],{},[16,3211,3212],{},"\u002Fsettings\u002F*",[162,3214,3215],{},"AI·안전·캐싱 설정",[141,3217,3218,3223],{},[162,3219,3220,3222],{},[16,3221,1068],{}," (CRUD + invite)",[162,3224,1063],{},[141,3226,3227,3231],{},[162,3228,3229],{},[16,3230,1095],{},[162,3232,3233],{},"감사 로그 조회",[24,3235,3236,3237,3240],{},"OpenAPI(",[16,3238,3239],{},"\u002Fdoc",")에 모두 추가.",[33,3242],{},[36,3244,3246],{"id":3245},"_6-권한인증","6. 권한·인증",[215,3248,3250],{"id":3249},"_6-1-인증","6-1. 인증",[24,3252,3253,1305,3256,3261],{},[28,3254,3255],{},"Cloudflare Access SSO",[3257,3258,3260],"a",{"href":3259},"CLOUDFLARE-ACCESS","CLOUDFLARE-ACCESS.md"," 가이드 적용)",[54,3263,3264,3267,3275,3282],{},[57,3265,3266],{},"admin 도메인 전체 보호 — 외부 접근 차단",[57,3268,3269,3270,3274],{},"이메일 도메인 화이트리스트 = ",[28,3271,3272],{},[16,3273,128],{}," 만 (협력사·고객사 차단)",[57,3276,3277,3278,3281],{},"세션 토큰을 API가 검증 (",[16,3279,3280],{},"cf-access-jwt-assertion"," 헤더)",[57,3283,3284],{},"외부 운영자 초대 케이스가 없으므로 자체 비밀번호 로직 불필요",[215,3286,3288],{"id":3287},"_6-2-권한-가드","6-2. 권한 가드",[24,3290,3291],{},"API 측 미들웨어:",[415,3293,3297],{"className":3294,"code":3295,"language":3296,"meta":423,"style":423},"language-ts shiki shiki-themes github-light github-dark","type Role = 'admin' | 'developer' | 'agent';\n\nfunction requireRole(...allowed: Role[]) {\n  return async (c, next) => {\n    const user = c.get('user'); \u002F\u002F CF Access JWT에서 추출 (email, role)\n    if (!user) return c.json({ error: 'unauthorized' }, 401);\n    if (!user.email.endsWith('@malgnsoft.com')) return c.json({ error: 'forbidden' }, 403);\n    if (!allowed.includes(user.role)) return c.json({ error: 'forbidden' }, 403);\n    await next();\n  };\n}\n","ts",[16,3298,3299,3333,3340,3366,3394,3424,3461,3502,3536,3548,3554],{"__ignoreMap":423},[2166,3300,3303,3307,3311,3314,3318,3321,3324,3326,3329],{"class":3301,"line":3302},"line",1,[2166,3304,3306],{"class":3305},"szBVR","type",[2166,3308,3310],{"class":3309},"sScJk"," Role",[2166,3312,3313],{"class":3305}," =",[2166,3315,3317],{"class":3316},"sZZnC"," 'admin'",[2166,3319,3320],{"class":3305}," |",[2166,3322,3323],{"class":3316}," 'developer'",[2166,3325,3320],{"class":3305},[2166,3327,3328],{"class":3316}," 'agent'",[2166,3330,3332],{"class":3331},"sVt8B",";\n",[2166,3334,3336],{"class":3301,"line":3335},2,[2166,3337,3339],{"emptyLinePlaceholder":3338},true,"\n",[2166,3341,3343,3346,3349,3352,3354,3358,3361,3363],{"class":3301,"line":3342},3,[2166,3344,3345],{"class":3305},"function",[2166,3347,3348],{"class":3309}," requireRole",[2166,3350,3351],{"class":3331},"(",[2166,3353,1900],{"class":3305},[2166,3355,3357],{"class":3356},"s4XuR","allowed",[2166,3359,3360],{"class":3305},":",[2166,3362,3310],{"class":3309},[2166,3364,3365],{"class":3331},"[]) {\n",[2166,3367,3369,3372,3375,3377,3380,3382,3385,3388,3391],{"class":3301,"line":3368},4,[2166,3370,3371],{"class":3305},"  return",[2166,3373,3374],{"class":3305}," async",[2166,3376,1305],{"class":3331},[2166,3378,3379],{"class":3356},"c",[2166,3381,105],{"class":3331},[2166,3383,3384],{"class":3356},"next",[2166,3386,3387],{"class":3331},") ",[2166,3389,3390],{"class":3305},"=>",[2166,3392,3393],{"class":3331}," {\n",[2166,3395,3397,3400,3404,3406,3409,3412,3414,3417,3420],{"class":3301,"line":3396},5,[2166,3398,3399],{"class":3305},"    const",[2166,3401,3403],{"class":3402},"sj4cs"," user",[2166,3405,3313],{"class":3305},[2166,3407,3408],{"class":3331}," c.",[2166,3410,3411],{"class":3309},"get",[2166,3413,3351],{"class":3331},[2166,3415,3416],{"class":3316},"'user'",[2166,3418,3419],{"class":3331},"); ",[2166,3421,3423],{"class":3422},"sJ8bj","\u002F\u002F CF Access JWT에서 추출 (email, role)\n",[2166,3425,3427,3430,3432,3435,3438,3441,3443,3446,3449,3452,3455,3458],{"class":3301,"line":3426},6,[2166,3428,3429],{"class":3305},"    if",[2166,3431,1305],{"class":3331},[2166,3433,3434],{"class":3305},"!",[2166,3436,3437],{"class":3331},"user) ",[2166,3439,3440],{"class":3305},"return",[2166,3442,3408],{"class":3331},[2166,3444,3445],{"class":3309},"json",[2166,3447,3448],{"class":3331},"({ error: ",[2166,3450,3451],{"class":3316},"'unauthorized'",[2166,3453,3454],{"class":3331}," }, ",[2166,3456,3457],{"class":3402},"401",[2166,3459,3460],{"class":3331},");\n",[2166,3462,3464,3466,3468,3470,3473,3476,3478,3481,3484,3486,3488,3490,3492,3495,3497,3500],{"class":3301,"line":3463},7,[2166,3465,3429],{"class":3305},[2166,3467,1305],{"class":3331},[2166,3469,3434],{"class":3305},[2166,3471,3472],{"class":3331},"user.email.",[2166,3474,3475],{"class":3309},"endsWith",[2166,3477,3351],{"class":3331},[2166,3479,3480],{"class":3316},"'@malgnsoft.com'",[2166,3482,3483],{"class":3331},")) ",[2166,3485,3440],{"class":3305},[2166,3487,3408],{"class":3331},[2166,3489,3445],{"class":3309},[2166,3491,3448],{"class":3331},[2166,3493,3494],{"class":3316},"'forbidden'",[2166,3496,3454],{"class":3331},[2166,3498,3499],{"class":3402},"403",[2166,3501,3460],{"class":3331},[2166,3503,3505,3507,3509,3511,3514,3517,3520,3522,3524,3526,3528,3530,3532,3534],{"class":3301,"line":3504},8,[2166,3506,3429],{"class":3305},[2166,3508,1305],{"class":3331},[2166,3510,3434],{"class":3305},[2166,3512,3513],{"class":3331},"allowed.",[2166,3515,3516],{"class":3309},"includes",[2166,3518,3519],{"class":3331},"(user.role)) ",[2166,3521,3440],{"class":3305},[2166,3523,3408],{"class":3331},[2166,3525,3445],{"class":3309},[2166,3527,3448],{"class":3331},[2166,3529,3494],{"class":3316},[2166,3531,3454],{"class":3331},[2166,3533,3499],{"class":3402},[2166,3535,3460],{"class":3331},[2166,3537,3539,3542,3545],{"class":3301,"line":3538},9,[2166,3540,3541],{"class":3305},"    await",[2166,3543,3544],{"class":3309}," next",[2166,3546,3547],{"class":3331},"();\n",[2166,3549,3551],{"class":3301,"line":3550},10,[2166,3552,3553],{"class":3331},"  };\n",[2166,3555,3557],{"class":3301,"line":3556},11,[2166,3558,3559],{"class":3331},"}\n",[24,3561,3562],{},"라우트 별 적용 예:",[135,3564,3565,3575],{},[138,3566,3567],{},[141,3568,3569,3572],{},[144,3570,3571],{},"라우트",[144,3573,3574],{},"가드",[157,3576,3577,3591,3604,3615,3625,3637,3648,3663],{},[141,3578,3579,3586],{},[162,3580,3581,2212,3584],{},[16,3582,3583],{},"POST \u002Fmaterials\u002F*",[16,3585,1491],{},[162,3587,3588],{},[16,3589,3590],{},"requireRole('admin', 'developer')",[141,3592,3593,3599],{},[162,3594,3595,2212,3597],{},[16,3596,1467],{},[16,3598,1473],{},[162,3600,3601],{},[16,3602,3603],{},"requireRole('admin', 'developer', 'agent')",[141,3605,3606,3611],{},[162,3607,3608],{},[16,3609,3610],{},"POST \u002Fstandard-answers",[162,3612,3613],{},[16,3614,3603],{},[141,3616,3617,3621],{},[162,3618,3619],{},[16,3620,2242],{},[162,3622,3623],{},[16,3624,3590],{},[141,3626,3627,3633],{},[162,3628,3629,2212,3631],{},[16,3630,2351],{},[16,3632,2357],{},[162,3634,3635],{},[16,3636,3590],{},[141,3638,3639,3644],{},[162,3640,3641],{},[16,3642,3643],{},"POST \u002Fsettings\u002F*",[162,3645,3646],{},[16,3647,3590],{},[141,3649,3650,3658],{},[162,3651,3652,2212,3655],{},[16,3653,3654],{},"POST \u002Faccounts\u002F*",[16,3656,3657],{},"PATCH \u002Faccounts\u002F:id\u002Frole",[162,3659,3660],{},[16,3661,3662],{},"requireRole('admin')",[141,3664,3665,3670],{},[162,3666,3667],{},[16,3668,3669],{},"GET \u002Faudit-logs",[162,3671,3672],{},[16,3673,3590],{},[33,3675],{},[36,3677,3679],{"id":3678},"_7-단계별-구현-우선순위-5주-기준","7. 단계별 구현 우선순위 (5주 기준)",[21,3681,3682],{},[24,3683,3684],{},"각 주차는 누적. 이전 주차 산출물 위에 추가.",[215,3686,3688],{"id":3687},"week-1-골격-인증","Week 1 — 골격 + 인증",[54,3690,3691,3694,3697,3702,3715],{},[57,3692,3693],{},"글로벌 레이아웃(사이드바·상단바·로그인 페이지)",[57,3695,3696],{},"Cloudflare Access SSO 적용 + JWT 검증 미들웨어",[57,3698,3699,3701],{},[16,3700,530],{}," 홈 (KPI 카드 mockup, 실제 데이터는 다음 주차)",[57,3703,3704,3705,2855,3707,2855,3709,2855,3711,2855,3713,78],{},"신규 테이블 5종 DDL (",[16,3706,1407],{},[16,3708,1435],{},[16,3710,2810],{},[16,3712,2941],{},[16,3714,2947],{},[57,3716,3717,2212,3719,3721],{},[16,3718,2125],{},[16,3720,77],{}," 컬럼 보강",[24,3723,3724,3727],{},[28,3725,3726],{},"산출물 검증",": 로그인 후 빈 홈 진입, 사이드바·역할 분기 동작",[215,3729,3731],{"id":3730},"week-2-표준답변-이미지-카탈로그","Week 2 — 표준답변 + 이미지 카탈로그",[54,3733,3734,3739,3745,3750],{},[57,3735,3736,3738],{},[16,3737,700],{}," 목록·상세·편집·승인 워크플로",[57,3740,3741,3744],{},[16,3742,3743],{},"\u002Fstandard-answers\u002Fsuggestions"," (자동 추출 후보 검토)",[57,3746,3747,3749],{},[16,3748,754],{}," 그리드·검색·태그·숨김",[57,3751,3752,3753,2212,3756,3758],{},"API: ",[16,3754,3755],{},"\u002Fstandard-answers\u002F:id\u002Fapprove|reject",[16,3757,3189],{}," CRUD",[24,3760,3761,3764,3765,3768],{},[28,3762,3763],{},"검증",": 운영자가 PMS에서 저장한 표준답변을 admin에서 승인, 챗봇이 ",[16,3766,3767],{},"approved","만 사용하는지 확인",[215,3770,3772],{"id":3771},"week-3-자료-업로드-인덱싱","Week 3 — 자료 업로드 + 인덱싱",[54,3774,3775,3780,3785],{},[57,3776,3777,3779],{},[16,3778,727],{}," 업로드·목록·재인덱싱·삭제",[57,3781,3752,3782,3784],{},[16,3783,727],{}," CRUD + R2 업로드 + 청크 + 임베딩 + OpenSearch 색인 (동기 MVP)",[57,3786,3787],{},"인덱싱 상태 폴링 UI",[24,3789,3790,3792,3793,3795],{},[28,3791,3763],{},": 매뉴얼 PDF 1건 업로드 → 청크 N개 색인 완료 → ",[16,3794,754],{}," 자동 채워짐",[215,3797,3799],{"id":3798},"week-4-설정-통합-모니터링","Week 4 — 설정 + 통합 모니터링",[54,3801,3802,3812,3819,3822],{},[57,3803,3804,2212,3806,2212,3808,2212,3810],{},[16,3805,941],{},[16,3807,965],{},[16,3809,989],{},[16,3811,1013],{},[57,3813,3814,2212,3816,3818],{},[16,3815,642],{},[16,3817,836],{}," (PMS와 동일 데이터, admin 톤으로 재구성)",[57,3820,3821],{},"홈 KPI 카드 실제 데이터 연동",[57,3823,3824,3825,3828],{},"자동 추출 후보(",[16,3826,3827],{},"hp_standard_answer\u002Fsuggestions",") 알림 → Slack 연동",[24,3830,3831,3833],{},[28,3832,3763],{},": 시스템 프롬프트 편집 후 챗봇·평가 호출 결과 변화 반영, 비용 임계 알림 동작",[215,3835,3837],{"id":3836},"week-5-계정권한감사-phase-2-준비","Week 5 — 계정·권한·감사 + Phase 2 준비",[54,3839,3840,3845,3850,3857],{},[57,3841,3842,3844],{},[16,3843,1068],{}," CRUD · 역할·초대",[57,3846,3847,3849],{},[16,3848,1095],{}," 감사 로그",[57,3851,3852,2212,3854,3856],{},[16,3853,615],{},[16,3855,588],{}," 페이지 골격 (Phase 2 챗봇 데이터 도착 전까지는 mockup)",[57,3858,3859,3860,3862],{},"모든 액션 감사 로그 기록 (",[16,3861,2947],{}," INSERT)",[24,3864,3865,3867],{},[28,3866,3763],{},": 운영자가 상담사 초대 → 상담사 가입 → 역할 가드 동작, 감사 로그 누적",[33,3869],{},[36,3871,3873],{"id":3872},"_8-다음-단계-이-기획서-승인-후","8. 다음 단계 (이 기획서 승인 후)",[1925,3875,3876,3888,3894,3900,3906],{},[57,3877,3878,1524,3881,3884,3885,3887],{},[28,3879,3880],{},"신규 테이블 5종 DDL 작성",[16,3882,3883],{},"\u002Fadmin\u002Fmigrate\u002F*"," 일회용 엔드포인트 (",[16,3886,77],{}," 패턴 재활용)",[57,3889,3890,3893],{},[28,3891,3892],{},"Cloudflare Access 셋업"," + admin 도메인 보호 적용",[57,3895,3896,3899],{},[28,3897,3898],{},"Week 1 골격 구현 시작"," — 사이드바·로그인·홈",[57,3901,3902,3905],{},[28,3903,3904],{},"OpenSearch 도메인 발주·셋업"," (자료 인덱싱 의존)",[57,3907,3908,3911],{},[28,3909,3910],{},"WBS 갱신"," — 본 기획의 5주차를 P1-3 \u002F P1-4 산하 task로 분해",[33,3913],{},[36,3915,3917],{"id":3916},"_9-결정-사항-기록","9. 결정 사항 기록",[135,3919,3920,3933],{},[138,3921,3922],{},[141,3923,3924,3927,3930],{},[144,3925,3926],{},"결정",[144,3928,3929],{},"일자",[144,3931,3932],{},"근거",[157,3934,3935,3949,3966,3980,3989,4002,4014,4027,4044,4076,4091,4106,4121],{},[141,3936,3937,3943,3946],{},[162,3938,3939,3940,3942],{},"사용자 = ",[28,3941,30],{}," (협력사·고객사 차단)",[162,3944,3945],{},"2026-06-08",[162,3947,3948],{},"사용자 합의",[141,3950,3951,3962,3964],{},[162,3952,3953,3954,3956,3957,3959,3960,78],{},"역할 3개 — 관리자(",[16,3955,171],{},") · 개발자(",[16,3958,189],{},") · 상담사(",[16,3961,207],{},[162,3963,3945],{},[162,3965,3948],{},[141,3967,3968,3975,3977],{},[162,3969,3970,3971,3974],{},"PMS ",[16,3972,3973],{},"\u002Fadmin\u002F*"," 페이지와 admin은 병행",[162,3976,3945],{},[162,3978,3979],{},"상담사 PMS 흐름 유지",[141,3981,3982,3985,3987],{},[162,3983,3984],{},"MVP = 챗봇 도입 전 필요한 전부 + 설정 + 계정",[162,3986,3945],{},[162,3988,3948],{},[141,3990,3991,3997,3999],{},[162,3992,3993,3994,3996],{},"인증은 Cloudflare Access SSO (",[16,3995,128],{}," 도메인 한정)",[162,3998,3945],{},[162,4000,4001],{},"직원 전용 + 기존 가이드",[141,4003,4004,4010,4012],{},[162,4005,4006,4009],{},[28,4007,4008],{},"동영상 자료는 URL 등록만",", Whisper 자막은 필요할 때 수동 트리거",[162,4011,3945],{},[162,4013,3948],{},[141,4015,4016,4022,4024],{},[162,4017,4018,4021],{},[28,4019,4020],{},"자료 보존 무기한"," (특별한 일 없는 한)",[162,4023,3945],{},[162,4025,4026],{},"사용자 합의 (자산 가치 우선)",[141,4028,4029,4039,4041],{},[162,4030,4031],{},[28,4032,4033,4034,530,4036,4038],{},"표준답변 분류 = scope(",[16,4035,1557],{},[16,4037,1569],{},") + topic + service_tag + tags",[162,4040,3945],{},[162,4042,4043],{},"사용자 합의 (도메인·SEO·일반 IT는 공통, 기능·법령은 서비스별)",[141,4045,4046,4068,4070],{},[162,4047,4048,1305,4051,530,4053,530,4056,530,4059,530,4062,530,4065,78],{},[28,4049,4050],{},"service_tag 기본 카탈로그 = LMS 패밀리 6종",[16,4052,1824],{},[16,4054,4055],{},"-refund",[16,4057,4058],{},"-public",[16,4060,4061],{},"-security",[16,4063,4064],{},"-hybrid",[16,4066,4067],{},"-global",[162,4069,3945],{},[162,4071,4072,4073,4075],{},"사용자 합의 — 같은 LMS라도 도메인 룰 달라 표준답변 분리 필요. ",[16,4074,1863],{},"는 정보보호 의무교육·ISMS-P 컴플라이언스 영역",[141,4077,4078,4086,4088],{},[162,4079,4080],{},[28,4081,4082,4083,4085],{},"AI 초안 생성 = 챗봇 응답 로직(",[16,4084,2561],{},") 재사용",[162,4087,3945],{},[162,4089,4090],{},"사용자 합의 (별도 prompt 안 만듦)",[141,4092,4093,4101,4103],{},[162,4094,4095],{},[28,4096,4097,4098,4100],{},"미커버 질문 = ",[16,4099,557],{}," 별도 전용 페이지",[162,4102,3945],{},[162,4104,4105],{},"사용자 합의 (작업 큐로 운영)",[141,4107,4108,4116,4118],{},[162,4109,4110],{},[28,4111,4112,4113,4115],{},"표준답변 작성 시 ",[16,4114,77],{}," 자동 추천·삽입",[162,4117,3945],{},[162,4119,4120],{},"사용자 합의 (이미지 캡션·설명 활용)",[141,4122,4123,4126,4128],{},[162,4124,4125],{},"다크모드 비활성 (CSS body bg 라이트 고정)",[162,4127,3945],{},[162,4129,4130],{},"PMS와 일관",[215,4132,4134],{"id":4133},"운영-정책-기본값-추가-합의-없을-시-적용","운영 정책 기본값 (추가 합의 없을 시 적용)",[135,4136,4137,4149],{},[138,4138,4139],{},[141,4140,4141,4144,4147],{},[144,4142,4143],{},"항목",[144,4145,4146],{},"기본값",[144,4148,3932],{},[157,4150,4151,4174,4191,4206,4219,4235],{},[141,4152,4153,4158,4171],{},[162,4154,4155],{},[28,4156,4157],{},"미커버 질문(uncovered) 알림 임계값",[162,4159,4160,4163,4164,4167,4168],{},[28,4161,4162],{},"챗봇(Phase 2)이 \"모름\"으로 분기","하거나 신뢰도 \u003C 0.5로 응답한 질문 중, 같은 의미가 ",[28,4165,4166],{},"주 3건"," 이상 누적되면 표준답변 후보로 큐 등록 + Slack DM. ",[2369,4169,4170],{},"답변 없는 게시물(inquiry-only)과는 별개 — 게시물은 이미 PMS에서 상담사가 처리",[162,4172,4173],{},"챗봇 지식 베이스의 구멍을 자료·표준답변 보강 신호로 환산",[141,4175,4176,4181,4188],{},[162,4177,4178],{},[28,4179,4180],{},"미커버 알림 채널",[162,4182,4183,4184,4187],{},"Slack ",[16,4185,4186],{},"#cs-helper-ops"," 채널 (Webhook 등록 후) — 부재 시 admin 홈의 \"후보 알림\" 카드만",[162,4189,4190],{},"외부 의존 최소화",[141,4192,4193,4198,4203],{},[162,4194,4195],{},[28,4196,4197],{},"상담사 답변 작성 시 AI 초안",[162,4199,4200,4202],{},[28,4201,2575],{},"에 \"초안 생성\" 버튼 (선택). 표준답변 등록 화면에는 없음(이미 LLM이 생성한 6개 변형이 PMS 측에 있음)",[162,4204,4205],{},"에스컬레이션 = 진짜 새 답변, 표준답변 = 큐레이션",[141,4207,4208,4213,4216],{},[162,4209,4210],{},[28,4211,4212],{},"데이터 보존 — 챗 로그",[162,4214,4215],{},"메시지 본문 90일 \u002F 메타(세션·피드백·신뢰도) 1년 \u002F 1년 후 익명화 후 통계 보관",[162,4217,4218],{},"개인정보 최소화 + 품질 평가용 보존",[141,4220,4221,4226,4232],{},[162,4222,4223],{},[28,4224,4225],{},"데이터 보존 — 자료",[162,4227,4228,4231],{},[28,4229,4230],{},"특별한 일이 없는 한 무기한 보관"," (soft delete + 영구 삭제는 운영자가 명시적으로 트리거). 청크·임베딩은 즉시 OpenSearch에서 제거",[162,4233,4234],{},"자산 가치 우선 (사용자 결정 — 챗봇 학습 베이스)",[141,4236,4237,4242,4245],{},[162,4238,4239],{},[28,4240,4241],{},"데이터 보존 — 표준답변·이미지",[162,4243,4244],{},"무기한 soft delete (수동 영구 삭제만 가능)",[162,4246,4247],{},"자산 가치 우선",[33,4249],{},[36,4251,4253],{"id":4252},"_10-열린-질문-확정-전","10. 열린 질문 (확정 전)",[24,4255,4256],{},"남아있는 결정 없음 — 모든 항목 §9 기본값으로 확정. 운영 중 조정 시 §9의 \"기본값\"을 갱신하고 history에 기록.",[4258,4259,4260],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":423,"searchDepth":3342,"depth":3342,"links":4262},[4263,4264,4268,4282,4319,4324,4328,4335,4336,4339],{"id":38,"depth":3335,"text":39},{"id":118,"depth":3335,"text":119,"children":4265},[4266,4267],{"id":217,"depth":3342,"text":218},{"id":380,"depth":3342,"text":381},{"id":412,"depth":3335,"text":413,"children":4269},[4270,4271,4278,4279,4280],{"id":426,"depth":3342,"text":427},{"id":456,"depth":3342,"text":457,"children":4272},[4273,4274,4275,4276,4277],{"id":484,"depth":3368,"text":485},{"id":659,"depth":3368,"text":660},{"id":798,"depth":3368,"text":799},{"id":905,"depth":3368,"text":906},{"id":1027,"depth":3368,"text":1028},{"id":1138,"depth":3342,"text":1139},{"id":1148,"depth":3342,"text":1149},{"id":1186,"depth":3342,"text":4281},"3-5. 신규 카탈로그 페이지 — \u002Fcatalog (그룹 2.4)",{"id":1204,"depth":3335,"text":1205,"children":4283},[4284,4286,4288,4298,4300,4302,4304,4305,4307,4309,4311,4313,4315,4317],{"id":1208,"depth":3342,"text":4285},"4-1. 홈 — \u002F",{"id":1272,"depth":3342,"text":4287},"4-2. 자료 관리 — \u002Fmaterials",{"id":1510,"depth":3342,"text":4289,"children":4290},"4-3. 표준답변 관리 — \u002Fstandard-answers",[4291,4292,4293,4295,4297],{"id":1516,"depth":3368,"text":1517},{"id":1965,"depth":3368,"text":1966},{"id":2020,"depth":3368,"text":4294},"4-3-3. 이미지 자동 배치 (hp_image_asset 활용)",{"id":2121,"depth":3368,"text":4296},"4-3-4. 스키마 보강 (hp_standard_answer)",{"id":2203,"depth":3368,"text":2204},{"id":2266,"depth":3342,"text":4299},"4-4. 이미지 카탈로그 — \u002Fimages",{"id":2363,"depth":3342,"text":4301},"4-5. 챗봇 응답 로그 — \u002Fchat-logs (Phase 2 준비)",{"id":2399,"depth":3342,"text":4303},"4-5-1. 미커버 질문 — \u002Funcovered (Phase 2 준비, 별도 전용 페이지)",{"id":2548,"depth":3342,"text":2549},{"id":2683,"depth":3342,"text":4306},"4-6. 에스컬레이션 큐 — \u002Fescalations (Phase 2 준비)",{"id":2723,"depth":3342,"text":4308},"4-7. Q&A 평가 \u002F LLM 비용 — \u002Fqa-evals · \u002Fcost",{"id":2756,"depth":3342,"text":4310},"4-8. AI 설정 — \u002Fsettings\u002Fai",{"id":2822,"depth":3342,"text":4312},"4-9. 안전 가드 — \u002Fsettings\u002Fsafety",{"id":2844,"depth":3342,"text":4314},"4-10. 캐싱 — \u002Fsettings\u002Fcache",{"id":2875,"depth":3342,"text":4316},"4-11. 외부 연동 — \u002Fsettings\u002Fintegrations",{"id":2909,"depth":3342,"text":4318},"4-12. 계정·권한 — \u002Faccounts",{"id":2959,"depth":3335,"text":2960,"children":4320},[4321,4322,4323],{"id":2963,"depth":3342,"text":2964},{"id":3119,"depth":3342,"text":3120},{"id":3156,"depth":3342,"text":3157},{"id":3245,"depth":3335,"text":3246,"children":4325},[4326,4327],{"id":3249,"depth":3342,"text":3250},{"id":3287,"depth":3342,"text":3288},{"id":3678,"depth":3335,"text":3679,"children":4329},[4330,4331,4332,4333,4334],{"id":3687,"depth":3342,"text":3688},{"id":3730,"depth":3342,"text":3731},{"id":3771,"depth":3342,"text":3772},{"id":3798,"depth":3342,"text":3799},{"id":3836,"depth":3342,"text":3837},{"id":3872,"depth":3335,"text":3873},{"id":3916,"depth":3335,"text":3917,"children":4337},[4338],{"id":4133,"depth":3342,"text":4134},{"id":4252,"depth":3335,"text":4253},"md",{},"\u002Fadmin-plan",{"title":6,"description":423},"ADMIN-PLAN","jbwozLXFNt4cA0XJVU1msQ5ZteYm6UK-mkkhssXeExc",{"id":4347,"title":4348,"body":4349,"description":4356,"extension":4340,"meta":4904,"navigation":3338,"path":4905,"seo":4906,"stem":4907,"__hash__":4908},"docs\u002FCLAUDE.md","Malgn Helper — 고객상담 AI 챗봇",{"type":8,"value":4350,"toc":4892},[4351,4354,4357,4361,4364,4422,4426,4463,4467,4546,4550,4556,4560,4597,4601,4620,4624,4630,4657,4713,4717,4787,4790,4889],[11,4352,4348],{"id":4353},"malgn-helper-고객상담-ai-챗봇",[24,4355,4356],{},"NotebookLM 수준의 사내 솔루션 전문 고객상담 AI 챗봇.\n자사 솔루션 사용 방법·안내를 자동화하여 상담 비용을 절감하고 24\u002F7 응답 채널을 확보한다.",[36,4358,4360],{"id":4359},"프로젝트-구성","프로젝트 구성",[24,4362,4363],{},"이 워크스페이스는 역할별로 5개의 독립 디렉토리로 분리되어 있다 (제품 4 + 관리 허브 1).",[54,4365,4366,4375,4384,4393,4413],{},[57,4367,4368,2448,4371,4374],{},[16,4369,4370],{},"malgn-helper\u002F",[28,4372,4373],{},"사용자 프론트엔드"," (고객이 챗봇과 대화하는 화면). Nuxt 3 \u002F Cloudflare Pages.",[57,4376,4377,2448,4380,4383],{},[16,4378,4379],{},"malgn-helper-admin\u002F",[28,4381,4382],{},"관리자 프론트엔드"," (자료 업로드, 표준 답변 관리, 상담 로그\u002F에스컬레이션 검토).",[57,4385,4386,2448,4389,4392],{},[16,4387,4388],{},"malgn-helper-api\u002F",[28,4390,4391],{},"API 서버"," (Hono on Cloudflare Workers). 검색·LLM·DB 접근을 모두 담당.",[57,4394,4395,2448,4398,4401,4402,4405,4406,1524,4409,4412],{},[16,4396,4397],{},"malgn-helper-pms\u002F",[28,4399,4400],{},"PMS 애드온"," (맑은프로젝트게시판 PMS에 탑재되는 상담사 도우미). PMS 내부에서 동작하며 ",[16,4403,4404],{},"malgn-helper-api","를 호출해 ",[28,4407,4408],{},"고객 문의 답변 추천",[28,4410,4411],{},"고객 문의 분석\u002F브리핑","을 PMS 상담사에게 제공.",[57,4414,4415,2448,4418,4421],{},[16,4416,4417],{},"malgn-helper-mng\u002F",[28,4419,4420],{},"프로젝트 관리 허브"," (대시보드·현황판·WBS·문서·작업 이력). 제품 코드가 아닌 이 프로젝트의 운영·조망용. Nuxt 3 \u002F Cloudflare Pages + D1.",[36,4423,4425],{"id":4424},"핵심-요구사항","핵심 요구사항",[54,4427,4428,4434,4440,4446,4452,4458],{},[57,4429,4430,4433],{},[28,4431,4432],{},"NotebookLM 수준의 답변 품질",": 업로드된 자료에 근거한 정확한 답변 + 출처 인용",[57,4435,4436,4439],{},[28,4437,4438],{},"정확성·일관성 우선",": 같은 질문에 매번 같은 답변, 잘못된 안내 방지",[57,4441,4442,4445],{},[28,4443,4444],{},"표준 답변 우선 사용",": 회사가 검증한 답변이 있으면 그것을 사용",[57,4447,4448,4451],{},[28,4449,4450],{},"\"모르면 모른다\"",": 추측 금지. 모호하면 상담사에게 에스컬레이션",[57,4453,4454,4457],{},[28,4455,4456],{},"데이터 소스",": 매뉴얼 문서, 동영상, 기존 Q&A DB",[57,4459,4460],{},[28,4461,4462],{},"한국어 컨텐츠 비중 높음",[36,4464,4466],{"id":4465},"인프라-제약","인프라 제약",[54,4468,4469,4476,4486,4493,4499,4510],{},[57,4470,4471,4472,4475],{},"프론트엔드\u002F백엔드는 ",[28,4473,4474],{},"Cloudflare"," (Pages + Workers)",[57,4477,4478,4479,105,4482,4485],{},"RDB는 ",[28,4480,4481],{},"Aurora MySQL",[28,4483,4484],{},"Hyperdrive","로 연결",[57,4487,4488,4489,4492],{},"검색 인프라는 외부 ",[28,4490,4491],{},"AWS OpenSearch Service"," (k-NN + BM25 하이브리드)",[57,4494,4495,4496],{},"원본 파일 저장소는 ",[28,4497,4498],{},"Cloudflare R2",[57,4500,4501,4502,4505,4506,4509],{},"인덱싱은 ",[28,4503,4504],{},"MVP에서 동기 처리",". 동영상\u002F대용량 자료가 늘어나면 ",[28,4507,4508],{},"Cloudflare Queues + Indexer Worker","로 2단계 도입.",[57,4511,4512,4513,1358,4516,4519,4520,4523,4524,4527,4528],{},"LLM 호출은 ",[28,4514,4515],{},"Cloudflare AI Gateway",[28,4517,4518],{},"OpenAI"," (기본 ",[16,4521,4522],{},"gpt-4o-mini",", 고품질 작업은 ",[16,4525,4526],{},"gpt-4o",")\n",[54,4529,4530,4535],{},[57,4531,4532,4533],{},"Gateway 이름: ",[16,4534,47],{},[57,4536,4537,4538,4541,4542,4545],{},"Worker 환경변수: ",[16,4539,4540],{},"AI_GATEWAY_URL"," (vars), ",[16,4543,4544],{},"OPENAI_API_KEY"," (secret)",[36,4547,4549],{"id":4548},"데이터-흐름","데이터 흐름",[415,4551,4554],{"className":4552,"code":4553,"language":420},[418],"사용자 브라우저       관리자 브라우저       PMS 상담사 화면\n      │                  │                      │\n      ▼                  ▼                      ▼\nmalgn-helper      malgn-helper-admin       malgn-helper-pms\n(Nuxt 3 \u002F Pages)  (Nuxt 3 \u002F Pages)         (Nuxt 3 \u002F Pages, PMS 임베드)\n      │                  │                      │\n      └──────────────────┼──────────────────────┘\n                         ▼\n                  malgn-helper-api\n                  (Hono \u002F Workers)\n                         │\n         ┌───────────────┼───────────────┐\n         ▼               ▼               ▼\n   Hyperdrive       OpenSearch           R2\n      │             (k-NN+BM25)       (원본파일)\n      ▼\n Aurora MySQL\n\n                         ▼\n                  AI Gateway → OpenAI\n\n  ※ 향후 동영상\u002F대용량 자료 도입 시:\n    Queue → Indexer Worker 비동기 파이프라인 추가\n",[16,4555,4553],{"__ignoreMap":423},[36,4557,4559],{"id":4558},"작업-시-유의사항","작업 시 유의사항",[54,4561,4562,4569,4572,4575,4578,4581,4584],{},[57,4563,4564,4565,4568],{},"답변 생성 로직은 ",[28,4566,4567],{},"출처 인용이 누락되지 않도록"," 보장한다.",[57,4570,4571],{},"검색은 하이브리드(벡터 + BM25)를 전제로 한다. 한쪽만 쓰는 변경은 의도와 영향 범위를 명확히.",[57,4573,4574],{},"\"표준 답변\" 매칭이 검색·생성 파이프라인보다 우선한다.",[57,4576,4577],{},"LLM이 자신 없을 때는 답변을 짜내지 말고 에스컬레이션 경로로 빠진다.",[57,4579,4580],{},"DB 접근은 Worker → Hyperdrive 경유. 직접 연결 코드 금지.",[57,4582,4583],{},"모든 LLM 호출은 AI Gateway를 통과시켜 캐싱·로깅·rate limit을 적용한다.",[57,4585,4586,4589,4590,4593,4594,4596],{},[16,4587,4588],{},"malgn-helper-pms","는 PMS 시스템 내부에서 동작하지만 ",[28,4591,4592],{},"DB·LLM 직접 접근 금지"," — 반드시 ",[16,4595,4404],{},"를 통해 호출한다 (인증\u002F권한·로깅 일원화).",[36,4598,4600],{"id":4599},"배포-절차","배포 절차",[24,4602,4603,4604,1365,4606,1365,4609,1365,4612,4615,4616,4619],{},"서브프로젝트(",[16,4605,47],{},[16,4607,4608],{},"-admin",[16,4610,4611],{},"-api",[16,4613,4614],{},"-pms",") 배포 시 ",[28,4617,4618],{},"커밋 → 푸시 → Cloudflare deploy → 이력 기록","을 일괄 처리한다.",[215,4621,4623],{"id":4622},"일괄-스크립트-권장","일괄 스크립트 (권장)",[24,4625,4626,4627,4629],{},"워크스페이스 루트(",[16,4628,47],{},")에서:",[415,4631,4635],{"className":4632,"code":4633,"language":4634,"meta":423,"style":423},"language-bash shiki shiki-themes github-light github-dark",".\u002Fscripts\u002Fdeploy.sh \u003Crepo-name> \"\u003Ccommit message>\"\n","bash",[16,4636,4637],{"__ignoreMap":423},[2166,4638,4639,4642,4645,4648,4651,4654],{"class":3301,"line":3302},[2166,4640,4641],{"class":3309},".\u002Fscripts\u002Fdeploy.sh",[2166,4643,4644],{"class":3305}," \u003C",[2166,4646,4647],{"class":3316},"repo-nam",[2166,4649,4650],{"class":3331},"e",[2166,4652,4653],{"class":3305},">",[2166,4655,4656],{"class":3316}," \"\u003Ccommit message>\"\n",[54,4658,4659,4677],{},[57,4660,4661,4664,4665,4667,4668,4667,4670,4667,4672,4667,4674],{},[16,4662,4663],{},"\u003Crepo-name>",": ",[16,4666,47],{}," | ",[16,4669,18],{},[16,4671,4404],{},[16,4673,4588],{},[16,4675,4676],{},"malgn-helper-mng",[57,4678,4679,4680],{},"스크립트가 자동 실행하는 4단계:\n",[1925,4681,4682,4688,4693,4703],{},[57,4683,4684,4687],{},[16,4685,4686],{},"git add -A && git commit -m \"\u003Cmessage>\""," (변경 없으면 commit skip)",[57,4689,4690],{},[16,4691,4692],{},"git push",[57,4694,4695,4696,2448,4699,4702],{},"해당 repo에서 ",[16,4697,4698],{},"pnpm deploy",[16,4700,4701],{},"wrangler.toml"," 존재 여부로 Pages\u002FWorkers 자동 분기",[57,4704,4705,4708,4709,4712],{},[16,4706,4707],{},"doc\u002Fhistory\u002Fhistory.{yyyyMMdd}.md","의 ",[16,4710,4711],{},"## 배포"," 섹션에 항목 append (파일 없으면 생성)",[215,4714,4716],{"id":4715},"수동-절차-스크립트-미사용-시","수동 절차 (스크립트 미사용 시)",[415,4718,4720],{"className":4632,"code":4719,"language":4634,"meta":423,"style":423},"cd ~\u002FProjects\u002F\u003Crepo>\ngit add . && git commit -m \"\u003Cmessage>\"\ngit push\npnpm deploy\n# doc\u002Fhistory\u002Fhistory.{yyyyMMdd}.md에 배포 항목 직접 추가\n",[16,4721,4722,4742,4767,4774,4782],{"__ignoreMap":423},[2166,4723,4724,4727,4730,4733,4736,4739],{"class":3301,"line":3302},[2166,4725,4726],{"class":3402},"cd",[2166,4728,4729],{"class":3316}," ~\u002FProjects\u002F",[2166,4731,4732],{"class":3305},"\u003C",[2166,4734,4735],{"class":3316},"rep",[2166,4737,4738],{"class":3331},"o",[2166,4740,4741],{"class":3305},">\n",[2166,4743,4744,4747,4750,4753,4756,4758,4761,4764],{"class":3301,"line":3335},[2166,4745,4746],{"class":3309},"git",[2166,4748,4749],{"class":3316}," add",[2166,4751,4752],{"class":3316}," .",[2166,4754,4755],{"class":3331}," && ",[2166,4757,4746],{"class":3309},[2166,4759,4760],{"class":3316}," commit",[2166,4762,4763],{"class":3402}," -m",[2166,4765,4766],{"class":3316}," \"\u003Cmessage>\"\n",[2166,4768,4769,4771],{"class":3301,"line":3342},[2166,4770,4746],{"class":3309},[2166,4772,4773],{"class":3316}," push\n",[2166,4775,4776,4779],{"class":3301,"line":3368},[2166,4777,4778],{"class":3309},"pnpm",[2166,4780,4781],{"class":3316}," deploy\n",[2166,4783,4784],{"class":3301,"line":3396},[2166,4785,4786],{"class":3422},"# doc\u002Fhistory\u002Fhistory.{yyyyMMdd}.md에 배포 항목 직접 추가\n",[215,4788,4789],{"id":4789},"규칙",[54,4791,4792,4795,4802,4805,4808,4853,4871],{},[57,4793,4794],{},"변경된 repo만 배포. 전체 일괄 배포 금지.",[57,4796,4797,4798,4801],{},"Secret 변경은 별도 — ",[16,4799,4800],{},"wrangler secret put \u003CKEY>"," 후 deploy.",[57,4803,4804],{},"배포 실패 시 history에 실패 사유 함께 기록.",[57,4806,4807],{},"이력 파일은 누적 — 같은 날 추가 배포는 기존 파일에 항목만 추가.",[57,4809,4810,4813,4814],{},[28,4811,4812],{},"account_id 주입 방식",":\n",[54,4815,4816,4827,4846],{},[57,4817,4818,4819,4822,4823,4826],{},"Workers (",[16,4820,4821],{},"wrangler.jsonc",")는 ",[16,4824,4825],{},"account_id"," 필드를 지원 → 파일에 명시.",[57,4828,4829,4830,4822,4832,4834,4835,1358,4838,4841,4842,4845],{},"Pages (",[16,4831,4701],{},[16,4833,4825],{}," 필드 ",[28,4836,4837],{},"미지원",[16,4839,4840],{},"scripts\u002Fdeploy.sh","에서 ",[16,4843,4844],{},"CLOUDFLARE_ACCOUNT_ID"," 환경변수로 주입.",[57,4847,4848,4849,4852],{},"수동 배포 시 Pages는 ",[16,4850,4851],{},"CLOUDFLARE_ACCOUNT_ID=... pnpm run deploy"," 형태로 실행 필요.",[57,4854,4855,2448,4863,4866,4867,4870],{},[28,4856,4857,4859,4860],{},[16,4858,4698],{}," 대신 ",[16,4861,4862],{},"pnpm run deploy",[16,4864,4865],{},"deploy","는 pnpm 예약어라 충돌. 항상 ",[16,4868,4869],{},"run","을 명시.",[57,4872,4873,2448,4879,4708,4881,4884,4885,4888],{},[28,4874,4875,4876],{},"Nuxt Cloudflare Pages 출력 디렉토리는 ",[16,4877,4878],{},"dist\u002F",[16,4880,4701],{},[16,4882,4883],{},"pages_build_output_dir","도 ",[16,4886,4887],{},"dist","로 설정.",[4258,4890,4891],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":423,"searchDepth":3342,"depth":3342,"links":4893},[4894,4895,4896,4897,4898,4899],{"id":4359,"depth":3335,"text":4360},{"id":4424,"depth":3335,"text":4425},{"id":4465,"depth":3335,"text":4466},{"id":4548,"depth":3335,"text":4549},{"id":4558,"depth":3335,"text":4559},{"id":4599,"depth":3335,"text":4600,"children":4900},[4901,4902,4903],{"id":4622,"depth":3342,"text":4623},{"id":4715,"depth":3342,"text":4716},{"id":4789,"depth":3342,"text":4789},{},"\u002Fclaude",{"title":4348,"description":4356},"CLAUDE","E4oqMVxN36p86l5LbGwi2v2lD72KLSVEDn4itTZFyTI",{"id":4910,"title":4911,"body":4912,"description":5759,"extension":4340,"meta":5760,"navigation":3338,"path":5761,"seo":5762,"stem":3259,"__hash__":5763},"docs\u002FCLOUDFLARE-ACCESS.md","Cloudflare Access — \u002Fadmin\u002F* 보호 가이드",{"type":8,"value":4913,"toc":5743},[4914,4921,4929,4938,4940,4944,5002,5004,5008,5031,5033,5037,5041,5158,5162,5165,5187,5189,5193,5200,5462,5465,5545,5548,5550,5554,5560,5567,5597,5600,5602,5608,5627,5629,5633,5680,5682,5686,5697,5699,5702,5713,5715,5717,5740],[11,4915,4917,4918,4920],{"id":4916},"cloudflare-access-admin-보호-가이드","Cloudflare Access — ",[16,4919,3973],{}," 보호 가이드",[24,4922,4923,4925,4926,4928],{},[16,4924,3973],{}," 라우트(현재: ",[16,4927,104],{},")와 함께 모든 노출 위험 페이지·API를 Cloudflare Access로 보호하는 단계별 가이드.",[21,4930,4931],{},[24,4932,4933,4934,4937],{},"현재 상태: ",[28,4935,4936],{},"무인증",". URL을 아는 사람은 누구나 비용·DB 탐색 엔드포인트에 접근 가능. 사내 운영 중에는 OK이지만, 공개 도메인에 둘 거라면 반드시 적용해야 한다.",[33,4939],{},[36,4941,4943],{"id":4942},"보호-대상","보호 대상",[135,4945,4946,4958],{},[138,4947,4948],{},[141,4949,4950,4953,4956],{},[144,4951,4952],{},"자원",[144,4954,4955],{},"호스트",[144,4957,503],{},[157,4959,4960,4974,4988],{},[141,4961,4962,4965,4970],{},[162,4963,4964],{},"LLM 비용 대시보드",[162,4966,4967],{},[16,4968,4969],{},"malgn-helper-pms.pages.dev",[162,4971,4972],{},[16,4973,3973],{},[141,4975,4976,4979,4984],{},[162,4977,4978],{},"비용 집계 API",[162,4980,4981],{},[16,4982,4983],{},"malgn-helper-api.malgnsoft.workers.dev",[162,4985,4986],{},[16,4987,3973],{},[141,4989,4990,4993,4997],{},[162,4991,4992],{},"DB 탐색 임시 엔드포인트",[162,4994,4995],{},[16,4996,4983],{},[162,4998,4999],{},[16,5000,5001],{},"\u002Fdb\u002F*",[33,5003],{},[36,5005,5007],{"id":5006},"사전-준비","사전 준비",[1925,5009,5010,5013],{},[57,5011,5012],{},"Cloudflare Zero Trust 무료 플랜 활성화 (월 50명까지)",[57,5014,5015,5016],{},"보호할 도메인이 Cloudflare에 등록되어 있어야 함\n",[54,5017,5018,5028],{},[57,5019,5020,5023,5024,5027],{},[16,5021,5022],{},"*.pages.dev"," 와 ",[16,5025,5026],{},"*.workers.dev","는 기본적으로 Access 적용 가능",[57,5029,5030],{},"커스텀 도메인이면 해당 zone 등록 필요",[33,5032],{},[36,5034,5036],{"id":5035},"_1-access-application-만들기","1) Access Application 만들기",[215,5038,5040],{"id":5039},"pages-페이지-pms-보호","Pages 페이지 (PMS) 보호",[1925,5042,5043,5063,5108,5114],{},[57,5044,5045,5050,5051,1358,5054,1358,5057,1358,5060],{},[3257,5046,5047],{"href":5047,"rel":5048},"https:\u002F\u002Fone.dash.cloudflare.com",[5049],"nofollow"," → 좌측 ",[28,5052,5053],{},"Access",[28,5055,5056],{},"Applications",[28,5058,5059],{},"Add an application",[28,5061,5062],{},"Self-hosted",[57,5064,5065,5066],{},"입력:\n",[54,5067,5068,5076,5085],{},[57,5069,5070,4664,5073],{},[28,5071,5072],{},"Application name",[16,5074,5075],{},"malgn-helper-pms admin",[57,5077,5078,4664,5081,5084],{},[28,5079,5080],{},"Session Duration",[16,5082,5083],{},"24h"," (또는 원하는 값)",[57,5086,5087,4813,5090],{},[28,5088,5089],{},"Application domain",[54,5091,5092,5097,5103],{},[57,5093,5094,5095],{},"Subdomain: ",[16,5096,4588],{},[57,5098,5099,5100],{},"Domain: ",[16,5101,5102],{},"pages.dev",[57,5104,5105,5106],{},"Path: ",[16,5107,3973],{},[57,5109,5110,5113],{},[28,5111,5112],{},"Identity providers",": One-time PIN (이메일 OTP) 또는 회사 SSO(Google Workspace\u002FOkta 등)",[57,5115,5116,4813,5119],{},[28,5117,5118],{},"Add a policy",[54,5120,5121,5129,5137,5151],{},[57,5122,5123,4664,5126],{},[28,5124,5125],{},"Policy name",[16,5127,5128],{},"staff only",[57,5130,5131,4664,5134],{},[28,5132,5133],{},"Action",[16,5135,5136],{},"Allow",[57,5138,5139,4813,5142],{},[28,5140,5141],{},"Include",[54,5143,5144],{},[57,5145,5146,1358,5149],{},[16,5147,5148],{},"Emails ending in",[16,5150,128],{},[57,5152,5153,5154,5157],{},"또는: ",[16,5155,5156],{},"Emails"," → 명시적 화이트리스트",[215,5159,5161],{"id":5160},"api-worker-보호","API Worker 보호",[24,5163,5164],{},"같은 절차로 두 번째 Application 추가:",[54,5166,5167,5171,5176,5184],{},[57,5168,5094,5169],{},[16,5170,4404],{},[57,5172,5099,5173],{},[16,5174,5175],{},"workers.dev",[57,5177,5105,5178,5180,5181,5183],{},[16,5179,3973],{}," (또는 ",[16,5182,5001],{},"까지 보호하려면 추가 Application)",[57,5185,5186],{},"동일 policy 적용",[33,5188],{},[36,5190,5192],{"id":5191},"_2-worker가-access-jwt를-검증하도록-옵션-강력-권장","2) Worker가 Access JWT를 검증하도록 (옵션, 강력 권장)",[24,5194,5195,5196,5199],{},"Access를 켜도 ",[2369,5197,5198],{},"직접 Worker 도메인 IP에 도달하는 우회 요청","은 막을 수 없다. Worker 측에서 한 번 더 검증해야 완전:",[415,5201,5203],{"className":3294,"code":5202,"language":3296,"meta":423,"style":423},"\u002F\u002F src\u002Fmiddleware\u002Faccess.ts\nimport { jwtVerify, createRemoteJWKSet } from \"jose\";\n\nconst JWKS = createRemoteJWKSet(\n  new URL(\"https:\u002F\u002F\u003Cteam>.cloudflareaccess.com\u002Fcdn-cgi\u002Faccess\u002Fcerts\"),\n);\nconst AUD = \"\u003Capplication-aud-tag>\"; \u002F\u002F Access Application의 AUD\n\nexport async function requireAccess(c: any) {\n  const token = c.req.header(\"cf-access-jwt-assertion\");\n  if (!token) return c.json({ error: \"no-access-jwt\" }, 401);\n  try {\n    await jwtVerify(token, JWKS, {\n      issuer: \"https:\u002F\u002F\u003Cteam>.cloudflareaccess.com\",\n      audience: AUD,\n    });\n  } catch {\n    return c.json({ error: \"invalid-access-jwt\" }, 401);\n  }\n}\n",[16,5204,5205,5210,5226,5230,5246,5262,5266,5284,5288,5313,5336,5365,5373,5390,5402,5413,5419,5430,5451,5457],{"__ignoreMap":423},[2166,5206,5207],{"class":3301,"line":3302},[2166,5208,5209],{"class":3422},"\u002F\u002F src\u002Fmiddleware\u002Faccess.ts\n",[2166,5211,5212,5215,5218,5221,5224],{"class":3301,"line":3335},[2166,5213,5214],{"class":3305},"import",[2166,5216,5217],{"class":3331}," { jwtVerify, createRemoteJWKSet } ",[2166,5219,5220],{"class":3305},"from",[2166,5222,5223],{"class":3316}," \"jose\"",[2166,5225,3332],{"class":3331},[2166,5227,5228],{"class":3301,"line":3342},[2166,5229,3339],{"emptyLinePlaceholder":3338},[2166,5231,5232,5235,5238,5240,5243],{"class":3301,"line":3368},[2166,5233,5234],{"class":3305},"const",[2166,5236,5237],{"class":3402}," JWKS",[2166,5239,3313],{"class":3305},[2166,5241,5242],{"class":3309}," createRemoteJWKSet",[2166,5244,5245],{"class":3331},"(\n",[2166,5247,5248,5251,5254,5256,5259],{"class":3301,"line":3396},[2166,5249,5250],{"class":3305},"  new",[2166,5252,5253],{"class":3309}," URL",[2166,5255,3351],{"class":3331},[2166,5257,5258],{"class":3316},"\"https:\u002F\u002F\u003Cteam>.cloudflareaccess.com\u002Fcdn-cgi\u002Faccess\u002Fcerts\"",[2166,5260,5261],{"class":3331},"),\n",[2166,5263,5264],{"class":3301,"line":3426},[2166,5265,3460],{"class":3331},[2166,5267,5268,5270,5273,5275,5278,5281],{"class":3301,"line":3463},[2166,5269,5234],{"class":3305},[2166,5271,5272],{"class":3402}," AUD",[2166,5274,3313],{"class":3305},[2166,5276,5277],{"class":3316}," \"\u003Capplication-aud-tag>\"",[2166,5279,5280],{"class":3331},"; ",[2166,5282,5283],{"class":3422},"\u002F\u002F Access Application의 AUD\n",[2166,5285,5286],{"class":3301,"line":3504},[2166,5287,3339],{"emptyLinePlaceholder":3338},[2166,5289,5290,5293,5295,5298,5301,5303,5305,5307,5310],{"class":3301,"line":3538},[2166,5291,5292],{"class":3305},"export",[2166,5294,3374],{"class":3305},[2166,5296,5297],{"class":3305}," function",[2166,5299,5300],{"class":3309}," requireAccess",[2166,5302,3351],{"class":3331},[2166,5304,3379],{"class":3356},[2166,5306,3360],{"class":3305},[2166,5308,5309],{"class":3402}," any",[2166,5311,5312],{"class":3331},") {\n",[2166,5314,5315,5318,5321,5323,5326,5329,5331,5334],{"class":3301,"line":3550},[2166,5316,5317],{"class":3305},"  const",[2166,5319,5320],{"class":3402}," token",[2166,5322,3313],{"class":3305},[2166,5324,5325],{"class":3331}," c.req.",[2166,5327,5328],{"class":3309},"header",[2166,5330,3351],{"class":3331},[2166,5332,5333],{"class":3316},"\"cf-access-jwt-assertion\"",[2166,5335,3460],{"class":3331},[2166,5337,5338,5341,5343,5345,5348,5350,5352,5354,5356,5359,5361,5363],{"class":3301,"line":3556},[2166,5339,5340],{"class":3305},"  if",[2166,5342,1305],{"class":3331},[2166,5344,3434],{"class":3305},[2166,5346,5347],{"class":3331},"token) ",[2166,5349,3440],{"class":3305},[2166,5351,3408],{"class":3331},[2166,5353,3445],{"class":3309},[2166,5355,3448],{"class":3331},[2166,5357,5358],{"class":3316},"\"no-access-jwt\"",[2166,5360,3454],{"class":3331},[2166,5362,3457],{"class":3402},[2166,5364,3460],{"class":3331},[2166,5366,5368,5371],{"class":3301,"line":5367},12,[2166,5369,5370],{"class":3305},"  try",[2166,5372,3393],{"class":3331},[2166,5374,5376,5378,5381,5384,5387],{"class":3301,"line":5375},13,[2166,5377,3541],{"class":3305},[2166,5379,5380],{"class":3309}," jwtVerify",[2166,5382,5383],{"class":3331},"(token, ",[2166,5385,5386],{"class":3402},"JWKS",[2166,5388,5389],{"class":3331},", {\n",[2166,5391,5393,5396,5399],{"class":3301,"line":5392},14,[2166,5394,5395],{"class":3331},"      issuer: ",[2166,5397,5398],{"class":3316},"\"https:\u002F\u002F\u003Cteam>.cloudflareaccess.com\"",[2166,5400,5401],{"class":3331},",\n",[2166,5403,5405,5408,5411],{"class":3301,"line":5404},15,[2166,5406,5407],{"class":3331},"      audience: ",[2166,5409,5410],{"class":3402},"AUD",[2166,5412,5401],{"class":3331},[2166,5414,5416],{"class":3301,"line":5415},16,[2166,5417,5418],{"class":3331},"    });\n",[2166,5420,5422,5425,5428],{"class":3301,"line":5421},17,[2166,5423,5424],{"class":3331},"  } ",[2166,5426,5427],{"class":3305},"catch",[2166,5429,3393],{"class":3331},[2166,5431,5433,5436,5438,5440,5442,5445,5447,5449],{"class":3301,"line":5432},18,[2166,5434,5435],{"class":3305},"    return",[2166,5437,3408],{"class":3331},[2166,5439,3445],{"class":3309},[2166,5441,3448],{"class":3331},[2166,5443,5444],{"class":3316},"\"invalid-access-jwt\"",[2166,5446,3454],{"class":3331},[2166,5448,3457],{"class":3402},[2166,5450,3460],{"class":3331},[2166,5452,5454],{"class":3301,"line":5453},19,[2166,5455,5456],{"class":3331},"  }\n",[2166,5458,5460],{"class":3301,"line":5459},20,[2166,5461,3559],{"class":3331},[24,5463,5464],{},"라우트에 적용:",[415,5466,5468],{"className":3294,"code":5467,"language":3296,"meta":423,"style":423},"app.use(\"\u002Fadmin\u002F*\", async (c, next) => {\n  const fail = await requireAccess(c);\n  if (fail) return fail;\n  await next();\n});\n",[16,5469,5470,5502,5519,5531,5540],{"__ignoreMap":423},[2166,5471,5472,5475,5478,5480,5483,5485,5488,5490,5492,5494,5496,5498,5500],{"class":3301,"line":3302},[2166,5473,5474],{"class":3331},"app.",[2166,5476,5477],{"class":3309},"use",[2166,5479,3351],{"class":3331},[2166,5481,5482],{"class":3316},"\"\u002Fadmin\u002F*\"",[2166,5484,105],{"class":3331},[2166,5486,5487],{"class":3305},"async",[2166,5489,1305],{"class":3331},[2166,5491,3379],{"class":3356},[2166,5493,105],{"class":3331},[2166,5495,3384],{"class":3356},[2166,5497,3387],{"class":3331},[2166,5499,3390],{"class":3305},[2166,5501,3393],{"class":3331},[2166,5503,5504,5506,5509,5511,5514,5516],{"class":3301,"line":3335},[2166,5505,5317],{"class":3305},[2166,5507,5508],{"class":3402}," fail",[2166,5510,3313],{"class":3305},[2166,5512,5513],{"class":3305}," await",[2166,5515,5300],{"class":3309},[2166,5517,5518],{"class":3331},"(c);\n",[2166,5520,5521,5523,5526,5528],{"class":3301,"line":3342},[2166,5522,5340],{"class":3305},[2166,5524,5525],{"class":3331}," (fail) ",[2166,5527,3440],{"class":3305},[2166,5529,5530],{"class":3331}," fail;\n",[2166,5532,5533,5536,5538],{"class":3301,"line":3368},[2166,5534,5535],{"class":3305},"  await",[2166,5537,3544],{"class":3309},[2166,5539,3547],{"class":3331},[2166,5541,5542],{"class":3301,"line":3396},[2166,5543,5544],{"class":3331},"});\n",[24,5546,5547],{},"AUD는 Access Application 상세에서 확인 (Audience tag).",[33,5549],{},[36,5551,5553],{"id":5552},"_3-pms에서-페이지가-access-토큰을-자동으로-처리하도록","3) PMS에서 페이지가 Access 토큰을 자동으로 처리하도록",[24,5555,5556,5557,407],{},"Pages 도메인 자체에 Access를 걸면 브라우저가 자동 로그인 → cookie\u002Fheader 자동 첨부. ",[28,5558,5559],{},"추가 코드 불필요",[24,5561,5562,5563,5566],{},"PMS → API 호출 시 cross-origin이면 ",[16,5564,5565],{},"credentials: \"include\""," 필요할 수 있음:",[415,5568,5570],{"className":3294,"code":5569,"language":3296,"meta":423,"style":423},"fetch(`${API_BASE}\u002Fadmin\u002Fcost`, { credentials: \"include\" })\n",[16,5571,5572],{"__ignoreMap":423},[2166,5573,5574,5577,5579,5582,5585,5588,5591,5594],{"class":3301,"line":3302},[2166,5575,5576],{"class":3309},"fetch",[2166,5578,3351],{"class":3331},[2166,5580,5581],{"class":3316},"`${",[2166,5583,5584],{"class":3402},"API_BASE",[2166,5586,5587],{"class":3316},"}\u002Fadmin\u002Fcost`",[2166,5589,5590],{"class":3331},", { credentials: ",[2166,5592,5593],{"class":3316},"\"include\"",[2166,5595,5596],{"class":3331}," })\n",[24,5598,5599],{},"만약 API가 다른 zone이면 별도 Application 통과 — 사용자가 한 번 더 OTP 로그인.",[33,5601],{},[36,5603,5605,5606,78],{"id":5604},"_4-db-탐색-엔드포인트-보호-db","4) DB 탐색 엔드포인트 보호 (",[16,5607,5001],{},[24,5609,5610,105,5613,105,5616,105,5619,5622,5623,5626],{},[16,5611,5612],{},"\u002Fdb\u002Fwhoami",[16,5614,5615],{},"\u002Fdb\u002Ftables",[16,5617,5618],{},"\u002Fdb\u002Fcolumns\u002F:t",[16,5620,5621],{},"\u002Fdb\u002Fsample\u002F:t"," 모두 운영 전 단계 노출. Access Application 추가하거나, ",[28,5624,5625],{},"차라리 제거"," 후 필요 시 일회용 admin 엔드포인트로 다시 만드는 게 깔끔.",[33,5628],{},[36,5630,5632],{"id":5631},"_5-적용-후-검증","5) 적용 후 검증",[415,5634,5636],{"className":4632,"code":5635,"language":4634,"meta":423,"style":423},"# Access 없이 호출 → 302 (Access 로그인 페이지로 리다이렉트) 또는 401\ncurl -sS -o \u002Fdev\u002Fnull -w \"%{http_code}\\n\" https:\u002F\u002Fmalgn-helper-api.malgnsoft.workers.dev\u002Fadmin\u002Fcost\n# → 302 또는 401 기대\n\n# 브라우저에서 페이지 접속 → OTP 메일 → 로그인 → 정상 표시\n",[16,5637,5638,5643,5666,5671,5675],{"__ignoreMap":423},[2166,5639,5640],{"class":3301,"line":3302},[2166,5641,5642],{"class":3422},"# Access 없이 호출 → 302 (Access 로그인 페이지로 리다이렉트) 또는 401\n",[2166,5644,5645,5648,5651,5654,5657,5660,5663],{"class":3301,"line":3335},[2166,5646,5647],{"class":3309},"curl",[2166,5649,5650],{"class":3402}," -sS",[2166,5652,5653],{"class":3402}," -o",[2166,5655,5656],{"class":3316}," \u002Fdev\u002Fnull",[2166,5658,5659],{"class":3402}," -w",[2166,5661,5662],{"class":3316}," \"%{http_code}\\n\"",[2166,5664,5665],{"class":3316}," https:\u002F\u002Fmalgn-helper-api.malgnsoft.workers.dev\u002Fadmin\u002Fcost\n",[2166,5667,5668],{"class":3301,"line":3342},[2166,5669,5670],{"class":3422},"# → 302 또는 401 기대\n",[2166,5672,5673],{"class":3301,"line":3368},[2166,5674,3339],{"emptyLinePlaceholder":3338},[2166,5676,5677],{"class":3301,"line":3396},[2166,5678,5679],{"class":3422},"# 브라우저에서 페이지 접속 → OTP 메일 → 로그인 → 정상 표시\n",[33,5681],{},[36,5683,5685],{"id":5684},"_6-비상시-해제","6) 비상시 해제",[54,5687,5688,5694],{},[57,5689,5690,5691],{},"Dashboard → Access → Applications → 해당 Application → ",[28,5692,5693],{},"Delete",[57,5695,5696],{},"Worker 측 미들웨어는 그대로 두면 401만 반환 → 미들웨어 임시 주석 처리 후 재배포",[33,5698],{},[36,5700,5701],{"id":5701},"비용",[54,5703,5704,5710],{},[57,5705,5706,5707],{},"Zero Trust Free: ",[28,5708,5709],{},"50명까지 무료",[57,5711,5712],{},"그 이상: 사용자당 월 $3 (Standard) — 현재 운영팀 규모면 무료 한도 안에 충분",[33,5714],{},[36,5716,2393],{"id":2393},[54,5718,5719,5726,5733],{},[57,5720,5721,5722],{},"공식 가이드: ",[3257,5723,5724],{"href":5724,"rel":5725},"https:\u002F\u002Fdevelopers.cloudflare.com\u002Fcloudflare-one\u002Fapplications\u002Fconfigure-apps\u002Fself-hosted-apps\u002F",[5049],[57,5727,5728,5729],{},"Worker에서 JWT 검증: ",[3257,5730,5731],{"href":5731,"rel":5732},"https:\u002F\u002Fdevelopers.cloudflare.com\u002Fcloudflare-one\u002Fidentity\u002Fauthorization-cookie\u002Fvalidating-json\u002F",[5049],[57,5734,5735,5736,5739],{},"AUD 위치: Application 상세 → ",[28,5737,5738],{},"Overview"," 탭 → \"Application Audience (AUD) Tag\"",[4258,5741,5742],{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":423,"searchDepth":3342,"depth":3342,"links":5744},[5745,5746,5747,5751,5752,5753,5755,5756,5757,5758],{"id":4942,"depth":3335,"text":4943},{"id":5006,"depth":3335,"text":5007},{"id":5035,"depth":3335,"text":5036,"children":5748},[5749,5750],{"id":5039,"depth":3342,"text":5040},{"id":5160,"depth":3342,"text":5161},{"id":5191,"depth":3335,"text":5192},{"id":5552,"depth":3335,"text":5553},{"id":5604,"depth":3335,"text":5754},"4) DB 탐색 엔드포인트 보호 (\u002Fdb\u002F*)",{"id":5631,"depth":3335,"text":5632},{"id":5684,"depth":3335,"text":5685},{"id":5701,"depth":3335,"text":5701},{"id":2393,"depth":3335,"text":2393},"\u002Fadmin\u002F* 라우트(현재: \u002Fadmin\u002Fcost)와 함께 모든 노출 위험 페이지·API를 Cloudflare Access로 보호하는 단계별 가이드.",{},"\u002Fcloudflare-access",{"title":4911,"description":5759},"7ITx0fVBm2H7cGdMsM7FCT0HZNIPfkwycHIwQfQ08QY",{"id":5765,"title":5766,"body":5767,"description":423,"extension":4340,"meta":9019,"navigation":3338,"path":9020,"seo":9021,"stem":9022,"__hash__":9023},"docs\u002Fexamples\u002F안전보건진흥원.md","안전보건진흥원 — 문의 분석 예시",{"type":8,"value":5768,"toc":8980},[5769,5772,5790,5911,5913,5917,6070,6072,6076,6135,6137,6141,6248,6250,6254,6287,6289,6293,6390,6392,6396,6405,6408,6412,6487,6491,6581,6585,6666,6670,6764,6768,6771,6857,6867,6871,6935,6939,6992,6994,6998,7013,7016,7020,7103,7113,7117,7196,7209,7213,7221,7302,7319,7323,7422,7431,7435,7520,7529,7533,7620,7624,7629,7646,7651,7747,7751,7757,7783,7795,7797,7801,7810,7814,7892,7901,7905,7914,7986,7995,7999,8072,8080,8088,8092,8170,8178,8182,8270,8279,8282,8371,8375,8379,8393,8398,8453,8457,8460,8531,8545,8549,8573,8575,8579,8951,8953,8957,8977],[11,5770,5766],{"id":5771},"안전보건진흥원-문의-분석-예시",[21,5773,5774],{},[24,5775,5776,5777,5781,5782,5785,5786,5789],{},"본 문서는 ",[3257,5778,5780],{"href":5779},"..\u002FPROJECT-INQUIRY-ANALYSIS","PROJECT-INQUIRY-ANALYSIS.md","의 보조 자료로, ",[28,5783,5784],{},"단일 프로젝트(고객사) 문의 패턴을 깊이 들여다본 예시 케이스","다.\n다른 업체에 대해서도 동일 양식으로 작성하여 ",[16,5787,5788],{},"doc\u002Fexamples\u002F"," 아래 누적한다.",[135,5791,5792,5801],{},[138,5793,5794],{},[141,5795,5796,5799],{},[144,5797,5798],{},"메타",[144,5800],{},[157,5802,5803,5811,5826,5834,5842,5850,5858,5866,5878,5889,5900],{},[141,5804,5805,5808],{},[162,5806,5807],{},"Project ID",[162,5809,5810],{},"1528",[141,5812,5813,5816],{},[162,5814,5815],{},"Project Name",[162,5817,5818,5821,5822,5825],{},[16,5819,5820],{},"*안전보건진흥원"," (종료 프로젝트 — ",[16,5823,5824],{},"*"," 접두사)",[141,5827,5828,5831],{},[162,5829,5830],{},"Site",[162,5832,5833],{},"1 (주)맑은소프트",[141,5835,5836,5839],{},[162,5837,5838],{},"기간",[162,5840,5841],{},"2022-03-30 ~ 2022-06-24 (약 3개월)",[141,5843,5844,5847],{},[162,5845,5846],{},"전체 게시글",[162,5848,5849],{},"48건",[141,5851,5852,5855],{},[162,5853,5854],{},"Q&A 후보 (엄격 필터 통과)",[162,5856,5857],{},"3건",[141,5859,5860,5863],{},[162,5861,5862],{},"Q&A 후보 (완화 필터, 댓글≥1)",[162,5864,5865],{},"39건",[141,5867,5868,5871],{},[162,5869,5870],{},"주 문의자",[162,5872,5873,5874,5877],{},"고은비 (",[16,5875,5876],{},"ke5635@shai.or.kr",", 안전보건진흥원 안전교육팀) — 거의 단독",[141,5879,5880,5883],{},[162,5881,5882],{},"응대자 (맑은소프트)",[162,5884,5885,5886,5888],{},"이영은(43%)·김서연(35%)·엄정원·이슬기·최종수·하근호 — ",[16,5887,128],{}," 도메인 기준 6인 분담",[141,5890,5891,5894],{},[162,5892,5893],{},"분류 규칙",[162,5895,5896,5897,5899],{},"직원\u002F고객 분류는 이메일 도메인 ",[16,5898,128],{}," 여부로 판정 (이름·게시판 패턴 추정 금지)",[141,5901,5902,5905],{},[162,5903,5904],{},"케이스 성격",[162,5906,5907,5908],{},"신규 LMS 도입 직후의 ",[28,5909,5910],{},"집중 운영 트러블슈팅 + 정책\u002F법령 대응 + 기능 개선 요청",[33,5912],{},[36,5914,5916],{"id":5915},"_1-카테고리별-분포","1. 카테고리별 분포",[135,5918,5919,5932],{},[138,5920,5921],{},[141,5922,5923,5926,5929],{},[144,5924,5925],{},"카테고리",[144,5927,5928],{},"건수",[144,5930,5931],{},"대표 문의",[157,5933,5934,5945,5956,5967,5977,5987,5997,6008,6018,6028,6038,6048,6059],{},[141,5935,5936,5939,5942],{},[162,5937,5938],{},"SMS\u002F문자\u002F카카오톡",[162,5940,5941],{},"8",[162,5943,5944],{},"비즈뿌리오 발송 오류·정지, 카카오톡 전환 가능성, 이중발송 모니터링, 학습독려 상시 모니터링",[141,5946,5947,5950,5953],{},[162,5948,5949],{},"SSO\u002FB2B 연동",[162,5951,5952],{},"5",[162,5954,5955],{},"S-OIL b2b 연동, 알파코 교육생 오류, 개발팀 연락 요청",[141,5957,5958,5961,5964],{},[162,5959,5960],{},"도메인\u002F사이트 운영",[162,5962,5963],{},"4",[162,5965,5966],{},"도메인 포워딩, 기존 도메인 연동, 인천교육청 팝업",[141,5968,5969,5972,5974],{},[162,5970,5971],{},"수료증\u002F이수확인증",[162,5973,5963],{},[162,5975,5976],{},"법령상 양식 추가 제작, 집합과정 일괄 다운로드, 출력 오류, 최종평가 점수 추출",[141,5978,5979,5982,5984],{},[162,5980,5981],{},"회원·교육 관리",[162,5983,5963],{},[162,5985,5986],{},"회원탈퇴 시 교육 자동 삭제, 회차 숨김 시 노출 차단, 사업장관리 엑셀 미작동, 상시입과 설정",[141,5988,5989,5992,5994],{},[162,5990,5991],{},"CDN\u002F인프라",[162,5993,5963],{},[162,5995,5996],{},"CDN 초과사용료·이용내역, 크롬 관리자 접속 오류",[141,5998,5999,6002,6005],{},[162,6000,6001],{},"콘텐츠 운영",[162,6003,6004],{},"3",[162,6006,6007],{},"MP4 진도제어 가능 여부, 자주묻는 질문 카테고리, 우편교육 배송추적",[141,6009,6010,6013,6015],{},[162,6011,6012],{},"비밀번호·인증",[162,6014,6004],{},[162,6016,6017],{},"임시비밀번호 단순화, 하이픈 없는 휴대폰 인증, 이메일 인증 발송 누락",[141,6019,6020,6023,6025],{},[162,6021,6022],{},"진도·순차학습",[162,6024,6004],{},[162,6026,6027],{},"진도제어 풀림 → 진도율 미반영, 강의 순차학습 기준",[141,6029,6030,6033,6035],{},[162,6031,6032],{},"UX 개선",[162,6034,6004],{},[162,6036,6037],{},"메일 첨부 기능, 세션타임 후 수강 가능, 팝업 링크 삽입",[141,6039,6040,6043,6045],{},[162,6041,6042],{},"운영 데이터 처리",[162,6044,6004],{},[162,6046,6047],{},"시험 응시 후 DB 미저장 민원, 명단 다운로드 컬럼 추가, 자동발송 메일 비활성화",[141,6049,6050,6053,6056],{},[162,6051,6052],{},"결제\u002F회계",[162,6054,6055],{},"1",[162,6057,6058],{},"교육비 영수증 비과세 처리",[141,6060,6061,6064,6067],{},[162,6062,6063],{},"맑은소프트 측 안내",[162,6065,6066],{},"6",[162,6068,6069],{},"CDN 이용내역\u002F초과사용료, 비즈뿌리오 점검, 공문 전달 (Q&A 형식 아님)",[33,6071],{},[36,6073,6075],{"id":6074},"_2-시기별-흐름","2. 시기별 흐름",[135,6077,6078,6090],{},[138,6079,6080],{},[141,6081,6082,6085,6087],{},[144,6083,6084],{},"시기",[144,6086,5928],{},[144,6088,6089],{},"특징",[157,6091,6092,6106,6121],{},[141,6093,6094,6097,6100],{},[162,6095,6096],{},"4월 (도입 초기)",[162,6098,6099],{},"~17",[162,6101,6102,6103],{},"기능 확인·진도제어·SSO 연동·수료증 양식·도메인 포워딩 등 ",[28,6104,6105],{},"시스템 안정화",[141,6107,6108,6111,6114],{},[162,6109,6110],{},"5월 (운영 중반)",[162,6112,6113],{},"~14",[162,6115,6116,6117,6120],{},"SMS 비즈뿌리오 이슈, 정규과정 운영, 비밀번호 인증, 템플릿 코드 등 ",[28,6118,6119],{},"운영 문제"," 집중",[141,6122,6123,6126,6128],{},[162,6124,6125],{},"6월 (정착기)",[162,6127,6099],{},[162,6129,6130,6131,6134],{},"SSO 추가 연동, 콘텐츠(MP4) 반영, 회원탈퇴 처리, ",[28,6132,6133],{},"기능 개발 요청"," 증가",[33,6136],{},[36,6138,6140],{"id":6139},"_3-답변-결과로-본-핵심-시스템-이슈","3. 답변 결과로 본 핵심 시스템 이슈",[135,6142,6143,6155],{},[138,6144,6145],{},[141,6146,6147,6150,6153],{},[144,6148,6149],{},"이슈",[144,6151,6152],{},"결과(요약)",[144,6154,2979],{},[157,6156,6157,6175,6193,6204,6215,6226,6237],{},[141,6158,6159,6162,6168],{},[162,6160,6161],{},"MP4 진도제어 (강의바 잠금)",[162,6163,6164,6165,6167],{},"현재 ",[28,6166,4837],{}," — 프로그램 WBT로 우회 권장",[162,6169,6170,6171,6174],{},"답변 일부가 ",[28,6172,6173],{},"비공개 댓글"," (post 94194)",[141,6176,6177,6180,6186],{},[162,6178,6179],{},"회원탈퇴 시 교육 자동 삭제",[162,6181,6182,6185],{},[28,6183,6184],{},"개발 불가"," — 내부 규정상 교육 데이터는 함께 삭제되지 않음",[162,6187,6188,6189,6192],{},"핵심 답변이 ",[28,6190,6191],{},"비공개"," (post 94221)",[141,6194,6195,6198,6201],{},[162,6196,6197],{},"수료증 양식 추가 제작",[162,6199,6200],{},"법령 지침 반영 위해 양식 추가 작업 진행",[162,6202,6203],{},"post 90527",[141,6205,6206,6209,6212],{},[162,6207,6208],{},"카카오톡 발송 전환",[162,6210,6211],{},"비즈뿌리오 SMS 운영 유지 — 카카오톡 별도 검토",[162,6213,6214],{},"post 90305",[141,6216,6217,6220,6223],{},[162,6218,6219],{},"S-OIL\u002F알파코 SSO 연동 오류",[162,6221,6222],{},"여러 차례 발생, 개발팀 직접 연계 처리",[162,6224,6225],{},"post 90472, 92978, 93677 등",[141,6227,6228,6231,6234],{},[162,6229,6230],{},"진도제어 풀림 → 진도율 미반영",[162,6232,6233],{},"긴급 처리, 원인 분석",[162,6235,6236],{},"post 90150",[141,6238,6239,6242,6245],{},[162,6240,6241],{},"비밀번호 휴대폰 인증 (하이픈 없음)",[162,6243,6244],{},"인증 로직 보완 요청",[162,6246,6247],{},"post 93228",[33,6249],{},[36,6251,6253],{"id":6252},"_4-케이스-특수성","4. 케이스 특수성",[1925,6255,6256,6265,6271,6281],{},[57,6257,6258,6261,6262,407],{},[28,6259,6260],{},"복합 LMS 운영자"," — 안전보건진흥원 자체 교육 + 다수 기업(S-OIL·알파코·인천교육청 등) B2B 교육을 동시에 운영. 다른 단일 고객사 대비 ",[28,6263,6264],{},"통합·연동 이슈가 압도적",[57,6266,6267,6270],{},[28,6268,6269],{},"법령\u002F규제 기반 요구사항"," 비중이 큼 — 수료증 양식, 비과세 영수증, 휴대폰 인증 규정 등.",[57,6272,6273,6276,6277,6280],{},[28,6274,6275],{},"운영 모니터링 의존도 높음"," — 상시 모니터링·이중발송 검출·민원 대응 요청 빈출. ",[28,6278,6279],{},"챗봇으로 자동화하기 어려운 운영 협업 요청"," 비중이 큼.",[57,6282,6283,6286],{},[28,6284,6285],{},"민감한 답변이 비공개 댓글에 다수 존재"," — \"개발 불가\", \"내부 규정상\" 같은 정책 거절성 답변이 비공개로 처리됨.",[33,6288],{},[36,6290,6292],{"id":6291},"_5-ai-챗봇-학습-자산-관점","5. AI 챗봇 학습 자산 관점",[135,6294,6295,6305],{},[138,6296,6297],{},[141,6298,6299,6302],{},[144,6300,6301],{},"관점",[144,6303,6304],{},"시사점",[157,6306,6307,6320,6333,6343,6362,6376],{},[141,6308,6309,6314],{},[162,6310,6311],{},[28,6312,6313],{},"신선도",[162,6315,6316,6317],{},"데이터가 2022년 → S-OIL\u002F알파코 연동 상태, 수료증 양식, MP4 진도제어 정책 등 ",[28,6318,6319],{},"현 시점 유효성 검증 필요",[141,6321,6322,6327],{},[162,6323,6324],{},[28,6325,6326],{},"표준 답변 후보",[162,6328,6329,6330],{},"진도제어 미지원, 회원탈퇴 정책, 비즈뿌리오 운영, SSO 연동 절차 등은 ",[28,6331,6332],{},"반복 등장 가능 → 표준 답변화 가치 큼",[141,6334,6335,6340],{},[162,6336,6337],{},[28,6338,6339],{},"공공\u002FHRD 특화 트랙",[162,6341,6342],{},"산인공\u002FK-디지털과 함께 별도 카테고리로 묶어 운영 권장",[141,6344,6345,6350],{},[162,6346,6347],{},[28,6348,6349],{},"민감 답변 격리",[162,6351,6352,6353,6356,6357,6361],{},"비공개 답변(법령\u002F규정상 거절·미지원 안내)은 Phase 1 상담사 도구에만 노출. Phase 2 챗봇에서는 ",[2369,6354,6355],{},"\"관련 정책은 상담사 확인 필요\""," 형태로 변환 — ",[3257,6358,6360],{"href":6359},"..\u002FLEGACY-DB-INVENTORY","LEGACY-DB-INVENTORY.md"," §6 비공개 댓글 처리 전략 참조",[141,6363,6364,6369],{},[162,6365,6366],{},[28,6367,6368],{},"운영 협업 요청 분리",[162,6370,6371,6372,6375],{},"\"상시 모니터링\", \"긴급 확인\", \"유선으로 받은 건 공유\" 등은 ",[28,6373,6374],{},"챗봇이 처리할 영역이 아님"," → 인덱싱 대상에서 제외 또는 에스컬레이션 분류",[141,6377,6378,6383],{},[162,6379,6380],{},[28,6381,6382],{},"B2B 연동 이슈",[162,6384,6385,6386,6389],{},"SSO\u002F도메인\u002FCDN 등 인프라 이슈는 업체별 세팅 차이가 커서 ",[28,6387,6388],{},"공통 답변보다는 표준 절차 가이드","가 더 유효",[33,6391],{},[36,6393,6395],{"id":6394},"_6-ai-챗봇-적합성-평가-cs-체크포인트-기반","6. AI 챗봇 적합성 평가 (CS 체크포인트 기반)",[21,6397,6398],{},[24,6399,6400,6401,6404],{},"5개 축(A 답변품질 \u002F B 운영지표 \u002F C 응대패턴 \u002F D 정책·민감정보 \u002F E 자동화 적합성)으로 점검한 결과 — ",[28,6402,6403],{},"AI 챗봇 학습\u002F노출 자산으로의 적합성 관점",".\n순수 CS 운영 품질 평가는 §7 참조.\n측정 가능한 항목은 수치로, 나머지는 정성 평가.\n평가 일자: 2026-05-18 · 표본: project_id=1528 · 댓글 162건 \u002F 게시글 48건(댓글 보유 44건).",[24,6406,6407],{},"범례: ✓ 양호 · ⚠ 주의 · ✕ 문제 · ㅡ 정보 부족(별도 검수 필요)",[215,6409,6411],{"id":6410},"a-답변-품질","A. 답변 품질",[135,6413,6414,6426],{},[138,6415,6416],{},[141,6417,6418,6420,6423],{},[144,6419,4143],{},[144,6421,6422],{},"측정\u002F관찰",[144,6424,6425],{},"판정",[157,6427,6428,6439,6450,6461,6472],{},[141,6429,6430,6433,6436],{},[162,6431,6432],{},"A-1 정확도",[162,6434,6435],{},"표본 검수 미시행",[162,6437,6438],{},"ㅡ — 표본 30건 검수 필요",[141,6440,6441,6444,6447],{},[162,6442,6443],{},"A-2 현재 유효성",[162,6445,6446],{},"데이터 2022년 → 시스템·정책 변경 가능성 큼",[162,6448,6449],{},"⚠ 신선도 재검증 필수",[141,6451,6452,6455,6458],{},[162,6453,6454],{},"A-3 완결성 (종결 멘트)",[162,6456,6457],{},"44건 중 40건(91%) 마지막 댓글에 \"감사\u002F확인\"",[162,6459,6460],{},"✓ 종결률 높음",[141,6462,6463,6466,6469],{},[162,6464,6465],{},"A-4 일관성",[162,6467,6468],{},"같은 테마 반복(SMS·SSO·비밀번호 등) — 일관성 검수 미시행",[162,6470,6471],{},"ㅡ",[141,6473,6474,6477,6484],{},[162,6475,6476],{},"A-5 출처·근거 인용",[162,6478,6479,6480,6483],{},"김서연 답변에 ",[16,6481,6482],{},"help.malgnsoft.com"," 링크 인용 사례 확인",[162,6485,6486],{},"✓ 부분적으로 양호",[215,6488,6490],{"id":6489},"b-운영-지표","B. 운영 지표",[135,6492,6493,6504],{},[138,6494,6495],{},[141,6496,6497,6499,6502],{},[144,6498,4143],{},[144,6500,6501],{},"측정값",[144,6503,6425],{},[157,6505,6506,6517,6528,6538,6548,6559,6570],{},[141,6507,6508,6511,6514],{},[162,6509,6510],{},"B-1 첫 응답 시간(FRT)",[162,6512,6513],{},"평균 5시간(309분), 최단 3분, 최장 65시간",[162,6515,6516],{},"⚠ 평균은 양호하나 일부 늦은 응답 존재",[141,6518,6519,6522,6525],{},[162,6520,6521],{},"B-1a FRT ≤ 1시간",[162,6523,6524],{},"18\u002F44 (41%)",[162,6526,6527],{},"✓",[141,6529,6530,6533,6536],{},[162,6531,6532],{},"B-1b FRT ≤ 4시간",[162,6534,6535],{},"34\u002F44 (77%)",[162,6537,6527],{},[141,6539,6540,6543,6546],{},[162,6541,6542],{},"B-1c FRT ≤ 1일",[162,6544,6545],{},"42\u002F44 (95%)",[162,6547,6527],{},[141,6549,6550,6553,6556],{},[162,6551,6552],{},"B-2 해결 소요(TTR)",[162,6554,6555],{},"단일 답변 후 종결 vs 일부 60일+ (90527 수료증, 94221 회원탈퇴)",[162,6557,6558],{},"⚠ 정책성 이슈는 장기화",[141,6560,6561,6564,6567],{},[162,6562,6563],{},"B-3 재문의 패턴",[162,6565,6566],{},"SSO 연동 5회(90472·90944·92832·92978·93677), 비밀번호 3회 등",[162,6568,6569],{},"⚠ 동일 주제 반복 — 표준답변 효과 클 것",[141,6571,6572,6575,6578],{},[162,6573,6574],{},"B-4 긴급 처리",[162,6576,6577],{},"\"긴급\" 표기 3건. 92237 \"긴급요청 문자 이중발송\" FRT 1614분(27시간)",[162,6579,6580],{},"✕ 긴급 표기 vs 실제 응답 속도 불일치",[215,6582,6584],{"id":6583},"c-응대-패턴-누가어떻게","C. 응대 패턴 (누가·어떻게)",[135,6586,6587,6597],{},[138,6588,6589],{},[141,6590,6591,6593,6595],{},[144,6592,4143],{},[144,6594,6501],{},[144,6596,6425],{},[157,6598,6599,6620,6631,6642,6652],{},[141,6600,6601,6604,6617],{},[162,6602,6603],{},"C-1 답변자 분포",[162,6605,6606,6609,6610,6613,6614,6616],{},[28,6607,6608],{},"맑은소프트 116건(72%)",": 이영은 50 · 김서연 41 · 엄정원 11 · 이슬기 9 · 최종수 3 · 하근호 2. ",[28,6611,6612],{},"고객 46건(28%)",": 고은비 43 · 플로즈(외부) 3. (이메일 도메인 ",[16,6615,128],{}," 기준)",[162,6618,6619],{},"✓ 정상 비율",[141,6621,6622,6625,6628],{},[162,6623,6624],{},"C-2 셀프 보완",[162,6626,6627],{},"고은비가 본인 글에 후속 정보 추가 43건 — 운영자 답변 기다리지 않고 능동 보완",[162,6629,6630],{},"✓ 협업적",[141,6632,6633,6636,6639],{},[162,6634,6635],{},"C-3 에스컬레이션 시그널",[162,6637,6638],{},"\"개발팀\" 5건(3%) · \"유선\u002F전화\" 6건(4%) · \"확인 후 답변\" 20건(12%)",[162,6640,6641],{},"⚠ 즉답 불가 케이스 약 19%",[141,6643,6644,6647,6650],{},[162,6645,6646],{},"C-4 답변 톤·정형성",[162,6648,6649],{},"정형 인삿말(\"안녕하세요. 맑은소프트입니다\") 일관 — 표준화 가능성 높음",[162,6651,6527],{},[141,6653,6654,6657,6663],{},[162,6655,6656],{},"C-5 반복 답변 가능성",[162,6658,6659,6660],{},"SMS 비즈뿌리오·SSO 연동·비밀번호 인증 등 동일 주제 다수 — ",[28,6661,6662],{},"표준답변 1순위",[162,6664,6665],{},"✓ 표준답변화 기회 큼",[215,6667,6669],{"id":6668},"d-정책규제민감-정보","D. 정책·규제·민감 정보",[135,6671,6672,6682],{},[138,6673,6674],{},[141,6675,6676,6678,6680],{},[144,6677,4143],{},[144,6679,6422],{},[144,6681,6425],{},[157,6683,6684,6695,6709,6720,6731,6742,6753],{},[141,6685,6686,6689,6692],{},[162,6687,6688],{},"D-1 거절·미지원 답변",[162,6690,6691],{},"거절성 키워드 포함 8건(5%) — \"MP4 진도제어 미지원\", \"회원탈퇴 시 자동삭제 개발 불가\" 등",[162,6693,6694],{},"⚠ 챗봇이 그대로 답하면 안 됨",[141,6696,6697,6700,6706],{},[162,6698,6699],{},"D-2 비공개 댓글 비율",[162,6701,6702,6703],{},"25\u002F162 (15.4%) — ",[28,6704,6705],{},"전체 평균(9.3%)보다 높음",[162,6707,6708],{},"⚠ 민감 정보 다수",[141,6710,6711,6714,6717],{},[162,6712,6713],{},"D-3 비공개에만 답 있는 글",[162,6715,6716],{},"0건 (모든 글에 최소 1개 공개 댓글)",[162,6718,6719],{},"✓ 단, 공개 댓글이 잡담일 가능성 별도 검수 필요",[141,6721,6722,6725,6728],{},[162,6723,6724],{},"D-4 PII 의심 패턴",[162,6726,6727],{},"이메일 유사 6건 · 010-xxxx-xxxx 2건 · 일반전화 7건 (162건 중 ~9%)",[162,6729,6730],{},"⚠ 마스킹 룰 필수",[141,6732,6733,6736,6739],{},[162,6734,6735],{},"D-5 고객사 식별정보",[162,6737,6738],{},"\"S-OIL\", \"알파코\", \"인천광역시교육청\" 등 타사명·내부 시스템명 다수 노출",[162,6740,6741],{},"✕ 챗봇 응답 시 마스킹·일반화 필요",[141,6743,6744,6747,6750],{},[162,6745,6746],{},"D-6 법령 종속 답변",[162,6748,6749],{},"수료증 양식 지침, 비과세 영수증, 휴대폰 인증 규정 등",[162,6751,6752],{},"⚠ 법령 변경 시 즉시 무효화 — 주기적 재검증",[141,6754,6755,6758,6761],{},[162,6756,6757],{},"D-7 비공개 작성자 패턴",[162,6759,6760],{},"직원 비공개 24\u002F116(20.7%) · 고객 비공개 1\u002F46(2.2%). 인원별: 최종수 3\u002F3(100%) · 엄정원 8\u002F11(73%) · 이슬기 3\u002F9(33%) · 이영은 8\u002F50(16%) · 김서연 2\u002F41(5%) · 하근호 0",[162,6762,6763],{},"⚠ 엄정원·최종수가 정책 거절·민감 안내 전담 — 가시성 분기 자동 학습 가능",[215,6765,6767],{"id":6766},"e-자동화-적합성-챗봇이-풀-수-있는가","E. 자동화 적합성 (챗봇이 풀 수 있는가)",[24,6769,6770],{},"제목 키워드 기반 자동 분류 (중복 포함):",[135,6772,6773,6785],{},[138,6774,6775],{},[141,6776,6777,6780,6782],{},[144,6778,6779],{},"분류",[144,6781,5928],{},[144,6783,6784],{},"챗봇 적합성",[157,6786,6787,6801,6815,6829,6843],{},[141,6788,6789,6795,6798],{},[162,6790,6791,6794],{},[28,6792,6793],{},"위탁·협업 요청"," (모니터링·작업·세팅·발송·체크)",[162,6796,6797],{},"25 (52%)",[162,6799,6800],{},"✕ 챗봇 부적합 — 사람 상담사 처리",[141,6802,6803,6809,6812],{},[162,6804,6805,6808],{},[28,6806,6807],{},"기능 질의"," (질의·문의·여부·가능한지)",[162,6810,6811],{},"13 (27%)",[162,6813,6814],{},"✓ 챗봇 적합 — 표준답변\u002F검색 응답 가능",[141,6816,6817,6823,6826],{},[162,6818,6819,6822],{},[28,6820,6821],{},"오류 신고"," (오류·작동·풀려·안되는)",[162,6824,6825],{},"12 (25%)",[162,6827,6828],{},"△ 표준답변 가능 vs 조사 필요 혼재",[141,6830,6831,6837,6840],{},[162,6832,6833,6836],{},[28,6834,6835],{},"개발 요청"," (개발·추가 제작·반영)",[162,6838,6839],{},"5 (10%)",[162,6841,6842],{},"✕ 챗봇 부적합 — 영업\u002F기획 처리",[141,6844,6845,6851,6854],{},[162,6846,6847,6850],{},[28,6848,6849],{},"긴급"," (긴급·★)",[162,6852,6853],{},"3 (6%)",[162,6855,6856],{},"✕ 즉시 에스컬레이션",[24,6858,6859,6862,6863,6866],{},[28,6860,6861],{},"추정 챗봇 자동 응답 가능 비중",": 약 ",[28,6864,6865],{},"30~40%",". 나머지 60% 이상은 위탁·개발·긴급으로 챗봇이 아닌 사람 상담사 \u002F 에스컬레이션 영역.",[215,6868,6870],{"id":6869},"종합-판정","종합 판정",[135,6872,6873,6883],{},[138,6874,6875],{},[141,6876,6877,6880],{},[144,6878,6879],{},"측면",[144,6881,6882],{},"평가",[157,6884,6885,6895,6905,6915,6925],{},[141,6886,6887,6892],{},[162,6888,6889],{},[28,6890,6891],{},"챗봇 학습 자산으로서 가치",[162,6893,6894],{},"△ 부분적 — 기능 질의·오류 신고 영역(약 25~40%)은 표준답변·검색 응답으로 유효",[141,6896,6897,6902],{},[162,6898,6899],{},[28,6900,6901],{},"그대로 인덱싱 적합성",[162,6903,6904],{},"✕ — 신선도 검증·PII 마스킹·민감 답변 격리·고객사명 일반화·종결 잡담 제거가 선행되어야 함",[141,6906,6907,6912],{},[162,6908,6909],{},[28,6910,6911],{},"표준답변 잠재성",[162,6913,6914],{},"✓ 큼 — SMS·SSO·비밀번호·진도\u002F순차학습·MP4 진도제어 등 반복 주제 다수",[141,6916,6917,6922],{},[162,6918,6919],{},[28,6920,6921],{},"운영 협업 요청 비중",[162,6923,6924],{},"✕ 과반 — 챗봇 영역 아님. 에스컬레이션 분류기로 별도 처리",[141,6926,6927,6932],{},[162,6928,6929],{},[28,6930,6931],{},"Phase 2 노출 위험",[162,6933,6934],{},"⚠ 비공개 답변·고객사 식별·법령 거절 답변이 그대로 노출되면 신뢰 훼손 위험",[215,6936,6938],{"id":6937},"권장-후속-조치-이-케이스-기준","권장 후속 조치 (이 케이스 기준)",[1925,6940,6941,6947,6960,6966,6972,6986],{},[57,6942,6943,6946],{},[28,6944,6945],{},"표본 30건 정답 검수",": A-1 정확도, A-4 일관성, D-3 공개 댓글의 실질성 검증.",[57,6948,6949,6952,6953,6955,6956,6959],{},[28,6950,6951],{},"신선도 룰 적용",": 본 케이스는 종료 프로젝트(",[16,6954,5824],{}," 접두사) → Phase 2 챗봇 노출은 ",[28,6957,6958],{},"명시적 가드"," 또는 제외.",[57,6961,6962,6965],{},[28,6963,6964],{},"PII 마스킹 룰 PoC",": 이메일\u002F휴대폰\u002F일반전화 정규식 적용 후 162건 전체 검출률·오탐률 측정.",[57,6967,6968,6971],{},[28,6969,6970],{},"고객사명 일반화 룰",": \"S-OIL\", \"알파코\" 등 → \"고객사 A\u002FB\" 형태로 변환. 답변 의미 보존 여부 검증.",[57,6973,6974,6977,6978,2367,6982,6985],{},[28,6975,6976],{},"자동 분류기 학습 자산",": 위탁\u002F협업 vs 기능 질의 vs 오류 신고 vs 개발 요청 라벨을 ",[3257,6979,6981],{"href":6980},"..\u002FROADMAP","ROADMAP.md",[28,6983,6984],{},"1.9 피드백 루프","의 에스컬레이션 분류기 학습 데이터로 활용.",[57,6987,6988,6991],{},[28,6989,6990],{},"표준답변 후보 자동 추출",": 반복 주제(SMS·SSO·비밀번호 등) → 임베딩 클러스터링으로 후보 도출.",[33,6993],{},[36,6995,6997],{"id":6996},"_7-순수-cs-운영-품질-평가-챗봇-관점-분리","7. 순수 CS 운영 품질 평가 (챗봇 관점 분리)",[21,6999,7000,7007],{},[24,7001,7002,7003,7006],{},"AI 자산화 적합성과 무관하게, ",[28,7004,7005],{},"CS 운영 그 자체로 안전보건진흥원 케이스가 잘 운영되고 있는가","를 일반 CS 품질 프레임(응답 신속성·해결 품질·인력 운영·프로세스 성숙도·고객 경험)으로 평가.\n평가 일자: 2026-05-18 · 표본: project_id=1528 · 댓글 162건 \u002F 게시글 48건(댓글 보유 44건).",[24,7008,7009,7012],{},[28,7010,7011],{},"한계",": 본 데이터는 게시판 기반 협업 도구 위에서 일어난 상호작용으로, 정식 헬프데스크\u002F티켓 시스템 메트릭과 직접 비교에는 주의 필요. CSAT\u002FNPS 등 직접 만족도 지표는 부재 — 종결 멘트로 proxy.",[24,7014,7015],{},"범례: ★ 점수(1~5) · ✓ 양호 · ⚠ 주의 · ✕ 문제",[215,7017,7019],{"id":7018},"a-응답-신속성-responsiveness-4-5","A. 응답 신속성 (Responsiveness) — ★ 4 \u002F 5",[135,7021,7022,7032],{},[138,7023,7024],{},[141,7025,7026,7028,7030],{},[144,7027,4143],{},[144,7029,6501],{},[144,7031,6425],{},[157,7033,7034,7044,7053,7062,7071,7081,7092],{},[141,7035,7036,7039,7042],{},[162,7037,7038],{},"평균 FRT",[162,7040,7041],{},"309분 (약 5시간)",[162,7043,6527],{},[141,7045,7046,7049,7051],{},[162,7047,7048],{},"1시간 내 응답",[162,7050,6524],{},[162,7052,6527],{},[141,7054,7055,7058,7060],{},[162,7056,7057],{},"4시간 내 응답",[162,7059,6535],{},[162,7061,6527],{},[141,7063,7064,7067,7069],{},[162,7065,7066],{},"1일 내 응답",[162,7068,6545],{},[162,7070,6527],{},[141,7072,7073,7076,7079],{},[162,7074,7075],{},"영업시간(09~18) 응답 비율",[162,7077,7078],{},"65\u002F69 (94%)",[162,7080,6527],{},[141,7082,7083,7086,7089],{},[162,7084,7085],{},"주말 응답",[162,7087,7088],{},"0건",[162,7090,7091],{},"✓ 일반적",[141,7093,7094,7097,7100],{},[162,7095,7096],{},"긴급 vs 실제 응답",[162,7098,7099],{},"긴급 3건 중 최장 27시간(post 92237)",[162,7101,7102],{},"✕ SLA 불일치",[24,7104,7105,7108,7109,7112],{},[28,7106,7107],{},"평",": 평일 영업시간 기반으로 응답이 매우 빠른 편. 단, ",[28,7110,7111],{},"\"긴급\" 표기에 대한 SLA 차별화가 작동하지 않음"," — 일반 응답과 동일 속도로 처리됨.",[215,7114,7116],{"id":7115},"b-해결-품질-resolution-quality-3-5","B. 해결 품질 (Resolution Quality) — ★ 3 \u002F 5",[135,7118,7119,7129],{},[138,7120,7121],{},[141,7122,7123,7125,7127],{},[144,7124,4143],{},[144,7126,6501],{},[144,7128,6425],{},[157,7130,7131,7142,7153,7163,7174,7185],{},[141,7132,7133,7136,7139],{},[162,7134,7135],{},"FCR (First Contact Resolution: 직원 단일 응답 후 종결)",[162,7137,7138],{},"14\u002F44 (31.8%)",[162,7140,7141],{},"⚠ 일반 CS 우수치 70%+ 대비 낮음",[141,7143,7144,7147,7150],{},[162,7145,7146],{},"평균 댓글 수 (게시글당)",[162,7148,7149],{},"3.68건 — 직원 2.6 + 고객 1.0 (이메일 기반 재분류)",[162,7151,7152],{},"⚠ 길어지는 경향",[141,7154,7155,7158,7161],{},[162,7156,7157],{},"종결 시그널 (감사·확인)",[162,7159,7160],{},"40\u002F44 (91%)",[162,7162,6527],{},[141,7164,7165,7168,7171],{},[162,7166,7167],{},"사과(죄송) 사용",[162,7169,7170],{},"4건",[162,7172,7173],{},"✓ 분쟁\u002F오류 노출 적음",[141,7175,7176,7179,7182],{},[162,7177,7178],{},"장기 미해결 (TTR > 30일)",[162,7180,7181],{},"90527 수료증(62일), 94221 회원탈퇴(192일)",[162,7183,7184],{},"⚠ 정책성 이슈 장기화",[141,7186,7187,7190,7193],{},[162,7188,7189],{},"반복 주제(재문의)",[162,7191,7192],{},"SMS 8 · 도메인\u002FB2B 7 · SSO 6 · 비밀번호 4 · 진도 3",[162,7194,7195],{},"✕ 표준화 부재 시그널",[24,7197,7198,7200,7201,7204,7205,7208],{},[28,7199,7107],{},": 종결률은 높지만 ",[28,7202,7203],{},"FCR 38%는 낮음"," — 한 번에 끝나지 않는 케이스가 많아 평균 4번 가까이 주고받음. 반복 주제가 8회까지 누적된다는 점은 ",[28,7206,7207],{},"표준 답변\u002FFAQ 부재","의 명확한 시그널.",[215,7210,7212],{"id":7211},"c-인력-운영-staffing-3-5","C. 인력 운영 (Staffing) — ★ 3 \u002F 5",[21,7214,7215],{},[24,7216,7217,7218,7220],{},"분류 기준: ",[16,7219,128],{}," = 직원, 그 외 = 고객\u002F협력사. 본 케이스 직원 응답 댓글 116건 기준.",[135,7222,7223,7233],{},[138,7224,7225],{},[141,7226,7227,7229,7231],{},[144,7228,4143],{},[144,7230,6501],{},[144,7232,6425],{},[157,7234,7235,7246,7259,7270,7280,7291],{},[141,7236,7237,7240,7243],{},[162,7238,7239],{},"응답 인력 수",[162,7241,7242],{},"직원 6명 (이영은·김서연·엄정원·이슬기·최종수·하근호)",[162,7244,7245],{},"✓ 적정",[141,7247,7248,7251,7256],{},[162,7249,7250],{},"주 응답자 집중도",[162,7252,7253],{},[28,7254,7255],{},"이영은 50 (43%) + 김서연 41 (35%) = 두 명이 78%",[162,7257,7258],{},"⚠ 2-인 의존 — 단일 의존보다는 양호",[141,7260,7261,7264,7267],{},[162,7262,7263],{},"역할 분담 패턴 (자연 형성)",[162,7265,7266],{},"이영은=운영·회계·유선 처리·B2B 협력 · 김서연=기술 응답·매뉴얼 안내 · 엄정원\u002F최종수=정책 거절·민감 안내(비공개 비율 73%·100%) · 이슬기\u002F하근호=보조",[162,7268,7269],{},"✓ 분담은 명확 (단 SOP 부재)",[141,7271,7272,7275,7278],{},[162,7273,7274],{},"백업\u002F순환 운영",[162,7276,7277],{},"주 응답자 2명 동시 운영 — 자연스러운 백업 효과",[162,7279,6527],{},[141,7281,7282,7285,7288],{},[162,7283,7284],{},"야간\u002F긴급 커버",[162,7286,7287],{},"야간 응답 4\u002F69 (6%) · 주말 0",[162,7289,7290],{},"⚠ 비영업시간 커버 부재",[141,7292,7293,7296,7299],{},[162,7294,7295],{},"표준답변·KMS 부재",[162,7297,7298],{},"반복 주제 매번 새로 답변",[162,7300,7301],{},"⚠",[24,7303,7304,7306,7307,7310,7311,7314,7315,7318],{},[28,7305,7107],{},": 이전 가설(김서연 단일 의존 62%)은 ",[28,7308,7309],{},"이메일 도메인 재분류로 뒤집힘"," — 실제로는 ",[28,7312,7313],{},"이영은·김서연 2-인 분담 체제","가 작동 중이며 역할까지 자연스럽게 갈려 있음(운영 vs 기술 vs 정책). 단일 의존 리스크는 낮아진 편이고, 가장 큰 결손은 ",[28,7316,7317],{},"표준답변\u002FKMS 부재로 인한 반복 응답"," 및 비영업시간 커버 부재.",[215,7320,7322],{"id":7321},"d-프로세스-성숙도-process-maturity-2-5","D. 프로세스 성숙도 (Process Maturity) — ★ 2 \u002F 5",[135,7324,7325,7336],{},[138,7326,7327],{},[141,7328,7329,7331,7334],{},[144,7330,4143],{},[144,7332,7333],{},"상태",[144,7335,6425],{},[157,7337,7338,7349,7359,7372,7382,7392,7402,7412],{},[141,7339,7340,7343,7346],{},[162,7341,7342],{},"정식 CS\u002F티켓 시스템",[162,7344,7345],{},"게시판 기반 — 티켓 ID·상태머신·우선순위·SLA 정의 없음",[162,7347,7348],{},"✕",[141,7350,7351,7354,7357],{},[162,7352,7353],{},"표준 답변\u002FFAQ",[162,7355,7356],{},"부재 — 반복 주제(SMS·SSO·도메인)에 매번 새로 답변",[162,7358,7348],{},[141,7360,7361,7364,7370],{},[162,7362,7363],{},"카테고리\u002F태그",[162,7365,7366,7369],{},[16,7367,7368],{},"tb_post_label"," 일부만 사용 — 일관 분류 없음",[162,7371,7301],{},[141,7373,7374,7377,7380],{},[162,7375,7376],{},"우선순위 표기",[162,7378,7379],{},"\"긴급\", \"★\" 임의 사용 — 실제 SLA 차별 없음",[162,7381,7348],{},[141,7383,7384,7387,7390],{},[162,7385,7386],{},"공개\u002F비공개 분리",[162,7388,7389],{},"운영됨 (15.4% 비공개로 정책 거절 격리)",[162,7391,6527],{},[141,7393,7394,7397,7400],{},[162,7395,7396],{},"지식 베이스 검색",[162,7398,7399],{},"같은 질문에 과거 답변 재활용 흔적 약함",[162,7401,7301],{},[141,7403,7404,7407,7410],{},[162,7405,7406],{},"에스컬레이션 경로",[162,7408,7409],{},"\"개발팀 전달\" 5건·\"유선\" 6건 — 채널 분기는 있으나 추적 부재",[162,7411,7301],{},[141,7413,7414,7417,7420],{},[162,7415,7416],{},"이슈 → 개발 환류",[162,7418,7419],{},"\"기능 개발 요청\" 5건 — 후속 개발 반영 추적 불명",[162,7421,7301],{},[24,7423,7424,7426,7427,7430],{},[28,7425,7107],{},": 게시판 위에서 자연스럽게 형성된 운영 — ",[28,7428,7429],{},"CS 시스템이라기보다 협업 도구",". SLA·표준답변·우선순위·검색이 모두 부재. 다만 비공개 격리는 의도적으로 잘 운영됨.",[215,7432,7434],{"id":7433},"e-고객-경험-customer-experience-4-5","E. 고객 경험 (Customer Experience) — ★ 4 \u002F 5",[135,7436,7437,7447],{},[138,7438,7439],{},[141,7440,7441,7443,7445],{},[144,7442,4143],{},[144,7444,6422],{},[144,7446,6425],{},[157,7448,7449,7459,7469,7479,7489,7500,7510],{},[141,7450,7451,7454,7457],{},[162,7452,7453],{},"만족 시그널",[162,7455,7456],{},"종결 멘트 91%, \"감사\" 138건(85%)",[162,7458,6527],{},[141,7460,7461,7464,7467],{},[162,7462,7463],{},"사과\u002F불만",[162,7465,7466],{},"4건 (낮음)",[162,7468,6527],{},[141,7470,7471,7474,7477],{},[162,7472,7473],{},"응답 톤 일관성",[162,7475,7476],{},"\"안녕하세요 맑은소프트입니다\" 정형 인삿말 일관",[162,7478,6527],{},[141,7480,7481,7484,7487],{},[162,7482,7483],{},"고객-담당자 관계",[162,7485,7486],{},"거의 모든 문의가 고은비 단독 → 동일 인원 응대 → 신뢰관계 형성",[162,7488,6527],{},[141,7490,7491,7494,7497],{},[162,7492,7493],{},"고객 측 능동성",[162,7495,7496],{},"고객 댓글이 57%로 더 많음 — 협업적·주체적",[162,7498,7499],{},"✓ 동시에 ⚠ (고객이 답변자 역할까지)",[141,7501,7502,7505,7508],{},[162,7503,7504],{},"긴급 대응 실패 사례",[162,7506,7507],{},"1건(92237) — 27시간 지연",[162,7509,7301],{},[141,7511,7512,7515,7518],{},[162,7513,7514],{},"거절 답변 노출",[162,7516,7517],{},"정책 거절은 비공개 처리되어 직접 노출 통제",[162,7519,6527],{},[24,7521,7522,7524,7525,7528],{},[28,7523,7107],{},": 정형화된 톤과 높은 종결률·낮은 사과 빈도는 만족도 양호 시그널. ",[28,7526,7527],{},"단일 컨택 포인트(고은비)에 의한 안정적 신뢰 관계","가 잡혀 있음. 다만 긴급 SLA 불이행 1건은 KPI 차원에서 명시적 결함.",[215,7530,7532],{"id":7531},"종합-점수표","종합 점수표",[135,7534,7535,7548],{},[138,7536,7537],{},[141,7538,7539,7542,7545],{},[144,7540,7541],{},"차원",[144,7543,7544],{},"점수 (★ \u002F 5)",[144,7546,7547],{},"핵심 요점",[157,7549,7550,7561,7572,7582,7593,7603],{},[141,7551,7552,7555,7558],{},[162,7553,7554],{},"응답 신속성",[162,7556,7557],{},"★ 4",[162,7559,7560],{},"FRT 우수, 영업시간 응답 94% — 단 긴급 SLA 부재",[141,7562,7563,7566,7569],{},[162,7564,7565],{},"해결 품질",[162,7567,7568],{},"★ 3",[162,7570,7571],{},"종결률 91% 좋지만 FCR 38%·평균 3.68턴 — 표준답변 부재",[141,7573,7574,7577,7579],{},[162,7575,7576],{},"인력 운영",[162,7578,7568],{},[162,7580,7581],{},"이영은·김서연 2-인 분담(78%), 역할 자연 분담 (운영\u002F기술\u002F정책)",[141,7583,7584,7587,7590],{},[162,7585,7586],{},"프로세스 성숙도",[162,7588,7589],{},"★ 2",[162,7591,7592],{},"게시판 기반, SLA·티켓·FAQ 부재",[141,7594,7595,7598,7600],{},[162,7596,7597],{},"고객 경험",[162,7599,7557],{},[162,7601,7602],{},"종결률·정형 응대·신뢰관계 양호",[141,7604,7605,7610,7615],{},[162,7606,7607],{},[28,7608,7609],{},"전체 평균",[162,7611,7612],{},[28,7613,7614],{},"★ 3.2 \u002F 5",[162,7616,7617],{},[28,7618,7619],{},"본 케이스 표본 기준, 일반 CS 운영의 중상 수준",[215,7621,7623],{"id":7622},"강점-vs-개선점","강점 vs 개선점",[24,7625,7626],{},[28,7627,7628],{},"강점",[54,7630,7631,7634,7637,7640,7643],{},[57,7632,7633],{},"평일 영업시간 응답 속도 빠름 (1일 내 95%)",[57,7635,7636],{},"종결률 높음 (91%)",[57,7638,7639],{},"정형 응대 톤 일관 — 신뢰감",[57,7641,7642],{},"정책 거절을 비공개로 격리 — 고객 노출 통제 양호",[57,7644,7645],{},"단일 컨택 포인트와 장기 신뢰 관계 형성",[24,7647,7648],{},[28,7649,7650],{},"개선점",[135,7652,7653,7666],{},[138,7654,7655],{},[141,7656,7657,7660,7663],{},[144,7658,7659],{},"우선순위",[144,7661,7662],{},"개선 항목",[144,7664,7665],{},"기대 효과",[157,7667,7668,7681,7695,7708,7721,7734],{},[141,7669,7670,7672,7678],{},[162,7671,6055],{},[162,7673,7674,7677],{},[28,7675,7676],{},"표준 답변\u002FFAQ 도입"," — 반복 주제(SSO·SMS·도메인·비밀번호 등 28건 이상)",[162,7679,7680],{},"FCR 상승, 평균 응답 횟수 감소",[141,7682,7683,7686,7692],{},[162,7684,7685],{},"2",[162,7687,7688,7691],{},[28,7689,7690],{},"역할 분담 SOP 명문화"," — 이영은=운영\u002F회계 · 김서연=기술 · 엄정원·최종수=정책 거절 등 자연 분담을 공식화",[162,7693,7694],{},"신규 인력 onboarding, 인원 부재 시 대체",[141,7696,7697,7699,7705],{},[162,7698,6004],{},[162,7700,7701,7704],{},[28,7702,7703],{},"SLA 정의·우선순위 분기"," — \"긴급\" 표기에 실제 처리 시간 차별화",[162,7706,7707],{},"긴급 SLA 불일치 해소",[141,7709,7710,7712,7718],{},[162,7711,5963],{},[162,7713,7714,7717],{},[28,7715,7716],{},"정식 티켓\u002F카테고리\u002F태그"," — 동일 주제 검색·재활용 가능",[162,7719,7720],{},"지식 자산화, 신규 인력 onboarding",[141,7722,7723,7725,7731],{},[162,7724,5952],{},[162,7726,7727,7730],{},[28,7728,7729],{},"이슈 → 개발 환류 추적"," — 기능 개발 요청 5건의 처리 상태 가시화",[162,7732,7733],{},"고객 신뢰 유지, 제품 개선 흐름",[141,7735,7736,7738,7744],{},[162,7737,6066],{},[162,7739,7740,7743],{},[28,7741,7742],{},"위탁성 운영 요청 분리"," — 모니터링·발송·세팅 등 정기 요청은 운영 SOP화",[162,7745,7746],{},"CS 문의 외 잡음 감소",[215,7748,7750],{"id":7749},"본-케이스-전사-시사점","본 케이스 → 전사 시사점",[24,7752,7753,7754,7756],{},"본 평가는 안전보건진흥원 단일 프로젝트 기준이지만, 동일 게시판이 다수 고객사를 공유하는 ",[3257,7755,5780],{"href":5779}," 분석을 고려하면 다음 패턴이 일반화될 가능성 높음:",[54,7758,7759,7765,7771,7777],{},[57,7760,7761,7764],{},[28,7762,7763],{},"FCR이 일반적으로 낮을 것"," — 게시판 협업 특성상",[57,7766,7767,7770],{},[28,7768,7769],{},"단일 인원 집중도"," — 김서연이 다른 프로젝트에서도 다수 답변자일 가능성 (별도 검증 필요)",[57,7772,7773,7776],{},[28,7774,7775],{},"표준답변\u002FFAQ 부재"," — 모든 프로젝트 공통 → 회사 차원의 KMS(Knowledge Management System) 도입 가치 큼",[57,7778,7779,7782],{},[28,7780,7781],{},"SLA·티켓 시스템 부재"," — 회사 차원 CS 운영 체계 정비 필요",[21,7784,7785],{},[24,7786,7787,7790,7791,7794],{},[28,7788,7789],{},"권장",": 다른 Top 5 프로젝트(에듀야·웅진·프라임에듀넷·케이에이치·경복대)에도 본 §7 양식을 적용해 ",[28,7792,7793],{},"전사 CS 운영 점수"," 산출 후 개선 우선순위 합의.",[33,7796],{},[36,7798,7800],{"id":7799},"_8-고객사-평가-안전보건진흥원-협업-행태","8. 고객사 평가 — 안전보건진흥원 (협업 행태)",[21,7802,7803],{},[24,7804,7805,7806,7809],{},"맑은소프트가 받는 입장에서, ",[28,7807,7808],{},"안전보건진흥원이 고객사로서 얼마나 다루기 쉬운가","를 평가.\n다섯 축: A 문의 품질 \u002F B 컨택 일관성 \u002F C 요청 합리성 \u002F D 협업 태도 \u002F E 운영 성숙도.",[215,7811,7813],{"id":7812},"a-문의-품질-inquiry-quality-5-5","A. 문의 품질 (Inquiry Quality) — ★ 5 \u002F 5",[135,7815,7816,7826],{},[138,7817,7818],{},[141,7819,7820,7822,7824],{},[144,7821,4143],{},[144,7823,6422],{},[144,7825,6425],{},[157,7827,7828,7842,7861,7872,7882],{},[141,7829,7830,7833,7839],{},[162,7831,7832],{},"제목 구조화",[162,7834,7835,7838],{},[16,7836,7837],{},"[안전보건진흥원] [카테고리] 내용"," 형식 — 44\u002F48 (92%) 일관 사용",[162,7840,7841],{},"✓ 매우 우수",[141,7843,7844,7847,7859],{},[162,7845,7846],{},"카테고리 라벨링",[162,7848,7849,105,7852,105,7855,7858],{},[16,7850,7851],{},"[SSO 연동]",[16,7853,7854],{},"[SMS 문자관련]",[16,7856,7857],{},"[수료증관련]"," 등 자체 분류 부여",[162,7860,6527],{},[141,7862,7863,7866,7869],{},[162,7864,7865],{},"본문 길이·정보량",[162,7867,7868],{},"평균 646자(HTML 포함), 100자 미만 0건, 500자+ 12건",[162,7870,7871],{},"✓ 상세함",[141,7873,7874,7877,7880],{},[162,7875,7876],{},"컨텍스트 첨부",[162,7878,7879],{},"첨부 보유 32\u002F48 (67%) — 스크린샷·문서로 보강",[162,7881,6527],{},[141,7883,7884,7887,7890],{},[162,7885,7886],{},"재현 정보",[162,7888,7889],{},"화면 캡처·오류 메시지·발생 시점 명시 사례 다수",[162,7891,6527],{},[24,7893,7894,7896,7897,7900],{},[28,7895,7107],{},": 운영자가 받았을 때 ",[28,7898,7899],{},"식별·분류·재현이 모두 쉬운 이상적 문의 형태",". 다른 고객사 대비 단연 우수.",[215,7902,7904],{"id":7903},"b-컨택-일관성-contact-reliability-2-5","B. 컨택 일관성 (Contact Reliability) — ★ 2 \u002F 5",[21,7906,7907],{},[24,7908,7909,7910,7913],{},"이메일 도메인 재분류 후: 안전보건진흥원 측 작성자는 ",[28,7911,7912],{},"고은비 단독",". 이전에 백업으로 보았던 \"이영은\"은 사실 맑은소프트 직원이었음.",[135,7915,7916,7926],{},[138,7917,7918],{},[141,7919,7920,7922,7924],{},[144,7921,4143],{},[144,7923,6501],{},[144,7925,6425],{},[157,7927,7928,7940,7954,7965,7975],{},[141,7929,7930,7933,7938],{},[162,7931,7932],{},"주 담당자",[162,7934,5873,7935,7937],{},[16,7936,5876],{},") — 게시글 44\u002F48 (92%)",[162,7939,6527],{},[141,7941,7942,7945,7948],{},[162,7943,7944],{},"협업자\u002F백업",[162,7946,7947],{},"안전보건진흥원 측 다른 작성자 사실상 없음",[162,7949,7950,7951],{},"✕ ",[28,7952,7953],{},"단일 인원 의존",[141,7955,7956,7959,7962],{},[162,7957,7958],{},"다중 채널 사용",[162,7960,7961],{},"게시판 + 가끔 유선 (\"유선 문의 주신 내용\" 표현 등장)",[162,7963,7964],{},"⚠ 채널 일원화 미흡",[141,7966,7967,7970,7973],{},[162,7968,7969],{},"응대 시간대",[162,7971,7972],{},"영업시간 중심 (평일 09~18)",[162,7974,6527],{},[141,7976,7977,7980,7983],{},[162,7978,7979],{},"후속 응답 속도",[162,7981,7982],{},"staff→customer 후속 17건 중 1일 내 11건(65%)",[162,7984,7985],{},"⚠ 일부 outlier 장기화",[24,7987,7988,7990,7991,7994],{},[28,7989,7107],{},": 고객 측이 ",[28,7992,7993],{},"고은비 1인 단독 컨택",". 인수인계·휴가·이직 시 운영 중단 리스크가 매우 큼. 정리하면 본 케이스의 운영 안정성은 안전보건진흥원 측의 인사 안정성에 전적으로 의존하는 구조.",[215,7996,7998],{"id":7997},"c-요청-합리성-demand-reasonability-3-5","C. 요청 합리성 (Demand Reasonability) — ★ 3 \u002F 5",[135,8000,8001,8011],{},[138,8002,8003],{},[141,8004,8005,8007,8009],{},[144,8006,4143],{},[144,8008,6501],{},[144,8010,6425],{},[157,8012,8013,8024,8034,8043,8052,8062],{},[141,8014,8015,8018,8021],{},[162,8016,8017],{},"위탁·협업 요청 비중",[162,8019,8020],{},"25\u002F48 (52%) — \"모니터링 부탁\", \"발송 확인\", \"작업 진행\" 등",[162,8022,8023],{},"⚠ 비중 높음",[141,8025,8026,8029,8032],{},[162,8027,8028],{},"단순 기능 질의",[162,8030,8031],{},"13\u002F48 (27%) — 정상 범위",[162,8033,6527],{},[141,8035,8036,8038,8041],{},[162,8037,6821],{},[162,8039,8040],{},"12\u002F48 (25%) — 정상 운영 비율",[162,8042,6527],{},[141,8044,8045,8047,8050],{},[162,8046,6835],{},[162,8048,8049],{},"5\u002F48 (10%) — 무리한 빈도 아님",[162,8051,6527],{},[141,8053,8054,8057,8060],{},[162,8055,8056],{},"긴급 표기 사용",[162,8058,8059],{},"3건 (긴급·★) — 남용 없음, 실제 긴급 사안과 일치",[162,8061,6527],{},[141,8063,8064,8067,8070],{},[162,8065,8066],{},"법령\u002F근거 인용",[162,8068,8069],{},"\"법령상 수료증 양식 지침\" 등 정확한 근거 제시",[162,8071,6527],{},[24,8073,8074,4664,8076,8079],{},[28,8075,7107],{},[28,8077,8078],{},"위탁성 요청 52%는 양면적"," — LMS 운영 위탁 계약이라면 정상이지만, 단순 시스템 공급 관계라면 부담 큼. 단 긴급 표기 남용 없고 법령 근거를 정확히 인용하는 점은 매우 성숙.",[21,8081,8082],{},[24,8083,8084,8085,8087],{},"본 비율은 ",[3257,8086,5780],{"href":5779},"의 다른 고객사와 비교해서 정상 운영 위탁 vs 비정상 부담 구간인지 별도 판단 필요.",[215,8089,8091],{"id":8090},"d-협업-태도-collaboration-attitude-5-5","D. 협업 태도 (Collaboration Attitude) — ★ 5 \u002F 5",[135,8093,8094,8104],{},[138,8095,8096],{},[141,8097,8098,8100,8102],{},[144,8099,4143],{},[144,8101,6501],{},[144,8103,6425],{},[157,8105,8106,8116,8126,8139,8149,8160],{},[141,8107,8108,8111,8114],{},[162,8109,8110],{},"종결 멘트 작성",[162,8112,8113],{},"마지막 댓글이 고객인 경우 5\u002F5 (100%), 직원인 경우 35\u002F39 (90%) — 양쪽 종결 책임",[162,8115,6527],{},[141,8117,8118,8121,8124],{},[162,8119,8120],{},"매너 키워드 (고객 댓글 46건 기준)",[162,8122,8123],{},"감사 33 (72%) · 확인 28 (61%) · 부탁 31 (67%)",[162,8125,6527],{},[141,8127,8128,8131,8137],{},[162,8129,8130],{},"사과·불만 표현",[162,8132,8133,8136],{},[28,8134,8135],{},"죄송 0건"," — 갈등·불만 표출 없음",[162,8138,6527],{},[141,8140,8141,8144,8147],{},[162,8142,8143],{},"회신 방향성",[162,8145,8146],{},"답변 후 \"확인했습니다, 감사합니다\" 추가 멘트 다수",[162,8148,6527],{},[141,8150,8151,8154,8157],{},[162,8152,8153],{},"답변자 역할 분담 인지",[162,8155,8156],{},"정책 거절 답변에 대해서도 \"감사합니다, 확인했습니다\"로 종결",[162,8158,8159],{},"✓ 성숙",[141,8161,8162,8165,8168],{},[162,8163,8164],{},"후속 정보 능동 제공",[162,8166,8167],{},"본인 글에 셀프 보완 댓글 43건 — 운영자 답변 기다리지 않고 능동 보완",[162,8169,6527],{},[24,8171,8172,4664,8174,8177],{},[28,8173,7107],{},[28,8175,8176],{},"모범적인 협업 태도",". 정책 거절(개발 불가·미지원)에도 분쟁 없이 종결. 운영자 측 응대 부담이 크게 경감.",[215,8179,8181],{"id":8180},"e-운영-성숙도-operational-maturity-3-5","E. 운영 성숙도 (Operational Maturity) — ★ 3 \u002F 5",[135,8183,8184,8194],{},[138,8185,8186],{},[141,8187,8188,8190,8192],{},[144,8189,4143],{},[144,8191,6422],{},[144,8193,6425],{},[157,8195,8196,8206,8219,8229,8239,8249,8260],{},[141,8197,8198,8201,8204],{},[162,8199,8200],{},"기술적 이해도",[162,8202,8203],{},"\"비즈뿌리오\", \"SSO\", \"CDN\", \"A레코드\", \"WBT\" 등 정확한 용어 사용",[162,8205,6527],{},[141,8207,8208,8211,8217],{},[162,8209,8210],{},"자체 분류 운영",[162,8212,8213,8214,8216],{},"게시글 카테고리(",[16,8215,7851],{}," 등) 자체 정의",[162,8218,6527],{},[141,8220,8221,8224,8227],{},[162,8222,8223],{},"FAQ 인지",[162,8225,8226],{},"\"자주하는 질문 카테고리 설정 관련 문의\"(93437) — 본인 시스템의 FAQ 기능 활용 의지",[162,8228,6527],{},[141,8230,8231,8234,8236],{},[162,8232,8233],{},"동일 주제 반복",[162,8235,7192],{},[162,8237,8238],{},"⚠ 운영 안정화 미흡",[141,8240,8241,8244,8247],{},[162,8242,8243],{},"의사결정 일관성",[162,8245,8246],{},"일부 정책 거절 답변 후에도 유사 요청 재제기 사례 적음",[162,8248,6527],{},[141,8250,8251,8254,8257],{},[162,8252,8253],{},"시스템 도입 단계",[162,8255,8256],{},"도입 직후 3개월 집중 문의 — 신규 도입의 자연스러운 형태",[162,8258,8259],{},"✓ (시기 한정)",[141,8261,8262,8265,8268],{},[162,8263,8264],{},"장기 미종결 처리",[162,8266,8267],{},"94221(192일), 90495(1652h) 등 일부 방치 — 후속 추적 부재",[162,8269,7301],{},[24,8271,8272,8274,8275,8278],{},[28,8273,7107],{},": 기술 용어 정확·자체 분류 운영·FAQ 인지 등 ",[28,8276,8277],{},"고객사 자체 운영 역량 양호",". 다만 동일 주제 반복이 8회까지 누적되는 점은 내부 정착·교육이 미진했음을 시사 — 다만 도입 초기라는 점 감안 필요.",[215,8280,7532],{"id":8281},"종합-점수표-1",[135,8283,8284,8296],{},[138,8285,8286],{},[141,8287,8288,8290,8293],{},[144,8289,7541],{},[144,8291,8292],{},"점수 (★\u002F5)",[144,8294,8295],{},"핵심",[157,8297,8298,8309,8322,8332,8345,8355],{},[141,8299,8300,8303,8306],{},[162,8301,8302],{},"문의 품질",[162,8304,8305],{},"★ 5",[162,8307,8308],{},"제목 구조화 92%, 본문 풍부, 첨부 67%",[141,8310,8311,8314,8316],{},[162,8312,8313],{},"컨택 일관성",[162,8315,7589],{},[162,8317,8318,8321],{},[28,8319,8320],{},"고은비 1인 단독"," — 백업 없음 (이전 가설 수정)",[141,8323,8324,8327,8329],{},[162,8325,8326],{},"요청 합리성",[162,8328,7568],{},[162,8330,8331],{},"위탁성 52% — 계약 형태에 따라 평가 갈림",[141,8333,8334,8337,8339],{},[162,8335,8336],{},"협업 태도",[162,8338,8305],{},[162,8340,8341,8342,8344],{},"매너 키워드 비율 60~70%, ",[28,8343,8135],{},", 종결 100%",[141,8346,8347,8350,8352],{},[162,8348,8349],{},"운영 성숙도",[162,8351,7568],{},[162,8353,8354],{},"기술 용어 정확, 반복 주제 다수, 일부 미종결 방치",[141,8356,8357,8361,8366],{},[162,8358,8359],{},[28,8360,7609],{},[162,8362,8363],{},[28,8364,8365],{},"★ 3.6 \u002F 5",[162,8367,8368],{},[28,8369,8370],{},"우수 고객이나 단일 인원 의존이 최대 리스크",[215,8372,8374],{"id":8373},"강점-vs-잠재-우려","강점 vs 잠재 우려",[24,8376,8377],{},[28,8378,7628],{},[54,8380,8381,8384,8387,8390],{},[57,8382,8383],{},"제목·본문이 정형화되어 식별·재현 매우 쉬움",[57,8385,8386],{},"매너·종결 책임 양호 (고객 댓글 46건 중 감사 33·부탁 31·죄송 0)",[57,8388,8389],{},"기술 용어 정확, 법령 근거 인용",[57,8391,8392],{},"정책 거절도 분쟁 없이 수용 — 협업 성숙도 높음",[24,8394,8395],{},[28,8396,8397],{},"잠재 우려",[135,8399,8400,8409],{},[138,8401,8402],{},[141,8403,8404,8407],{},[144,8405,8406],{},"우려",[144,8408,1292],{},[157,8410,8411,8421,8429,8437,8445],{},[141,8412,8413,8418],{},[162,8414,8415],{},[28,8416,8417],{},"단일 인원 의존 (고은비 1인)",[162,8419,8420],{},"백업 없음. 인사 이동·휴가 시 운영 즉시 중단 위험. 본 평가의 가장 큰 결손",[141,8422,8423,8426],{},[162,8424,8425],{},"위탁·운영 요청 비중 (52%)",[162,8427,8428],{},"LMS 운영 자체를 위탁받은 관계라면 정상. 단순 공급이라면 SLA·과금 재정의 필요",[141,8430,8431,8434],{},[162,8432,8433],{},"반복 주제 누적",[162,8435,8436],{},"동일 카테고리 8회 발생 — 사용자 교육·매뉴얼·FAQ 제공 가치 큼",[141,8438,8439,8442],{},[162,8440,8441],{},"장기 미종결 글 방치",[162,8443,8444],{},"일부 스레드가 6개월~수년 후 잡담 댓글로 끝남 — 명시적 종결 프로세스 필요",[141,8446,8447,8450],{},[162,8448,8449],{},"유선 채널 병행",[162,8451,8452],{},"게시판 추적성 부분 단절 — 모든 컨택을 게시판으로 일원화 권장",[215,8454,8456],{"id":8455},"매트릭스-제공자-vs-고객사","매트릭스 — 제공자 vs 고객사",[24,8458,8459],{},"본 케이스에서 양측 평가를 비교하면:",[135,8461,8462,8474],{},[138,8463,8464],{},[141,8465,8466,8468,8471],{},[144,8467,7541],{},[144,8469,8470],{},"맑은소프트 (§7)",[144,8472,8473],{},"안전보건진흥원 (§8)",[157,8475,8476,8487,8498,8509,8520],{},[141,8477,8478,8481,8484],{},[162,8479,8480],{},"응답·문의 신속\u002F품질",[162,8482,8483],{},"★ 4 (FRT 우수)",[162,8485,8486],{},"★ 5 (제목·본문 우수)",[141,8488,8489,8492,8495],{},[162,8490,8491],{},"일관성·신뢰성",[162,8493,8494],{},"★ 3 (FCR 32%)",[162,8496,8497],{},"★ 2 (1인 단독 의존)",[141,8499,8500,8503,8506],{},[162,8501,8502],{},"인력·운영 역량",[162,8504,8505],{},"★ 3 (2-인 분담)",[162,8507,8508],{},"★ 3 (도입 직후)",[141,8510,8511,8514,8517],{},[162,8512,8513],{},"프로세스·성숙도",[162,8515,8516],{},"★ 2 (시스템 부재)",[162,8518,8519],{},"★ 3 (자체 분류·FAQ 인지)",[141,8521,8522,8525,8528],{},[162,8523,8524],{},"태도·경험",[162,8526,8527],{},"★ 4 (정형 톤)",[162,8529,8530],{},"★ 5 (매너·종결)",[24,8532,8533,8536,8537,8540,8541,8544],{},[28,8534,8535],{},"관계 진단",": 이메일 도메인 재분류 후 그림이 달라짐 — ",[28,8538,8539],{},"양측 모두 인력 안정성 측면에서 결손",". 맑소는 2-인 분담은 양호하나 표준답변\u002FSLA\u002F티켓 시스템 부재(★2), 안전보건진흥원은 협업 행태와 문의 품질은 모범적이지만 고은비 1인 단독으로 백업 부재. 즉, ",[28,8542,8543],{},"공급자는 시스템적 결손, 고객사는 인적 단일점 의존","이 각각의 핵심 리스크. 챗봇·표준답변 도입이 양측 모두에게 동시에 이익이 되는 구조.",[215,8546,8548],{"id":8547},"후속-활용","후속 활용",[54,8550,8551,8561,8567],{},[57,8552,8553,8556,8557,8560],{},[28,8554,8555],{},"고객사 우수 사례",": 본 케이스의 제목 구조화·매너·종결 책임 행태를 ",[28,8558,8559],{},"신규 고객사 온보딩 가이드","의 모범 예시로 활용.",[57,8562,8563,8566],{},[28,8564,8565],{},"위탁 비중 검증",": 다른 Top 5 고객사의 위탁성 요청 비중과 비교해 본 케이스가 평균인지 outlier인지 판단.",[57,8568,8569,8572],{},[28,8570,8571],{},"고객사 SLA 자가진단 도구",": 본 5축 평가를 고객사가 스스로 점검할 수 있는 셀프 체크리스트로 발전 가능 — 도입 시점·계약 갱신 시점에 활용.",[33,8574],{},[36,8576,8578],{"id":8577},"_9-추출-쿼리-재현용","9. 추출 쿼리 (재현용)",[415,8580,8584],{"className":8581,"code":8582,"language":8583,"meta":423,"style":423},"language-sql shiki shiki-themes github-light github-dark","-- 안전보건진흥원 프로젝트 전체 게시글\nSELECT p.id, p.subject, p.writer, p.comm_cnt,\n       SUBSTRING(p.reg_date, 1, 8) AS reg\nFROM tb_post p\nWHERE p.project_id = 1528 AND p.status = 1\nORDER BY p.reg_date;\n\n-- 댓글까지 결합한 스레드 본문\nSELECT 'POST' kind, id, writer, 'N' priv, content, reg_date\nFROM tb_post WHERE project_id = 1528 AND status = 1\nUNION ALL\nSELECT 'COMMENT', c.id, c.writer, c.private_yn, c.content, c.reg_date\nFROM tb_post_comment c\nJOIN tb_post p ON p.id = c.post_id\nWHERE p.project_id = 1528 AND p.status = 1 AND c.status = 1\nORDER BY 6;\n\n-- FCR (First Contact Resolution) proxy: 직원(@malgnsoft.com) 단일 답변 후 종결\nWITH staff_first AS (\n  SELECT c.post_id, COUNT(*) AS staff_replies\n  FROM tb_post_comment c JOIN tb_post p ON p.id = c.post_id\n       LEFT JOIN tb_user u ON u.id = c.user_id\n  WHERE p.project_id = 1528 AND p.status = 1 AND c.status = 1\n    AND u.email LIKE '%@malgnsoft.com'\n  GROUP BY c.post_id\n)\nSELECT\n  SUM(staff_replies = 1) AS fcr_count,\n  COUNT(*) AS total,\n  ROUND(100.0 * SUM(staff_replies = 1) \u002F COUNT(*), 1) AS fcr_pct\nFROM staff_first;\n\n-- 응답 시간 분포 (FRT 분)\nSELECT\n  ROUND(AVG(frt)) avg_min,\n  SUM(frt \u003C= 60) within_1h,\n  SUM(frt \u003C= 240) within_4h,\n  SUM(frt \u003C= 1440) within_1d,\n  COUNT(*) total\nFROM (\n  SELECT TIMESTAMPDIFF(MINUTE,\n    STR_TO_DATE(p.reg_date,'%Y%m%d%H%i%s'),\n    STR_TO_DATE(MIN(c.reg_date),'%Y%m%d%H%i%s')) AS frt\n  FROM tb_post p JOIN tb_post_comment c ON c.post_id = p.id\n  WHERE p.project_id = 1528 AND p.status = 1 AND c.status = 1\n  GROUP BY p.id\n) t WHERE frt IS NOT NULL;\n\n-- 고객사 평가: 제목 구조화, 본문 길이, 첨부 보유, 매너 키워드\nSELECT\n  SUM(subject LIKE '[안전보건진흥원]%') AS structured,\n  COUNT(*) AS total,\n  ROUND(AVG(CHAR_LENGTH(content))) AS avg_body_len\nFROM tb_post WHERE project_id = 1528 AND status = 1;\n\n-- 고객 측 매너 키워드: @malgnsoft.com 이 아닌 작성자만\nSELECT\n  SUM(c.content LIKE '%감사%') AS thanks,\n  SUM(c.content LIKE '%확인%') AS confirm,\n  SUM(c.content LIKE '%부탁%') AS please,\n  SUM(c.content LIKE '%죄송%') AS apology,\n  COUNT(*) AS customer_comments\nFROM tb_post_comment c JOIN tb_post p ON p.id = c.post_id\n     LEFT JOIN tb_user u ON u.id = c.user_id\nWHERE p.project_id = 1528 AND c.status = 1\n  AND (u.email IS NULL OR u.email NOT LIKE '%@malgnsoft.com');\n","sql",[16,8585,8586,8591,8596,8601,8606,8611,8616,8620,8625,8630,8635,8640,8645,8650,8655,8660,8665,8669,8674,8679,8684,8690,8696,8702,8708,8714,8719,8725,8731,8737,8743,8749,8754,8760,8765,8771,8777,8783,8789,8795,8801,8807,8813,8819,8825,8830,8836,8842,8847,8853,8858,8864,8869,8875,8881,8886,8892,8897,8903,8909,8915,8921,8927,8933,8939,8945],{"__ignoreMap":423},[2166,8587,8588],{"class":3301,"line":3302},[2166,8589,8590],{},"-- 안전보건진흥원 프로젝트 전체 게시글\n",[2166,8592,8593],{"class":3301,"line":3335},[2166,8594,8595],{},"SELECT p.id, p.subject, p.writer, p.comm_cnt,\n",[2166,8597,8598],{"class":3301,"line":3342},[2166,8599,8600],{},"       SUBSTRING(p.reg_date, 1, 8) AS reg\n",[2166,8602,8603],{"class":3301,"line":3368},[2166,8604,8605],{},"FROM tb_post p\n",[2166,8607,8608],{"class":3301,"line":3396},[2166,8609,8610],{},"WHERE p.project_id = 1528 AND p.status = 1\n",[2166,8612,8613],{"class":3301,"line":3426},[2166,8614,8615],{},"ORDER BY p.reg_date;\n",[2166,8617,8618],{"class":3301,"line":3463},[2166,8619,3339],{"emptyLinePlaceholder":3338},[2166,8621,8622],{"class":3301,"line":3504},[2166,8623,8624],{},"-- 댓글까지 결합한 스레드 본문\n",[2166,8626,8627],{"class":3301,"line":3538},[2166,8628,8629],{},"SELECT 'POST' kind, id, writer, 'N' priv, content, reg_date\n",[2166,8631,8632],{"class":3301,"line":3550},[2166,8633,8634],{},"FROM tb_post WHERE project_id = 1528 AND status = 1\n",[2166,8636,8637],{"class":3301,"line":3556},[2166,8638,8639],{},"UNION ALL\n",[2166,8641,8642],{"class":3301,"line":5367},[2166,8643,8644],{},"SELECT 'COMMENT', c.id, c.writer, c.private_yn, c.content, c.reg_date\n",[2166,8646,8647],{"class":3301,"line":5375},[2166,8648,8649],{},"FROM tb_post_comment c\n",[2166,8651,8652],{"class":3301,"line":5392},[2166,8653,8654],{},"JOIN tb_post p ON p.id = c.post_id\n",[2166,8656,8657],{"class":3301,"line":5404},[2166,8658,8659],{},"WHERE p.project_id = 1528 AND p.status = 1 AND c.status = 1\n",[2166,8661,8662],{"class":3301,"line":5415},[2166,8663,8664],{},"ORDER BY 6;\n",[2166,8666,8667],{"class":3301,"line":5421},[2166,8668,3339],{"emptyLinePlaceholder":3338},[2166,8670,8671],{"class":3301,"line":5432},[2166,8672,8673],{},"-- FCR (First Contact Resolution) proxy: 직원(@malgnsoft.com) 단일 답변 후 종결\n",[2166,8675,8676],{"class":3301,"line":5453},[2166,8677,8678],{},"WITH staff_first AS (\n",[2166,8680,8681],{"class":3301,"line":5459},[2166,8682,8683],{},"  SELECT c.post_id, COUNT(*) AS staff_replies\n",[2166,8685,8687],{"class":3301,"line":8686},21,[2166,8688,8689],{},"  FROM tb_post_comment c JOIN tb_post p ON p.id = c.post_id\n",[2166,8691,8693],{"class":3301,"line":8692},22,[2166,8694,8695],{},"       LEFT JOIN tb_user u ON u.id = c.user_id\n",[2166,8697,8699],{"class":3301,"line":8698},23,[2166,8700,8701],{},"  WHERE p.project_id = 1528 AND p.status = 1 AND c.status = 1\n",[2166,8703,8705],{"class":3301,"line":8704},24,[2166,8706,8707],{},"    AND u.email LIKE '%@malgnsoft.com'\n",[2166,8709,8711],{"class":3301,"line":8710},25,[2166,8712,8713],{},"  GROUP BY c.post_id\n",[2166,8715,8717],{"class":3301,"line":8716},26,[2166,8718,4527],{},[2166,8720,8722],{"class":3301,"line":8721},27,[2166,8723,8724],{},"SELECT\n",[2166,8726,8728],{"class":3301,"line":8727},28,[2166,8729,8730],{},"  SUM(staff_replies = 1) AS fcr_count,\n",[2166,8732,8734],{"class":3301,"line":8733},29,[2166,8735,8736],{},"  COUNT(*) AS total,\n",[2166,8738,8740],{"class":3301,"line":8739},30,[2166,8741,8742],{},"  ROUND(100.0 * SUM(staff_replies = 1) \u002F COUNT(*), 1) AS fcr_pct\n",[2166,8744,8746],{"class":3301,"line":8745},31,[2166,8747,8748],{},"FROM staff_first;\n",[2166,8750,8752],{"class":3301,"line":8751},32,[2166,8753,3339],{"emptyLinePlaceholder":3338},[2166,8755,8757],{"class":3301,"line":8756},33,[2166,8758,8759],{},"-- 응답 시간 분포 (FRT 분)\n",[2166,8761,8763],{"class":3301,"line":8762},34,[2166,8764,8724],{},[2166,8766,8768],{"class":3301,"line":8767},35,[2166,8769,8770],{},"  ROUND(AVG(frt)) avg_min,\n",[2166,8772,8774],{"class":3301,"line":8773},36,[2166,8775,8776],{},"  SUM(frt \u003C= 60) within_1h,\n",[2166,8778,8780],{"class":3301,"line":8779},37,[2166,8781,8782],{},"  SUM(frt \u003C= 240) within_4h,\n",[2166,8784,8786],{"class":3301,"line":8785},38,[2166,8787,8788],{},"  SUM(frt \u003C= 1440) within_1d,\n",[2166,8790,8792],{"class":3301,"line":8791},39,[2166,8793,8794],{},"  COUNT(*) total\n",[2166,8796,8798],{"class":3301,"line":8797},40,[2166,8799,8800],{},"FROM (\n",[2166,8802,8804],{"class":3301,"line":8803},41,[2166,8805,8806],{},"  SELECT TIMESTAMPDIFF(MINUTE,\n",[2166,8808,8810],{"class":3301,"line":8809},42,[2166,8811,8812],{},"    STR_TO_DATE(p.reg_date,'%Y%m%d%H%i%s'),\n",[2166,8814,8816],{"class":3301,"line":8815},43,[2166,8817,8818],{},"    STR_TO_DATE(MIN(c.reg_date),'%Y%m%d%H%i%s')) AS frt\n",[2166,8820,8822],{"class":3301,"line":8821},44,[2166,8823,8824],{},"  FROM tb_post p JOIN tb_post_comment c ON c.post_id = p.id\n",[2166,8826,8828],{"class":3301,"line":8827},45,[2166,8829,8701],{},[2166,8831,8833],{"class":3301,"line":8832},46,[2166,8834,8835],{},"  GROUP BY p.id\n",[2166,8837,8839],{"class":3301,"line":8838},47,[2166,8840,8841],{},") t WHERE frt IS NOT NULL;\n",[2166,8843,8845],{"class":3301,"line":8844},48,[2166,8846,3339],{"emptyLinePlaceholder":3338},[2166,8848,8850],{"class":3301,"line":8849},49,[2166,8851,8852],{},"-- 고객사 평가: 제목 구조화, 본문 길이, 첨부 보유, 매너 키워드\n",[2166,8854,8856],{"class":3301,"line":8855},50,[2166,8857,8724],{},[2166,8859,8861],{"class":3301,"line":8860},51,[2166,8862,8863],{},"  SUM(subject LIKE '[안전보건진흥원]%') AS structured,\n",[2166,8865,8867],{"class":3301,"line":8866},52,[2166,8868,8736],{},[2166,8870,8872],{"class":3301,"line":8871},53,[2166,8873,8874],{},"  ROUND(AVG(CHAR_LENGTH(content))) AS avg_body_len\n",[2166,8876,8878],{"class":3301,"line":8877},54,[2166,8879,8880],{},"FROM tb_post WHERE project_id = 1528 AND status = 1;\n",[2166,8882,8884],{"class":3301,"line":8883},55,[2166,8885,3339],{"emptyLinePlaceholder":3338},[2166,8887,8889],{"class":3301,"line":8888},56,[2166,8890,8891],{},"-- 고객 측 매너 키워드: @malgnsoft.com 이 아닌 작성자만\n",[2166,8893,8895],{"class":3301,"line":8894},57,[2166,8896,8724],{},[2166,8898,8900],{"class":3301,"line":8899},58,[2166,8901,8902],{},"  SUM(c.content LIKE '%감사%') AS thanks,\n",[2166,8904,8906],{"class":3301,"line":8905},59,[2166,8907,8908],{},"  SUM(c.content LIKE '%확인%') AS confirm,\n",[2166,8910,8912],{"class":3301,"line":8911},60,[2166,8913,8914],{},"  SUM(c.content LIKE '%부탁%') AS please,\n",[2166,8916,8918],{"class":3301,"line":8917},61,[2166,8919,8920],{},"  SUM(c.content LIKE '%죄송%') AS apology,\n",[2166,8922,8924],{"class":3301,"line":8923},62,[2166,8925,8926],{},"  COUNT(*) AS customer_comments\n",[2166,8928,8930],{"class":3301,"line":8929},63,[2166,8931,8932],{},"FROM tb_post_comment c JOIN tb_post p ON p.id = c.post_id\n",[2166,8934,8936],{"class":3301,"line":8935},64,[2166,8937,8938],{},"     LEFT JOIN tb_user u ON u.id = c.user_id\n",[2166,8940,8942],{"class":3301,"line":8941},65,[2166,8943,8944],{},"WHERE p.project_id = 1528 AND c.status = 1\n",[2166,8946,8948],{"class":3301,"line":8947},66,[2166,8949,8950],{},"  AND (u.email IS NULL OR u.email NOT LIKE '%@malgnsoft.com');\n",[33,8952],{},[36,8954,8956],{"id":8955},"cross-link","Cross-link",[54,8958,8959,8964,8969],{},[57,8960,8961,8962],{},"전체 업체 분포·키워드 분석: ",[3257,8963,5780],{"href":5779},[57,8965,8966,8967],{},"스키마·인제스트 정책: ",[3257,8968,6360],{"href":6359},[57,8970,8971,8972,2367,8974],{},"로드맵 위치: ",[3257,8973,6981],{"href":6980},[28,8975,8976],{},"Phase 1 · 1.4 자료 수집 \u002F 1.9 피드백 루프",[4258,8978,8979],{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":423,"searchDepth":3342,"depth":3342,"links":8981},[8982,8983,8984,8985,8986,8987,8996,9006,9017,9018],{"id":5915,"depth":3335,"text":5916},{"id":6074,"depth":3335,"text":6075},{"id":6139,"depth":3335,"text":6140},{"id":6252,"depth":3335,"text":6253},{"id":6291,"depth":3335,"text":6292},{"id":6394,"depth":3335,"text":6395,"children":8988},[8989,8990,8991,8992,8993,8994,8995],{"id":6410,"depth":3342,"text":6411},{"id":6489,"depth":3342,"text":6490},{"id":6583,"depth":3342,"text":6584},{"id":6668,"depth":3342,"text":6669},{"id":6766,"depth":3342,"text":6767},{"id":6869,"depth":3342,"text":6870},{"id":6937,"depth":3342,"text":6938},{"id":6996,"depth":3335,"text":6997,"children":8997},[8998,8999,9000,9001,9002,9003,9004,9005],{"id":7018,"depth":3342,"text":7019},{"id":7115,"depth":3342,"text":7116},{"id":7211,"depth":3342,"text":7212},{"id":7321,"depth":3342,"text":7322},{"id":7433,"depth":3342,"text":7434},{"id":7531,"depth":3342,"text":7532},{"id":7622,"depth":3342,"text":7623},{"id":7749,"depth":3342,"text":7750},{"id":7799,"depth":3335,"text":7800,"children":9007},[9008,9009,9010,9011,9012,9013,9014,9015,9016],{"id":7812,"depth":3342,"text":7813},{"id":7903,"depth":3342,"text":7904},{"id":7997,"depth":3342,"text":7998},{"id":8090,"depth":3342,"text":8091},{"id":8180,"depth":3342,"text":8181},{"id":8281,"depth":3342,"text":7532},{"id":8373,"depth":3342,"text":8374},{"id":8455,"depth":3342,"text":8456},{"id":8547,"depth":3342,"text":8548},{"id":8577,"depth":3335,"text":8578},{"id":8955,"depth":3335,"text":8956},{},"\u002Fexamples",{"title":5766,"description":423},"examples\u002F안전보건진흥원","m6uQE6SvU9WeMOSZkd9QUFzbttZYJuVTFmJ3bW1E1zk",{"id":9025,"title":9026,"body":9027,"description":423,"extension":4340,"meta":9190,"navigation":3338,"path":9020,"seo":9191,"stem":9192,"__hash__":9193},"docs\u002Fexamples\u002F현대엔지비.md","현대엔지비 LMS — 브리핑 카드 예시",{"type":8,"value":9028,"toc":9185},[9029,9032,9049,9097,9099,9103,9109,9111,9115,9163,9165,9167],[11,9030,9026],{"id":9031},"현대엔지비-lms-브리핑-카드-예시",[21,9033,9034],{},[24,9035,9036,9040,9041,9044,9045,9048],{},[3257,9037,9039],{"href":9038},"..\u002Fprompts\u002Fcustomer-briefing","doc\u002Fprompts\u002Fcustomer-briefing.md"," 프롬프트로 생성한 ",[28,9042,9043],{},"고객사 브리핑 카드"," 예시.\n같은 업체에 대한 풀 평가 양식 예시는 ",[3257,9046,9047],{"href":423},"doc\u002Fexamples\u002F안전보건진흥원.md"," 참조.",[135,9050,9051,9059],{},[138,9052,9053],{},[141,9054,9055,9057],{},[144,9056,5798],{},[144,9058],{},[157,9060,9061,9068,9080,9088],{},[141,9062,9063,9065],{},[162,9064,5807],{},[162,9066,9067],{},"1162",[141,9069,9070,9072],{},[162,9071,5815],{},[162,9073,9074,9077,9078,5825],{},[16,9075,9076],{},"# 현대엔지비 LMS"," (활성 — ",[16,9079,497],{},[141,9081,9082,9085],{},[162,9083,9084],{},"생성 시점",[162,9086,9087],{},"2026-05-28",[141,9089,9090,9092],{},[162,9091,5893],{},[162,9093,9094,9096],{},[16,9095,128],{}," = 직원, 그 외 = 고객\u002F협력사",[33,9098],{},[36,9100,9102],{"id":9101},"_1-브리핑-카드","1. 브리핑 카드",[415,9104,9107],{"className":9105,"code":9106,"language":420},[418],"┌─────────────────────────────────────────────────────────────────────────────┐\n│  # 현대엔지비 LMS                                                ⚠ 주의      │\n│  대기업 인하우스 LMS · 유지보수 진행 (구축 2018-07 완료) · 최근 활동 2022-05 │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  👤 고객  장희정 (@hyundai-ngv.com) — 주 담당                                │\n│         보조  전영수 · 우규휘 · 정도현 (4인 운영팀)                         │\n│  🛠 담당  PM 장재훈 (응대 12건) · 운영 이영은 (7) · 기술 김서연 (3)           │\n│         보조  주승운 · 김도형 · 송세종 (각 1)                                │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  📨 누적 19건 · 평균 FRT 62h · 미응답 0건 · 긴급 표기 0건                    │\n│  🔥 핫 카테고리 (역대)                                                       │\n│      주제   디자인·배너 4 · 유지보수·견적 4 · 콘텐츠·영상·WBT 3              │\n│      라벨   플로즈(디자인) 5 · 오류 5 · 기타문의 5 · LMS 이용 3              │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  ⚠ 알림                                                                     │\n│   • 직원 응답 없음 1건 — \"게이트페이지 내 콘텐츠 수정 요청\"                  │\n│     (장희정, 2022-05-23, post 92843) — 응답 누락 가능, 우선 확인             │\n│   • 종결 멘트 없는 글 11건 — 응대 마무리 확인 필요                          │\n│   • 평균 FRT 62시간 — 응답이 느린 편                                        │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  📚 자주 묻는 주제                                                           │\n│   1. 디자인·배너·썸네일 제작 견적 (홍보자료·포스터)                          │\n│   2. 유지보수 — 상시학습 데이터 추출·인정시간 일괄 조정                     │\n│   3. 콘텐츠 재생 오류 (CDN 차단 정책 관련) · WBT 운영                       │\n│   4. 수료증 양식·교육 시간 행 추가                                          │\n│   5. 학습자 일괄 등록·게이트페이지·과정 삭제                                │\n│  🚫 이미 안내된 정책                                                         │\n│   • 온라인 콘텐츠 재생 불가 — CDN 별도 차단 정책 (2022-04-14, CDN 업체 회신) │\n└─────────────────────────────────────────────────────────────────────────────┘\n",[16,9108,9106],{"__ignoreMap":423},[33,9110],{},[36,9112,9114],{"id":9113},"_2-카드-해석-상담자에게-도움될-포인트","2. 카드 해석 — 상담자에게 도움될 포인트",[54,9116,9117,9127,9133,9143,9153],{},[57,9118,9119,9122,9123,9126],{},[28,9120,9121],{},"고객사 성격",": 현대그룹 계열사 인하우스 LMS — ",[16,9124,9125],{},"hyundai-ngv.com"," 도메인. 운영팀 4명이 분담 컨택.",[57,9128,9129,9132],{},[28,9130,9131],{},"응대 패턴",": 장재훈이 PM 주축(63%), 이영은이 운영 보조, 김서연이 기술. 정책 거절 전담자(엄정원·최종수)는 본 프로젝트에 없음 — 거절성 답변이 적은 케이스.",[57,9134,9135,9138,9139,9142],{},[28,9136,9137],{},"핵심 위험",": post 92843 게이트페이지 콘텐츠 수정 요청에 ",[28,9140,9141],{},"직원 응답이 없음"," — 가장 먼저 확인 필요. 종결 멘트가 11건이나 비어 있는 것도 응대 마무리 관행 부족 시그널.",[57,9144,9145,9148,9149,9152],{},[28,9146,9147],{},"응답 속도가 느린 이유 추정",": 디자인·견적·유지보수처럼 ",[28,9150,9151],{},"외부 협업이 필요한 작업","(플로즈 라벨 5건)이 많아 평균 FRT가 길어진 것으로 보임 — 단순 트러블슈팅이 적은 케이스.",[57,9154,9155,9158,9159,9162],{},[28,9156,9157],{},"특이점",": 라벨 ",[16,9160,9161],{},"플로즈","(디자인 외주)가 가장 많음 — 다른 고객사에서 잘 안 보이는 분류. 디자인 견적·제작 의뢰가 핵심 업무.",[33,9164],{},[36,9166,8956],{"id":8955},[54,9168,9169,9174,9179],{},[57,9170,9171,9172],{},"브리핑 양식 정의: ",[3257,9173,9039],{"href":9038},[57,9175,9176,9177],{},"풀 평가 양식 예시: ",[3257,9178,9047],{"href":423},[57,9180,9181,9182],{},"전체 업체 분포: ",[3257,9183,9184],{"href":5779},"doc\u002FPROJECT-INQUIRY-ANALYSIS.md",{"title":423,"searchDepth":3342,"depth":3342,"links":9186},[9187,9188,9189],{"id":9101,"depth":3335,"text":9102},{"id":9113,"depth":3335,"text":9114},{"id":8955,"depth":3335,"text":8956},{},{"title":9026,"description":423},"examples\u002F현대엔지비","Z08vl_ADc5QVF0x9y-KWHXfkqQrpPf-vdaEuOncFevA",{"id":9195,"title":9196,"body":9197,"description":423,"extension":4340,"meta":9908,"navigation":3338,"path":9909,"seo":9910,"stem":9911,"__hash__":9912},"docs\u002Fexamples\u002Fqa-94227-사용자매뉴얼.md","Q&A 요약·평가 예시 — post 94227 \"사용자 매뉴얼\"",{"type":8,"value":9198,"toc":9891},[9199,9202,9207,9305,9307,9311,9316,9320,9331,9335,9342,9344,9348,9351,9355,9409,9414,9418,9461,9465,9509,9513,9533,9538,9544,9548,9610,9623,9625,9629,9709,9711,9715,9747,9749,9753,9764,9775,9780,9782,9786,9854,9856,9858,9889],[11,9200,9196],{"id":9201},"qa-요약평가-예시-post-94227-사용자-매뉴얼",[21,9203,9204],{},[24,9205,9206],{},"단일 Q&A pair의 요약 + 평가 예시. 챗봇 추천 답변 검토·표준답변 후보 평가 시 사용할 양식.",[135,9208,9209,9217],{},[138,9210,9211],{},[141,9212,9213,9215],{},[144,9214,5798],{},[144,9216,1540],{},[157,9218,9219,9229,9241,9253,9265,9273,9283,9296],{},[141,9220,9221,9224],{},[162,9222,9223],{},"Post ID",[162,9225,9226],{},[28,9227,9228],{},"94227",[141,9230,9231,9234],{},[162,9232,9233],{},"Project",[162,9235,9236,9237,9240],{},"1561 · ",[16,9238,9239],{},"*에듀야"," (HRD 직업훈련 LMS, 종료 프로젝트)",[141,9242,9243,9246],{},[162,9244,9245],{},"문의자",[162,9247,9248,9249,9252],{},"진현미 (",[16,9250,9251],{},"sos7885@nate.com"," → 고객)",[141,9254,9255,9258],{},[162,9256,9257],{},"응대자",[162,9259,9260,9261,9264],{},"최종수 (",[16,9262,9263],{},"js0692@malgnsoft.com"," → 직원)",[141,9266,9267,9270],{},[162,9268,9269],{},"일시",[162,9271,9272],{},"문의 2022-06-24 10:32 · 응답 2022-06-24 10:41",[141,9274,9275,9278],{},[162,9276,9277],{},"FRT",[162,9279,9280],{},[28,9281,9282],{},"8분",[141,9284,9285,9288],{},[162,9286,9287],{},"가시성",[162,9289,9290,1305,9293,78],{},[28,9291,9292],{},"비공개 답변",[16,9294,9295],{},"private_yn = Y",[141,9297,9298,9300],{},[162,9299,5893],{},[162,9301,9302,9304],{},[16,9303,128],{}," = 직원 · 그 외 = 고객\u002F협력사",[33,9306],{},[36,9308,9310],{"id":9309},"_1-문의-본문","1. 문의 본문",[21,9312,9313],{},[24,9314,9315],{},"관리자 매뉴얼은 사이트에서 제공이 되는거 같은데\n혹시 사용자 메뉴얼도 있을까요??",[36,9317,9319],{"id":9318},"_2-답변-본문-비공개","2. 답변 본문 (비공개)",[21,9321,9322,9325,9328],{},[24,9323,9324],{},"안녕하세요",[24,9326,9327],{},"현재 저희는 고객사에 따라 페이지가 달라서 사용자 매뉴얼은 제공하지 않고\n관리자 매뉴얼만 안내 드리고 있습니다.\n불편하시더라도 관리자 매뉴얼 참고해서 운영 부탁드립니다.",[24,9329,9330],{},"감사합니다.",[36,9332,9334],{"id":9333},"_3-한-줄-요약","3. 한 줄 요약",[21,9336,9337],{},[24,9338,9339],{},[28,9340,9341],{},"고객(에듀야)의 사용자 매뉴얼 제공 여부 문의 → 고객사별 페이지 상이로 사용자 매뉴얼은 미제공, 관리자 매뉴얼만 제공한다는 정책을 비공개로 안내.",[33,9343],{},[36,9345,9347],{"id":9346},"_4-평가-5축","4. 평가 (5축)",[24,9349,9350],{},"범례: ★ 1~5 점수 · ✓ 양호 · ⚠ 주의 · ✕ 문제",[215,9352,9354],{"id":9353},"a-답변-정확성완결성-4","A. 답변 정확성·완결성 — ★ 4",[135,9356,9357,9367],{},[138,9358,9359],{},[141,9360,9361,9363,9365],{},[144,9362,4143],{},[144,9364,6422],{},[144,9366,6425],{},[157,9368,9369,9379,9389,9399],{},[141,9370,9371,9374,9377],{},[162,9372,9373],{},"질문에 대한 직접 답변",[162,9375,9376],{},"\"사용자 매뉴얼 없음\" 명확히 답함",[162,9378,6527],{},[141,9380,9381,9384,9387],{},[162,9382,9383],{},"이유 설명",[162,9385,9386],{},"\"고객사별 페이지가 다름\" — 정책 근거 제시",[162,9388,6527],{},[141,9390,9391,9394,9397],{},[162,9392,9393],{},"대안 제시",[162,9395,9396],{},"\"관리자 매뉴얼 참고\"",[162,9398,6527],{},[141,9400,9401,9404,9407],{},[162,9402,9403],{},"구체적 안내 (링크·경로)",[162,9405,9406],{},"관리자 매뉴얼 위치·다운로드 링크 부재",[162,9408,7301],{},[24,9410,9411,9413],{},[28,9412,7107],{},": 핵심 메시지는 명확. 다만 \"관리자 매뉴얼을 어디서 어떻게 받는지\" 후속 안내가 없어 고객 측 추가 액션이 막연해질 여지.",[215,9415,9417],{"id":9416},"b-응대-시간턴-효율성-5","B. 응대 시간·턴 효율성 — ★ 5",[135,9419,9420,9430],{},[138,9421,9422],{},[141,9423,9424,9426,9428],{},[144,9425,4143],{},[144,9427,6422],{},[144,9429,6425],{},[157,9431,9432,9441,9451],{},[141,9433,9434,9436,9439],{},[162,9435,9277],{},[162,9437,9438],{},"8분 — 영업시간 평균(5h) 대비 매우 빠름",[162,9440,6527],{},[141,9442,9443,9446,9449],{},[162,9444,9445],{},"응답 횟수",[162,9447,9448],{},"단일 응답으로 종결 (FCR 달성)",[162,9450,6527],{},[141,9452,9453,9456,9459],{},[162,9454,9455],{},"재문의 발생",[162,9457,9458],{},"없음",[162,9460,6527],{},[215,9462,9464],{"id":9463},"c-톤친절도-4","C. 톤·친절도 — ★ 4",[135,9466,9467,9477],{},[138,9468,9469],{},[141,9470,9471,9473,9475],{},[144,9472,4143],{},[144,9474,6422],{},[144,9476,6425],{},[157,9478,9479,9489,9499],{},[141,9480,9481,9484,9487],{},[162,9482,9483],{},"인삿말·종결말",[162,9485,9486],{},"\"안녕하세요\" \u002F \"감사합니다\" — 정형 응대",[162,9488,6527],{},[141,9490,9491,9494,9497],{},[162,9492,9493],{},"사과\u002F공감 표현",[162,9495,9496],{},"\"불편하시더라도\" — 적절한 양해 표현",[162,9498,6527],{},[141,9500,9501,9504,9507],{},[162,9502,9503],{},"능동 안내",[162,9505,9506],{},"매뉴얼 다운로드 위치 같은 next step 부재",[162,9508,7301],{},[215,9510,9512],{"id":9511},"d-표준답변화-가능성-5","D. 표준답변화 가능성 — ★ 5",[54,9514,9515,9521,9528],{},[57,9516,9517,9520],{},[28,9518,9519],{},"반복 가능성 매우 높음",": 신규 고객사 도입 직후 흔히 나오는 질문",[57,9522,9523,9524,9527],{},"답변 내용이 ",[28,9525,9526],{},"정책성"," (개별 LMS 환경 무관)",[57,9529,9530],{},[28,9531,9532],{},"표준 답변 1순위 후보",[24,9534,9535],{},[28,9536,9537],{},"권장 표준답변 템플릿 (공개판):",[415,9539,9542],{"className":9540,"code":9541,"language":420},[418],"사용자 매뉴얼은 고객사별 LMS 페이지 구성이 달라 통합 제공이 어렵습니다.\n대신 사이트별 관리자 매뉴얼을 통해 운영 절차를 안내드리고 있으며,\n사용자 안내 자료가 별도로 필요하신 경우 협의를 통해 작성해 드리고 있습니다.\n\n▸ 관리자 매뉴얼: \u003C고객사별 LMS 관리자 페이지 → 헬프센터>\n▸ 사용자용 자료 요청: help@malgnsoft.com\n",[16,9543,9541],{"__ignoreMap":423},[215,9545,9547],{"id":9546},"e-챗봇-자동화-적합성-가시성-주의","E. 챗봇 자동화 적합성 + 가시성 — ⚠ 주의",[135,9549,9550,9560],{},[138,9551,9552],{},[141,9553,9554,9556,9558],{},[144,9555,4143],{},[144,9557,6422],{},[144,9559,6425],{},[157,9561,9562,9572,9587,9597],{},[141,9563,9564,9567,9570],{},[162,9565,9566],{},"자동 응답 가능성",[162,9568,9569],{},"정책성·일반화 가능 답변 — 챗봇 적합",[162,9571,6527],{},[141,9573,9574,9579,9585],{},[162,9575,9576],{},[28,9577,9578],{},"가시성 (private_yn)",[162,9580,9581,9584],{},[28,9582,9583],{},"Y (비공개)"," → Phase 2 챗봇 노출 금지",[162,9586,7348],{},[141,9588,9589,9592,9595],{},[162,9590,9591],{},"정책 거절성 분류",[162,9593,9594],{},"\"제공하지 않음\" — 거절 답변 패턴과 일치",[162,9596,7301],{},[141,9598,9599,9602,9608],{},[162,9600,9601],{},"공개판 작성 필요",[162,9603,9604,9607],{},[28,9605,9606],{},"필요"," — 위 §4-D 템플릿이 그 후보",[162,9609,538],{},[24,9611,9612,9614,9615,9618,9619,9622],{},[28,9613,7107],{},": 답변 내용 자체는 자동화에 매우 적합하나 ",[28,9616,9617],{},"현재 답변은 비공개","라 ",[3257,9620,9621],{"href":6359},"LEGACY-DB-INVENTORY.md §6 비공개 댓글 처리 전략","에 따라 챗봇 노출 금지. 별도 공개 버전 작성·승인이 필요.",[33,9624],{},[36,9626,9628],{"id":9627},"_5-종합-점수표","5. 종합 점수표",[135,9630,9631,9641],{},[138,9632,9633],{},[141,9634,9635,9637,9639],{},[144,9636,7541],{},[144,9638,7544],{},[144,9640,8295],{},[157,9642,9643,9653,9663,9673,9683,9693],{},[141,9644,9645,9648,9650],{},[162,9646,9647],{},"답변 정확성·완결성",[162,9649,7557],{},[162,9651,9652],{},"명확하나 매뉴얼 링크 부재",[141,9654,9655,9658,9660],{},[162,9656,9657],{},"응대 시간·턴 효율성",[162,9659,8305],{},[162,9661,9662],{},"FRT 8분, 단일 응답 종결",[141,9664,9665,9668,9670],{},[162,9666,9667],{},"톤·친절도",[162,9669,7557],{},[162,9671,9672],{},"정형 응대·사과 표현 양호, 능동 next step 부족",[141,9674,9675,9678,9680],{},[162,9676,9677],{},"표준답변화 가능성",[162,9679,8305],{},[162,9681,9682],{},"1순위 후보 — 신규 고객 빈출",[141,9684,9685,9688,9690],{},[162,9686,9687],{},"챗봇 자동화 적합성",[162,9689,7301],{},[162,9691,9692],{},"내용 적합하나 비공개라 별도 공개판 필요",[141,9694,9695,9699,9704],{},[162,9696,9697],{},[28,9698,7609],{},[162,9700,9701],{},[28,9702,9703],{},"★ 4.5 \u002F 5",[162,9705,9706],{},[28,9707,9708],{},"가시성 이슈만 해결되면 표준답변 즉시 등록 가치",[33,9710],{},[36,9712,9714],{"id":9713},"_6-후속-조치-권장","6. 후속 조치 권장",[1925,9716,9717,9723,9729,9735,9741],{},[57,9718,9719,9722],{},[28,9720,9721],{},"표준 답변 등록",": §4-D 템플릿을 표준답변 카탈로그에 등록. 관리자 매뉴얼 경로·요청 채널 보강",[57,9724,9725,9728],{},[28,9726,9727],{},"공개판 별도 작성",": 비공개 답변 → 고객 노출 가능한 공개 버전 승인 (검토자: 운영 PM)",[57,9730,9731,9734],{},[28,9732,9733],{},"자동 추천 트리거 학습",": 유사 표현 매칭 — \"사용자 매뉴얼\", \"매뉴얼 다운로드\", \"교육 자료\", \"도움말\"",[57,9736,9737,9740],{},[28,9738,9739],{},"UX 차원 개선 제안",": 고객 진입 시 관리자 매뉴얼 위치를 자동 안내하는 헬프센터 위젯 검토",[57,9742,9743,9746],{},[28,9744,9745],{},"거절성 답변 일관화",": 다른 \"제공하지 않음\" 답변과 톤·구조 일치시켜 표준 거절 가이드 작성",[33,9748],{},[36,9750,9752],{"id":9751},"_7-관찰-비공개-패턴-일관성","7. 관찰 — 비공개 패턴 일관성",[24,9754,9755,9756,9759,9760,9763],{},"본 답변은 ",[28,9757,9758],{},"정책 거절성 안내","임에도 비공개 처리됨. 안전보건진흥원 케이스(",[3257,9761,9762],{"href":423},"안전보건진흥원.md",")와 동일 패턴:",[54,9765,9766,9769,9772],{},[57,9767,9768],{},"\"제공하지 않음\" \u002F \"개발 불가\" \u002F \"규정상\" 같은 거절 답변 → 비공개 처리하여 고객 직접 노출 통제",[57,9770,9771],{},"고객 측에서 화면상 안 보일 가능성 (실제 노출 정책은 시스템 운영 룰 확인 필요)",[57,9773,9774],{},"Phase 2 챗봇은 별도 공개 버전을 사용해야 안전",[21,9776,9777],{},[24,9778,9779],{},"운영 룰 검증 필요: 비공개 댓글이 게시글 작성자(고객) 화면에서 실제로 가려지는지 확인. 가려진다면 고객은 답변을 보지 못한 상태로 종결됐을 수도 있음 — CX 관점 별도 점검 권장.",[33,9781],{},[36,9783,9785],{"id":9784},"_8-추출-쿼리-재현용","8. 추출 쿼리 (재현용)",[415,9787,9789],{"className":8581,"code":9788,"language":8583,"meta":423,"style":423},"SELECT p.id, p.subject, p.writer, u.email AS writer_email,\n       pr.name AS project_name, p.reg_date,\n       REGEXP_REPLACE(p.content, '\u003C[^>]+>', '') AS body\nFROM tb_post p\nJOIN tb_project pr ON pr.id = p.project_id\nLEFT JOIN tb_user u ON u.id = p.user_id\nWHERE p.id = 94227;\n\nSELECT c.id, c.writer, u.email AS writer_email,\n       c.private_yn, c.reg_date,\n       REGEXP_REPLACE(c.content, '\u003C[^>]+>', '') AS body\nFROM tb_post_comment c LEFT JOIN tb_user u ON u.id = c.user_id\nWHERE c.post_id = 94227 ORDER BY c.reg_date;\n",[16,9790,9791,9796,9801,9806,9810,9815,9820,9825,9829,9834,9839,9844,9849],{"__ignoreMap":423},[2166,9792,9793],{"class":3301,"line":3302},[2166,9794,9795],{},"SELECT p.id, p.subject, p.writer, u.email AS writer_email,\n",[2166,9797,9798],{"class":3301,"line":3335},[2166,9799,9800],{},"       pr.name AS project_name, p.reg_date,\n",[2166,9802,9803],{"class":3301,"line":3342},[2166,9804,9805],{},"       REGEXP_REPLACE(p.content, '\u003C[^>]+>', '') AS body\n",[2166,9807,9808],{"class":3301,"line":3368},[2166,9809,8605],{},[2166,9811,9812],{"class":3301,"line":3396},[2166,9813,9814],{},"JOIN tb_project pr ON pr.id = p.project_id\n",[2166,9816,9817],{"class":3301,"line":3426},[2166,9818,9819],{},"LEFT JOIN tb_user u ON u.id = p.user_id\n",[2166,9821,9822],{"class":3301,"line":3463},[2166,9823,9824],{},"WHERE p.id = 94227;\n",[2166,9826,9827],{"class":3301,"line":3504},[2166,9828,3339],{"emptyLinePlaceholder":3338},[2166,9830,9831],{"class":3301,"line":3538},[2166,9832,9833],{},"SELECT c.id, c.writer, u.email AS writer_email,\n",[2166,9835,9836],{"class":3301,"line":3550},[2166,9837,9838],{},"       c.private_yn, c.reg_date,\n",[2166,9840,9841],{"class":3301,"line":3556},[2166,9842,9843],{},"       REGEXP_REPLACE(c.content, '\u003C[^>]+>', '') AS body\n",[2166,9845,9846],{"class":3301,"line":5367},[2166,9847,9848],{},"FROM tb_post_comment c LEFT JOIN tb_user u ON u.id = c.user_id\n",[2166,9850,9851],{"class":3301,"line":5375},[2166,9852,9853],{},"WHERE c.post_id = 94227 ORDER BY c.reg_date;\n",[33,9855],{},[36,9857,8956],{"id":8955},[54,9859,9860,9866,9873,9879],{},[57,9861,9862,9863,9865],{},"비공개 댓글 처리 전략: ",[3257,9864,6360],{"href":6359}," §6",[57,9867,9868,9869],{},"평가 양식 (장문): ",[3257,9870,9872],{"href":9871},"..\u002Fprompts\u002Fcs-evaluation","prompts\u002Fcs-evaluation.md",[57,9874,9875,9876],{},"브리핑 카드 양식: ",[3257,9877,9878],{"href":9038},"prompts\u002Fcustomer-briefing.md",[57,9880,9881,9882,9884,9885,9888],{},"다른 예시: ",[3257,9883,9762],{"href":423}," (풀 평가) · ",[3257,9886,9887],{"href":423},"현대엔지비.md"," (브리핑 카드)",[4258,9890,8979],{},{"title":423,"searchDepth":3342,"depth":3342,"links":9892},[9893,9894,9895,9896,9903,9904,9905,9906,9907],{"id":9309,"depth":3335,"text":9310},{"id":9318,"depth":3335,"text":9319},{"id":9333,"depth":3335,"text":9334},{"id":9346,"depth":3335,"text":9347,"children":9897},[9898,9899,9900,9901,9902],{"id":9353,"depth":3342,"text":9354},{"id":9416,"depth":3342,"text":9417},{"id":9463,"depth":3342,"text":9464},{"id":9511,"depth":3342,"text":9512},{"id":9546,"depth":3342,"text":9547},{"id":9627,"depth":3335,"text":9628},{"id":9713,"depth":3335,"text":9714},{"id":9751,"depth":3335,"text":9752},{"id":9784,"depth":3335,"text":9785},{"id":8955,"depth":3335,"text":8956},{},"\u002Fexamples\u002Fqa-94227",{"title":9196,"description":423},"examples\u002Fqa-94227-사용자매뉴얼","7YcQ5tjCbAdIm0Urdiu48P4fYOxUG6vnPkgW-IoBnM4",{"id":9914,"title":9915,"body":9916,"description":423,"extension":4340,"meta":12019,"navigation":3338,"path":12020,"seo":12021,"stem":12022,"__hash__":12023},"docs\u002Fhistory\u002Fhistory.20260528.md","작업 이력 — 2026-05-28",{"type":8,"value":9917,"toc":11934},[9918,9921,9924,9929,9931,9935,9942,9967,9971,9980,10042,10046,10056,10060,10153,10159,10163,10204,10218,10225,10231,10257,10259,10263,10350,10352,10356,10392,10394,10398,10477,10479,10483,10487,10508,10512,10567,10574,10577,10643,10647,10650,10655,10727,10732,10775,10780,10860,10865,10869,10891,10895,10909,10913,10919,10928,10961,10966,11009,11017,11024,11028,11031,11040,11057,11066,11106,11115,11124,11132,11137,11157,11162,11176,11182,11195,11199,11204,11222,11226,11282,11300,11308,11312,11337,11341,11392,11396,11402,11409,11442,11448,11477,11485,11499,11504,11518,11527,11530,11537,11548,11555,11564,11569,11577,11583,11591,11597,11607,11613,11623,11629,11639,11645,11655,11661,11671,11677,11687,11693,11703,11709,11719,11725,11739,11745,11755,11761,11771,11777,11787,11793,11803,11809,11819,11825,11835,11841,11851,11857,11867,11873,11883,11889,11899,11905,11915,11921,11931],[11,9919,9915],{"id":9920},"작업-이력-2026-05-28",[36,9922,9923],{"id":9923},"요약",[24,9925,9926,9928],{},[16,9927,4588],{},"(PMS 애드온) 정의 추가 → 4개 GitHub repo 연결 → Cloudflare Workers\u002FPages 보일러플레이트 셋업 → Pages 프로젝트 생성 → 다중 계정 대응(account_id 명시)까지 완료. 4개 워크스페이스가 모두 즉시 배포 가능한 상태.",[33,9930],{},[36,9932,9934],{"id":9933},"작업-내역","작업 내역",[215,9936,9938,9939,9941],{"id":9937},"_1-malgn-helper-pms-정의-추가","1. ",[16,9940,4588],{}," 정의 추가",[54,9943,9944,9951,9958],{},[57,9945,9946,9950],{},[3257,9947,9949],{"href":9948},"..\u002F..\u002FCLAUDE","CLAUDE.md",": 프로젝트 구성 3개 → 4개로 확장. PMS 애드온 항목 추가",[57,9952,9953,9954,9957],{},"데이터 흐름 다이어그램에 ",[28,9955,9956],{},"PMS 상담사 화면 → malgn-helper-pms"," 진입 경로 추가",[57,9959,9960,9961,9963,9964,9966],{},"작업 규칙: ",[16,9962,4588],{},"는 DB·LLM 직접 접근 금지, 반드시 ",[16,9965,4404],{}," 경유",[215,9968,9970],{"id":9969},"_2-github-연결-4개-repo","2. GitHub 연결 (4개 repo)",[24,9972,9973,9974,1524,9977,3360],{},"각 디렉토리에 ",[16,9975,9976],{},"git init -b main",[16,9978,9979],{},"git remote add origin \u003CURL>",[135,9981,9982,9992],{},[138,9983,9984],{},[141,9985,9986,9989],{},[144,9987,9988],{},"디렉토리",[144,9990,9991],{},"원격",[157,9993,9994,10006,10018,10030],{},[141,9995,9996,10000],{},[162,9997,9998],{},[16,9999,47],{},[162,10001,10002],{},[3257,10003,10004],{"href":10004,"rel":10005},"https:\u002F\u002Fgithub.com\u002Fmalgnsoft\u002Fmalgn-helper.git",[5049],[141,10007,10008,10012],{},[162,10009,10010],{},[16,10011,18],{},[162,10013,10014],{},[3257,10015,10016],{"href":10016,"rel":10017},"https:\u002F\u002Fgithub.com\u002Fmalgnsoft\u002Fmalgn-helper-admin.git",[5049],[141,10019,10020,10024],{},[162,10021,10022],{},[16,10023,4404],{},[162,10025,10026],{},[3257,10027,10028],{"href":10028,"rel":10029},"https:\u002F\u002Fgithub.com\u002Fmalgnsoft\u002Fmalgn-helper-api.git",[5049],[141,10031,10032,10036],{},[162,10033,10034],{},[16,10035,4588],{},[162,10037,10038],{},[3257,10039,10040],{"href":10040,"rel":10041},"https:\u002F\u002Fgithub.com\u002Fmalgnsoft\u002Fmalgn-helper-pms.git",[5049],[215,10043,10045],{"id":10044},"_3-첫-커밋-푸시","3. 첫 커밋 + 푸시",[54,10047,10048,10053],{},[57,10049,10050,10052],{},[16,10051,47],{},": CLAUDE.md + README.md + .gitignore + doc\u002F (총 11 파일, 2344 줄)",[57,10054,10055],{},"나머지 3 repo: README.md + .gitignore",[215,10057,10059],{"id":10058},"_4-cloudflare-보일러플레이트","4. Cloudflare 보일러플레이트",[135,10061,10062,10075],{},[138,10063,10064],{},[141,10065,10066,10069,10072],{},[144,10067,10068],{},"Repo",[144,10070,10071],{},"스택",[144,10073,10074],{},"추가 파일",[157,10076,10077,10097,10113,10134],{},[141,10078,10079,10083,10086],{},[162,10080,10081],{},[16,10082,47],{},[162,10084,10085],{},"Nuxt 3 \u002F Pages",[162,10087,10088,105,10091,105,10094],{},[16,10089,10090],{},"package.json",[16,10092,10093],{},"nuxt.config.ts",[16,10095,10096],{},"app.vue",[141,10098,10099,10103,10105],{},[162,10100,10101],{},[16,10102,18],{},[162,10104,10085],{},[162,10106,10107,105,10109,105,10111],{},[16,10108,10090],{},[16,10110,10093],{},[16,10112,10096],{},[141,10114,10115,10119,10122],{},[162,10116,10117],{},[16,10118,4404],{},[162,10120,10121],{},"Hono \u002F Workers",[162,10123,10124,105,10126,105,10128,105,10131],{},[16,10125,10090],{},[16,10127,4821],{},[16,10129,10130],{},"src\u002Findex.ts",[16,10132,10133],{},"tsconfig.json",[141,10135,10136,10140,10142],{},[162,10137,10138],{},[16,10139,4588],{},[162,10141,10085],{},[162,10143,10144,105,10146,105,10148,105,10150,10152],{},[16,10145,10090],{},[16,10147,10093],{},[16,10149,10096],{},[16,10151,4701],{}," (재구성 — §9 참조)",[24,10154,10155,10158],{},[16,10156,10157],{},"pnpm install"," 4개 repo 모두 완료. README에 개발·배포 명령 추가.",[215,10160,10162],{"id":10161},"_5-cloudflare-pages-프로젝트-생성","5. Cloudflare Pages 프로젝트 생성",[54,10164,10165,10170,10175,10187],{},[57,10166,10167],{},[16,10168,10169],{},"wrangler pages project create malgn-helper --production-branch main",[57,10171,10172],{},[16,10173,10174],{},"wrangler pages project create malgn-helper-admin --production-branch main",[57,10176,10177,10178,1305,10184,78],{},"계정: ",[28,10179,10180],{},[3257,10181,10183],{"href":10182},"mailto:Info@malgnsoft.com","Info@malgnsoft.com",[16,10185,10186],{},"d2b8c5524b7259214fa302f1fecb4ad6",[57,10188,10189,10190],{},"배포 URL (첫 deploy 후 활성화):\n",[54,10191,10192,10198],{},[57,10193,10194],{},[3257,10195,10196],{"href":10196,"rel":10197},"https:\u002F\u002Fmalgn-helper.pages.dev\u002F",[5049],[57,10199,10200],{},[3257,10201,10202],{"href":10202,"rel":10203},"https:\u002F\u002Fmalgn-helper-admin.pages.dev\u002F",[5049],[21,10205,10206],{},[24,10207,10208,10209,105,10211,10213,10214,10217],{},"Workers 2개(",[16,10210,4611],{},[16,10212,4614],{},")는 첫 ",[16,10215,10216],{},"wrangler deploy"," 시점에 자동 생성.",[215,10219,10221,10222,10224],{"id":10220},"_6-다중-계정-대응-account_id-명시","6. 다중 계정 대응 — ",[16,10223,4825],{}," 명시",[24,10226,10227,10228,10230],{},"다중 계정 환경에서 매번 ",[16,10229,4844],{}," 환경변수를 지정해야 하던 문제 제거:",[54,10232,10233,10242,10248],{},[57,10234,10235,10236,10238,10239,3141],{},"Workers (-api, -pms): ",[16,10237,4821],{},"에 ",[16,10240,10241],{},"\"account_id\"",[57,10243,10244,10245,10247],{},"Pages (helper, -admin): ",[16,10246,4701],{}," 신규 (name + account_id + compatibility_date + pages_build_output_dir)",[57,10249,10250,10251,10253,10254],{},"Pages 2개의 ",[16,10252,10090],{}," deploy 스크립트 간소화 → ",[16,10255,10256],{},"nuxt build && wrangler pages deploy",[33,10258],{},[36,10260,10262],{"id":10261},"커밋-요약","커밋 요약",[135,10264,10265,10274],{},[138,10266,10267],{},[141,10268,10269,10271],{},[144,10270,10068],{},[144,10272,10273],{},"오늘 커밋 (시간순)",[157,10275,10276,10296,10314,10333],{},[141,10277,10278,10282],{},[162,10279,10280],{},[16,10281,47],{},[162,10283,10284,10287,10288,10291,10292,10295],{},[16,10285,10286],{},"1e612b8"," 초기 문서 → ",[16,10289,10290],{},"d1c7b4a"," Nuxt 보일러플레이트 → ",[16,10293,10294],{},"065e6ff"," Pages config",[141,10297,10298,10302],{},[162,10299,10300],{},[16,10301,18],{},[162,10303,10304,10307,10308,10291,10311,10295],{},[16,10305,10306],{},"d92f689"," README → ",[16,10309,10310],{},"9dfc2c5",[16,10312,10313],{},"5052765",[141,10315,10316,10320],{},[162,10317,10318],{},[16,10319,4404],{},[162,10321,10322,10307,10325,10328,10329,10332],{},[16,10323,10324],{},"1416518",[16,10326,10327],{},"f21e53c"," Hono 보일러플레이트 → ",[16,10330,10331],{},"8ea04c5"," account_id",[141,10334,10335,10339],{},[162,10336,10337],{},[16,10338,4588],{},[162,10340,10341,10307,10344,10328,10347,10332],{},[16,10342,10343],{},"1dd81d4",[16,10345,10346],{},"5207784",[16,10348,10349],{},"4728faf",[33,10351],{},[36,10353,10355],{"id":10354},"외부-리소스-변경","외부 리소스 변경",[135,10357,10358,10368],{},[138,10359,10360],{},[141,10361,10362,10365],{},[144,10363,10364],{},"시스템",[144,10366,10367],{},"변경",[157,10369,10370,10378],{},[141,10371,10372,10375],{},[162,10373,10374],{},"GitHub",[162,10376,10377],{},"4개 repo에 main 브랜치 생성 + 초기 커밋 푸시",[141,10379,10380,10385],{},[162,10381,10382,10383,78],{},"Cloudflare (",[3257,10384,10183],{"href":10182},[162,10386,10387,10388,105,10390,78],{},"Pages 프로젝트 2개 생성 (",[16,10389,47],{},[16,10391,18],{},[33,10393],{},[36,10395,10397],{"id":10396},"다음-단계-후보","다음 단계 후보",[54,10399,10402,10414,10433,10445,10453,10465],{"className":10400},[10401],"contains-task-list",[57,10403,10406,10410,10411],{"className":10404},[10405],"task-list-item",[10407,10408],"input",{"disabled":3338,"type":10409},"checkbox"," 첫 Workers\u002FPages 배포 시도 — ",[16,10412,10413],{},".\u002Fscripts\u002Fdeploy.sh \u003Crepo> \"\u003Cmsg>\"",[57,10415,10417,2367,10419,2367,10423,10426,10427,10238,10429,10432],{"className":10416},[10405],[10407,10418],{"disabled":3338,"type":10409},[3257,10420,10422],{"href":10421},"..\u002FWBS","WBS.md",[28,10424,10425],{},"P1-1.4 Aurora MySQL + Hyperdrive 바인딩"," — Aurora 프로비저닝 후 ",[16,10428,4821],{},[16,10430,10431],{},"HYPERDRIVE"," 바인딩 추가",[57,10434,10436,2367,10438,2448,10441,10444],{"className":10435},[10405],[10407,10437],{"disabled":3338,"type":10409},[28,10439,10440],{},"P1-1.6 R2 버킷 생성",[16,10442,10443],{},"wrangler r2 bucket create malgn-helper-files"," + 바인딩",[57,10446,10448,2367,10450],{"className":10447},[10405],[10407,10449],{"disabled":3338,"type":10409},[28,10451,10452],{},"P1-1.7 OpenSearch 도메인 프로비저닝",[57,10454,10456,2367,10458,10461,10462,78],{"className":10455},[10405],[10407,10457],{"disabled":3338,"type":10409},[28,10459,10460],{},"P1-1.8 AI Gateway 설정"," + Anthropic API 키 secret 등록 (",[16,10463,10464],{},"wrangler secret put ANTHROPIC_API_KEY",[57,10466,10468,2367,10470,2367,10473,10476],{"className":10467},[10405],[10407,10469],{"disabled":3338,"type":10409},[3257,10471,10472],{"href":6980},"doc\u002FROADMAP.md",[28,10474,10475],{},"Phase 1 M1"," 인프라 Ready 게이트 점검",[33,10478],{},[36,10480,10482],{"id":10481},"추가-작업-이력-시스템배포-자동화","추가 작업 (이력 시스템·배포 자동화)",[215,10484,10486],{"id":10485},"_7-일단위-작업-이력-도입","7. 일단위 작업 이력 도입",[54,10488,10489,10496,10503],{},[57,10490,10491,10495],{},[3257,10492,10494],{"href":10493},"history.20260528","doc\u002Fhistory\u002Fhistory.20260528.md"," (본 파일) 신규 — 오늘 작업 6건 정리",[57,10497,10498,10499,10502],{},"메모리에 규칙 저장: ",[16,10500,10501],{},"doc\u002Fhistory\u002Fhistory.yyyyMMdd.md","에 매일 누적 기록 (덮어쓰기 X)",[57,10504,10505,10507],{},[3257,10506,9949],{"href":9948}," 직접 변경은 없음. 메모리·MEMORY.md 인덱스 갱신",[215,10509,10511],{"id":10510},"_8-배포-일괄-처리-스크립트","8. 배포 일괄 처리 스크립트",[54,10513,10514,10547,10553,10561],{},[57,10515,10516,10519,10520],{},[3257,10517,4840],{"href":10518},"..\u002F..\u002Fscripts\u002Fdeploy.sh"," 신규 — 4단계 일괄 처리:\n",[1925,10521,10522,10528,10532,10540],{},[57,10523,10524,10527],{},[16,10525,10526],{},"git commit -m \u003Cmsg>"," (변경 없으면 skip)",[57,10529,10530],{},[16,10531,4692],{},[57,10533,10534,10536,10537,10539],{},[16,10535,4698],{}," (Workers\u002FPages 자동 분기 — ",[16,10538,4701],{}," 존재 여부로)",[57,10541,10542,4708,10544,10546],{},[16,10543,4707],{},[16,10545,4711],{}," 섹션에 항목 append",[57,10548,10549,10550],{},"사용법: ",[16,10551,10552],{},".\u002Fscripts\u002Fdeploy.sh \u003Crepo> \"\u003Ccommit message>\"",[57,10554,10555,10238,10557,10560],{},[3257,10556,9949],{"href":9948},[16,10558,10559],{},"## 배포 절차"," 섹션 추가 — 일괄 스크립트 사용법 + 수동 절차 + 규칙",[57,10562,10563,10564,10566],{},"배포 실패·secret 변경·",[16,10565,4825],{}," 규칙 모두 문서화",[215,10568,10570,10571,10573],{"id":10569},"_9-malgn-helper-pms-스택-전환-workers-pages","9. ",[16,10572,4588],{}," 스택 전환 — Workers → Pages",[24,10575,10576],{},"사용자 결정 변경에 따라 PMS 애드온 스택을 Hono Workers에서 Nuxt 3 \u002F Pages로 전환.",[54,10578,10579,10589,10599,10615,10621,10631,10640],{},[57,10580,10581,10582,105,10584,105,10586,10588],{},"제거: ",[16,10583,10130],{},[16,10585,4821],{},[16,10587,10133],{}," (Hono Worker 보일러플레이트)",[57,10590,10591,10592,105,10594,105,10596,10598],{},"추가: ",[16,10593,10093],{},[16,10595,10096],{},[16,10597,4701],{}," (Pages config, account_id 포함)",[57,10600,10601,10603,10604,1358,10607,10610,10611,10614],{},[16,10602,10090],{}," 의존성 교체: ",[16,10605,10606],{},"hono",[16,10608,10609],{},"nuxt",". deploy 스크립트 ",[16,10612,10613],{},"wrangler pages deploy","로 변경",[57,10616,10617,10620],{},[16,10618,10619],{},"README.md"," 스택 섹션 갱신 (Hono on Workers → Nuxt 3 \u002F Pages, iframe·위젯 임베드 명시)",[57,10622,10623,10624,1358,10627],{},"Cloudflare Pages 프로젝트 생성: ",[16,10625,10626],{},"wrangler pages project create malgn-helper-pms",[3257,10628,10629],{"href":10629,"rel":10630},"https:\u002F\u002Fmalgn-helper-pms.pages.dev\u002F",[5049],[57,10632,10633,10635,10636,10639],{},[3257,10634,9949],{"href":9948}," 데이터 흐름 다이어그램에서 pms 라벨을 ",[16,10637,10638],{},"(Nuxt 3 \u002F Pages, PMS 임베드)","로 명시",[57,10641,10642],{},"본 history 파일 §4 표의 pms 행 갱신 (Workers → Pages)",[215,10644,10646],{"id":10645},"_10-첫-cloudflare-배포-배포-환경-이슈-수정","10. 첫 Cloudflare 배포 + 배포 환경 이슈 수정",[24,10648,10649],{},"4개 repo 전체를 Cloudflare에 최초 배포. 진행 중 세 가지 이슈 발견·수정.",[24,10651,10652],{},[28,10653,10654],{},"발견된 이슈",[135,10656,10657,10669],{},[138,10658,10659],{},[141,10660,10661,10663,10666],{},[144,10662,497],{},[144,10664,10665],{},"증상",[144,10667,10668],{},"원인",[157,10670,10671,10688,10706],{},[141,10672,10673,10675,10680],{},[162,10674,6055],{},[162,10676,10677],{},[16,10678,10679],{},"ERR_PNPM_CANNOT_DEPLOY  A deploy is only possible from inside a workspace",[162,10681,10682,10684,10685,10687],{},[16,10683,4698],{},"는 pnpm 워크스페이스 예약어. 스크립트 호출은 ",[16,10686,4862],{},"여야 함",[141,10689,10690,10692,10697],{},[162,10691,7685],{},[162,10693,10694],{},[16,10695,10696],{},"Configuration file for Pages projects does not support \"account_id\"",[162,10698,10699,10700,10702,10703,10705],{},"Pages용 ",[16,10701,4701],{},"은 ",[16,10704,4825],{}," 필드 미지원 (Workers만 지원)",[141,10707,10708,10710,10722],{},[162,10709,6004],{},[162,10711,10712,10713,10715,10716,10702,10718,10721],{},"Nuxt 빌드 산출물이 ",[16,10714,4878],{},"인데 ",[16,10717,4701],{},[16,10719,10720],{},".output\u002Fpublic","로 설정",[162,10723,10724,10725],{},"Nuxt 3 cloudflare-pages preset의 실제 출력은 ",[16,10726,4878],{},[24,10728,10729],{},[28,10730,10731],{},"수정 사항",[54,10733,10734,10746,10762],{},[57,10735,10736,4664,10738,1358,10740,10742,10743,10745],{},[16,10737,4840],{},[16,10739,4698],{},[16,10741,4862],{}," 로 변경. Pages용으로 ",[16,10744,4844],{}," env 변수 export 추가",[57,10747,10748,1365,10750,1365,10752,4708,10754,4664,10756,10758,10759],{},[16,10749,47],{},[16,10751,4608],{},[16,10753,4614],{},[16,10755,4701],{},[16,10757,4825],{}," 제거 + ",[16,10760,10761],{},"pages_build_output_dir = \"dist\"",[57,10763,10764,2367,10766,10768,10769,10771,10772,10774],{},[3257,10765,9949],{"href":9948},[16,10767,10559],{},"의 account_id 안내 갱신 (Workers와 Pages 차이, ",[16,10770,4862],{}," 명시, 출력 디렉토리 ",[16,10773,4878],{}," 명시)",[24,10776,10777],{},[28,10778,10779],{},"배포 결과",[135,10781,10782,10794],{},[138,10783,10784],{},[141,10785,10786,10788,10791],{},[144,10787,10068],{},[144,10789,10790],{},"Production URL",[144,10792,10793],{},"커밋",[157,10795,10796,10812,10828,10844],{},[141,10797,10798,10802,10808],{},[162,10799,10800],{},[16,10801,4404],{},[162,10803,10804],{},[3257,10805,10806],{"href":10806,"rel":10807},"https:\u002F\u002Fmalgn-helper-api.malgnsoft.workers.dev",[5049],[162,10809,10810],{},[16,10811,10331],{},[141,10813,10814,10818,10823],{},[162,10815,10816],{},[16,10817,4588],{},[162,10819,10820],{},[3257,10821,10629],{"href":10629,"rel":10822},[5049],[162,10824,10825],{},[16,10826,10827],{},"676724d",[141,10829,10830,10834,10839],{},[162,10831,10832],{},[16,10833,47],{},[162,10835,10836],{},[3257,10837,10196],{"href":10196,"rel":10838},[5049],[162,10840,10841],{},[16,10842,10843],{},"cf1e931",[141,10845,10846,10850,10855],{},[162,10847,10848],{},[16,10849,18],{},[162,10851,10852],{},[3257,10853,10202],{"href":10202,"rel":10854},[5049],[162,10856,10857],{},[16,10858,10859],{},"a613e64",[24,10861,10862,10864],{},[16,10863,4840],{},"가 4건 모두 자동 처리 (commit-skip 또는 fix 커밋 → push → build·deploy → 이력 append).",[215,10866,10868],{"id":10867},"_11-브리핑-카드-예시-저장","11. 브리핑 카드 예시 저장",[54,10870,10871,10881],{},[57,10872,10873,10877,10878,10880],{},[3257,10874,10876],{"href":10875},"..\u002Fexamples\u002F","doc\u002Fexamples\u002F현대엔지비.md"," 신규 — ",[16,10879,9076],{}," 프로젝트 브리핑 카드 예시",[57,10882,10883,10884,10886,10887,10890],{},"같은 폴더의 ",[3257,10885,9762],{"href":10875},"는 풀 평가(케이스 스터디), 본 파일은 ",[3257,10888,10889],{"href":9038},"customer-briefing.md"," 프롬프트로 만든 짧은 카드",[215,10892,10894],{"id":10893},"_12-현대엔지비-브리핑에서-비교-섹션-제거","12. 현대엔지비 브리핑에서 비교 섹션 제거",[54,10896,10897,10900,10903,10906],{},[57,10898,10899],{},"사용자 피드백: 단일 고객사 브리핑에 다른 업체와의 비교는 불필요",[57,10901,10902],{},"삭제: §3 \"안전보건진흥원과 비교\" 표·관계 진단 단락 전체",[57,10904,10905],{},"본문 내 인라인 비교 언급 제거 (카드의 \"안전보건진흥원 5h 대비 12배\", §2의 \"안전보건진흥원의 1인 단독과 정반대\")",[57,10907,10908],{},"Cross-link의 \"풀 평가 양식 예시: 안전보건진흥원.md\"는 포맷 참조이므로 유지",[215,10910,10912],{"id":10911},"_13-malgn-helper-pms에-브리핑-카드-디자인-통합","13. malgn-helper-pms에 브리핑 카드 디자인 통합",[24,10914,10915,10918],{},[16,10916,10917],{},"design_handoff_briefing_card\u002F"," 핸드오프 패키지를 malgn-helper-pms에 통합.",[24,10920,10921,1305,10924,10927],{},[28,10922,10923],{},"복사한 파일",[16,10925,10926],{},"source\u002F"," → repo root):",[54,10929,10930,10936,10944,10949,10955],{},[57,10931,10932,10935],{},[16,10933,10934],{},"app.config.ts"," (ui.primary = sky, ui.gray = neutral)",[57,10937,10938,2212,10941],{},[16,10939,10940],{},"types\u002Fbriefing.ts",[16,10942,10943],{},"data\u002Fbriefing.example.ts",[57,10945,10946],{},[16,10947,10948],{},"composables\u002FuseBriefingClipboard.ts",[57,10950,10951,10954],{},[16,10952,10953],{},"components\u002FBriefingCard.vue"," (메인 모달)",[57,10956,10957,10960],{},[16,10958,10959],{},"pages\u002Fprojects\u002F[id].vue"," (사용 예시)",[24,10962,10963,3360],{},[28,10964,10965],{},"환경 설정",[54,10967,10968,10974,10980,10990,10999],{},[57,10969,10970,10973],{},[16,10971,10972],{},"pnpm add @nuxt\u002Fui"," (4.8.0 설치됨)",[57,10975,10976,10979],{},[16,10977,10978],{},"assets\u002Fcss\u002Ffonts.css"," 신규 — Pretendard Variable CDN 임포트",[57,10981,10982,10238,10984,1524,10987,3141],{},[16,10983,10093],{},[16,10985,10986],{},"modules: ['@nuxt\u002Fui']",[16,10988,10989],{},"css: ['~\u002Fassets\u002Fcss\u002Ffonts.css']",[57,10991,10992,10994,10995,10998],{},[16,10993,10096],{}," → 페이지 슬롯 (",[16,10996,10997],{},"\u003CNuxtPage \u002F>",")로 변경",[57,11000,11001,11004,11005,11008],{},[16,11002,11003],{},"pages\u002Findex.vue"," 신규 — 예시 페이지 링크 안내 (",[16,11006,11007],{},"\u002Fprojects\u002F1162"," → 현대엔지비 데모)",[24,11010,11011,4664,11013,11016],{},[28,11012,3763],{},[16,11014,11015],{},"pnpm run build"," 성공. dist\u002F 산출 정상 (560 kB \u002F 182 kB gzip).",[24,11018,11019,11020,11023],{},"핸드오프 시안의 \"디자인 사양 100% 재현\" 목표는 컴포넌트 자체에서 처리. 실제 API 연결(",[16,11021,11022],{},"\u002Fapi\u002Fprojects\u002F:id\u002Fbriefing",")은 추후 malgn-helper-api 엔드포인트 구현 시 연결.",[215,11025,11027],{"id":11026},"_14-malgn-helper-pms-예시-화면-구성","14. malgn-helper-pms 예시 화면 구성",[24,11029,11030],{},"브리핑 카드를 실제 운영 맥락에서 보여주기 위한 데모 화면 두 개 추가.",[24,11032,11033],{},[28,11034,11035,1305,11037,11039],{},[16,11036,530],{},[16,11038,11003],{},") — 고객사 목록",[54,11041,11042,11045,11051],{},[57,11043,11044],{},"PMS 배지·헤더·안내 문구",[57,11046,11047,11048,11050],{},"프로젝트 카드 1개(현대엔지비 LMS) — 클릭 시 ",[16,11049,11007],{},"로 이동",[57,11052,11053,11054,11056],{},"분류 규칙(",[16,11055,128],{},") 풋터 안내",[24,11058,11059],{},[28,11060,11061,1305,11063,11065],{},[16,11062,11007],{},[16,11064,10959],{},") — 상세 페이지",[54,11067,11068,11071,11078,11085,11103],{},[57,11069,11070],{},"브레드크럼: 고객사 목록 → #1162",[57,11072,11073,11074,11077],{},"헤더: 활성 점·프로젝트명·부제·우상단 ",[28,11075,11076],{},"브리핑 카드"," 버튼",[57,11079,11080,11081,11084],{},"라벨 필터 chips (",[16,11082,11083],{},"briefing.hotLabels"," 기반)",[57,11086,11087,11090,11091,11094,11095],{},[28,11088,11089],{},"가짜 게시글 테이블"," 7건 — ",[16,11092,11093],{},"tb_post"," 스타일 (ID·라벨·제목·작성자·댓글·등록일·상태)\n",[54,11096,11097,11100],{},[57,11098,11099],{},"라벨\u002F상태별 색상 ring (rose\u002Famber\u002Fneutral\u002Fprimary\u002Femerald)",[57,11101,11102],{},"첫 행(post 92843)은 미응답으로 표시 — 브리핑 알림과 정합",[57,11104,11105],{},"푸터: 데모 데이터임 명시",[24,11107,11108,11110,11111,11114],{},[28,11109,3763],{},": 빌드 성공 (576 kB \u002F 186 kB gzip). 배포 후 ",[3257,11112,10629],{"href":10629,"rel":11113},[5049]," 에서 두 페이지 확인 가능.",[24,11116,11117,11118,11120,11121,11123],{},"실제 운영 시 ",[16,11119,11003],{},"의 카드와 ",[16,11122,10959],{},"의 게시글 테이블은 malgn-helper-api 엔드포인트 응답으로 채워질 예정.",[215,11125,11127,11128,11131],{"id":11126},"_15-nuxtui-v4-v3-다운그레이드-시안-호환성","15. ",[16,11129,11130],{},"@nuxt\u002Fui"," v4 → v3 다운그레이드 (시안 호환성)",[24,11133,11134,11136],{},[28,11135,10665],{},": 브리핑 카드 모달이 핸드오프 시안과 다르게 렌더링됨.",[24,11138,11139,11141,11142,11145,11146,11149,11150,11152,11153,11156],{},[28,11140,10668],{},": 핸드오프 README는 ",[16,11143,11144],{},"@nuxt\u002Fui v2 또는 v3"," 기준으로 작성됐고, ",[16,11147,11148],{},"source\u002Fcomponents\u002FBriefingCard.vue","도 v3 API에 맞춰져 있음. 그러나 ",[16,11151,10972],{},"로 설치되는 latest는 ",[28,11154,11155],{},"v4.8.0","으로 메이저 변경(컴포넌트 API·슬롯·prop 이름 등)이 있어 호환 문제가 발생.",[24,11158,11159,3360],{},[28,11160,11161],{},"조치",[54,11163,11164,11173],{},[57,11165,11166,1358,11169,11172],{},[16,11167,11168],{},"pnpm remove @nuxt\u002Fui",[16,11170,11171],{},"pnpm add @nuxt\u002Fui@^3"," (3.3.7 설치됨)",[57,11174,11175],{},"빌드 확인 후 재배포",[24,11177,11178,11181],{},[28,11179,11180],{},"결과",": 모달이 핸드오프 시안 의도대로 렌더링되어야 함. 사용자 확인 필요.",[21,11183,11184],{},[24,11185,11186,11187,11190,11191,11194],{},"Lesson: 외부 디자인 시스템·컴포넌트 패키지를 통합할 때 ",[28,11188,11189],{},"README가 명시한 버전 범위를 반드시 준수",". ",[16,11192,11193],{},"latest","로 설치하지 말 것.",[215,11196,11198],{"id":11197},"_16-tailwind-css-v4-스캔-누락-수정","16. Tailwind CSS v4 스캔 누락 수정",[24,11200,11201,11203],{},[28,11202,10665],{},": 브리핑 카드 모달이 스타일 없이 plain HTML로 렌더링됨 (스크린샷 확인). v3 다운그레이드만으로 해결되지 않은 별도 이슈.",[24,11205,11206,4664,11208,11210,11211,11214,11215,105,11218,11221],{},[28,11207,10668],{},[16,11209,11130],{}," v3은 Tailwind v4 기반인데, Tailwind v4는 CSS 파일이 위치한 디렉토리(",[16,11212,11213],{},"assets\u002Fcss\u002F",")부터만 스캔. 우리의 Vue 컴포넌트(",[16,11216,11217],{},"components\u002F",[16,11219,11220],{},"pages\u002F",")는 스캔 범위 밖이라 사용된 utility 클래스가 컴파일되지 않음.",[24,11223,11224,3360],{},[28,11225,11161],{},[54,11227,11228,11268,11274],{},[57,11229,11230,11233,11234],{},[16,11231,11232],{},"assets\u002Fcss\u002Fmain.css"," 신규(기존 fonts.css 통합):\n",[415,11235,11239],{"className":11236,"code":11237,"language":11238,"meta":423,"style":423},"language-css shiki shiki-themes github-light github-dark","@import \"tailwindcss\";\n@import \"@nuxt\u002Fui\";\n@source \"..\u002F..\";\n","css",[16,11240,11241,11251,11260],{"__ignoreMap":423},[2166,11242,11243,11246,11249],{"class":3301,"line":3302},[2166,11244,11245],{"class":3305},"@import",[2166,11247,11248],{"class":3316}," \"tailwindcss\"",[2166,11250,3332],{"class":3331},[2166,11252,11253,11255,11258],{"class":3301,"line":3335},[2166,11254,11245],{"class":3305},[2166,11256,11257],{"class":3316}," \"@nuxt\u002Fui\"",[2166,11259,3332],{"class":3331},[2166,11261,11262,11265],{"class":3301,"line":3342},[2166,11263,11264],{"class":3305},"@source",[2166,11266,11267],{"class":3331}," \"..\u002F..\";\n",[57,11269,11270,11273],{},[16,11271,11272],{},"@source \"..\u002F..\"","로 프로젝트 전체를 Tailwind 스캔 범위에 포함",[57,11275,11276,10238,11278,11281],{},[16,11277,10093],{},[16,11279,11280],{},"@tailwindcss\u002Fvite"," 플러그인 명시 등록 (자동 등록이 안 됨)",[24,11283,11284,11286,11287,10238,11290,105,11293,105,11296,11299],{},[28,11285,3763],{},": 빌드 후 ",[16,11288,11289],{},"entry-styles",[16,11291,11292],{},"max-w-[960px]",[16,11294,11295],{},"hover:bg-neutral-50",[16,11297,11298],{},"backdrop-blur"," 등 컴포넌트 사용 클래스 모두 포함됨.",[21,11301,11302],{},[24,11303,11304,11305,11307],{},"Lesson: Tailwind v4는 CSS 파일 위치 기준으로 스캔. 프로젝트 구조에 따라 ",[16,11306,11264],{}," 디렉티브로 명시적 스캔 범위 지정이 필요.",[215,11309,11311],{"id":11310},"_17-단일-qa-요약평가-예시-추가","17. 단일 Q&A 요약·평가 예시 추가",[54,11313,11314,11321,11324,11331,11334],{},[57,11315,11316,11320],{},[3257,11317,11319],{"href":11318},"..\u002Fexamples\u002Fqa-94227","doc\u002Fexamples\u002Fqa-94227-사용자매뉴얼.md"," 신규 — post 94227 (에듀야 \"사용자 매뉴얼\" 문의) 케이스",[57,11322,11323],{},"5축 평가: 답변 정확성·완결성 \u002F 응대 시간·턴 효율성 \u002F 톤·친절도 \u002F 표준답변화 가능성 \u002F 챗봇 자동화 적합성·가시성",[57,11325,11326,11327,11330],{},"종합 ★ 4.5\u002F5 — 답변 내용은 1순위 표준답변 후보지만 ",[28,11328,11329],{},"비공개 처리","라 챗봇용 공개판 별도 작성 필요",[57,11332,11333],{},"표준답변 템플릿(공개판) 초안 포함 + 후속 조치 5건",[57,11335,11336],{},"안전보건진흥원·현대엔지비 예시와 함께 examples\u002F에 누적 — 풀 평가\u002F브리핑\u002FQ&A 세 양식 비교 가능",[215,11338,11340],{"id":11339},"_18-qa-평가-프롬프트-정의","18. Q&A 평가 프롬프트 정의",[54,11342,11343,11350,11363,11366,11369,11372,11378],{},[57,11344,11345,11349],{},[3257,11346,11348],{"href":11347},"..\u002Fprompts\u002Fqa-evaluation","doc\u002Fprompts\u002Fqa-evaluation.md"," 신규 — 단일 Q&A에 대한 요약·평가 보고서를 AI에게 생성시키는 재사용 프롬프트",[57,11351,11352,11353,105,11356,11359,11360,78],{},"입력 변수: ",[16,11354,11355],{},"POST_ID",[16,11357,11358],{},"EVAL_DATE"," (선택: ",[16,11361,11362],{},"COMMENT_ID",[57,11364,11365],{},"데이터 수집 쿼리 4개: 게시글 메타·본문 \u002F 댓글 시간순 \u002F 타이밍(FRT·첫 직원 응답·TTR) \u002F 첨부",[57,11367,11368],{},"5축 평가 프레임(정확성·시간·톤·표준답변화·챗봇 적합성) + 측정 항목 표",[57,11370,11371],{},"출력 양식·작성 규칙·품질 체크리스트 명문화",[57,11373,11374,11375],{},"산출물 저장 경로 표준화: ",[16,11376,11377],{},"doc\u002Fexamples\u002Fqa-{POST_ID}-{슬러그}.md",[57,11379,11380,11381,11384,11385,11387,11388,11391],{},"이로써 prompts\u002F는 3종 완성 — ",[16,11382,11383],{},"cs-evaluation.md","(프로젝트 풀평가) \u002F ",[16,11386,10889],{},"(프로젝트 브리핑) \u002F ",[16,11389,11390],{},"qa-evaluation.md","(단일 Q&A)",[215,11393,11395],{"id":11394},"_19-malgn-helper-pms에-qa-평가-카드-통합","19. malgn-helper-pms에 Q&A 평가 카드 통합",[24,11397,11398,11401],{},[16,11399,11400],{},"design_handoff_qa_eval_card\u002F"," 핸드오프 패키지를 malgn-helper-pms에 통합. 브리핑 카드 통합과 동일한 패턴.",[24,11403,11404,1305,11406,11408],{},[28,11405,10923],{},[16,11407,10926],{}," → repo):",[54,11410,11411,11420,11425,11437],{},[57,11412,11413,2212,11416,11419],{},[16,11414,11415],{},"types\u002Fqa-eval.ts",[16,11417,11418],{},"data\u002Fqa-eval.example.ts"," (post #94227 데이터 내장)",[57,11421,11422],{},[16,11423,11424],{},"composables\u002FuseQaEvalClipboard.ts",[57,11426,11427,11430,11431,1524,11434],{},[16,11428,11429],{},"components\u002FQaEvalCard.vue"," (메인 모달) + ",[16,11432,11433],{},"components\u002Fqa\u002FQaAxisCard.vue",[16,11435,11436],{},"components\u002Fqa\u002FQaScoreSummary.vue",[57,11438,11439,10960],{},[16,11440,11441],{},"pages\u002Fposts\u002F[id]\u002Feval.vue",[24,11443,11444,11447],{},[28,11445,11446],{},"적용한 패턴 수정"," (브리핑 카드에서 학습한 lesson 재적용):",[54,11449,11450,11462,11465],{},[57,11451,11452,4708,11455,1358,11458,11461],{},[16,11453,11454],{},"QaEvalCard.vue",[16,11456,11457],{},"\u003CUModal>",[28,11459,11460],{},"Teleport + 자체 백드랍"," 으로 교체 (Nuxt UI v3 UModal 슬롯 호환 X)",[57,11463,11464],{},"ESC·백드랍 클릭 닫기, body 스크롤 잠금, fade Transition 동일 적용",[57,11466,11467,11469,11470,11473,11474],{},[16,11468,11441],{},": 모달 자동 오픈 + 닫힘 시 ",[16,11471,11472],{},"window.close()"," + parent ",[16,11475,11476],{},"postMessage({type:'malgn-helper:qa-eval:close'})",[24,11478,11479,3360],{},[28,11480,11481,11482,11484],{},"메인 페이지(",[16,11483,530],{},") 통합",[54,11486,11487,11490,11496],{},[57,11488,11489],{},"\"Q&A 평가 카드\" 섹션 신규 — post 94227 행 표시(post·제목·프로젝트·문의자·일자·점수·가시성)",[57,11491,11492,11493,11495],{},"행 클릭 시 ",[16,11494,2739],{}," 모달 팝업",[57,11497,11498],{},"임베드 가이드 섹션과 함께 데모 흐름 완성",[24,11500,11501,3360],{},[28,11502,11503],{},"연결 자산",[54,11505,11506,11512],{},[57,11507,11508,11509,11511],{},"데모는 ",[3257,11510,11319],{"href":11318}," 평가 내용을 시각화한 것",[57,11513,11514,11515,11517],{},"양식·프롬프트는 ",[3257,11516,11348],{"href":11347},"에 정의됨",[24,11519,11520,11522,11523,11526],{},[28,11521,3763],{},": 빌드 1.15 MB \u002F 337 kB gzip. 배포 후 ",[3257,11524,10629],{"href":10629,"rel":11525},[5049]," 메인에서 Q&A 행 클릭 → 모달 확인 가능.",[36,11528,11529],{"id":11529},"배포",[215,11531,11533,11534,11536],{"id":11532},"_1139-malgn-helper-api-cloudflare-workers","11:39 — ",[16,11535,4404],{}," → Cloudflare Workers",[54,11538,11539,11545],{},[57,11540,11541,11542,11544],{},"커밋: ",[16,11543,10331],{}," (신규 커밋: no)",[57,11546,11547],{},"메시지: chore: Cloudflare 최초 배포",[215,11549,11551,11552,11554],{"id":11550},"_1141-malgn-helper-pms-cloudflare-pages","11:41 — ",[16,11553,4588],{}," → Cloudflare Pages",[54,11556,11557,11562],{},[57,11558,11541,11559,11561],{},[16,11560,10827],{}," (신규 커밋: yes)",[57,11563,11547],{},[215,11565,11551,11567,11554],{"id":11566},"_1141-malgn-helper-cloudflare-pages",[16,11568,47],{},[54,11570,11571,11575],{},[57,11572,11541,11573,11561],{},[16,11574,10843],{},[57,11576,11547],{},[215,11578,11580,11581,11554],{"id":11579},"_1142-malgn-helper-admin-cloudflare-pages","11:42 — ",[16,11582,18],{},[54,11584,11585,11589],{},[57,11586,11541,11587,11561],{},[16,11588,10859],{},[57,11590,11547],{},[215,11592,11594,11595,11554],{"id":11593},"_1242-malgn-helper-pms-cloudflare-pages","12:42 — ",[16,11596,4588],{},[54,11598,11599,11604],{},[57,11600,11541,11601,11561],{},[16,11602,11603],{},"095f641",[57,11605,11606],{},"메시지: feat: 브리핑 카드 디자인 통합 (Nuxt UI + Pretendard)",[215,11608,11610,11611,11554],{"id":11609},"_1255-malgn-helper-pms-cloudflare-pages","12:55 — ",[16,11612,4588],{},[54,11614,11615,11620],{},[57,11616,11541,11617,11561],{},[16,11618,11619],{},"5c58977",[57,11621,11622],{},"메시지: feat: 예시 화면 - 고객사 목록 + 상세 페이지 + 가짜 게시글 테이블",[215,11624,11626,11627,11554],{"id":11625},"_1300-malgn-helper-pms-cloudflare-pages","13:00 — ",[16,11628,4588],{},[54,11630,11631,11636],{},[57,11632,11541,11633,11561],{},[16,11634,11635],{},"a9decc2",[57,11637,11638],{},"메시지: fix: @nuxt\u002Fui를 v3.3.7로 다운그레이드 (핸드오프 시안 호환)",[215,11640,11642,11643,11554],{"id":11641},"_1309-malgn-helper-pms-cloudflare-pages","13:09 — ",[16,11644,4588],{},[54,11646,11647,11652],{},[57,11648,11541,11649,11561],{},[16,11650,11651],{},"7f4cab9",[57,11653,11654],{},"메시지: fix: Tailwind v4 @source 지시자 추가로 컴포넌트 클래스 스캔 활성화",[215,11656,11658,11659,11554],{"id":11657},"_1348-malgn-helper-pms-cloudflare-pages","13:48 — ",[16,11660,4588],{},[54,11662,11663,11668],{},[57,11664,11541,11665,11561],{},[16,11666,11667],{},"2baa795",[57,11669,11670],{},"메시지: refactor: 상세 페이지를 브리핑 모달 단독 표시로 단순화",[215,11672,11674,11675,11554],{"id":11673},"_1351-malgn-helper-pms-cloudflare-pages","13:51 — ",[16,11676,4588],{},[54,11678,11679,11684],{},[57,11680,11541,11681,11561],{},[16,11682,11683],{},"eec6d64",[57,11685,11686],{},"메시지: feat: 고객사 카드 클릭 시 브리핑 모달 팝업 (페이지 이동 X)",[215,11688,11690,11691,11554],{"id":11689},"_1356-malgn-helper-pms-cloudflare-pages","13:56 — ",[16,11692,4588],{},[54,11694,11695,11700],{},[57,11696,11541,11697,11561],{},[16,11698,11699],{},"df9023b",[57,11701,11702],{},"메시지: fix: 브리핑 카드를 Teleport 기반 모달로 변경 (UModal v3 슬롯 호환 X)",[215,11704,11706,11707,11554],{"id":11705},"_1429-malgn-helper-pms-cloudflare-pages","14:29 — ",[16,11708,4588],{},[54,11710,11711,11716],{},[57,11712,11541,11713,11561],{},[16,11714,11715],{},"3e5412e",[57,11717,11718],{},"메시지: feat: 임베드 가이드 추가 (URL\u002Fwindow.open\u002Fiframe 스니펫) + postMessage 닫기",[215,11720,11722,11723,11554],{"id":11721},"_1503-malgn-helper-pms-cloudflare-pages","15:03 — ",[16,11724,4588],{},[54,11726,11727,11732],{},[57,11728,11541,11729,11561],{},[16,11730,11731],{},"4c98af3",[57,11733,11734,11735,11738],{},"메시지: feat: Q&A 평가 카드 통합 (post 94227 데모) + \u002Fposts\u002F",[2166,11736,11737],{},"id","\u002Feval 모달 페이지",[215,11740,11742,11743,11554],{"id":11741},"_1511-malgn-helper-pms-cloudflare-pages","15:11 — ",[16,11744,4588],{},[54,11746,11747,11752],{},[57,11748,11541,11749,11561],{},[16,11750,11751],{},"b161474",[57,11753,11754],{},"메시지: feat: Q&A 평가 카드 임베드 가이드 추가 (URL\u002Fwindow.open\u002Fiframe)",[215,11756,11758,11759,11554],{"id":11757},"_1522-malgn-helper-pms-cloudflare-pages","15:22 — ",[16,11760,4588],{},[54,11762,11763,11768],{},[57,11764,11541,11765,11561],{},[16,11766,11767],{},"fbce0cb",[57,11769,11770],{},"메시지: feat: 브리핑 워크플로 페이지 (빈 상태 + AI 생성 + 히스토리 셀렉트)",[215,11772,11774,11775,11554],{"id":11773},"_1529-malgn-helper-pms-cloudflare-pages","15:29 — ",[16,11776,4588],{},[54,11778,11779,11784],{},[57,11780,11541,11781,11561],{},[16,11782,11783],{},"64de77e",[57,11785,11786],{},"메시지: feat: 브리핑 히스토리 툴바를 모달 내부로 이동 (version-bar 슬롯)",[215,11788,11790,11791,11554],{"id":11789},"_1537-malgn-helper-pms-cloudflare-pages","15:37 — ",[16,11792,4588],{},[54,11794,11795,11800],{},[57,11796,11541,11797,11561],{},[16,11798,11799],{},"24eab33",[57,11801,11802],{},"메시지: feat: 인덱스 모달에도 version-bar 표시 (useBriefingHistory 컴포저블 추출)",[215,11804,11806,11807,11554],{"id":11805},"_1540-malgn-helper-pms-cloudflare-pages","15:40 — ",[16,11808,4588],{},[54,11810,11811,11816],{},[57,11812,11541,11813,11561],{},[16,11814,11815],{},"9c3b83f",[57,11817,11818],{},"메시지: fix: 주의 배지에 ring 테두리 추가 (시안 ring-amber-200 적용)",[215,11820,11822,11823,11554],{"id":11821},"_1556-malgn-helper-pms-cloudflare-pages","15:56 — ",[16,11824,4588],{},[54,11826,11827,11832],{},[57,11828,11541,11829,11561],{},[16,11830,11831],{},"46bc320",[57,11833,11834],{},"메시지: feat: Q&A 카드에 표준답변 다중 + '표준 질문·답변으로 저장하기' 버튼",[215,11836,11838,11839,11554],{"id":11837},"_1601-malgn-helper-pms-cloudflare-pages","16:01 — ",[16,11840,4588],{},[54,11842,11843,11848],{},[57,11844,11541,11845,11561],{},[16,11846,11847],{},"b451c27",[57,11849,11850],{},"메시지: feat: 표준답변 6종 스타일 (친절·공감형 \u002F 상세 안내형 \u002F 공식 격식형 추가)",[215,11852,11854,11855,11554],{"id":11853},"_1607-malgn-helper-pms-cloudflare-pages","16:07 — ",[16,11856,4588],{},[54,11858,11859,11864],{},[57,11860,11541,11861,11561],{},[16,11862,11863],{},"6a7cf51",[57,11865,11866],{},"메시지: fix: 표준답변 저장 버튼 잘림 수정 (라벨 단축 + whitespace-nowrap + size xs)",[215,11868,11870,11871,11554],{"id":11869},"_1609-malgn-helper-pms-cloudflare-pages","16:09 — ",[16,11872,4588],{},[54,11874,11875,11880],{},[57,11876,11541,11877,11561],{},[16,11878,11879],{},"68f7009",[57,11881,11882],{},"메시지: fix: color='gray' → color='neutral' (Nuxt UI v3 컬러 토큰 변경 반영)",[215,11884,11886,11887,11554],{"id":11885},"_1613-malgn-helper-pms-cloudflare-pages","16:13 — ",[16,11888,4588],{},[54,11890,11891,11896],{},[57,11892,11541,11893,11561],{},[16,11894,11895],{},"6b0707a",[57,11897,11898],{},"메시지: fix: Q&A 평균 점수를 5-스타 시각 표시로 변경 (각 축 카드와 일관성)",[215,11900,11902,11903,11554],{"id":11901},"_1616-malgn-helper-pms-cloudflare-pages","16:16 — ",[16,11904,4588],{},[54,11906,11907,11912],{},[57,11908,11541,11909,11561],{},[16,11910,11911],{},"ed7713d",[57,11913,11914],{},"메시지: fix: 평균 별점 표시 amber 토큰 + UTooltip 제거 (v3 컬러 호환)",[215,11916,11918,11919,11554],{"id":11917},"_1630-malgn-helper-pms-cloudflare-pages","16:30 — ",[16,11920,4588],{},[54,11922,11923,11928],{},[57,11924,11541,11925,11561],{},[16,11926,11927],{},"98f3a07",[57,11929,11930],{},"메시지: fix: Q&A 평균 점수 배지에서 별 아이콘 제거 (텍스트만)",[4258,11932,11933],{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":423,"searchDepth":3342,"depth":3342,"links":11935},[11936,11937,11947,11948,11949,11950,11967],{"id":9923,"depth":3335,"text":9923},{"id":9933,"depth":3335,"text":9934,"children":11938},[11939,11941,11942,11943,11944,11945],{"id":9937,"depth":3342,"text":11940},"1. malgn-helper-pms 정의 추가",{"id":9969,"depth":3342,"text":9970},{"id":10044,"depth":3342,"text":10045},{"id":10058,"depth":3342,"text":10059},{"id":10161,"depth":3342,"text":10162},{"id":10220,"depth":3342,"text":11946},"6. 다중 계정 대응 — account_id 명시",{"id":10261,"depth":3335,"text":10262},{"id":10354,"depth":3335,"text":10355},{"id":10396,"depth":3335,"text":10397},{"id":10481,"depth":3335,"text":10482,"children":11951},[11952,11953,11954,11956,11957,11958,11959,11960,11961,11963,11964,11965,11966],{"id":10485,"depth":3342,"text":10486},{"id":10510,"depth":3342,"text":10511},{"id":10569,"depth":3342,"text":11955},"9. malgn-helper-pms 스택 전환 — Workers → Pages",{"id":10645,"depth":3342,"text":10646},{"id":10867,"depth":3342,"text":10868},{"id":10893,"depth":3342,"text":10894},{"id":10911,"depth":3342,"text":10912},{"id":11026,"depth":3342,"text":11027},{"id":11126,"depth":3342,"text":11962},"15. @nuxt\u002Fui v4 → v3 다운그레이드 (시안 호환성)",{"id":11197,"depth":3342,"text":11198},{"id":11310,"depth":3342,"text":11311},{"id":11339,"depth":3342,"text":11340},{"id":11394,"depth":3342,"text":11395},{"id":11529,"depth":3335,"text":11529,"children":11968},[11969,11971,11973,11975,11977,11979,11981,11983,11985,11987,11989,11991,11993,11995,11997,11999,12001,12003,12005,12007,12009,12011,12013,12015,12017],{"id":11532,"depth":3342,"text":11970},"11:39 — malgn-helper-api → Cloudflare Workers",{"id":11550,"depth":3342,"text":11972},"11:41 — malgn-helper-pms → Cloudflare Pages",{"id":11566,"depth":3342,"text":11974},"11:41 — malgn-helper → Cloudflare Pages",{"id":11579,"depth":3342,"text":11976},"11:42 — malgn-helper-admin → Cloudflare Pages",{"id":11593,"depth":3342,"text":11978},"12:42 — malgn-helper-pms → Cloudflare Pages",{"id":11609,"depth":3342,"text":11980},"12:55 — malgn-helper-pms → Cloudflare Pages",{"id":11625,"depth":3342,"text":11982},"13:00 — malgn-helper-pms → Cloudflare Pages",{"id":11641,"depth":3342,"text":11984},"13:09 — malgn-helper-pms → Cloudflare Pages",{"id":11657,"depth":3342,"text":11986},"13:48 — malgn-helper-pms → Cloudflare Pages",{"id":11673,"depth":3342,"text":11988},"13:51 — malgn-helper-pms → Cloudflare Pages",{"id":11689,"depth":3342,"text":11990},"13:56 — malgn-helper-pms → Cloudflare Pages",{"id":11705,"depth":3342,"text":11992},"14:29 — malgn-helper-pms → Cloudflare Pages",{"id":11721,"depth":3342,"text":11994},"15:03 — malgn-helper-pms → Cloudflare Pages",{"id":11741,"depth":3342,"text":11996},"15:11 — malgn-helper-pms → Cloudflare Pages",{"id":11757,"depth":3342,"text":11998},"15:22 — malgn-helper-pms → Cloudflare Pages",{"id":11773,"depth":3342,"text":12000},"15:29 — malgn-helper-pms → Cloudflare Pages",{"id":11789,"depth":3342,"text":12002},"15:37 — malgn-helper-pms → Cloudflare Pages",{"id":11805,"depth":3342,"text":12004},"15:40 — malgn-helper-pms → Cloudflare Pages",{"id":11821,"depth":3342,"text":12006},"15:56 — malgn-helper-pms → Cloudflare Pages",{"id":11837,"depth":3342,"text":12008},"16:01 — malgn-helper-pms → Cloudflare Pages",{"id":11853,"depth":3342,"text":12010},"16:07 — malgn-helper-pms → Cloudflare Pages",{"id":11869,"depth":3342,"text":12012},"16:09 — malgn-helper-pms → Cloudflare Pages",{"id":11885,"depth":3342,"text":12014},"16:13 — malgn-helper-pms → Cloudflare Pages",{"id":11901,"depth":3342,"text":12016},"16:16 — malgn-helper-pms → Cloudflare Pages",{"id":11917,"depth":3342,"text":12018},"16:30 — malgn-helper-pms → Cloudflare Pages",{},"\u002Fhistory\u002Fhistory.20260528",{"title":9915,"description":423},"history\u002Fhistory.20260528","F-QRWBmsCCa6XnXPRVMpNgyw3mhFmoBioYB7SC3AUT0",{"id":12025,"title":12026,"body":12027,"description":423,"extension":4340,"meta":15228,"navigation":3338,"path":15229,"seo":15230,"stem":15231,"__hash__":15232},"docs\u002Fhistory\u002Fhistory.20260529.md","작업 이력 — 2026-05-29",{"type":8,"value":12028,"toc":15005},[12029,12032,12036,12043,12380,12384,12474,12478,12548,12552,12593,12597,12631,12635,12684,12686,12688,12693,12695,12697,12701,12704,12709,12732,12737,12757,12762,12795,12800,12805,12810,12830,12834,12837,12899,12904,12912,12918,12923,12970,12975,12986,12992,12998,13002,13011,13019,13038,13043,13079,13084,13164,13168,13171,13191,13226,13228,13234,13244,13250,13260,13266,13276,13281,13291,13297,13307,13313,13323,13329,13339,13345,13355,13361,13371,13377,13387,13393,13403,13409,13423,13429,13439,13445,13455,13461,13471,13477,13487,13493,13503,13509,13519,13525,13535,13541,13551,13557,13567,13573,13583,13589,13599,13605,13615,13621,13631,13637,13647,13653,13663,13669,13679,13684,13694,13700,13710,13716,13726,13732,13742,13747,13757,13763,13773,13779,13789,13794,13804,13810,13820,13825,13835,13841,13851,13856,13866,13872,13882,13888,13898,13904,13914,13919,13929,13935,13945,13951,13961,13967,13977,13983,13993,13998,14008,14014,14024,14029,14039,14045,14055,14061,14071,14076,14086,14092,14102,14107,14117,14123,14133,14138,14148,14154,14164,14170,14180,14185,14195,14201,14210,14215,14229,14235,14248,14254,14264,14269,14279,14285,14295,14299,14309,14314,14324,14330,14343,14348,14358,14364,14374,14380,14390,14396,14406,14412,14422,14428,14438,14444,14454,14460,14470,14476,14486,14492,14502,14508,14518,14524,14534,14540,14550,14556,14566,14572,14582,14588,14598,14604,14620,14626,14636,14642,14652,14658,14668,14674,14684,14690,14700,14706,14716,14722,14732,14737,14747,14753,14763,14769,14785,14791,14807,14813,14828,14834,14852,14858,14973,14979,15003],[11,12030,12026],{"id":12031},"작업-이력-2026-05-29",[36,12033,12035],{"id":12034},"종합-end-of-day","종합 (end-of-day)",[24,12037,12038,12039,12042],{},"하루 안에 ",[28,12040,12041],{},"스토리보드 수준 PMS 데모 → 진짜 동작하는 LLM 기반 CS 헬퍼 백엔드\u002F관리자","로 도약. 6개 단계 흐름:",[1925,12044,12045,12073,12112,12156,12192,12243,12269],{},[57,12046,12047,12050],{},[28,12048,12049],{},"WBS 페이지 폴리시·정합성 정리",[54,12051,12052,12055,12058],{},[57,12053,12054],{},"인라인 편집(목표일·완료일·상태) + R2 자동 저장(800ms 디바운스)",[57,12056,12057],{},"가중평균 수식 버그 수정 + stage weight 합 100 정규화 (0.2% → 24.2%)",[57,12059,12060,12061,12064,12065,12068,12069,12072],{},"PMS 통합 항목(",[16,12062,12063],{},"P1-3-9~13",")이 실구현이 아닌 ",[28,12066,12067],{},"사용자단 스토리보드","임을 식별하고 ",[16,12070,12071],{},"P1-2-7~11","로 재배치 → 진행률 더 정직해짐",[57,12074,12075,12078],{},[28,12076,12077],{},"인프라 활성화 (Hyperdrive · R2 · AI Gateway)",[54,12079,12080,12091,12098,12104],{},[57,12081,12082,12083,12086,12087,12090],{},"Hyperdrive ",[16,12084,12085],{},"pms"," (id ",[16,12088,12089],{},"aea3...",") → PMS MySQL(5.6.51) 연결",[57,12092,12093,12094,12097],{},"R2 ",[16,12095,12096],{},"malgn-helper-files"," 생성 (WBS 영속화)",[57,12099,12100,12101,12103],{},"AI Gateway ",[16,12102,47],{}," (Authenticated 모드, compat endpoint)",[57,12105,12106,12107,105,12109],{},"시크릿: ",[16,12108,4544],{},[16,12110,12111],{},"AI_GATEWAY_TOKEN",[57,12113,12114,12117],{},[28,12115,12116],{},"PMS DB 연동 + 첫 실 엔드포인트",[54,12118,12119,12125,12131,12140,12146],{},[57,12120,12121,12122,12124],{},"DB 탐색용 dev 엔드포인트(",[16,12123,5615],{}," 등) 신설, PMS 27개 테이블 구조 파악",[57,12126,12127,12130],{},[16,12128,12129],{},"GET \u002Fpms\u002Fprojects"," (검색·페이지네이션, 활성 1,653건)",[57,12132,12133,12136,12137,78],{},[16,12134,12135],{},"GET \u002Fpms\u002Fposts\u002F:id"," (직원\u002F고객 분류 + ",[28,12138,12139],{},"비공개 댓글 본문 마스킹",[57,12141,12142,12145],{},[16,12143,12144],{},"GET \u002Fpms\u002Fprojects\u002F:id\u002Fbriefing"," (DB-only 집계 — 멤버\u002F통계\u002F라벨\u002F알림)",[57,12147,2731,12148,12151,12152,12155],{},[16,12149,12150],{},"BriefingCard"," 모킹을 ",[28,12153,12154],{},"실 API 호출","로 전환 (P1-2-7 스토리보드 → 실서비스)",[57,12157,12158,12161],{},[28,12159,12160],{},"헬퍼 전용 DB 스키마 + 캐싱 인프라",[54,12162,12163,12178,12181],{},[57,12164,12165,12168,12169,1365,12171,1365,12173,1365,12175],{},[16,12166,12167],{},"hp_*"," 4 테이블 설계·문서화: ",[16,12170,2854],{},[16,12172,2858],{},[16,12174,2125],{},[16,12176,12177],{},"hp_llm_log",[57,12179,12180],{},"일회용 admin 엔드포인트로 DDL 실행 후 secret·코드 제거",[57,12182,12183,2448,12186,12188,12189,12191],{},[16,12184,12185],{},"POST \u002Fpms\u002Fprojects\u002F:id\u002Fbriefing\u002Fgenerate",[16,12187,2800],{}," 기반 24h 캐시 hit + ",[16,12190,12177],{}," 감사 기록 + graceful degrade",[57,12193,12194,12197],{},[28,12195,12196],{},"LLM 실 연동 (OpenAI via AI Gateway)",[54,12198,12199,12205,12208,12226,12233],{},[57,12200,12201,12202,12204],{},"CLAUDE.md: Claude → OpenAI(",[16,12203,4522],{}," 기본)로 변경",[57,12206,12207],{},"첫 호출 검증: project 1446 hotTopics 7개 군집화 (\"훈련생 오류 15 \u002F 서버 10 \u002F ...\")",[57,12209,12210,12211,1524,12214,1524,12217,1524,12220,1524,12223],{},"브리핑 LLM 확장: ",[16,12212,12213],{},"oneLiner",[16,12215,12216],{},"statusReason",[16,12218,12219],{},"urgentCount",[16,12221,12222],{},"faq",[16,12224,12225],{},"policies",[57,12227,12228,12229,12232],{},"Q&A 평가 카드 전체 LLM 연동: 5축(A~E) score + commentary + ",[28,12230,12231],{},"D축 templates 자동 생성"," + followups + observation",[57,12234,12235,12236,1305,12239,12242],{},"LLM 2회 호출 ",[28,12237,12238],{},"병렬화",[16,12240,12241],{},"Promise.allSettled","): 7s → 3.5s (50% 단축)",[57,12244,12245,12248],{},[28,12246,12247],{},"운영·관리자 도구",[54,12249,12250,12258,12263],{},[57,12251,12252,12254,12255,12257],{},[16,12253,104],{}," 대시보드 (",[16,12256,12177],{}," 일·모델·엔티티 집계 + 최근 100건 추적)",[57,12259,12260,12262],{},[16,12261,108],{}," Q&A 평가 목록 (정렬·필터·점수 색 분기, score_asc로 취약 응대 발굴)",[57,12264,12265,12268],{},[16,12266,12267],{},"\u002Fprojects"," 프로젝트 목록 (1,653건, 검색·페이지네이션)",[57,12270,12271,12274,12275],{},[28,12272,12273],{},"Q&A 평가 카드 폴리시 라운드"," (20:10 이후)",[54,12276,12277,12287,12296,12326,12336,12346,12364,12369,12372],{},[57,12278,12279,12282,12283,12286],{},[28,12280,12281],{},"Vision으로 이미지 직접 분석"," — 원본 응답의 ",[16,12284,12285],{},"\u003Cimg src>","를 절대URL로 변환 후 GPT-4o Vision에 첨부. LLM이 화면 내용(메뉴\u002F버튼명)을 인지하고 적절한 캡션과 함께 답변에 배치 (이미지 있을 때만 mini → 4o 자동 업그레이드)",[57,12288,12289,12292,12293,12295],{},[28,12290,12291],{},"표준답변 컨텍스트 보강"," — 같은 프로젝트의 ",[16,12294,2125],{}," 최근 5건을 톤·구조 참고용으로 LLM에 전달 (복붙 금지)",[57,12297,12298,12301,12302,12305,12306,12309,12310,12312,12313,12315,12316,12318,12319,12321,12322,12325],{},[28,12299,12300],{},"문단 분리 prompt 강제"," — 한 ",[16,12303,12304],{},"\u003Cp>","에 모든 답변을 몰아넣던 문제 해결. ",[2166,12307,12308],{},"인사\u002F공감\u002F핵심\u002F보조\u002F마무리","를 별도 ",[16,12311,12304],{},"로 분리, 변형별 최소 ",[16,12314,12304],{}," 수 명시. 검증: 짧은 답변 1 → 4 ",[16,12317,12304],{},", 긴 답변 1 → 6 ",[16,12320,12304],{},", 단계별 안내는 ",[16,12323,12324],{},"\u003Col>"," 절차로 시각화",[57,12327,12328,12331,12332,12335],{},[28,12329,12330],{},"모달 UX 개선"," — 분석 모달은 valid 결과(",[16,12333,12334],{},"axes.length > 0",") 도착 후에만 열기 (빈 0점 모달 노출 fix). Q&A 본문은 초기 접힌 상태로. 모달 안 🗑 삭제 → 서버 + 메모리 동기화",[57,12337,12338,12341,12342,12345],{},[28,12339,12340],{},"빈 섹션 정리"," — LLM이 매번 빈 배열만 채워 ",[16,12343,12344],{},"후속 조치 0"," 빈 박스만 보이던 followups 필드 완전 제거 (schema·prompt·UI·clipboard 4곳)",[57,12347,12348,12353,12354,1358,12357,12359,12360,12363],{},[28,12349,12350,12352],{},[16,12351,108],{}," 모달 즉시 열기"," — 행 클릭 시 라우팅 대신 ",[16,12355,12356],{},"GET \u002Fpms\u002Fevals\u002F:id",[16,12358,2739],{}," 모달. db_only 폴백·빈 결과 행은 기본 목록에서 숨김 (",[16,12361,12362],{},"?includeEmpty=1","로 디버그 노출)",[57,12365,12366,12368],{},[16,12367,3239],{}," Scalar + OpenAPI 3.1 (수동 스펙, 22개 엔드포인트)",[57,12370,12371],{},"홈에 4개 진입 링크 노출, 헤더 제목 \"고객사 목록\" → \"맑은도우미 데모\"",[57,12373,12374,12375,2367,12377,12379],{},"Cloudflare Access ",[16,12376,3973],{},[16,12378,5001],{}," 보호 가이드 문서",[215,12381,12383],{"id":12382},"산출-카운트","산출 카운트",[135,12385,12386,12396],{},[138,12387,12388],{},[141,12389,12390,12392],{},[144,12391,4143],{},[144,12393,12395],{"align":12394},"right","수",[157,12397,12398,12406,12425,12435,12443,12458,12466],{},[141,12399,12400,12403],{},[162,12401,12402],{},"신규 API 엔드포인트",[162,12404,12405],{"align":12394},"22개",[141,12407,12408,12411],{},[162,12409,12410],{},"신규 PMS 페이지",[162,12412,12413,12414,2367,12416,2367,12418,2367,12420,2367,12422,12424],{"align":12394},"5개 (",[16,12415,12267],{},[16,12417,104],{},[16,12419,108],{},[16,12421,104],{},[16,12423,3239],{},"은 API 측)",[141,12426,12427,12430],{},[162,12428,12429],{},"신규 DB 테이블 (PMS DB)",[162,12431,12432,12433,78],{"align":12394},"4개 (",[16,12434,12167],{},[141,12436,12437,12440],{},[162,12438,12439],{},"신규 인프라",[162,12441,12442],{"align":12394},"R2 버킷 1 \u002F Hyperdrive 1 \u002F AI Gateway 1",[141,12444,12445,12448],{},[162,12446,12447],{},"신규 문서",[162,12449,12450,1365,12453,1365,12456],{"align":12394},[16,12451,12452],{},"WBS-TRACKER.md",[16,12454,12455],{},"HP-SCHEMA.md",[16,12457,3260],{},[141,12459,12460,12463],{},[162,12461,12462],{},"메모리 추가",[162,12464,12465],{"align":12394},"2건 (스토리보드 식별 \u002F Hyperdrive 캐싱 stale)",[141,12467,12468,12471],{},[162,12469,12470],{},"배포 (정식 deploy.sh)",[162,12472,12473],{"align":12394},"약 35회 (말미 기준)",[215,12475,12477],{"id":12476},"첫-llm-호출-결과-project-1446","첫 LLM 호출 결과 (project 1446)",[135,12479,12480,12488],{},[138,12481,12482],{},[141,12483,12484,12486],{},[144,12485,4143],{},[144,12487,1540],{},[157,12489,12490,12498,12506,12517,12525,12533,12540],{},[141,12491,12492,12495],{},[162,12493,12494],{},"hotTopics",[162,12496,12497],{},"훈련생 오류 15 \u002F 서버·접속 10 \u002F 강의·콘텐츠 10 \u002F 수료증 8 \u002F 문서 6 \u002F 결제 5 \u002F 기타 4",[141,12499,12500,12503],{},[162,12501,12502],{},"statusReason (LLM)",[162,12504,12505],{},"\"긴급 문의가 다수 발생\"",[141,12507,12508,12511],{},[162,12509,12510],{},"urgent",[162,12512,12513,12514,12516],{},"0 (DB) → ",[28,12515,6066],{}," (LLM 추정)",[141,12518,12519,12522],{},[162,12520,12521],{},"faq (자동 추출)",[162,12523,12524],{},"학습시간 오류 \u002F SSL 갱신 \u002F 강의 오류메세지 \u002F 모바일 영상 \u002F 과제 재제출 불가",[141,12526,12527,12530],{},[162,12528,12529],{},"policies (직원 응답 패턴)",[162,12531,12532],{},"강의 수강 환경 안내 \u002F SSL 인증서 관리",[141,12534,12535,12537],{},[162,12536,5701],{},[162,12538,12539],{},"$0.0012 (≈ ₩1.6) \u002F brief 1회",[141,12541,12542,12545],{},[162,12543,12544],{},"캐시 hit 시 비용",[162,12546,12547],{},"$0",[215,12549,12551],{"id":12550},"결정사건","결정\u002F사건",[54,12553,12554,12560,12569,12575,12581,12587],{},[57,12555,12556,12559],{},[28,12557,12558],{},"D1 DB 거부 → R2 + JSON 영속화"," (어제 결정 유지)",[57,12561,12562,12568],{},[28,12563,12564,12565,12567],{},"PMS 운영 DB에 ",[16,12566,12167],{}," 접두사로 헬퍼 테이블 공존"," (별도 DB 분리는 추후 시나리오 문서화)",[57,12570,12571,12574],{},[28,12572,12573],{},"LLM 공급자 Claude → OpenAI"," (사용자 키 제공 따라)",[57,12576,12577,12580],{},[28,12578,12579],{},"AI Gateway Authenticated 모드"," (cf-aig-authorization 토큰)",[57,12582,12583,12586],{},[28,12584,12585],{},"사용자단 스토리보드 vs 실서비스 구분"," 룰 명문화 (메모리)",[57,12588,12589,12592],{},[28,12590,12591],{},"OpenAI 키 채팅 노출"," 사용자가 재발급 보류 — 그대로 사용 결정",[215,12594,12596],{"id":12595},"알려진-잔여-이슈","알려진 잔여 이슈",[54,12598,12599,12612,12615,12626],{},[57,12600,12601,1358,12608,12611],{},[12602,12603,12604,12607],"del",{},[16,12605,12606],{},"hp_qa_eval.overall_verdict"," VARCHAR(20)",[28,12609,12610],{},"VARCHAR(100) 마이그레이션 완료"," (eod 추가 작업, 검증: \"문의에 대한 답변이 부족하여 개선이 필요합니다.\" 26자 정상 저장)",[57,12613,12614],{},"Hyperdrive read 캐싱으로 write 후 GET이 stale 보일 수 있음 (메모리 기록, 임팩트 작음)",[57,12616,12617,2367,12619,12621,12622,12625],{},[16,12618,3973],{},[16,12620,5001],{}," 무인증 — 가이드(",[16,12623,12624],{},"doc\u002FCLOUDFLARE-ACCESS.md",")대로 적용 권장",[57,12627,12628,12630],{},[16,12629,5001],{}," 탐색 엔드포인트는 안정화 후 제거 예정 (OpenAPI에 명시)",[215,12632,12634],{"id":12633},"미리보기-링크","미리보기 링크",[54,12636,12637,12643,12650,12657,12664,12671,12678],{},[57,12638,12639,12640],{},"홈: ",[3257,12641,10629],{"href":10629,"rel":12642},[5049],[57,12644,12645,12646],{},"프로젝트 목록: ",[3257,12647,12648],{"href":12648,"rel":12649},"https:\u002F\u002Fmalgn-helper-pms.pages.dev\u002Fprojects",[5049],[57,12651,12652,12653],{},"프로젝트 브리핑 (LLM): ",[3257,12654,12655],{"href":12655,"rel":12656},"https:\u002F\u002Fmalgn-helper-pms.pages.dev\u002Fprojects\u002F1446",[5049],[57,12658,12659,12660],{},"Q&A 평가 목록: ",[3257,12661,12662],{"href":12662,"rel":12663},"https:\u002F\u002Fmalgn-helper-pms.pages.dev\u002Fadmin\u002Fevals",[5049],[57,12665,12666,12667],{},"LLM 비용 대시보드: ",[3257,12668,12669],{"href":12669,"rel":12670},"https:\u002F\u002Fmalgn-helper-pms.pages.dev\u002Fadmin\u002Fcost",[5049],[57,12672,12673,12674],{},"WBS Tracker: ",[3257,12675,12676],{"href":12676,"rel":12677},"https:\u002F\u002Fmalgn-helper-pms.pages.dev\u002Fwbs",[5049],[57,12679,12680,12681],{},"API 문서: ",[3257,12682,1121],{"href":1121,"rel":12683},[5049],[33,12685],{},[36,12687,9923],{"id":9923},[24,12689,12690,12692],{},[3257,12691,10422],{"href":10421}," 현행화. 어제(2026-05-28) 누적된 19개 작업 단위와 4개 repo의 진행 상태를 반영해 전 단계 진행률·상태·신규 카테고리(PMS 애드온)를 추가.",[33,12694],{},[36,12696,9934],{"id":9933},[215,12698,12700],{"id":12699},"_1-wbs-전면-현행화","1. WBS 전면 현행화",[24,12702,12703],{},"기존 WBS는 작업 항목만 나열한 상태였음. 다음을 추가·갱신:",[24,12705,12706,3360],{},[28,12707,12708],{},"상단 신규 섹션",[54,12710,12711,12717,12726],{},[57,12712,12713,12716],{},[28,12714,12715],{},"진행률 스냅샷"," — 6개 단계별 % + 핵심 진행 사항",[57,12718,12719,12722,12723,12725],{},[28,12720,12721],{},"누적 완료 자산"," — 인프라 \u002F 문서·자산 \u002F ",[16,12724,4588],{}," 데모 \u002F 운영 정책 4개 카테고리로 정리",[57,12727,12728,12731],{},[28,12729,12730],{},"상태 범례"," (✅ 완료 · 🟢 진행 중 · ⚪ 대기 · ⛔ 보류)",[24,12733,12734,3360],{},[28,12735,12736],{},"기존 표 갱신",[54,12738,12739,12745,12751],{},[57,12740,12741,12742,3141],{},"모든 작업 항목에 ",[28,12743,12744],{},"상태 컬럼",[57,12746,12747,12750],{},[28,12748,12749],{},"산출물 컬럼","에 실제 생성된 파일·경로 명시",[57,12752,12753,12756],{},[28,12754,12755],{},"비고 컬럼"," 신설 — 미진 사유·후속 작업 안내",[24,12758,12759,3360],{},[28,12760,12761],{},"P1-3 구현에 신규 카테고리 추가",[54,12763,12764],{},[57,12765,12766,12771,12772],{},[28,12767,12768,12769,78],{},"PMS 애드온 (",[16,12770,4588],{}," — 3-9 ~ 3-15 (총 7개 항목)\n",[54,12773,12774,12777,12780,12783,12786,12789,12792],{},[57,12775,12776],{},"3-9 브리핑 카드 컴포넌트 통합 ✅",[57,12778,12779],{},"3-10 Q&A 평가 카드 컴포넌트 통합 ✅",[57,12781,12782],{},"3-11 워크플로 페이지 ✅",[57,12784,12785],{},"3-12 임베드 인터페이스 ✅",[57,12787,12788],{},"3-13 표준답변 다중 템플릿 + 저장 ✅",[57,12790,12791],{},"3-14 실제 API 연동 ⚪",[57,12793,12794],{},"3-15 Q&A 평가 워크플로 페이지 ⚪",[24,12796,12797,3360],{},[28,12798,12799],{},"횡단 운영 도구 섹션 신규",[54,12801,12802],{},[57,12803,12804],{},"일괄 배포 스크립트 \u002F 일단위 이력 \u002F 다중 계정 Cloudflare \u002F Pages 배포 표준 \u002F 작성자 분류 규칙 — 모두 ✅",[24,12806,12807,3360],{},[28,12808,12809],{},"다음 단계 우선순위 제안 (6건)",[1925,12811,12812,12815,12818,12821,12824,12827],{},[57,12813,12814],{},"P1-3-1 DB 구축",[57,12816,12817],{},"P1-2-4 데이터 설계",[57,12819,12820],{},"P1-3-6 API 개발 (1차)",[57,12822,12823],{},"P1-3-14 PMS ↔ API 실연동",[57,12825,12826],{},"P1-2-6 AI 프로토타입",[57,12828,12829],{},"P1-3-15 Q&A 평가 워크플로 페이지",[215,12831,12833],{"id":12832},"_2-진행률-현황-산정","2. 진행률 현황 산정",[24,12835,12836],{},"각 단계별로 어제까지 누적된 작업을 환산:",[135,12838,12839,12849],{},[138,12840,12841],{},[141,12842,12843,12846],{},[144,12844,12845],{},"Phase 1 단계",[144,12847,12848],{},"진행률",[157,12850,12851,12859,12867,12875,12883,12891],{},[141,12852,12853,12856],{},[162,12854,12855],{},"착수\u002F분석",[162,12857,12858],{},"70% (요구사항만 미완)",[141,12860,12861,12864],{},[162,12862,12863],{},"설계",[162,12865,12866],{},"40% (데이터 설계·AI PoC 미진)",[141,12868,12869,12872],{},[162,12870,12871],{},"구현",[162,12873,12874],{},"25% (보일러플레이트+PMS 데모만, API·DB·관리자 본격 미진)",[141,12876,12877,12880],{},[162,12878,12879],{},"교육·연동",[162,12881,12882],{},"10% (배포 스크립트·이력 시스템)",[141,12884,12885,12888],{},[162,12886,12887],{},"테스트",[162,12889,12890],{},"0%",[141,12892,12893,12896],{},[162,12894,12895],{},"이행",[162,12897,12898],{},"5% (보일러플레이트 첫 배포만)",[21,12900,12901],{},[24,12902,12903],{},"M1 인프라 Ready 게이트 직전. 다음 6개 작업 완료 시 M2(자료 수집) 진입.",[215,12905,12907,12908,12911],{"id":12906},"_2-malgn-helper-pms에-wbs-진행-현황-페이지-신규","2. malgn-helper-pms에 ",[16,12909,12910],{},"\u002Fwbs"," 진행 현황 페이지 신규",[24,12913,12914,12915,12917],{},"WBS.md 내용을 시각화한 페이지. 메인 페이지(",[16,12916,530],{},")에서 우상단 링크로 진입.",[24,12919,12920,3360],{},[28,12921,12922],{},"섹션 구성",[54,12924,12925,12928,12934,12940,12945,12956,12962,12967],{},[57,12926,12927],{},"헤더 — WBS 배지 + 마지막 현행화 일자",[57,12929,12930,12933],{},[28,12931,12932],{},"가중평균 진행률"," 큰 숫자 + 게이지 바 (Phase 1 6단계 가중 계산)",[57,12935,12936,12939],{},[28,12937,12938],{},"단계별 진행률"," 6개 카드 (각 단계 ID·이름·비중·진행률·요약 + 게이지)",[57,12941,12942,12944],{},[28,12943,12721],{}," 4 카드 (인프라\u002F문서\u002FPMS 데모\u002F운영 정책 + 진행률·항목 리스트)",[57,12946,12947,12950,12951],{},[28,12948,12949],{},"Phase 1 작업 상세"," — 6개 접기\u002F펴기 details 블록 (진행 중인 단계는 기본 펼침)\n",[54,12952,12953],{},[57,12954,12955],{},"각 작업 항목 한 줄: ID · 제목 · 비고 · 상태 배지(✅\u002F🟢\u002F⚪\u002F⛔)",[57,12957,12958,12961],{},[28,12959,12960],{},"다음 단계 우선순위 6건"," 카드",[57,12963,12964,12966],{},[28,12965,3088],{}," placeholder (모두 대기)",[57,12968,12969],{},"푸터에 WBS.md \u002F history\u002F 원본 링크",[24,12971,12972,3360],{},[28,12973,12974],{},"디자인 토큰",[54,12976,12977,12980,12983],{},[57,12978,12979],{},"상태 배지: emerald(done) · amber(in_progress) · neutral(pending) · rose(blocked)",[57,12981,12982],{},"게이지 색상: 70%+ emerald · 30%+ amber · 0%+ neutral",[57,12984,12985],{},"카드: rounded-lg border-neutral-200 bg-white p-4 (브리핑\u002FQA 카드와 일관)",[24,12987,12988,12991],{},[28,12989,12990],{},"데이터",": 현재 WBS.md를 미러링한 TypeScript 인라인. 추후 빌드 타임 마크다운 파싱으로 자동화 검토.",[24,12993,12994,12995],{},"배포 URL: ",[3257,12996,12676],{"href":12676,"rel":12997},[5049],[215,12999,13001],{"id":13000},"_3-wbs-데이터-저장소를-json-정적-파일로-결정","3. WBS 데이터 저장소를 JSON 정적 파일로 결정",[24,13003,13004,13007,13008,407],{},[28,13005,13006],{},"경위",": WBS 영속화를 위해 D1 DB를 한 차례 시도(생성·바인딩·CRUD 엔드포인트·CORS까지 구현 완료) 했으나, 사용자 결정으로 ",[28,13009,13010],{},"정적 JSON 공유 방식으로 전환",[24,13012,13013,4664,13016],{},[28,13014,13015],{},"최종 채택",[16,13017,13018],{},"malgn-helper-pms\u002Fpublic\u002Fwbs.json",[54,13020,13021,13028,13035],{},[57,13022,13023,13024,13027],{},"파일 1개. 편집 후 ",[16,13025,13026],{},".\u002Fscripts\u002Fdeploy.sh malgn-helper-pms ..."," 한 번이면 배포·공유 완료",[57,13029,13030,13031,13034],{},"공개 URL ",[16,13032,13033],{},"https:\u002F\u002Fmalgn-helper-pms.pages.dev\u002Fwbs.json"," 으로 다른 시스템에서도 fetch 가능 (CORS 별도 설정 불요)",[57,13036,13037],{},"DB·런타임 의존 없음 → 장애 영향 0",[24,13039,13040,3360],{},[28,13041,13042],{},"롤백 \u002F 정리",[54,13044,13045,13054,13059,13065],{},[57,13046,13047,4841,13050,13053],{},[16,13048,13049],{},"malgn-helper-api\u002Fwrangler.jsonc",[16,13051,13052],{},"d1_databases"," 바인딩 제거",[57,13055,13056,13058],{},[16,13057,10130],{},"를 원래 형태(hello + healthz)로 환원",[57,13060,13061,13064],{},[16,13062,13063],{},"migrations\u002F"," 폴더 삭제",[57,13066,13067,13068,105,13071,13074,13075,13078],{},"D1 DB 자체는 Cloudflare에 잔존 (",[16,13069,13070],{},"malgn-helper-wbs",[16,13072,13073],{},"558d397e-…",") — 사용 안함. 추후 ",[16,13076,13077],{},"wrangler d1 delete malgn-helper-wbs"," 가능",[24,13080,13081,3360],{},[28,13082,13083],{},"JSON 스키마",[415,13085,13089],{"className":13086,"code":13087,"language":13088,"meta":423,"style":423},"language-jsonc shiki shiki-themes github-light github-dark","{\n  \"_meta\": { \"lastUpdated\": \"2026-05-29\", \"project\": \"...\", \"source\": \"...\", \"editGuide\": \"...\" },\n  \"phase1\": {\n    \"stages\": [\n      {\n        \"id\": \"P1-1\", \"name\": \"...\", \"weight\": 10, \"progress\": 70, \"summary\": \"...\",\n        \"tasks\": [\n          { \"id\": \"P1-1-1\", \"taskNo\": \"1-1\", \"title\": \"...\",\n            \"status\": \"done|in_progress|pending|blocked\",\n            \"note\": \"...\", \"targetDate\": \"YYYY-MM-DD\", \"completionDate\": \"YYYY-MM-DD\" }\n        ]\n      }\n    ]\n  }\n}\n","jsonc",[16,13090,13091,13096,13101,13106,13111,13116,13121,13126,13131,13136,13141,13146,13151,13156,13160],{"__ignoreMap":423},[2166,13092,13093],{"class":3301,"line":3302},[2166,13094,13095],{},"{\n",[2166,13097,13098],{"class":3301,"line":3335},[2166,13099,13100],{},"  \"_meta\": { \"lastUpdated\": \"2026-05-29\", \"project\": \"...\", \"source\": \"...\", \"editGuide\": \"...\" },\n",[2166,13102,13103],{"class":3301,"line":3342},[2166,13104,13105],{},"  \"phase1\": {\n",[2166,13107,13108],{"class":3301,"line":3368},[2166,13109,13110],{},"    \"stages\": [\n",[2166,13112,13113],{"class":3301,"line":3396},[2166,13114,13115],{},"      {\n",[2166,13117,13118],{"class":3301,"line":3426},[2166,13119,13120],{},"        \"id\": \"P1-1\", \"name\": \"...\", \"weight\": 10, \"progress\": 70, \"summary\": \"...\",\n",[2166,13122,13123],{"class":3301,"line":3463},[2166,13124,13125],{},"        \"tasks\": [\n",[2166,13127,13128],{"class":3301,"line":3504},[2166,13129,13130],{},"          { \"id\": \"P1-1-1\", \"taskNo\": \"1-1\", \"title\": \"...\",\n",[2166,13132,13133],{"class":3301,"line":3538},[2166,13134,13135],{},"            \"status\": \"done|in_progress|pending|blocked\",\n",[2166,13137,13138],{"class":3301,"line":3550},[2166,13139,13140],{},"            \"note\": \"...\", \"targetDate\": \"YYYY-MM-DD\", \"completionDate\": \"YYYY-MM-DD\" }\n",[2166,13142,13143],{"class":3301,"line":3556},[2166,13144,13145],{},"        ]\n",[2166,13147,13148],{"class":3301,"line":5367},[2166,13149,13150],{},"      }\n",[2166,13152,13153],{"class":3301,"line":5375},[2166,13154,13155],{},"    ]\n",[2166,13157,13158],{"class":3301,"line":5392},[2166,13159,5456],{},[2166,13161,13162],{"class":3301,"line":5404},[2166,13163,3559],{},[215,13165,13167],{"id":13166},"_4-wbs-페이지에-목표일완료일-컬럼-추가","4. \u002Fwbs 페이지에 목표일·완료일 컬럼 추가",[24,13169,13170],{},"페이지 본문의 작업 상세를 표 구조로 변경:",[135,13172,13173],{},[138,13174,13175],{},[141,13176,13177,13180,13183,13186,13189],{},[144,13178,13179],{},"ID",[144,13181,13182],{},"작업",[144,13184,13185],{},"목표일",[144,13187,13188],{},"완료일",[144,13190,7333],{},[54,13192,13193,13206,13213,13219],{},[57,13194,13195,13197,13198,105,13200,1305,13203,78],{},[28,13196,13185],{}," — 미설정 시 ",[16,13199,538],{},[28,13201,13202],{},"지난 미완료는 빨강 강조",[16,13204,13205],{},"text-rose-600 font-semibold",[57,13207,13208,13210,13211],{},[28,13209,13188],{}," — 완료된 경우 emerald, 그 외 ",[16,13212,538],{},[57,13214,13215,13218],{},[16,13216,13217],{},"useFetch('\u002Fwbs.json')"," 로 동기 로드, 로딩·에러 상태 표시",[57,13220,13221,13222,13225],{},"헤더·푸터에 ",[16,13223,13224],{},"\u002Fwbs.json"," 링크 노출 (외부 시스템 임베드 가이드)",[36,13227,11529],{"id":11529},[215,13229,13231,13232,11554],{"id":13230},"_0834-malgn-helper-pms-cloudflare-pages","08:34 — ",[16,13233,4588],{},[54,13235,13236,13241],{},[57,13237,11541,13238,11561],{},[16,13239,13240],{},"b803162",[57,13242,13243],{},"메시지: feat: \u002Fwbs 진행 현황 페이지 + 인덱스 링크",[215,13245,13247,13248,11536],{"id":13246},"_0840-malgn-helper-api-cloudflare-workers","08:40 — ",[16,13249,4404],{},[54,13251,13252,13257],{},[57,13253,11541,13254,11561],{},[16,13255,13256],{},"f29e575",[57,13258,13259],{},"메시지: feat: D1(malgn-helper-wbs) 바인딩 + \u002Fwbs CRUD 엔드포인트 + CORS",[215,13261,13263,13264,11536],{"id":13262},"_0846-malgn-helper-api-cloudflare-workers","08:46 — ",[16,13265,4404],{},[54,13267,13268,13273],{},[57,13269,11541,13270,11561],{},[16,13271,13272],{},"d177b29",[57,13274,13275],{},"메시지: revert: D1 제거 (WBS는 JSON 정적 파일로 전환)",[215,13277,13263,13279,11554],{"id":13278},"_0846-malgn-helper-pms-cloudflare-pages",[16,13280,4588],{},[54,13282,13283,13288],{},[57,13284,11541,13285,11561],{},[16,13286,13287],{},"5eda3a4",[57,13289,13290],{},"메시지: feat: WBS를 정적 JSON(\u002Fwbs.json)으로 전환 + 목표일·완료일 컬럼 추가",[215,13292,13294,13295,11554],{"id":13293},"_0851-malgn-helper-pms-cloudflare-pages","08:51 — ",[16,13296,4588],{},[54,13298,13299,13304],{},[57,13300,11541,13301,11561],{},[16,13302,13303],{},"a8bd1cb",[57,13305,13306],{},"메시지: fix: \u002Fwbs 페이지의 wbs.json fetch를 client-only로 (SSR 404 회피)",[215,13308,13310,13311,11554],{"id":13309},"_0858-malgn-helper-pms-cloudflare-pages","08:58 — ",[16,13312,4588],{},[54,13314,13315,13320],{},[57,13316,11541,13317,11561],{},[16,13318,13319],{},"81031f3",[57,13321,13322],{},"메시지: feat: WBS 산출물 URL 컬럼·인라인 편집·JSON 복사 (localStorage 임시 저장)",[215,13324,13326,13327,11554],{"id":13325},"_0905-malgn-helper-pms-cloudflare-pages","09:05 — ",[16,13328,4588],{},[54,13330,13331,13336],{},[57,13332,11541,13333,11561],{},[16,13334,13335],{},"c75d600",[57,13337,13338],{},"메시지: redesign(\u002Fwbs): Editorial Blueprint — Instrument Serif 이탤릭 + JetBrains Mono + 따뜻한 크림지 + 안전 오렌지 액센트 + 플로팅 편집바",[215,13340,13342,13343,11554],{"id":13341},"_0913-malgn-helper-pms-cloudflare-pages","09:13 — ",[16,13344,4588],{},[54,13346,13347,13352],{},[57,13348,11541,13349,11561],{},[16,13350,13351],{},"42a259f",[57,13353,13354],{},"메시지: redesign(\u002Fwbs): Terminal\u002FIDE — GitHub Dark Dimmed + JetBrains Mono + 탭바·라인거터·상태바",[215,13356,13358,13359,11554],{"id":13357},"_0918-malgn-helper-pms-cloudflare-pages","09:18 — ",[16,13360,4588],{},[54,13362,13363,13368],{},[57,13364,11541,13365,11561],{},[16,13366,13367],{},"21b172c",[57,13369,13370],{},"메시지: redesign(\u002Fwbs): Soft SaaS (Notion\u002FLinear 풍) — 라이트 + Pretendard + 부드러운 모서리·여백",[215,13372,13374,13375,11554],{"id":13373},"_0921-malgn-helper-pms-cloudflare-pages","09:21 — ",[16,13376,4588],{},[54,13378,13379,13384],{},[57,13380,11541,13381,11561],{},[16,13382,13383],{},"5460422",[57,13385,13386],{},"메시지: tweak(\u002Fwbs): 전체 폰트 사이즈 +1px (가독성)",[215,13388,13390,13391,11554],{"id":13389},"_0924-malgn-helper-pms-cloudflare-pages","09:24 — ",[16,13392,4588],{},[54,13394,13395,13400],{},[57,13396,11541,13397,11561],{},[16,13398,13399],{},"e704617",[57,13401,13402],{},"메시지: tweak(\u002Fwbs): 전체 폰트 -1px (이전 +1 환원)",[215,13404,13406,13407,11554],{"id":13405},"_0929-malgn-helper-pms-cloudflare-pages","09:29 — ",[16,13408,4588],{},[54,13410,13411,13416],{},[57,13412,11541,13413,11561],{},[16,13414,13415],{},"8f64bed",[57,13417,13418,13419,13422],{},"메시지: tweak(\u002Fwbs): 목표일·완료일 input",[2166,13420,13421],{},"type=date"," 편집 + 컬럼 너비 키움 + 상태 nowrap + URL -1px",[215,13424,13426,13427,11536],{"id":13425},"_0946-malgn-helper-api-cloudflare-workers","09:46 — ",[16,13428,4404],{},[54,13430,13431,13436],{},[57,13432,11541,13433,11561],{},[16,13434,13435],{},"25de7c4",[57,13437,13438],{},"메시지: feat: \u002Fwbs GET·PUT (R2 자동저장) + CORS",[215,13440,13442,13443,11554],{"id":13441},"_0950-malgn-helper-pms-cloudflare-pages","09:50 — ",[16,13444,4588],{},[54,13446,13447,13452],{},[57,13448,11541,13449,11561],{},[16,13450,13451],{},"3ce38a9",[57,13453,13454],{},"메시지: feat(\u002Fwbs): API(R2) 자동저장 — 800ms debounce + 저장 상태 표시 + status 인라인 select",[215,13456,13458,13459,11554],{"id":13457},"_1009-malgn-helper-pms-cloudflare-pages","10:09 — ",[16,13460,4588],{},[54,13462,13463,13468],{},[57,13464,11541,13465,11561],{},[16,13466,13467],{},"ce94486",[57,13469,13470],{},"메시지: fix(\u002Fwbs): 가중평균 수식 보정 + stage weight 합 100 정규화 (0.2% → 24.2%)",[215,13472,13474,13475,11554],{"id":13473},"_1019-malgn-helper-pms-cloudflare-pages","10:19 — ",[16,13476,4588],{},[54,13478,13479,13484],{},[57,13480,11541,13481,11561],{},[16,13482,13483],{},"e341642",[57,13485,13486],{},"메시지: chore(\u002Fwbs): PMS 스토리보드 5건을 P1-2(설계) 하위로 재배치 (id·taskNo 압축)",[215,13488,13490,13491,11536],{"id":13489},"_1037-malgn-helper-api-cloudflare-workers","10:37 — ",[16,13492,4404],{},[54,13494,13495,13500],{},[57,13496,11541,13497,11561],{},[16,13498,13499],{},"acac93e",[57,13501,13502],{},"메시지: feat: Hyperdrive(pms) 바인딩 + GET \u002Fdb\u002Fping (mysql2)",[215,13504,13506,13507,11536],{"id":13505},"_1045-malgn-helper-api-cloudflare-workers","10:45 — ",[16,13508,4404],{},[54,13510,13511,13516],{},[57,13512,11541,13513,11561],{},[16,13514,13515],{},"36ef602",[57,13517,13518],{},"메시지: feat: PMS 연동 GET \u002Fpms\u002Fposts\u002F:id — 직원\u002F고객 분류 + 비공개 댓글 마스킹 + 탐색용 \u002Fdb\u002F* 엔드포인트",[215,13520,13522,13523,11554],{"id":13521},"_1052-malgn-helper-pms-cloudflare-pages","10:52 — ",[16,13524,4588],{},[54,13526,13527,13532],{},[57,13528,11541,13529,11561],{},[16,13530,13531],{},"eadcbd2",[57,13533,13534],{},"메시지: feat: BriefingCard 실 API 연동 — generateBriefing()이 \u002Fpms\u002Fprojects\u002F:id\u002Fbriefing 호출 (P1-2-7 스토리보드 → 실서비스)",[215,13536,13538,13539,11536],{"id":13537},"_1053-malgn-helper-api-cloudflare-workers","10:53 — ",[16,13540,4404],{},[54,13542,13543,13548],{},[57,13544,11541,13545,11561],{},[16,13546,13547],{},"615204f",[57,13549,13550],{},"메시지: feat: GET \u002Fpms\u002Fprojects\u002F:id\u002Fbriefing — 멤버\u002F통계\u002F라벨\u002F알림 집계 (LLM 영역 제외)",[215,13552,13554,13555,11554],{"id":13553},"_1059-malgn-helper-pms-cloudflare-pages","10:59 — ",[16,13556,4588],{},[54,13558,13559,13564],{},[57,13560,11541,13561,11561],{},[16,13562,13563],{},"04f41d0",[57,13565,13566],{},"메시지: feat: \u002Fprojects 프로젝트 목록 페이지 (검색·페이지네이션·최근활동)",[215,13568,13570,13571,11536],{"id":13569},"_1100-malgn-helper-api-cloudflare-workers","11:00 — ",[16,13572,4404],{},[54,13574,13575,13580],{},[57,13576,11541,13577,11561],{},[16,13578,13579],{},"e8f5d31",[57,13581,13582],{},"메시지: feat: GET \u002Fpms\u002Fprojects?q=&limit=&offset= 목록 + 검색 + 카운트",[215,13584,13586,13587,11536],{"id":13585},"_1104-malgn-helper-api-cloudflare-workers","11:04 — ",[16,13588,4404],{},[54,13590,13591,13596],{},[57,13592,11541,13593,11561],{},[16,13594,13595],{},"778453c",[57,13597,13598],{},"메시지: fix(\u002Fpms\u002Fprojects): id > 0 조건 추가 (시스템\u002F임시 row 제외)",[215,13600,13602,13603,11536],{"id":13601},"_1115-malgn-helper-api-cloudflare-workers","11:15 — ",[16,13604,4404],{},[54,13606,13607,13612],{},[57,13608,11541,13609,11561],{},[16,13610,13611],{},"d28a282",[57,13613,13614],{},"메시지: feat: \u002Fdoc API 문서 페이지 (Scalar + OpenAPI 3.1)",[215,13616,13618,13619,11536],{"id":13617},"_1131-malgn-helper-api-cloudflare-workers","11:31 — ",[16,13620,4404],{},[54,13622,13623,13628],{},[57,13624,11541,13625,11544],{},[16,13626,13627],{},"d7ce674",[57,13629,13630],{},"메시지: chore: migrate-hp-tables 일회용 엔드포인트 제거 (4테이블 생성 완료)",[215,13632,13634,13635,11554],{"id":13633},"_1137-malgn-helper-pms-cloudflare-pages","11:37 — ",[16,13636,4588],{},[54,13638,13639,13644],{},[57,13640,11541,13641,11561],{},[16,13642,13643],{},"e1d8d20",[57,13645,13646],{},"메시지: feat: BriefingCard generateBriefing()을 POST ...\u002Fgenerate로 전환 (서버 id 사용)",[215,13648,13650,13651,11536],{"id":13649},"_1138-malgn-helper-api-cloudflare-workers","11:38 — ",[16,13652,4404],{},[54,13654,13655,13660],{},[57,13656,11541,13657,11561],{},[16,13658,13659],{},"4bab4d2",[57,13661,13662],{},"메시지: feat: POST \u002Fbriefing\u002Fgenerate + 캐시·로깅 (hp_briefing, hp_llm_log) + 목록\u002F단건\u002F삭제 + OpenAPI 갱신",[215,13664,13666,13667,11554],{"id":13665},"_1144-malgn-helper-pms-cloudflare-pages","11:44 — ",[16,13668,4588],{},[54,13670,13671,13676],{},[57,13672,11541,13673,11561],{},[16,13674,13675],{},"b724b9f",[57,13677,13678],{},"메시지: feat: QaEvalCard 저장 버튼을 POST \u002Fstandard-answers로 실연동 (localStorage → hp_standard_answer)",[215,13680,13666,13682,11536],{"id":13681},"_1144-malgn-helper-api-cloudflare-workers",[16,13683,4404],{},[54,13685,13686,13691],{},[57,13687,11541,13688,11561],{},[16,13689,13690],{},"5ee2608",[57,13692,13693],{},"메시지: feat: \u002Fstandard-answers CRUD + \u002Fuse + OpenAPI (hp_standard_answer)",[215,13695,13697,13698,11536],{"id":13696},"_1155-malgn-helper-api-cloudflare-workers","11:55 — ",[16,13699,4404],{},[54,13701,13702,13707],{},[57,13703,11541,13704,11561],{},[16,13705,13706],{},"d0b91e8",[57,13708,13709],{},"메시지: feat: OpenAI 연동 인프라 — AI Gateway + LLM hotTopics + hp_llm_log 비용·토큰",[215,13711,13713,13714,11536],{"id":13712},"_1203-malgn-helper-api-cloudflare-workers","12:03 — ",[16,13715,4404],{},[54,13717,13718,13723],{},[57,13719,11541,13720,11561],{},[16,13721,13722],{},"ea13e0d",[57,13724,13725],{},"메시지: fix(llm): cost 계산이 model prefix(openai\u002F...)를 인식하도록 base 추출 + Gateway 토큰 헤더 지원",[215,13727,13729,13730,11554],{"id":13728},"_1214-malgn-helper-pms-cloudflare-pages","12:14 — ",[16,13731,4588],{},[54,13733,13734,13739],{},[57,13735,11541,13736,11561],{},[16,13737,13738],{},"d8a0197",[57,13740,13741],{},"메시지: feat(QaEvalCard): 실 API 연동 — POST \u002Fpms\u002Fposts\u002F:id\u002Feval\u002Fgenerate",[215,13743,13729,13745,11536],{"id":13744},"_1214-malgn-helper-api-cloudflare-workers",[16,13746,4404],{},[54,13748,13749,13754],{},[57,13750,11541,13751,11561],{},[16,13752,13753],{},"2368b29",[57,13755,13756],{},"메시지: feat: Q&A 평가 카드 LLM 연동 (5축 + templates + hp_qa_eval) + OpenAPI 4건 추가",[215,13758,13760,13761,11536],{"id":13759},"_1218-malgn-helper-api-cloudflare-workers","12:18 — ",[16,13762,4404],{},[54,13764,13765,13770],{},[57,13766,11541,13767,11561],{},[16,13768,13769],{},"e191511",[57,13771,13772],{},"메시지: feat: 브리핑 LLM 확장 — oneLiner\u002FstatusReason\u002Furgent\u002Ffaq\u002Fpolicies 채우기",[215,13774,13776,13777,11554],{"id":13775},"_1231-malgn-helper-pms-cloudflare-pages","12:31 — ",[16,13778,4588],{},[54,13780,13781,13786],{},[57,13782,11541,13783,11561],{},[16,13784,13785],{},"78d4873",[57,13787,13788],{},"메시지: feat: \u002Fadmin\u002Fcost LLM 비용·호출 대시보드 페이지",[215,13790,13776,13792,11536],{"id":13791},"_1231-malgn-helper-api-cloudflare-workers",[16,13793,4404],{},[54,13795,13796,13801],{},[57,13797,11541,13798,11561],{},[16,13799,13800],{},"60b6f30",[57,13802,13803],{},"메시지: feat: GET \u002Fadmin\u002Fcost — hp_llm_log 일·모델·엔티티 집계 + OpenAPI",[215,13805,13807,13808,11554],{"id":13806},"_1241-malgn-helper-pms-cloudflare-pages","12:41 — ",[16,13809,4588],{},[54,13811,13812,13817],{},[57,13813,11541,13814,11561],{},[16,13815,13816],{},"281ba35",[57,13818,13819],{},"메시지: feat: 홈에 \u002Fadmin\u002Fcost · \u002Fprojects · \u002Fwbs 진입 링크 노출",[215,13821,13807,13823,11536],{"id":13822},"_1241-malgn-helper-api-cloudflare-workers",[16,13824,4404],{},[54,13826,13827,13832],{},[57,13828,11541,13829,11561],{},[16,13830,13831],{},"845515f",[57,13833,13834],{},"메시지: perf: briefing LLM 2회 호출 병렬화 (Promise.allSettled) — 7s→3.5s",[215,13836,13838,13839,11554],{"id":13837},"_1246-malgn-helper-pms-cloudflare-pages","12:46 — ",[16,13840,4588],{},[54,13842,13843,13848],{},[57,13844,11541,13845,11561],{},[16,13846,13847],{},"b023aab",[57,13849,13850],{},"메시지: feat: \u002Fadmin\u002Fevals Q&A 평가 목록·정렬·필터 + 홈 링크 추가",[215,13852,13838,13854,11536],{"id":13853},"_1246-malgn-helper-api-cloudflare-workers",[16,13855,4404],{},[54,13857,13858,13863],{},[57,13859,11541,13860,11561],{},[16,13861,13862],{},"68c9bd6",[57,13864,13865],{},"메시지: feat: GET \u002Fadmin\u002Fevals (정렬·필터·post\u002Fproject JOIN) + OpenAPI",[215,13867,13869,13870,11554],{"id":13868},"_1249-malgn-helper-pms-cloudflare-pages","12:49 — ",[16,13871,4588],{},[54,13873,13874,13879],{},[57,13875,11541,13876,11561],{},[16,13877,13878],{},"014c513",[57,13880,13881],{},"메시지: tweak(home): 제목 '고객사 목록' → '맑은도우미 데모'",[215,13883,13885,13886,11536],{"id":13884},"_1254-malgn-helper-api-cloudflare-workers","12:54 — ",[16,13887,4404],{},[54,13889,13890,13895],{},[57,13891,11541,13892,11561],{},[16,13893,13894],{},"614dff7",[57,13896,13897],{},"메시지: chore(hp_qa_eval): overall_verdict VARCHAR(20→100) + trim 완화 + admin 엔드포인트 정리",[215,13899,13901,13902,11554],{"id":13900},"_1301-malgn-helper-pms-cloudflare-pages","13:01 — ",[16,13903,4588],{},[54,13905,13906,13911],{},[57,13907,11541,13908,11561],{},[16,13909,13910],{},"bbf380d",[57,13912,13913],{},"메시지: feat: \u002Fadmin\u002Fsuggestions 표준답변 후보 자동 추출 페이지 + evals\u002F홈 링크",[215,13915,13901,13917,11536],{"id":13916},"_1301-malgn-helper-api-cloudflare-workers",[16,13918,4404],{},[54,13920,13921,13926],{},[57,13922,11541,13923,11561],{},[16,13924,13925],{},"c4342d1",[57,13927,13928],{},"메시지: feat: POST \u002Fpms\u002Fprojects\u002F:id\u002Fstandard-answer-suggestions — LLM 패턴 추출 + OpenAPI",[215,13930,13932,13933,11554],{"id":13931},"_1311-malgn-helper-pms-cloudflare-pages","13:11 — ",[16,13934,4588],{},[54,13936,13937,13942],{},[57,13938,11541,13939,11561],{},[16,13940,13941],{},"a7de0f3",[57,13943,13944],{},"메시지: feat: AppHeader 공통 컴포넌트로 5개 페이지 상단 디자인 통일 + 현재 라우트 강조",[215,13946,13948,13949,11554],{"id":13947},"_1321-malgn-helper-pms-cloudflare-pages","13:21 — ",[16,13950,4588],{},[54,13952,13953,13958],{},[57,13954,11541,13955,11561],{},[16,13956,13957],{},"ad807cd",[57,13959,13960],{},"메시지: feat: 5개 admin 페이지 본문 톤을 메인·브리핑·QnA 카드와 통일 (UContainer\u002Fh1 text-3xl\u002F표 thead bg-neutral-50 uppercase tracking-wider\u002F카드 hover primary-500\u002F링 칩)",[215,13962,13964,13965,11536],{"id":13963},"_1325-malgn-helper-api-cloudflare-workers","13:25 — ",[16,13966,4404],{},[54,13968,13969,13974],{},[57,13970,11541,13971,11561],{},[16,13972,13973],{},"870fa16",[57,13975,13976],{},"메시지: feat(\u002Fpms\u002Fprojects): site_id=1 기본 필터 (?siteId=all로 우회 가능) + OpenAPI",[215,13978,13980,13981,11554],{"id":13979},"_1335-malgn-helper-pms-cloudflare-pages","13:35 — ",[16,13982,4588],{},[54,13984,13985,13990],{},[57,13986,11541,13987,11561],{},[16,13988,13989],{},"ed0e208",[57,13991,13992],{},"메시지: feat(\u002Fprojects): 그룹 컬럼 추가 (tb_project_group 매칭)",[215,13994,13980,13996,11536],{"id":13995},"_1335-malgn-helper-api-cloudflare-workers",[16,13997,4404],{},[54,13999,14000,14005],{},[57,14001,11541,14002,11561],{},[16,14003,14004],{},"0a0ef9a",[57,14006,14007],{},"메시지: feat(\u002Fpms\u002Fprojects): tb_project_group JOIN으로 groupName 반환 + OpenAPI",[215,14009,14011,14012,11554],{"id":14010},"_1341-malgn-helper-pms-cloudflare-pages","13:41 — ",[16,14013,4588],{},[54,14015,14016,14021],{},[57,14017,11541,14018,11561],{},[16,14019,14020],{},"7712afb",[57,14022,14023],{},"메시지: feat: \u002Fprojects 그룹 셀렉트 + \u002Fadmin\u002Fevals 그룹 인라인 칩",[215,14025,14011,14027,11536],{"id":14026},"_1341-malgn-helper-api-cloudflare-workers",[16,14028,4404],{},[54,14030,14031,14036],{},[57,14032,11541,14033,11561],{},[16,14034,14035],{},"71771f8",[57,14037,14038],{},"메시지: feat: GET \u002Fpms\u002Fgroups + \u002Fpms\u002Fprojects ?groupId + \u002Fadmin\u002Fevals groupName JOIN",[215,14040,14042,14043,11554],{"id":14041},"_1345-malgn-helper-pms-cloudflare-pages","13:45 — ",[16,14044,4588],{},[54,14046,14047,14052],{},[57,14048,11541,14049,11561],{},[16,14050,14051],{},"d7b8edc",[57,14053,14054],{},"메시지: fix(BriefingCard): 담당자\u002F보조 이름 표시 — UTooltip 제거하고 일반 span+title",[215,14056,14058,14059,11554],{"id":14057},"_1409-malgn-helper-pms-cloudflare-pages","14:09 — ",[16,14060,4588],{},[54,14062,14063,14068],{},[57,14064,11541,14065,11561],{},[16,14066,14067],{},"8b60916",[57,14069,14070],{},"메시지: fix(BriefingCard): 고객 primary\u002Fothers도 UTooltip 제거하여 이름 표시",[215,14072,14058,14074,11536],{"id":14073},"_1409-malgn-helper-api-cloudflare-workers",[16,14075,4404],{},[54,14077,14078,14083],{},[57,14079,11541,14080,11561],{},[16,14081,14082],{},"81b422f",[57,14084,14085],{},"메시지: feat(briefing): 180일 cutoff — 사람·FRT·미응답·긴급·알림은 180일 \u002F 누적·핫카테고리·FAQ·정책은 전체. statusLabel '휴면' 추가. extras LLM input에 RECENT_180 분리",[215,14087,14089,14090,11554],{"id":14088},"_1417-malgn-helper-pms-cloudflare-pages","14:17 — ",[16,14091,4588],{},[54,14093,14094,14099],{},[57,14095,11541,14096,11561],{},[16,14097,14098],{},"0874622",[57,14100,14101],{},"메시지: tweak(BriefingCard): 평균 FRT hint를 영업시간 안내로 (avgFRTNote)",[215,14103,14089,14105,11536],{"id":14104},"_1417-malgn-helper-api-cloudflare-workers",[16,14106,4404],{},[54,14108,14109,14114],{},[57,14110,11541,14111,11561],{},[16,14112,14113],{},"e8a7500",[57,14115,14116],{},"메시지: feat(FRT): 영업시간(KST 평일 9~17, 공휴일 제외) 기준 계산",[215,14118,14120,14121,11554],{"id":14119},"_1422-malgn-helper-pms-cloudflare-pages","14:22 — ",[16,14122,4588],{},[54,14124,14125,14130],{},[57,14126,11541,14127,11561],{},[16,14128,14129],{},"ce0aaec",[57,14131,14132],{},"메시지: tweak(BriefingCard): FRT hint를 avgFRTGrade로 (매우 빠름\u002F빠른 편\u002F보통\u002F느린 편\u002F응답 지연)",[215,14134,14120,14136,11536],{"id":14135},"_1422-malgn-helper-api-cloudflare-workers",[16,14137,4404],{},[54,14139,14140,14145],{},[57,14141,11541,14142,11561],{},[16,14143,14144],{},"afe3cbf",[57,14146,14147],{},"메시지: feat(briefing): avgFRTGrade 동적 등급 — 영업시간 분 기준 5단계",[215,14149,14151,14152,11536],{"id":14150},"_1425-malgn-helper-api-cloudflare-workers","14:25 — ",[16,14153,4404],{},[54,14155,14156,14161],{},[57,14157,11541,14158,11561],{},[16,14159,14160],{},"a0237f1",[57,14162,14163],{},"메시지: fix(timezone): PMS DB가 KST 기준 — mysql2 timezone='+09:00' + toIso에 +09:00 명시",[215,14165,14167,14168,11554],{"id":14166},"_1437-malgn-helper-pms-cloudflare-pages","14:37 — ",[16,14169,4588],{},[54,14171,14172,14177],{},[57,14173,11541,14174,11561],{},[16,14175,14176],{},"d5d5b59",[57,14178,14179],{},"메시지: feat(BriefingCard): 응대 통계 5칸으로(최근 180일 추가) + customer.primary name fallback 강화",[215,14181,14167,14183,11536],{"id":14182},"_1437-malgn-helper-api-cloudflare-workers",[16,14184,4404],{},[54,14186,14187,14192],{},[57,14188,11541,14189,11561],{},[16,14190,14191],{},"c7946dc",[57,14193,14194],{},"메시지: feat(briefing): stats.recent 180일 문의수 + customer 이름 fallback(email 로컬파트)",[215,14196,14198,14199,11554],{"id":14197},"_1445-malgn-helper-pms-cloudflare-pages","14:45 — ",[16,14200,4588],{},[54,14202,14203,14207],{},[57,14204,11541,14205,11544],{},[16,14206,14176],{},[57,14208,14209],{},"메시지: chore: BriefingCard 캐시 무효화 (협력사 분류 적용)",[215,14211,14198,14213,11536],{"id":14212},"_1445-malgn-helper-api-cloudflare-workers",[16,14214,4404],{},[54,14216,14217,14222],{},[57,14218,11541,14219,11561],{},[16,14220,14221],{},"f56abe5",[57,14223,14224,14225,14228],{},"메시지: feat: 협력사 분류 (PARTNER_WHITELIST=",[2166,14226,14227],{},"'플로즈'",") — customer.primary 후순위, partners 배열 신설",[215,14230,14232,14233,11554],{"id":14231},"_1447-malgn-helper-pms-cloudflare-pages","14:47 — ",[16,14234,4588],{},[54,14236,14237,14242],{},[57,14238,11541,14239,11561],{},[16,14240,14241],{},"6459da6",[57,14243,14244,14245,14247],{},"메시지: tweak(\u002Fprojects\u002F",[2166,14246,11737],{},"): 미니 통계 5칸으로 + 최근 180일 추가",[215,14249,14251,14252,11554],{"id":14250},"_1535-malgn-helper-pms-cloudflare-pages","15:35 — ",[16,14253,4588],{},[54,14255,14256,14261],{},[57,14257,11541,14258,11561],{},[16,14259,14260],{},"e62f2e5",[57,14262,14263],{},"메시지: feat(BriefingCard): 고객 응대 톤·태도 박스 추가 (customer.persona)",[215,14265,14251,14267,11536],{"id":14266},"_1535-malgn-helper-api-cloudflare-workers",[16,14268,4404],{},[54,14270,14271,14276],{},[57,14272,11541,14273,11561],{},[16,14274,14275],{},"520c200",[57,14277,14278],{},"메시지: feat(briefing): customerPersona LLM 추출 — 고객 메시지(180일, 비공개·직원·협력사 제외) 30건 분석",[215,14280,14282,14283,11536],{"id":14281},"_1550-malgn-helper-api-cloudflare-workers","15:50 — ",[16,14284,4404],{},[54,14286,14287,14292],{},[57,14288,11541,14289,11561],{},[16,14290,14291],{},"978f358",[57,14293,14294],{},"메시지: feat(briefing): statusLabel 5단계 enum + 미응답 임계값 룰 고정. LLM은 statusLabel·statusReason 출력 금지. urgentCount≥5만 긴급 격상",[215,14296,11854,14297,11554],{"id":11853},[16,14298,4588],{},[54,14300,14301,14306],{},[57,14302,11541,14303,11561],{},[16,14304,14305],{},"43f6582",[57,14307,14308],{},"메시지: feat(BriefingCard): 협력사 영역 + 상담사 톤·태도 + 직함 trim + 라벨 변경",[215,14310,11854,14312,11536],{"id":14311},"_1607-malgn-helper-api-cloudflare-workers",[16,14313,4404],{},[54,14315,14316,14321],{},[57,14317,11541,14318,11561],{},[16,14319,14320],{},"246b27c",[57,14322,14323],{},"메시지: feat(briefing): partners 분리 + staffPersona LLM 추출",[215,14325,14327,14328,11554],{"id":14326},"_1700-malgn-helper-pms-cloudflare-pages","17:00 — ",[16,14329,4588],{},[54,14331,14332,14337],{},[57,14333,11541,14334,11561],{},[16,14335,14336],{},"19a34e5",[57,14338,14339,14340,14342],{},"메시지: fix(\u002Fprojects\u002F",[2166,14341,11737],{},"): 헤더 메타를 API 단건 호출로 로드 (이름·발주처·그룹·마지막활동·상태)",[215,14344,14327,14346,11536],{"id":14345},"_1700-malgn-helper-api-cloudflare-workers",[16,14347,4404],{},[54,14349,14350,14355],{},[57,14351,11541,14352,11561],{},[16,14353,14354],{},"0cfe132",[57,14356,14357],{},"메시지: feat: GET \u002Fpms\u002Fprojects\u002F:id 단건 메타 엔드포인트",[215,14359,14361,14362,11554],{"id":14360},"_1705-malgn-helper-pms-cloudflare-pages","17:05 — ",[16,14363,4588],{},[54,14365,14366,14371],{},[57,14367,11541,14368,11561],{},[16,14369,14370],{},"5fd1550",[57,14372,14373],{},"메시지: fix(BriefingHistory): localStorage → 서버 fetch — 모든 브라우저에서 동일 데이터",[215,14375,14377,14378,11536],{"id":14376},"_1720-malgn-helper-api-cloudflare-workers","17:20 — ",[16,14379,4404],{},[54,14381,14382,14387],{},[57,14383,11541,14384,11561],{},[16,14385,14386],{},"4ea9760",[57,14388,14389],{},"메시지: perf(briefing): MySQL 부하 큰 폭 감소 — quick-check 캐시 + email LIKE → user_id IN",[215,14391,14393,14394,11536],{"id":14392},"_1748-malgn-helper-api-cloudflare-workers","17:48 — ",[16,14395,4404],{},[54,14397,14398,14403],{},[57,14399,11541,14400,11561],{},[16,14401,14402],{},"f77e24b",[57,14404,14405],{},"메시지: perf(briefing): members 쿼리 분리로 92s → 244ms (380배 단축, force=1 총 130s→10s) + timings 응답 노출",[215,14407,14409,14410,11536],{"id":14408},"_1752-malgn-helper-api-cloudflare-workers","17:52 — ",[16,14411,4404],{},[54,14413,14414,14419],{},[57,14415,11541,14416,11561],{},[16,14417,14418],{},"c0fddd8",[57,14420,14421],{},"메시지: fix(briefing): persona 없는 옛 캐시는 자동 폐기 후 재생성 + LLM 프롬프트에 persona 누락 금지 명시",[215,14423,14425,14426,11536],{"id":14424},"_1757-malgn-helper-api-cloudflare-workers","17:57 — ",[16,14427,4404],{},[54,14429,14430,14435],{},[57,14431,11541,14432,11561],{},[16,14433,14434],{},"4bdc3eb",[57,14436,14437],{},"메시지: feat(classify): 직원 룰에 tb_user.company='맑은소프트' 추가 (이메일 + 회사명 OR)",[215,14439,14441,14442,11536],{"id":14440},"_1759-malgn-helper-api-cloudflare-workers","17:59 — ",[16,14443,4404],{},[54,14445,14446,14451],{},[57,14447,11541,14448,11561],{},[16,14449,14450],{},"69256bb",[57,14452,14453],{},"메시지: fix(cors): allowMethods에 DELETE\u002FPATCH 추가 (브리핑·평가 삭제 실패 fix)",[215,14455,14457,14458,11554],{"id":14456},"_1805-malgn-helper-pms-cloudflare-pages","18:05 — ",[16,14459,4588],{},[54,14461,14462,14467],{},[57,14463,11541,14464,11561],{},[16,14465,14466],{},"25bcd37",[57,14468,14469],{},"메시지: tweak(BriefingCard): 협력사를 고객 영역 하단으로 + 두 persona를 사람 grid 밖 좌우 나란히",[215,14471,14473,14474,11554],{"id":14472},"_1810-malgn-helper-pms-cloudflare-pages","18:10 — ",[16,14475,4588],{},[54,14477,14478,14483],{},[57,14479,11541,14480,11561],{},[16,14481,14482],{},"64f8340",[57,14484,14485],{},"메시지: fix(BriefingHistory): v1 localStorage 자동 정리 (옛 캐시 잔존 → 삭제한 카드가 새로고침 시 다시 표시되던 문제)",[215,14487,14489,14490,11554],{"id":14488},"_1812-malgn-helper-pms-cloudflare-pages","18:12 — ",[16,14491,4588],{},[54,14493,14494,14499],{},[57,14495,11541,14496,11561],{},[16,14497,14498],{},"43dd327",[57,14500,14501],{},"메시지: tweak(BriefingCard): 헤더 제목 옆 statusLabel 칩 제거",[215,14503,14505,14506,11536],{"id":14504},"_1816-malgn-helper-api-cloudflare-workers","18:16 — ",[16,14507,4404],{},[54,14509,14510,14515],{},[57,14511,11541,14512,11561],{},[16,14513,14514],{},"268daca",[57,14516,14517],{},"메시지: feat(classify): PARTNER_WHITELIST에 '옐로우윈' 추가",[215,14519,14521,14522,11536],{"id":14520},"_1819-malgn-helper-api-cloudflare-workers","18:19 — ",[16,14523,4404],{},[54,14525,14526,14531],{},[57,14527,11541,14528,11561],{},[16,14529,14530],{},"4eab3f4",[57,14532,14533],{},"메시지: feat(classify): PARTNER_WHITELIST에 오케어\u002F송한나 추가",[215,14535,14537,14538,11536],{"id":14536},"_1820-malgn-helper-api-cloudflare-workers","18:20 — ",[16,14539,4404],{},[54,14541,14542,14547],{},[57,14543,11541,14544,11561],{},[16,14545,14546],{},"77969bf",[57,14548,14549],{},"메시지: fix(classify): '오케어' → '온케어' 오타 수정",[215,14551,14553,14554,11554],{"id":14552},"_1830-malgn-helper-pms-cloudflare-pages","18:30 — ",[16,14555,4588],{},[54,14557,14558,14563],{},[57,14559,11541,14560,11561],{},[16,14561,14562],{},"ab42ce6",[57,14564,14565],{},"메시지: feat: \u002Fprojects\u002F:id\u002Fposts 게시글 목록 페이지 + 진입 링크",[215,14567,14569,14570,11536],{"id":14568},"_1831-malgn-helper-api-cloudflare-workers","18:31 — ",[16,14571,4404],{},[54,14573,14574,14579],{},[57,14575,11541,14576,11561],{},[16,14577,14578],{},"5bffb41",[57,14580,14581],{},"메시지: feat: GET \u002Fpms\u002Fprojects\u002F:id\u002Fposts (검색·필터·페이지네이션 + 작성자 분류) + OpenAPI",[215,14583,14585,14586,11554],{"id":14584},"_1834-malgn-helper-pms-cloudflare-pages","18:34 — ",[16,14587,4588],{},[54,14589,14590,14595],{},[57,14591,11541,14592,11561],{},[16,14593,14594],{},"75b3e8e",[57,14596,14597],{},"메시지: fix(BriefingCard): '새 카드 생성' 버튼이 force=true로 호출 (캐시 hit 우회)",[215,14599,14601,14602,11554],{"id":14600},"_1835-malgn-helper-pms-cloudflare-pages","18:35 — ",[16,14603,4588],{},[54,14605,14606,14611],{},[57,14607,11541,14608,11561],{},[16,14609,14610],{},"2a4e75b",[57,14612,14613,14614,14616,14617,14619],{},"메시지: fix(routing): pages\u002Fprojects\u002F",[2166,14615,11737],{},".vue → ",[2166,14618,11737],{},"\u002Findex.vue (게시글 페이지로 이동 안 되던 문제)",[215,14621,14623,14624,11554],{"id":14622},"_1938-malgn-helper-pms-cloudflare-pages","19:38 — ",[16,14625,4588],{},[54,14627,14628,14633],{},[57,14629,11541,14630,11561],{},[16,14631,14632],{},"9e123e8",[57,14634,14635],{},"메시지: feat: \u002Fposts\u002F:id 게시물 상세 페이지 + 게시글 목록 행 클릭은 상세로 (평가는 별도)",[215,14637,14639,14640,11554],{"id":14638},"_1943-malgn-helper-pms-cloudflare-pages","19:43 — ",[16,14641,4588],{},[54,14643,14644,14649],{},[57,14645,11541,14646,11561],{},[16,14647,14648],{},"465d635",[57,14650,14651],{},"메시지: fix(posts): \u002Fdata\u002F 절대경로 이미지·링크에 ppm.malgn.co.kr 도메인 prefix",[215,14653,14655,14656,11554],{"id":14654},"_1950-malgn-helper-pms-cloudflare-pages","19:50 — ",[16,14657,4588],{},[54,14659,14660,14665],{},[57,14661,11541,14662,11561],{},[16,14663,14664],{},"6c66221",[57,14666,14667],{},"메시지: feat(posts): AI 문의 답변 분석을 게시물 페이지 모달로 + 분석 로딩 + Q&A HTML 렌더",[215,14669,14671,14672,11536],{"id":14670},"_1954-malgn-helper-api-cloudflare-workers","19:54 — ",[16,14673,4404],{},[54,14675,14676,14681],{},[57,14677,11541,14678,11561],{},[16,14679,14680],{},"fc5b701",[57,14682,14683],{},"메시지: feat(QaEval): D축 templates 6개로 확장 (1~3개 → 정확히 6개, maxTokens 1500→3000)",[215,14685,14687,14688,11554],{"id":14686},"_1957-malgn-helper-pms-cloudflare-pages","19:57 — ",[16,14689,4588],{},[54,14691,14692,14697],{},[57,14693,11541,14694,11561],{},[16,14695,14696],{},"43724ce",[57,14698,14699],{},"메시지: feat(QaEvalCard): '평가' 라벨 → '분석' + 더보기(...) 버튼을 삭제 버튼으로 교체 + 부모에서 DELETE 처리",[215,14701,14703,14704,11536],{"id":14702},"_2001-malgn-helper-api-cloudflare-workers","20:01 — ",[16,14705,4404],{},[54,14707,14708,14713],{},[57,14709,11541,14710,11561],{},[16,14711,14712],{},"2f3151b",[57,14714,14715],{},"메시지: feat(QaEval): D축 templates answer 형식·길이 가이드 강화 (인사+본문+마무리, 변형별 길이 명시)",[215,14717,14719,14720,11536],{"id":14718},"_2007-malgn-helper-api-cloudflare-workers","20:07 — ",[16,14721,4404],{},[54,14723,14724,14729],{},[57,14725,11541,14726,11561],{},[16,14727,14728],{},"6c185f3",[57,14730,14731],{},"메시지: feat(QaEval): templates answer를 HTML 허용 + 원본 이미지 그대로 포함 가이드",[215,14733,14719,14735,11554],{"id":14734},"_2007-malgn-helper-pms-cloudflare-pages",[16,14736,4588],{},[54,14738,14739,14744],{},[57,14740,11541,14741,11561],{},[16,14742,14743],{},"48d4fd1",[57,14745,14746],{},"메시지: feat(QaAxisCard): 답변을 HTML 렌더 + fixPmsHtml로 이미지·링크 도메인 처리",[215,14748,14750,14751,11536],{"id":14749},"_2010-malgn-helper-api-cloudflare-workers","20:10 — ",[16,14752,4404],{},[54,14754,14755,14760],{},[57,14756,11541,14757,11561],{},[16,14758,14759],{},"b37e9de",[57,14761,14762],{},"메시지: feat(QaEval): 원본 이미지 src 명시적 입력 + HTML 출력 강제 + 단계별 안내에 이미지 배치 가이드",[215,14764,14766,14767,11554],{"id":14765},"_2025-malgn-helper-pms-cloudflare-pages","20:25 — ",[16,14768,4588],{},[54,14770,14771,14776,14782],{},[57,14772,11541,14773,14775],{},[16,14774,14743],{}," 재배포 (신규 커밋: no — 사용자 브라우저의 옛 chunk hash 캐시 무효화용)",[57,14777,14778,14779],{},"배포: ",[16,14780,14781],{},"c9d9460e.malgn-helper-pms.pages.dev",[57,14783,14784],{},"메시지: (재배포) QaAxisCard 답변 HTML 렌더가 브라우저 캐시로 인해 plain text로 보이던 문제 — chunk hash 갱신",[215,14786,14788,14789,11536],{"id":14787},"_2040-malgn-helper-api-cloudflare-workers","20:40 — ",[16,14790,4404],{},[54,14792,14793,14804],{},[57,14794,14795,14796,14799,14800,14803],{},"배포: version ",[16,14797,14798],{},"e4c91fd1-fa0f-4906-9d52-71c0a88d8a2e"," (커밋은 21:10 ",[16,14801,14802],{},"1446679","에 일괄 포함)",[57,14805,14806],{},"메시지: feat(QaEval): followups 필드 제거 (LLM이 매번 빈 배열만 채워 \"후속 조치 0\" 빈 박스만 노출되던 문제) — schema·prompt·매핑·기본값 모두 제거",[215,14808,14810,14811,11554],{"id":14809},"_2042-malgn-helper-pms-cloudflare-pages","20:42 — ",[16,14812,4588],{},[54,14814,14815,14820,14825],{},[57,14816,11541,14817,11561],{},[16,14818,14819],{},"88910ba",[57,14821,14778,14822],{},[16,14823,14824],{},"bb78b5be.malgn-helper-pms.pages.dev",[57,14826,14827],{},"메시지: feat(QaEval): followups 섹션 제거 — QaEvalCard·clipboard·types·example 정리",[215,14829,14831,14832,11554],{"id":14830},"_2055-malgn-helper-pms-cloudflare-pages","20:55 — ",[16,14833,4588],{},[54,14835,14836,14841,14846],{},[57,14837,11541,14838,11561],{},[16,14839,14840],{},"60239a4",[57,14842,14778,14843],{},[16,14844,14845],{},"d8868fac.malgn-helper-pms.pages.dev",[57,14847,14848,14849,14851],{},"메시지: fix(posts): 분석 모달은 valid 결과 도착 후에만 열기 + Q&A 본문 초기 접기 — 빈 결과(axes=",[2166,14850],{},") 응답이 0점 모달로 보이던 문제 fix, 다시 시도 옵션 추가",[215,14853,14855,14856,11536],{"id":14854},"_2110-malgn-helper-api-cloudflare-workers","21:10 — ",[16,14857,4404],{},[54,14859,14860,14865,14880,14958],{},[57,14861,11541,14862,14864],{},[16,14863,14802],{}," (신규 커밋: yes — followups 제거·Vision·표준답변 컨텍스트·문단 분리 prompt·admin\u002Fevals 필터를 한 커밋에 통합)",[57,14866,14867,14868,1358,14871,1358,14874,1358,14877,78],{},"배포: 통산 4회 (",[16,14869,14870],{},"e4c91fd1",[16,14872,14873],{},"3893f30d",[16,14875,14876],{},"d9cb7e26",[16,14878,14879],{},"0b4c6b5a",[57,14881,14882,14883],{},"메시지: feat(QaEval): Vision 이미지 분석 + 표준답변 컨텍스트 + 문단 분리 prompt 강화\n",[54,14884,14885,14895,14923,14948],{},[57,14886,14887,14888,10238,14891,14894],{},"llm.ts: ",[16,14889,14890],{},"callOpenAiJson",[16,14892,14893],{},"images?: string[]"," 추가 (image_url multimodal). 이미지 있으면 자동 gpt-4o 업그레이드",[57,14896,14897,14898,14900,14901,14904,14905,14908,14909,14911,14912,14915,14916,14918,14919,14922],{},"eval\u002Fgenerate:\n· 원본 응답의 ",[16,14899,12285],{},"를 절대URL(",[16,14902,14903],{},"ppm.malgn.co.kr",")로 변환 후 Vision에 첨부 (최대 8장, ",[16,14906,14907],{},"detail=low",")\n· 같은 프로젝트의 ",[16,14910,2125],{}," 최근 5건을 톤·구조 참고 컨텍스트로 전달 (복붙 금지)\n· ",[16,14913,14914],{},"maxTokens"," 6000 → 8000, ",[16,14917,2788],{}," 0.2 → 0.3, ",[16,14920,14921],{},"timeoutMs"," 25s → 60s",[57,14924,14925,14928,14929,14936,14937,14939,14940,12309,14942,14944,14945,14947],{},[16,14926,14927],{},"QA_SYSTEM_PROMPT",":\n· 이미지 처리 규칙 — 이미지마다 ",[2166,14930,14931,14932,14935],{},"안내 1~2줄 + ",[16,14933,14934],{},"\u003Cimg>"," + 짧은 캡션(실제 메뉴\u002F버튼명 그대로)"," 묶음 강제\n· 문단 분리 강제 — 한 ",[16,14938,12304],{},"에 몰아넣지 말고 ",[2166,14941,12308],{},[16,14943,12304],{},"로. 변형별 최소 ",[16,14946,12304],{}," 수 명시",[57,14949,14950,14951,14954,14955,14957],{},"admin\u002Fevals: 기본 필터로 ",[16,14952,14953],{},"generator='hybrid' AND overall_score IS NOT NULL"," 강제 (db_only 폴백·빈 결과 행 숨김). ",[16,14956,12362],{},"로 전체 노출 가능",[57,14959,14960,14961,14964,14965,14968,14969,14972],{},"검증 (post 149512 \u002F id 24): 짧은 답변 ",[16,14962,14963],{},"\u003Cp>=4",", 긴 답변 ",[16,14966,14967],{},"\u003Cp>=6",", 단계별 안내 ",[16,14970,14971],{},"\u003Cp>=6 + \u003Col>=1 + \u003Cli>=3"," — 한 덩어리 텍스트 사라지고 의미 단위로 분리",[215,14974,14976,14977,11554],{"id":14975},"_2125-malgn-helper-pms-cloudflare-pages","21:25 — ",[16,14978,4588],{},[54,14980,14981,14986,14991],{},[57,14982,11541,14983,11561],{},[16,14984,14985],{},"8c794f7",[57,14987,14778,14988],{},[16,14989,14990],{},"4429f5b1.malgn-helper-pms.pages.dev",[57,14992,14993,14994,4859,14997,14999,15000,15002],{},"메시지: feat(admin\u002Fevals): 행 클릭 시 평가 카드 모달 즉시 열기 — ",[16,14995,14996],{},"$router.push",[16,14998,12356],{}," 호출 → ",[16,15001,2739],{}," 모달. 로딩 스피너 \u002F 빈 결과 에러 모달 \u002F 삭제·표준답변 저장 핸들러 추가",[4258,15004,8979],{},{"title":423,"searchDepth":3342,"depth":3342,"links":15006},[15007,15014,15015,15023],{"id":12034,"depth":3335,"text":12035,"children":15008},[15009,15010,15011,15012,15013],{"id":12382,"depth":3342,"text":12383},{"id":12476,"depth":3342,"text":12477},{"id":12550,"depth":3342,"text":12551},{"id":12595,"depth":3342,"text":12596},{"id":12633,"depth":3342,"text":12634},{"id":9923,"depth":3335,"text":9923},{"id":9933,"depth":3335,"text":9934,"children":15016},[15017,15018,15019,15021,15022],{"id":12699,"depth":3342,"text":12700},{"id":12832,"depth":3342,"text":12833},{"id":12906,"depth":3342,"text":15020},"2. malgn-helper-pms에 \u002Fwbs 진행 현황 페이지 신규",{"id":13000,"depth":3342,"text":13001},{"id":13166,"depth":3342,"text":13167},{"id":11529,"depth":3335,"text":11529,"children":15024},[15025,15027,15029,15031,15033,15035,15037,15039,15041,15043,15045,15047,15049,15051,15053,15055,15057,15059,15061,15063,15065,15067,15069,15071,15073,15075,15077,15079,15081,15083,15085,15087,15089,15091,15093,15095,15097,15099,15101,15103,15105,15107,15109,15111,15113,15115,15117,15119,15121,15123,15125,15127,15129,15131,15133,15135,15137,15139,15141,15143,15145,15147,15149,15151,15153,15155,15157,15159,15160,15162,15164,15166,15168,15170,15172,15174,15176,15178,15180,15182,15184,15186,15188,15190,15192,15194,15196,15198,15200,15202,15204,15206,15208,15210,15212,15214,15216,15218,15220,15222,15224,15226],{"id":13230,"depth":3342,"text":15026},"08:34 — malgn-helper-pms → Cloudflare Pages",{"id":13246,"depth":3342,"text":15028},"08:40 — malgn-helper-api → Cloudflare Workers",{"id":13262,"depth":3342,"text":15030},"08:46 — malgn-helper-api → Cloudflare Workers",{"id":13278,"depth":3342,"text":15032},"08:46 — malgn-helper-pms → Cloudflare Pages",{"id":13293,"depth":3342,"text":15034},"08:51 — malgn-helper-pms → Cloudflare Pages",{"id":13309,"depth":3342,"text":15036},"08:58 — malgn-helper-pms → Cloudflare Pages",{"id":13325,"depth":3342,"text":15038},"09:05 — malgn-helper-pms → Cloudflare Pages",{"id":13341,"depth":3342,"text":15040},"09:13 — malgn-helper-pms → Cloudflare Pages",{"id":13357,"depth":3342,"text":15042},"09:18 — malgn-helper-pms → Cloudflare Pages",{"id":13373,"depth":3342,"text":15044},"09:21 — malgn-helper-pms → Cloudflare Pages",{"id":13389,"depth":3342,"text":15046},"09:24 — malgn-helper-pms → Cloudflare Pages",{"id":13405,"depth":3342,"text":15048},"09:29 — malgn-helper-pms → Cloudflare Pages",{"id":13425,"depth":3342,"text":15050},"09:46 — malgn-helper-api → Cloudflare Workers",{"id":13441,"depth":3342,"text":15052},"09:50 — malgn-helper-pms → Cloudflare Pages",{"id":13457,"depth":3342,"text":15054},"10:09 — malgn-helper-pms → Cloudflare Pages",{"id":13473,"depth":3342,"text":15056},"10:19 — malgn-helper-pms → Cloudflare Pages",{"id":13489,"depth":3342,"text":15058},"10:37 — malgn-helper-api → Cloudflare Workers",{"id":13505,"depth":3342,"text":15060},"10:45 — malgn-helper-api → Cloudflare Workers",{"id":13521,"depth":3342,"text":15062},"10:52 — malgn-helper-pms → Cloudflare Pages",{"id":13537,"depth":3342,"text":15064},"10:53 — malgn-helper-api → Cloudflare Workers",{"id":13553,"depth":3342,"text":15066},"10:59 — malgn-helper-pms → Cloudflare Pages",{"id":13569,"depth":3342,"text":15068},"11:00 — malgn-helper-api → Cloudflare Workers",{"id":13585,"depth":3342,"text":15070},"11:04 — malgn-helper-api → Cloudflare Workers",{"id":13601,"depth":3342,"text":15072},"11:15 — malgn-helper-api → Cloudflare Workers",{"id":13617,"depth":3342,"text":15074},"11:31 — malgn-helper-api → Cloudflare Workers",{"id":13633,"depth":3342,"text":15076},"11:37 — malgn-helper-pms → Cloudflare Pages",{"id":13649,"depth":3342,"text":15078},"11:38 — malgn-helper-api → Cloudflare Workers",{"id":13665,"depth":3342,"text":15080},"11:44 — malgn-helper-pms → Cloudflare Pages",{"id":13681,"depth":3342,"text":15082},"11:44 — malgn-helper-api → Cloudflare Workers",{"id":13696,"depth":3342,"text":15084},"11:55 — malgn-helper-api → Cloudflare Workers",{"id":13712,"depth":3342,"text":15086},"12:03 — malgn-helper-api → Cloudflare Workers",{"id":13728,"depth":3342,"text":15088},"12:14 — malgn-helper-pms → Cloudflare Pages",{"id":13744,"depth":3342,"text":15090},"12:14 — malgn-helper-api → Cloudflare Workers",{"id":13759,"depth":3342,"text":15092},"12:18 — malgn-helper-api → Cloudflare Workers",{"id":13775,"depth":3342,"text":15094},"12:31 — malgn-helper-pms → Cloudflare Pages",{"id":13791,"depth":3342,"text":15096},"12:31 — malgn-helper-api → Cloudflare Workers",{"id":13806,"depth":3342,"text":15098},"12:41 — malgn-helper-pms → Cloudflare Pages",{"id":13822,"depth":3342,"text":15100},"12:41 — malgn-helper-api → Cloudflare Workers",{"id":13837,"depth":3342,"text":15102},"12:46 — malgn-helper-pms → Cloudflare Pages",{"id":13853,"depth":3342,"text":15104},"12:46 — malgn-helper-api → Cloudflare Workers",{"id":13868,"depth":3342,"text":15106},"12:49 — malgn-helper-pms → Cloudflare Pages",{"id":13884,"depth":3342,"text":15108},"12:54 — malgn-helper-api → Cloudflare Workers",{"id":13900,"depth":3342,"text":15110},"13:01 — malgn-helper-pms → Cloudflare Pages",{"id":13916,"depth":3342,"text":15112},"13:01 — malgn-helper-api → Cloudflare Workers",{"id":13931,"depth":3342,"text":15114},"13:11 — malgn-helper-pms → Cloudflare Pages",{"id":13947,"depth":3342,"text":15116},"13:21 — malgn-helper-pms → Cloudflare Pages",{"id":13963,"depth":3342,"text":15118},"13:25 — malgn-helper-api → Cloudflare Workers",{"id":13979,"depth":3342,"text":15120},"13:35 — malgn-helper-pms → Cloudflare Pages",{"id":13995,"depth":3342,"text":15122},"13:35 — malgn-helper-api → Cloudflare Workers",{"id":14010,"depth":3342,"text":15124},"13:41 — malgn-helper-pms → Cloudflare Pages",{"id":14026,"depth":3342,"text":15126},"13:41 — malgn-helper-api → Cloudflare Workers",{"id":14041,"depth":3342,"text":15128},"13:45 — malgn-helper-pms → Cloudflare Pages",{"id":14057,"depth":3342,"text":15130},"14:09 — malgn-helper-pms → Cloudflare Pages",{"id":14073,"depth":3342,"text":15132},"14:09 — malgn-helper-api → Cloudflare Workers",{"id":14088,"depth":3342,"text":15134},"14:17 — malgn-helper-pms → Cloudflare Pages",{"id":14104,"depth":3342,"text":15136},"14:17 — malgn-helper-api → Cloudflare Workers",{"id":14119,"depth":3342,"text":15138},"14:22 — malgn-helper-pms → Cloudflare Pages",{"id":14135,"depth":3342,"text":15140},"14:22 — malgn-helper-api → Cloudflare Workers",{"id":14150,"depth":3342,"text":15142},"14:25 — malgn-helper-api → Cloudflare Workers",{"id":14166,"depth":3342,"text":15144},"14:37 — malgn-helper-pms → Cloudflare Pages",{"id":14182,"depth":3342,"text":15146},"14:37 — malgn-helper-api → Cloudflare Workers",{"id":14197,"depth":3342,"text":15148},"14:45 — malgn-helper-pms → Cloudflare Pages",{"id":14212,"depth":3342,"text":15150},"14:45 — malgn-helper-api → Cloudflare Workers",{"id":14231,"depth":3342,"text":15152},"14:47 — malgn-helper-pms → Cloudflare Pages",{"id":14250,"depth":3342,"text":15154},"15:35 — malgn-helper-pms → Cloudflare Pages",{"id":14266,"depth":3342,"text":15156},"15:35 — malgn-helper-api → Cloudflare Workers",{"id":14281,"depth":3342,"text":15158},"15:50 — malgn-helper-api → Cloudflare Workers",{"id":11853,"depth":3342,"text":12010},{"id":14311,"depth":3342,"text":15161},"16:07 — malgn-helper-api → Cloudflare Workers",{"id":14326,"depth":3342,"text":15163},"17:00 — malgn-helper-pms → Cloudflare Pages",{"id":14345,"depth":3342,"text":15165},"17:00 — malgn-helper-api → Cloudflare Workers",{"id":14360,"depth":3342,"text":15167},"17:05 — malgn-helper-pms → Cloudflare Pages",{"id":14376,"depth":3342,"text":15169},"17:20 — malgn-helper-api → Cloudflare Workers",{"id":14392,"depth":3342,"text":15171},"17:48 — malgn-helper-api → Cloudflare Workers",{"id":14408,"depth":3342,"text":15173},"17:52 — malgn-helper-api → Cloudflare Workers",{"id":14424,"depth":3342,"text":15175},"17:57 — malgn-helper-api → Cloudflare Workers",{"id":14440,"depth":3342,"text":15177},"17:59 — malgn-helper-api → Cloudflare Workers",{"id":14456,"depth":3342,"text":15179},"18:05 — malgn-helper-pms → Cloudflare Pages",{"id":14472,"depth":3342,"text":15181},"18:10 — malgn-helper-pms → Cloudflare Pages",{"id":14488,"depth":3342,"text":15183},"18:12 — malgn-helper-pms → Cloudflare Pages",{"id":14504,"depth":3342,"text":15185},"18:16 — malgn-helper-api → Cloudflare Workers",{"id":14520,"depth":3342,"text":15187},"18:19 — malgn-helper-api → Cloudflare Workers",{"id":14536,"depth":3342,"text":15189},"18:20 — malgn-helper-api → Cloudflare Workers",{"id":14552,"depth":3342,"text":15191},"18:30 — malgn-helper-pms → Cloudflare Pages",{"id":14568,"depth":3342,"text":15193},"18:31 — malgn-helper-api → Cloudflare Workers",{"id":14584,"depth":3342,"text":15195},"18:34 — malgn-helper-pms → Cloudflare Pages",{"id":14600,"depth":3342,"text":15197},"18:35 — malgn-helper-pms → Cloudflare Pages",{"id":14622,"depth":3342,"text":15199},"19:38 — malgn-helper-pms → Cloudflare Pages",{"id":14638,"depth":3342,"text":15201},"19:43 — malgn-helper-pms → Cloudflare Pages",{"id":14654,"depth":3342,"text":15203},"19:50 — malgn-helper-pms → Cloudflare Pages",{"id":14670,"depth":3342,"text":15205},"19:54 — malgn-helper-api → Cloudflare Workers",{"id":14686,"depth":3342,"text":15207},"19:57 — malgn-helper-pms → Cloudflare Pages",{"id":14702,"depth":3342,"text":15209},"20:01 — malgn-helper-api → Cloudflare Workers",{"id":14718,"depth":3342,"text":15211},"20:07 — malgn-helper-api → Cloudflare Workers",{"id":14734,"depth":3342,"text":15213},"20:07 — malgn-helper-pms → Cloudflare Pages",{"id":14749,"depth":3342,"text":15215},"20:10 — malgn-helper-api → Cloudflare Workers",{"id":14765,"depth":3342,"text":15217},"20:25 — malgn-helper-pms → Cloudflare Pages",{"id":14787,"depth":3342,"text":15219},"20:40 — malgn-helper-api → Cloudflare Workers",{"id":14809,"depth":3342,"text":15221},"20:42 — malgn-helper-pms → Cloudflare Pages",{"id":14830,"depth":3342,"text":15223},"20:55 — malgn-helper-pms → Cloudflare Pages",{"id":14854,"depth":3342,"text":15225},"21:10 — malgn-helper-api → Cloudflare Workers",{"id":14975,"depth":3342,"text":15227},"21:25 — malgn-helper-pms → Cloudflare Pages",{},"\u002Fhistory\u002Fhistory.20260529",{"title":12026,"description":423},"history\u002Fhistory.20260529","XbhKTVJvYwuNzfcH93QGSc_6pzNQtAT9Y7oYOTsidzw",{"id":15234,"title":15235,"body":15236,"description":423,"extension":4340,"meta":15521,"navigation":3338,"path":15522,"seo":15523,"stem":15524,"__hash__":15525},"docs\u002Fhistory\u002Fhistory.20260601.md","작업 이력 — 2026-06-01",{"type":8,"value":15237,"toc":15512},[15238,15241,15245,15251,15323,15329,15434,15437,15440,15473,15479,15493,15497,15504],[11,15239,15235],{"id":15240},"작업-이력-2026-06-01",[36,15242,15244],{"id":15243},"문서-현행화","문서 현행화",[24,15246,15247,15248,15250],{},"5\u002F29 종일 진행된 다음 작업이 ",[3257,15249,10422],{"href":10421},"에 미반영 상태로 누적되어 일괄 현행화:",[54,15252,15253,15265,15275,15286,15300,15303,15306,15309,15318],{},[57,15254,15255,15256,15258,15259,15261,15262,15264],{},"인프라 활성화 (Hyperdrive ",[16,15257,12085],{}," · R2 ",[16,15260,12096],{}," · AI Gateway ",[16,15263,47],{}," Authenticated)",[57,15266,15267,15268,2855,15270,2855,15272,15274],{},"API 22+ 엔드포인트 (PMS 조회·브리핑·Q&A 평가·표준답변 CRUD·",[16,15269,104],{},[16,15271,108],{},[16,15273,3239],{}," OpenAPI)",[57,15276,15277,15278,2212,15280,2212,15282,2212,15284,78],{},"hp_* 4테이블 적용 (",[16,15279,2854],{},[16,15281,2858],{},[16,15283,2125],{},[16,15285,12177],{},[57,15287,15288,15289,1365,15291,15293,15294,15296,15297,15299],{},"LLM 실연동 (OpenAI ",[16,15290,4522],{},[16,15292,4526],{}," via AI Gateway, 24h ",[16,15295,2800],{}," 캐시, ",[16,15298,12177],{}," 감사)",[57,15301,15302],{},"PMS 신규 페이지 5종 + UX 폴리시 라운드 (분석 모달 valid 결과 후 표시·Q&A 본문 초기 접힘·빈 결과 \"다시 시도\"·followups 빈 섹션 제거)",[57,15304,15305],{},"LLM 품질 라운드 (GPT-4o Vision 이미지 분석 + 캡션 배치 · 표준답변 컨텍스트 첨부 · 4파트 답변 강제)",[57,15307,15308],{},"운영 정책 메모리 5건 (직원·협력사 분류 \u002F 브리핑 statusLabel 5단계 \u002F Hyperdrive read 캐시 stale \u002F PMS 스토리보드 식별 \u002F md 파일 doc\u002F 배치)",[57,15310,15311,15312,2855,15314,15317],{},"MySQL 부하 대책 (",[16,15313,11093],{},[16,15315,15316],{},"tb_post_comment"," 인덱스 추가 → 91s→244ms)",[57,15319,15320,15322],{},[16,15321,12606],{}," VARCHAR(20)→VARCHAR(100) 마이그레이션",[215,15324,15326,15328],{"id":15325},"wbsmd-갱신",[3257,15327,10422],{"href":10421}," 갱신",[135,15330,15331,15343],{},[138,15332,15333],{},[141,15334,15335,15337,15340],{},[144,15336,4143],{},[144,15338,15339],{"align":12394},"Before",[144,15341,15342],{"align":12394},"After",[157,15344,15345,15358,15371,15384,15397,15408,15421],{},[141,15346,15347,15350,15353],{},[162,15348,15349],{},"진행률 — 착수\u002F분석",[162,15351,15352],{"align":12394},"70%",[162,15354,15355],{"align":12394},[28,15356,15357],{},"95%",[141,15359,15360,15363,15366],{},[162,15361,15362],{},"진행률 — 설계",[162,15364,15365],{"align":12394},"40%",[162,15367,15368],{"align":12394},[28,15369,15370],{},"80%",[141,15372,15373,15376,15379],{},[162,15374,15375],{},"진행률 — 구현",[162,15377,15378],{"align":12394},"25%",[162,15380,15381],{"align":12394},[28,15382,15383],{},"65%",[141,15385,15386,15389,15392],{},[162,15387,15388],{},"진행률 — 교육·연동",[162,15390,15391],{"align":12394},"10%",[162,15393,15394],{"align":12394},[28,15395,15396],{},"35%",[141,15398,15399,15402,15404],{},[162,15400,15401],{},"진행률 — 테스트",[162,15403,12890],{"align":12394},[162,15405,15406],{"align":12394},[28,15407,15391],{},[141,15409,15410,15413,15416],{},[162,15411,15412],{},"진행률 — 이행",[162,15414,15415],{"align":12394},"5%",[162,15417,15418],{"align":12394},[28,15419,15420],{},"30%",[141,15422,15423,15426,15429],{},[162,15424,15425],{},"마지막 현행화",[162,15427,15428],{"align":12394},"2026-05-29",[162,15430,15431],{"align":12394},[28,15432,15433],{},"2026-06-01",[24,15435,15436],{},"표 안 모든 ID 산출물·비고 컬럼 갱신. P1-3-14·3-15 ✅ 전환. P1-3-16(UX 폴리시)·P1-3-17(LLM 품질) 신규 항목 추가.",[24,15438,15439],{},"\"다음 단계 우선순위\" 섹션을 M2(자료 수집 + 검색) 진입 기준으로 재작성:",[1925,15441,15442,15445,15450,15456,15461,15464,15467],{},[57,15443,15444],{},"OpenSearch 도메인 + 인덱스 매핑 (k-NN 1536d + BM25)",[57,15446,15447,15449],{},[16,15448,18],{}," 자료 업로드 MVP (R2 → 청크 → 임베딩 → 색인)",[57,15451,15452,15455],{},[16,15453,15454],{},"\u002Fchat"," 응답 파이프라인 (표준답변 우선 → 하이브리드 검색 → LLM + 출처 + \"모름\" 가드)",[57,15457,15458,15460],{},[16,15459,47],{}," 사용자 챗봇 UI",[57,15462,15463],{},"관리자 추가 화면 (표준답변 승인 · 상담 로그 · 에스컬레이션 큐)",[57,15465,15466],{},"OpenSearch 매핑·R2 키 규칙 문서화 (P1-2-4 잔여)",[57,15468,15469,15470,15472],{},"PMS UX 잔여 (",[16,15471,108],{}," LLM 행 즉시 모달 등)",[215,15474,15476,15328],{"id":15475},"hp-schemamd-갱신",[3257,15477,12455],{"href":15478},"..\u002FHP-SCHEMA",[54,15480,15481],{},[57,15482,15483,15485,15486,1358,15489,15492],{},[16,15484,12606],{}," 컬럼 정의·DDL 모두 ",[16,15487,15488],{},"VARCHAR(20)",[16,15490,15491],{},"VARCHAR(100)"," 반영 + 마이그레이션 일자(2026-05-29) 명시",[36,15494,15496],{"id":15495},"사용자-보고","사용자 보고",[24,15498,15499,15500,15503],{},"이력 확인 후 ",[28,15501,15502],{},"다음 작업 추천"," 제시:",[54,15505,15506,15509],{},[57,15507,15508],{},"(권장) OpenSearch + 자료 업로드 MVP 묶음 진행으로 챗봇 응답 파이프라인 데이터 채우기",[57,15510,15511],{},"또는 사용자 챗봇 UI \u002F 관리자 화면 \u002F PMS UX 폴리시 잔여 중 택일",{"title":423,"searchDepth":3342,"depth":3342,"links":15513},[15514,15520],{"id":15243,"depth":3335,"text":15244,"children":15515},[15516,15518],{"id":15325,"depth":3342,"text":15517},"WBS.md 갱신",{"id":15475,"depth":3342,"text":15519},"HP-SCHEMA.md 갱신",{"id":15495,"depth":3335,"text":15496},{},"\u002Fhistory\u002Fhistory.20260601",{"title":15235,"description":423},"history\u002Fhistory.20260601","22XKPTB4Vn2tl6I3f5-wgxKPx-yWZ8Pyaw1-gI2iVkM",{"id":15527,"title":15528,"body":15529,"description":423,"extension":4340,"meta":15994,"navigation":3338,"path":15995,"seo":15996,"stem":15997,"__hash__":15998},"docs\u002Fhistory\u002Fhistory.20260602.md","작업 이력 — 2026-06-02",{"type":8,"value":15530,"toc":15969},[15531,15534,15537,15540,15649,15653,15760,15762,15792,15796,15812,15814,15816,15822,15832,15838,15848,15854,15864,15870,15879,15883,15893,15899,15909,15915,15925,15931,15956,15960],[11,15532,15528],{"id":15533},"작업-이력-2026-06-02",[36,15535,15536],{"id":15536},"종합",[24,15538,15539],{},"다음 5가지 흐름이 하루에 진행:",[1925,15541,15542,15563,15573,15586,15632],{},[57,15543,15544,15547,15548,4708,15551,15554,15555,2855,15557,2855,15560,15562],{},[28,15545,15546],{},"WBS 페이지 다크모드 → 라이트 톤 강제"," — wbs.vue 단독 useColorMode override → nuxt.config 글로벌 colorMode → plugin으로 localStorage 덮어쓰기 → 최종적으로 ",[16,15549,15550],{},"main.css",[16,15552,15553],{},"body { background-color: #ffffff }","로 일원화 (관련 colorMode 코드는 모두 제거). 다른 3개 repo(",[16,15556,171],{},[16,15558,15559],{},"helper",[16,15561,12085],{},")도 nuxt.config 정리·일관성 적용.",[57,15564,15565,15568,15569,15572],{},[28,15566,15567],{},"QaEvalCard 구조 개편"," — \"추천 문의 답변\"을 D축(표준화 가능성) 안에서 빼내 ",[28,15570,15571],{},"Q&A 본문 다음 별도 섹션","으로 배치. templates 6개 표시·복사·표준답변 저장 동작 모두 유지. QaAxisCard에서 templates 렌더링·관련 import 제거.",[57,15574,15575,2448,15578,15581,15582,15585],{},[28,15576,15577],{},"안내글 평가 엔드포인트 신설",[16,15579,15580],{},"POST \u002Fpms\u002Fposts\u002F:id\u002Fannounce-eval\u002Fgenerate",". 작성자가 직원(staff)일 때만 동작, 3축(톤·자세 \u002F 명확성 \u002F 완전성) + 3개 변형 추천(짧은 \u002F 명료한 \u002F 자세한). 캐싱·hp_qa_eval 저장·hp_llm_log 감사 모두 동일 구조 재활용. ",[28,15583,15584],{},"PMS UI 통합은 보류"," (코드만 들어가 있음).",[57,15587,15588,15591,15592],{},[28,15589,15590],{},"AI Gateway·LLM 정비 (큰 변화)"," — Cloudflare AI Gateway 결제 정책 변경 + 한국 region IP block 정책이 겹쳐 OpenAI 호출 경로가 다수 차단됨. 6가지 경로 검증 후 최종 안정 구성으로 안착:",[54,15593,15594,15601,15608,15619,15622,15625],{},[57,15595,15596,15597,15600],{},"새 게이트웨이 ",[16,15598,15599],{},"malgn-helper2"," (Authentication disabled, BYOK Provider 키 등록)",[57,15602,15603,15604,15607],{},"모델 ",[16,15605,15606],{},"openai\u002Fgpt-4.1-mini"," (Vision 포함)",[57,15609,15610,15611,15614,15615,15618],{},"헤더 원래 방식 — ",[16,15612,15613],{},"Authorization","(OpenAI 키) + ",[16,15616,15617],{},"cf-aig-authorization","(Gateway 토큰)",[57,15620,15621],{},"Smart Placement + AI binding 활성 (유지)",[57,15623,15624],{},"callOpenAiJson 경로 복귀 (callWorkersAi는 코드에 유지하되 미사용)",[57,15626,15627,15628,15631],{},"검증: post 149694 평점 ",[28,15629,15630],{},"4.4–4.8",", oneLiner 자연스러움, D templates 6개 정상",[57,15633,15634,15637,15638,15641,15642,15645,15646,15648],{},[28,15635,15636],{},"5\u002F29 작업 → 문서 현행화"," — WBS.md 전면 갱신(진행률 6단계 모두 상향, 누적 자산 갱신, 다음 우선순위 M2 진입 기준 재작성), HP-SCHEMA.md ",[16,15639,15640],{},"overall_verdict"," VARCHAR(100) 마이그레이션 반영, history.20260601.md 작성. R2의 ",[16,15643,15644],{},"wbs.json","도 PUT으로 갱신해 ",[16,15647,12910],{}," 라이브 트래커 동기화.",[215,15650,15652],{"id":15651},"시도된-openai-호출-경로-트러블슈팅-기록","시도된 OpenAI 호출 경로 (트러블슈팅 기록)",[135,15654,15655,15665],{},[138,15656,15657],{},[141,15658,15659,15661,15663],{},[144,15660,497],{},[144,15662,503],{},[144,15664,11180],{},[157,15666,15667,15680,15690,15700,15710,15725,15740],{},[141,15668,15669,15671,15677],{},[162,15670,6055],{},[162,15672,15673,15674,15676],{},"AI Gateway compat (",[16,15675,47],{},") + BYOK",[162,15678,15679],{},"region 차단",[141,15681,15682,15684,15687],{},[162,15683,7685],{},[162,15685,15686],{},"AI Gateway compat + Cloudflare credit",[162,15688,15689],{},"compat에 미적용",[141,15691,15692,15694,15697],{},[162,15693,6004],{},[162,15695,15696],{},"Worker → OpenAI 직접",[162,15698,15699],{},"region 차단 (Workers IP block)",[141,15701,15702,15704,15707],{},[162,15703,5963],{},[162,15705,15706],{},"위 + Smart Placement",[162,15708,15709],{},"학습 안 됨, 동일 차단",[141,15711,15712,15714,15720],{},[162,15713,5952],{},[162,15715,15716,15717],{},"Workers AI binding ",[16,15718,15719],{},"@cf\u002Fopenai\u002F...",[162,15721,15722],{},[16,15723,15724],{},"5007 No such model",[141,15726,15727,15729,15734],{},[162,15728,6066],{},[162,15730,15716,15731,15733],{},[16,15732,15606],{}," + Provider 키",[162,15735,15736,15739],{},[16,15737,15738],{},"2021 Payment error"," (partner 결제 정책)",[141,15741,15742,15747,15754],{},[162,15743,15744],{},[28,15745,15746],{},"7",[162,15748,15749],{},[28,15750,15673,15751,15753],{},[16,15752,15599],{},") + Authorization + cf-aig-authorization",[162,15755,15756,15759],{},[28,15757,15758],{},"정상 동작"," ✅",[215,15761,12551],{"id":12550},[54,15763,15764,15772,15779,15782,15785],{},[57,15765,15766,15768,15769,15771],{},[16,15767,47],{}," 게이트웨이는 결제 정책상 더 이상 사용 불가 → ",[16,15770,15599],{}," 신규 게이트웨이로 전환 (사용자가 직접 생성)",[57,15773,15774,15775,15778],{},"AI Gateway에 OpenAI Provider 키 ",[28,15776,15777],{},"재등록"," (이전에 BYOK region 차단 우려로 삭제했던 키 다시 등록)",[57,15780,15781],{},"AI Gateway $10 크레딧 충전 (단 partner 모델 호출에는 적용되지 않음 — Cloudflare 자체 모델 전용)",[57,15783,15784],{},"Llama 3.3 70B로의 fallback 가능성 검증 완료 (평점 4.0, 한국어 OK) — 비상시 옵션으로 유지",[57,15786,15787,15788,15791],{},"안내글 평가 기능은 코드 들어감, UI 통합은 별도 작업 (PMS의 ",[16,15789,15790],{},"pages\u002Fposts\u002F[id]\u002Findex.vue"," 작성자 staff 분기 + 모달 재활용)",[215,15793,15795],{"id":15794},"다음-작업-후보","다음 작업 후보",[54,15797,15798,15804,15807],{},[57,15799,15800,15801,78],{},"안내글 평가 UI 통합 (",[16,15802,15803],{},"작성자 staff → \"AI 안내글 분석\" 버튼 + 모달",[57,15805,15806],{},"OpenSearch 셋업 + 자료 업로드 MVP (M2 진입)",[57,15808,15809,15811],{},[16,15810,108],{},"에서 LLM 행 클릭 시 모달 즉시 열기",[33,15813],{},[36,15815,11529],{"id":11529},[215,15817,15819,15820,11554],{"id":15818},"_1354-malgn-helper-pms-cloudflare-pages","13:54 — ",[16,15821,4588],{},[54,15823,15824,15829],{},[57,15825,11541,15826,11561],{},[16,15827,15828],{},"c7670ba",[57,15830,15831],{},"메시지: feat(wbs): 다크 모드여도 항상 라이트 톤 — useColorMode override",[215,15833,15835,15836,11554],{"id":15834},"_1405-malgn-helper-pms-cloudflare-pages","14:05 — ",[16,15837,4588],{},[54,15839,15840,15845],{},[57,15841,11541,15842,11561],{},[16,15843,15844],{},"77395c7",[57,15846,15847],{},"메시지: fix(ui): colorMode를 글로벌 light 고정 — nuxt.config + wbs.vue 페이지별 override 제거",[215,15849,15851,15852,11554],{"id":15850},"_1412-malgn-helper-admin-cloudflare-pages","14:12 — ",[16,15853,18],{},[54,15855,15856,15861],{},[57,15857,11541,15858,11561],{},[16,15859,15860],{},"c754924",[57,15862,15863],{},"메시지: chore: 다크모드 비활성 — colorMode light 글로벌 (모듈 추가 시 자동 발효)",[215,15865,15867,15868,11554],{"id":15866},"_1413-malgn-helper-cloudflare-pages","14:13 — ",[16,15869,47],{},[54,15871,15872,15877],{},[57,15873,11541,15874,11561],{},[16,15875,15876],{},"8ed0965",[57,15878,15863],{},[215,15880,14120,15881,11554],{"id":14119},[16,15882,4588],{},[54,15884,15885,15890],{},[57,15886,11541,15887,11561],{},[16,15888,15889],{},"acb8940",[57,15891,15892],{},"메시지: fix(ui): localStorage 옛 dark 값 무시 — plugin으로 light 강제",[215,15894,15896,15897,11554],{"id":15895},"_1427-malgn-helper-pms-cloudflare-pages","14:27 — ",[16,15898,4588],{},[54,15900,15901,15906],{},[57,15902,11541,15903,11561],{},[16,15904,15905],{},"2d273db",[57,15907,15908],{},"메시지: fix(ui): colorMode 제거 + body background-color: #ffffff 강제 (다크 모드 무관)",[215,15910,15912,15913,11554],{"id":15911},"_1559-malgn-helper-pms-cloudflare-pages","15:59 — ",[16,15914,4588],{},[54,15916,15917,15922],{},[57,15918,11541,15919,11561],{},[16,15920,15921],{},"1e1eb28",[57,15923,15924],{},"메시지: feat(QaEvalCard): '추천 문의 답변' 별도 섹션으로 분리 — Q&A 본문 다음에 배치",[215,15926,15928,15929,11536],{"id":15927},"_1758-malgn-helper-api-cloudflare-workers","17:58 — ",[16,15930,4404],{},[54,15932,15933,15938,15941,15944,15947,15950,15953],{},[57,15934,11541,15935,11561],{},[16,15936,15937],{},"bab7867",[57,15939,15940],{},"메시지: feat(eval): announce-eval 엔드포인트 신설 + LLM 모델·게이트웨이 정비",[57,15942,15943],{},"\u002Fpms\u002Fposts\u002F:id\u002Fannounce-eval\u002Fgenerate (직원 작성 안내글 평가, 3축 + 3개 추천)",[57,15945,15946],{},"llm.ts: Workers AI binding 호출 함수(callWorkersAi) 추가",[57,15948,15949],{},"AI Gateway malgn-helper2로 전환 (이전 malgn-helper는 결제 정책 변경으로 차단)",[57,15951,15952],{},"LLM_MODEL: openai\u002Fgpt-4.1-mini (Vision 포함)",[57,15954,15955],{},"Smart Placement + AI binding 활성",[215,15957,14489,15958,11554],{"id":14488},[16,15959,4588],{},[54,15961,15962,15966],{},[57,15963,11541,15964,11544],{},[16,15965,15921],{},[57,15967,15968],{},"메시지: chore: 청크 hash 갱신 — '추천 문의 답변' 섹션 분리 변경이 브라우저 캐시로 안 보이는 사례 대응",{"title":423,"searchDepth":3342,"depth":3342,"links":15970},[15971,15976],{"id":15536,"depth":3335,"text":15536,"children":15972},[15973,15974,15975],{"id":15651,"depth":3342,"text":15652},{"id":12550,"depth":3342,"text":12551},{"id":15794,"depth":3342,"text":15795},{"id":11529,"depth":3335,"text":11529,"children":15977},[15978,15980,15982,15984,15986,15987,15989,15991,15993],{"id":15818,"depth":3342,"text":15979},"13:54 — malgn-helper-pms → Cloudflare Pages",{"id":15834,"depth":3342,"text":15981},"14:05 — malgn-helper-pms → Cloudflare Pages",{"id":15850,"depth":3342,"text":15983},"14:12 — malgn-helper-admin → Cloudflare Pages",{"id":15866,"depth":3342,"text":15985},"14:13 — malgn-helper → Cloudflare Pages",{"id":14119,"depth":3342,"text":15138},{"id":15895,"depth":3342,"text":15988},"14:27 — malgn-helper-pms → Cloudflare Pages",{"id":15911,"depth":3342,"text":15990},"15:59 — malgn-helper-pms → Cloudflare Pages",{"id":15927,"depth":3342,"text":15992},"17:58 — malgn-helper-api → Cloudflare Workers",{"id":14488,"depth":3342,"text":15183},{},"\u002Fhistory\u002Fhistory.20260602",{"title":15528,"description":423},"history\u002Fhistory.20260602","j0OaZK6VVJ7SnWfBLZ-nb-2YqCaE1i25Jc5qYmTdZQc",{"id":16000,"title":16001,"body":16002,"description":423,"extension":4340,"meta":16289,"navigation":3338,"path":16290,"seo":16291,"stem":16292,"__hash__":16293},"docs\u002Fhistory\u002Fhistory.20260604.md","작업 이력 — 2026-06-04",{"type":8,"value":16003,"toc":16267},[16004,16007,16012,16014,16017,16115,16117,16135,16137,16152,16154,16156,16162,16172,16178,16188,16194,16204,16210,16220,16226,16236,16242,16252,16257],[11,16005,16001],{"id":16006},"작업-이력-2026-06-04",[21,16008,16009],{},[24,16010,16011],{},"6\u002F3 작업 없음 — 6\u002F2 다음 작업 재개.",[36,16013,15536],{"id":15536},[24,16015,16016],{},"PMS 분석 모달 UX와 임베드 인터페이스, Vision 이미지 URL 안정화 4개 흐름 진행:",[1925,16018,16019,16040,16056,16085],{},[57,16020,16021,2448,16024,16027,16028,16031,16032,16035,16036,16039],{},[28,16022,16023],{},"임베드 모드 신호 정리",[16,16025,16026],{},"\u002Fprojects\u002F[id]"," 페이지에 ",[16,16029,16030],{},"isEmbedded"," 도입(",[16,16033,16034],{},"?embed=1","). 임베드 시 PMS 내부 nav(\"📋 게시글 목록 →\", breadcrumb) 숨김. ",[16,16037,16038],{},"?modal=open","(모달 자동 오픈)과 시그널 분리해서 혼동 제거.",[57,16041,16042,2448,16045,16048,16049,16052,16053,133],{},[28,16043,16044],{},"\"최근 활동\" 풀 타임스탬프",[16,16046,16047],{},"slice(0,7)","(YYYY-MM)에서 ",[16,16050,16051],{},"slice(0,19).replace('T',' ')","로 확장 (KST 기준 ",[16,16054,16055],{},"YYYY-MM-DD HH:mm:ss",[57,16057,16058,16061,16062,16065,16066,2855,16069,16072,16073,16076,16077,16080,16081,16084],{},[28,16059,16060],{},"QaEvalCard 인-모달 상태 전환"," — 외부 로딩\u002F에러 Teleport 2개 제거. 모달이 클릭 즉시 열리고 같은 모달 안에서 ",[16,16063,16064],{},"로딩(✨ 펄스) → 분석 결과 \u002F 에러(다시 시도)","로 자연 전환. 프로젝트 브리핑 모달과 동일 UX. props에 ",[16,16067,16068],{},"loading?",[16,16070,16071],{},"error?"," 추가, ",[16,16074,16075],{},"qa"," nullable, ",[16,16078,16079],{},"retry"," emit 신설. 모달 임베드 전용 페이지 ",[16,16082,16083],{},"\u002Fposts\u002F[id]\u002Feval","도 같은 패턴으로 통일.",[57,16086,16087,16090,16091,16094,16095,16098,16099,16102,16103,16106,16107,16110,16111,16114],{},[28,16088,16089],{},"Vision 이미지 URL 절대화 확장"," — 원본 PMS 본문의 이미지 src가 ",[16,16092,16093],{},"..\u002Fdata\u002F1\u002F..."," 같은 상대 경로일 때 OpenAI Vision이 ",[16,16096,16097],{},"invalid_image_url"," 400. ",[16,16100,16101],{},"toAbsolute","(API 측)와 ",[16,16104,16105],{},"fixPmsHtml","(PMS 측) 모두 ",[16,16108,16109],{},"\u002Fdata\u002F·..\u002Fdata\u002F·.\u002Fdata\u002F·data\u002F"," 등 모든 상대경로를 ",[16,16112,16113],{},"https:\u002F\u002Fppm.malgn.co.kr\u002Fdata\u002F...","로 변환하도록 확장.",[215,16116,12551],{"id":12550},[54,16118,16119,16127,16130],{},[57,16120,16121,16123,16124,16126],{},[16,16122,16034],{}," = PMS 임베드 시그널(내부 nav 숨김) \u002F ",[16,16125,16038],{}," = 모달 자동 오픈 — 두 시그널 의도 분리",[57,16128,16129],{},"QaEvalCard는 모달이 항상 열리는 동안 내부 상태(loading\u002Ferror\u002Fresult) 분기. UX 안정성이 별도 모달 전환보다 자연스러움",[57,16131,16132,16134],{},[16,16133,171],{}," repo nuxt.config의 colorMode 항목도 PMS와 일관성 위해 제거(13903cc)",[215,16136,15795],{"id":15794},[54,16138,16139,16146,16148],{},[57,16140,16141,16142,16145],{},"안내글 평가(",[16,16143,16144],{},"\u002Fpms\u002Fposts\u002F:id\u002Fannounce-eval\u002Fgenerate",") PMS UI 통합 — 작성자 staff 분기 + 모달 재활용",[57,16147,15806],{},[57,16149,16150,15811],{},[16,16151,108],{},[33,16153],{},[36,16155,11529],{"id":11529},[215,16157,16159,16160,11554],{"id":16158},"_1633-malgn-helper-pms-cloudflare-pages","16:33 — ",[16,16161,4588],{},[54,16163,16164,16169],{},[57,16165,11541,16166,11561],{},[16,16167,16168],{},"074504b",[57,16170,16171],{},"메시지: feat(projects): 임베드 모드(?embed=1 또는 ?modal=open) — 게시글 목록 버튼·breadcrumb 숨김",[215,16173,16175,16176,11554],{"id":16174},"_1635-malgn-helper-pms-cloudflare-pages","16:35 — ",[16,16177,4588],{},[54,16179,16180,16185],{},[57,16181,11541,16182,11561],{},[16,16183,16184],{},"f743545",[57,16186,16187],{},"메시지: feat(projects): 최근 활동 표시를 yyyy-MM에서 yyyy-MM-dd HH:mm:ss로 확장",[215,16189,16191,16192,11554],{"id":16190},"_1649-malgn-helper-pms-cloudflare-pages","16:49 — ",[16,16193,4588],{},[54,16195,16196,16201],{},[57,16197,11541,16198,11561],{},[16,16199,16200],{},"2c9aca3",[57,16202,16203],{},"메시지: feat(QaEvalCard): 모달이 클릭 즉시 열리고 안에서 loading→결과\u002F에러 상태 전환 (프로젝트 분석과 동일 UX)",[215,16205,16207,16208,11554],{"id":16206},"_1706-malgn-helper-pms-cloudflare-pages","17:06 — ",[16,16209,4588],{},[54,16211,16212,16217],{},[57,16213,11541,16214,11561],{},[16,16215,16216],{},"7dad92b",[57,16218,16219],{},"메시지: fix(projects): isEmbedded는 ?embed=1만 — modal=open과 분리 + 새 청크 hash로 캐시 갱신",[215,16221,16223,16224,11554],{"id":16222},"_1722-malgn-helper-pms-cloudflare-pages","17:22 — ",[16,16225,4588],{},[54,16227,16228,16233],{},[57,16229,11541,16230,11561],{},[16,16231,16232],{},"9c14a01",[57,16234,16235],{},"메시지: refactor(posts\u002Feval): 인-모달 loading\u002Ferror 패턴으로 통일 (적용 URL 변경 없음)",[215,16237,16239,16240,11536],{"id":16238},"_1732-malgn-helper-api-cloudflare-workers","17:32 — ",[16,16241,4404],{},[54,16243,16244,16249],{},[57,16245,11541,16246,11561],{},[16,16247,16248],{},"3dd0abf",[57,16250,16251],{},"메시지: fix(vision): Vision 이미지 URL 변환에 ..\u002Fdata\u002F .\u002Fdata\u002F data\u002F 등 상대경로 모두 절대화",[215,16253,16239,16255,11554],{"id":16254},"_1732-malgn-helper-pms-cloudflare-pages",[16,16256,4588],{},[54,16258,16259,16264],{},[57,16260,11541,16261,11561],{},[16,16262,16263],{},"8d51e8b",[57,16265,16266],{},"메시지: fix(fixPmsHtml): ..\u002Fdata\u002F .\u002Fdata\u002F 등 상대경로 자산도 PMS 도메인으로 절대화",{"title":423,"searchDepth":3342,"depth":3342,"links":16268},[16269,16273],{"id":15536,"depth":3335,"text":15536,"children":16270},[16271,16272],{"id":12550,"depth":3342,"text":12551},{"id":15794,"depth":3342,"text":15795},{"id":11529,"depth":3335,"text":11529,"children":16274},[16275,16277,16279,16281,16283,16285,16287],{"id":16158,"depth":3342,"text":16276},"16:33 — malgn-helper-pms → Cloudflare Pages",{"id":16174,"depth":3342,"text":16278},"16:35 — malgn-helper-pms → Cloudflare Pages",{"id":16190,"depth":3342,"text":16280},"16:49 — malgn-helper-pms → Cloudflare Pages",{"id":16206,"depth":3342,"text":16282},"17:06 — malgn-helper-pms → Cloudflare Pages",{"id":16222,"depth":3342,"text":16284},"17:22 — malgn-helper-pms → Cloudflare Pages",{"id":16238,"depth":3342,"text":16286},"17:32 — malgn-helper-api → Cloudflare Workers",{"id":16254,"depth":3342,"text":16288},"17:32 — malgn-helper-pms → Cloudflare Pages",{},"\u002Fhistory\u002Fhistory.20260604",{"title":16001,"description":423},"history\u002Fhistory.20260604","WmRmdwHHeh1vCgmJngTjGtwJQyPvAbfmXmAfp1wm6Cg",{"id":16295,"title":16296,"body":16297,"description":423,"extension":4340,"meta":16699,"navigation":3338,"path":16700,"seo":16701,"stem":16702,"__hash__":16703},"docs\u002Fhistory\u002Fhistory.20260605.md","작업 이력 — 2026-06-05",{"type":8,"value":16298,"toc":16669},[16299,16302,16304,16310,16431,16433,16456,16458,16478,16480,16482,16488,16498,16504,16514,16520,16530,16536,16546,16552,16562,16566,16576,16581,16591,16597,16607,16611,16621,16627,16637,16643,16653,16659],[11,16300,16296],{"id":16301},"작업-이력-2026-06-05",[36,16303,15536],{"id":15536},[24,16305,16306,16307,3360],{},"오늘 5개 흐름 진행 — 답변 없는 문의 추천 답변 모드, PMS UI 폴리시 다회, ",[28,16308,16309],{},"hp_image_asset 신설(Vision 자동 캡션)",[1925,16311,16312,16321,16359,16412],{},[57,16313,16314,2448,16317,16320],{},[28,16315,16316],{},"답변 없는 문의 → inquiry-only 모드",[16,16318,16319],{},"QA_INQUIRY_ONLY_SYSTEM_PROMPT"," 신설. resp 없으면 5축 평가 생략하고 D축 1개에 추천 답변 6개(짧은\u002F긴\u002F친절\u002F비즈니스\u002FFAQ\u002F단계별)만 wrap. 모호한 문의면 commentary에 \"추가 확인 필요 정보\" 명시.",[57,16322,16323,16326,16327],{},[28,16324,16325],{},"PMS UI 폴리시 라운드"," (10회 배포)",[54,16328,16329,16336,16342,16349,16352],{},[57,16330,16331,16332,16335],{},"임베드 시그널 ",[16,16333,16334],{},"modal=open"," 다시 포함 → 모달 진입 시 게시글 목록 버튼\u002Fbreadcrumb 숨김",[57,16337,16338,16339,16341],{},"빈 상태 카드: ",[16,16340,11093],{}," 코드 라벨 제거, \"1.5초 시뮬레이션\" 안내 제거. \"약 30초~1분 소요\" 안내만 남김",[57,16343,16344,16345,16348],{},"메타 일시 표시: ISO → ",[16,16346,16347],{},"yyyy.MM.dd HH:mm:ss"," 한 줄, MetaTile 폰트 18→14px",[57,16350,16351],{},"PersonBlock: UTooltip 안 텍스트가 안 보이던 이슈 fix (title 속성으로 대체), 이름·뱃지·이메일을 한 줄로 (좁으면 wrap)",[57,16353,16354,16355,16358],{},"추천 답변 가독성: 문단 간격 ",[16,16356,16357],{},"my-3",", line-height 1.8, 폰트 13px, 패딩 py-4",[57,16360,16361,16364,16365],{},[28,16362,16363],{},"hp_image_asset 신설 + 자동 Vision 캡션"," (오늘의 핵심)",[54,16366,16367,16374,16385,16400,16403,16409],{},[57,16368,16369,16370,16373],{},"5번째 hp_* 테이블. ",[16,16371,16372],{},"src_path"," UNIQUE(prefix 191 — MySQL 5.6 utf8mb4 767 byte 한도 대응)로 한 이미지는 한 번만 분석",[57,16375,16376,16379,16380,1524,16382,16384],{},[16,16377,16378],{},"analyzeAndStoreImage()",": 캐시 hit이면 usage_count++, 없으면 GPT-4o Vision으로 ",[16,16381,2286],{},[16,16383,2289],{}," 생성 → INSERT",[57,16386,16387,16388,16391,16392,16395,16396,16399],{},"eval\u002Fgenerate에서 본문(",[16,16389,16390],{},"inquiry",") + 응답(",[16,16393,16394],{},"reply",") HTML의 ",[16,16397,16398],{},"\u002Fdata\u002F*"," 이미지 추출 → 병렬 분석·저장 (최대 16장)",[57,16401,16402],{},"HP-SCHEMA.md 3-5 섹션 + DDL 추가",[57,16404,16405,16408],{},[16,16406,16407],{},"\u002Fadmin\u002Fmigrate\u002Fhp_image_asset?confirm=yes"," 일회용 엔드포인트로 마이그레이션 완료",[57,16410,16411],{},"검증: post 149694의 이미지 9장이 정확한 한국어 캡션으로 저장 (예: \"메시지관리 메뉴 화면\", \"발신프로필 정보 화면\", \"알림톡 템플릿 수정 화면\")",[57,16413,16414,16417,16418,16421,16422,1358,16424,16426,16427,16430],{},[28,16415,16416],{},"표준답변 저장 흐름 정리"," — 사용자 질의에 따라 전 경로 (QaEvalCard ",[16,16419,16420],{},"save-template"," emit → ",[16,16423,3610],{},[16,16425,2125],{}," INSERT) 문서화. axisLetter는 모두 ",[16,16428,16429],{},"'D'","로 고정.",[215,16432,12551],{"id":12550},[54,16434,16435,16441,16447,16450],{},[57,16436,16437,16438,16440],{},"AI Gateway는 ",[16,16439,15599],{}," + Provider OpenAI 키 + Authorization+cf-aig-authorization 헤더 조합으로 안정 운영",[57,16442,16443,16444,16446],{},"hp_image_asset의 ",[16,16445,16372],{},"는 VARCHAR(500)이지만 UNIQUE 인덱스는 prefix 191자만 — utf8mb4 4byte × 191 = 764 byte ≤ 767 한도",[57,16448,16449],{},"inquiry-only 응답의 axes는 D축 1개만 들어가지만 UI는 그대로 정상 동작 (5축 평가 섹션은 D축 카드 1개 + 추천 답변 섹션은 별도 분리되어 표시)",[57,16451,16452,16455],{},[16,16453,16454],{},"\u002Fadmin\u002Fmigrate\u002Fhp_image_asset"," 엔드포인트는 일회용 — 후속 정리 시 코드에서 제거 권장",[215,16457,15795],{"id":15794},[54,16459,16460,16465,16470,16473,16475],{},[57,16461,16141,16462,16464],{},[16,16463,16144],{},") PMS UI 통합 — 코드만 들어가 있음",[57,16466,16467,16469],{},[16,16468,77],{},"을 표준답변·챗봇 컨텍스트로 활용 (이미지 설명을 텍스트로 인용)",[57,16471,16472],{},"관리자 화면에 이미지 카탈로그 (검색·태그 큐레이션)",[57,16474,15806],{},[57,16476,16477],{},"inquiry-only 응답에 axes가 D축만 들어갈 때 UI에서 5축 평가 섹션 숨기는 분기",[33,16479],{},[36,16481,11529],{"id":11529},[215,16483,16485,16486,11536],{"id":16484},"_1109-malgn-helper-api-cloudflare-workers","11:09 — ",[16,16487,4404],{},[54,16489,16490,16495],{},[57,16491,11541,16492,11561],{},[16,16493,16494],{},"2b0689d",[57,16496,16497],{},"메시지: feat(eval): 답변이 없는 문의는 inquiry-only 모드로 추천 답변 6개만 생성",[215,16499,16501,16502,11554],{"id":16500},"_1116-malgn-helper-pms-cloudflare-pages","11:16 — ",[16,16503,4588],{},[54,16505,16506,16511],{},[57,16507,11541,16508,11561],{},[16,16509,16510],{},"a3d0f43",[57,16512,16513],{},"메시지: fix(projects): modal=open도 임베드 시그널에 다시 포함 — 모달 진입 시 게시글 목록 버튼 숨김",[215,16515,16517,16518,11554],{"id":16516},"_1117-malgn-helper-pms-cloudflare-pages","11:17 — ",[16,16519,4588],{},[54,16521,16522,16527],{},[57,16523,11541,16524,11561],{},[16,16525,16526],{},"9205573",[57,16528,16529],{},"메시지: chore(ui): 빈 상태 카드 문구 정리 — tb_post 코드 라벨·1.5초 시뮬레이션 안내 제거",[215,16531,16533,16534,11554],{"id":16532},"_1119-malgn-helper-pms-cloudflare-pages","11:19 — ",[16,16535,4588],{},[54,16537,16538,16543],{},[57,16539,11541,16540,11561],{},[16,16541,16542],{},"20c17f3",[57,16544,16545],{},"메시지: chore(ui): 빈 상태 카드에 생성 소요 시간 안내 복원 (약 30초~1분)",[215,16547,16549,16550,11554],{"id":16548},"_1134-malgn-helper-pms-cloudflare-pages","11:34 — ",[16,16551,4588],{},[54,16553,16554,16559],{},[57,16555,11541,16556,11561],{},[16,16557,16558],{},"795bdc3",[57,16560,16561],{},"메시지: feat(QaEvalCard): 문의·응답 일시를 yyyy.MM.dd HH:mm:ss 형식으로 표시",[215,16563,13634,16564,11554],{"id":13633},[16,16565,4588],{},[54,16567,16568,16573],{},[57,16569,11541,16570,11561],{},[16,16571,16572],{},"11f92a0",[57,16574,16575],{},"메시지: chore(QaEvalCard): 문의·응답 메타타일에 날짜+시간 한 줄로 합쳐 표시",[215,16577,11533,16579,11554],{"id":16578},"_1139-malgn-helper-pms-cloudflare-pages",[16,16580,4588],{},[54,16582,16583,16588],{},[57,16584,11541,16585,11561],{},[16,16586,16587],{},"a47445a",[57,16589,16590],{},"메시지: fix(QaEvalCard): PersonBlock에서 UTooltip 제거 → 이름이 안 보이던 이슈 fix (title 속성으로 툴팁 대체)",[215,16592,16594,16595,11554],{"id":16593},"_1140-malgn-helper-pms-cloudflare-pages","11:40 — ",[16,16596,4588],{},[54,16598,16599,16604],{},[57,16600,11541,16601,11561],{},[16,16602,16603],{},"0446352",[57,16605,16606],{},"메시지: chore(ui): MetaTile value 폰트 18px→14px — 한 줄 일시 표시 시 줄바꿈 방지",[215,16608,13666,16609,11554],{"id":13665},[16,16610,4588],{},[54,16612,16613,16618],{},[57,16614,11541,16615,11561],{},[16,16616,16617],{},"b17be67",[57,16619,16620],{},"메시지: chore(QaEvalCard): PersonBlock의 이름·뱃지·이메일을 한 줄로 표시 (좁으면 wrap)",[215,16622,16624,16625,11554],{"id":16623},"_1147-malgn-helper-pms-cloudflare-pages","11:47 — ",[16,16626,4588],{},[54,16628,16629,16634],{},[57,16630,11541,16631,11561],{},[16,16632,16633],{},"ecd7955",[57,16635,16636],{},"메시지: chore(QaEvalCard): 추천 답변 가독성 — 문단 간격(my-3) + 줄간격(1.8) + 폰트 13px 적용",[215,16638,16640,16641,11536],{"id":16639},"_1201-malgn-helper-api-cloudflare-workers","12:01 — ",[16,16642,4404],{},[54,16644,16645,16650],{},[57,16646,11541,16647,11561],{},[16,16648,16649],{},"b3ce7e1",[57,16651,16652],{},"메시지: feat(image-asset): hp_image_asset 신설 + Vision으로 PMS 자산 이미지 자동 캡션·설명 추출·저장",[215,16654,16656,16657,11536],{"id":16655},"_1852-malgn-helper-api-cloudflare-workers","18:52 — ",[16,16658,4404],{},[54,16660,16661,16666],{},[57,16662,11541,16663,11561],{},[16,16664,16665],{},"137dc9c",[57,16667,16668],{},"메시지: fix(hp_image_asset): UNIQUE 인덱스 prefix 255→191 (MySQL 5.6 utf8mb4 키 길이 767 byte 제한)",{"title":423,"searchDepth":3342,"depth":3342,"links":16670},[16671,16675],{"id":15536,"depth":3335,"text":15536,"children":16672},[16673,16674],{"id":12550,"depth":3342,"text":12551},{"id":15794,"depth":3342,"text":15795},{"id":11529,"depth":3335,"text":11529,"children":16676},[16677,16679,16681,16683,16685,16687,16688,16690,16692,16693,16695,16697],{"id":16484,"depth":3342,"text":16678},"11:09 — malgn-helper-api → Cloudflare Workers",{"id":16500,"depth":3342,"text":16680},"11:16 — malgn-helper-pms → Cloudflare Pages",{"id":16516,"depth":3342,"text":16682},"11:17 — malgn-helper-pms → Cloudflare Pages",{"id":16532,"depth":3342,"text":16684},"11:19 — malgn-helper-pms → Cloudflare Pages",{"id":16548,"depth":3342,"text":16686},"11:34 — malgn-helper-pms → Cloudflare Pages",{"id":13633,"depth":3342,"text":15076},{"id":16578,"depth":3342,"text":16689},"11:39 — malgn-helper-pms → Cloudflare Pages",{"id":16593,"depth":3342,"text":16691},"11:40 — malgn-helper-pms → Cloudflare Pages",{"id":13665,"depth":3342,"text":15080},{"id":16623,"depth":3342,"text":16694},"11:47 — malgn-helper-pms → Cloudflare Pages",{"id":16639,"depth":3342,"text":16696},"12:01 — malgn-helper-api → Cloudflare Workers",{"id":16655,"depth":3342,"text":16698},"18:52 — malgn-helper-api → Cloudflare Workers",{},"\u002Fhistory\u002Fhistory.20260605",{"title":16296,"description":423},"history\u002Fhistory.20260605","qzQvsK_bDPLX-kD-ynA5xvrEIxSWLpMh_OqSuJzpJOU",{"id":16705,"title":16706,"body":16707,"description":423,"extension":4340,"meta":17364,"navigation":3338,"path":17365,"seo":17366,"stem":17367,"__hash__":17368},"docs\u002Fhistory\u002Fhistory.20260608.md","작업 이력 — 2026-06-08",{"type":8,"value":16708,"toc":17341},[16709,16712,16714,16723,16727,16734,16807,16811,16817,16897,16903,16907,16910,16993,17001,17005,17021,17137,17140,17142,17163,17165,17184,17186,17236,17238,17240,17246,17277,17283,17293,17299,17309,17315,17325,17331],[11,16710,16706],{"id":16711},"작업-이력-2026-06-08",[36,16713,15536],{"id":15536},[24,16715,16716,16717,407],{},"오늘 4개 흐름 — ",[28,16718,16719,16720,16722],{},"관리자단(",[16,16721,18],{},") 기획부터 실 운영 화면·인증까지 일괄 진입",[215,16724,16726],{"id":16725},"_1-admin-plan-기획서-완성-6-라운드","1. ADMIN-PLAN 기획서 완성 (6 라운드)",[24,16728,16729,16733],{},[3257,16730,16732],{"href":16731},"..\u002FADMIN-PLAN","doc\u002FADMIN-PLAN.md"," 신설 + 5회 갱신:",[54,16735,16736,16742,16755,16776,16787,16797],{},[57,16737,16738,16741],{},[28,16739,16740],{},"1차",": IA(12 섹션) + 화면 명세 12종 + Week 1~5 단계별 구현",[57,16743,16744,16747,16748,530,16750,530,16752,16754],{},[28,16745,16746],{},"2차",": 3 역할 (",[16,16749,171],{},[16,16751,189],{},[16,16753,207],{},") 권한 매트릭스 + 동영상 URL 정책 (Whisper 수동 트리거) + 운영 기본값 5건 확정",[57,16756,16757,16760,16761,1524,16763,1524,16765,1524,16767,16769,16770,16772,16773,16775],{},[28,16758,16759],{},"3차",": 표준답변 분류 체계 (",[16,16762,1552],{},[16,16764,1579],{},[16,16766,1592],{},[16,16768,1605],{},") + 이미지 자동 배치 3방식 + AI 초안 = ",[16,16771,2561],{}," 재사용 + ",[16,16774,557],{}," 전용 페이지",[57,16777,16778,4664,16781,1358,16784,16786],{},[28,16779,16780],{},"4차",[16,16782,16783],{},"lms-private",[16,16785,1863],{}," 라벨 변경 (민간보안 LMS 도메인 명시)",[57,16788,16789,16792,16793,16796],{},[28,16790,16791],{},"5차",": 사이드바 메뉴 §3-2~3-5 정의 — ",[28,16794,16795],{},"5 그룹 × 17 메뉴",", 권한별 가시성, heroicons 아이콘",[57,16798,16799,16802,16803,16806],{},[28,16800,16801],{},"6차",": '미커버 질문' 정의 명확화 — 답변 없는 PMS 게시물(",[16,16804,16805],{},"inquiry-only",")과 구분",[215,16808,16810],{"id":16809},"_2-admin-골격-구현-handoff_noti-디자인-톤-차용","2. admin 골격 구현 (handoff_noti 디자인 톤 차용)",[24,16812,16813,16814,407],{},"빈 보일러플레이트 → ",[28,16815,16816],{},"256px LNB + 64px TopBar + 17 페이지 stub",[135,16818,16819,16829],{},[138,16820,16821],{},[141,16822,16823,16826],{},[144,16824,16825],{},"영역",[144,16827,16828],{},"파일",[157,16830,16831,16848,16859,16875,16887],{},[141,16832,16833,16836],{},[162,16834,16835],{},"의존성",[162,16837,16838,2212,16841,2212,16844,16847],{},[16,16839,16840],{},"@nuxt\u002Fui@3.3.7",[16,16842,16843],{},"@tailwindcss\u002Fvite@4.3",[16,16845,16846],{},"lucide-vue-next"," · DM Sans + Pretendard",[141,16849,16850,16853],{},[162,16851,16852],{},"메뉴 데이터",[162,16854,16855,16858],{},[16,16856,16857],{},"composables\u002Fuse-admin-menu.ts"," — 5 그룹 × 17 메뉴 + 권한·배지 + 검색",[141,16860,16861,16864],{},[162,16862,16863],{},"컴포넌트",[162,16865,16866,2212,16869,2212,16872],{},[16,16867,16868],{},"SidebarMenu.vue",[16,16870,16871],{},"TopBar.vue",[16,16873,16874],{},"PagePlaceholder.vue",[141,16876,16877,16880],{},[162,16878,16879],{},"레이아웃",[162,16881,16882,2212,16885],{},[16,16883,16884],{},"layouts\u002Fdefault.vue",[16,16886,10096],{},[141,16888,16889,16892],{},[162,16890,16891],{},"페이지",[162,16893,16894,16896],{},[16,16895,11003],{}," (홈 KPI mockup) + 16개 stub",[24,16898,16899,16900,16902],{},"초기 ",[16,16901,11130],{}," v4 설치 후 Nuxt 3 호환 미충족 발견 → v3.3.7로 다운그레이드.",[215,16904,16906],{"id":16905},"_3-1순위-4-화면-실데이터-구현","3. 1순위 4 화면 실데이터 구현",[24,16908,16909],{},"PMS의 기존 데이터·컴포넌트를 admin에서 즉시 활용 가능한 4 메뉴 구현:",[135,16911,16912,16923],{},[138,16913,16914],{},[141,16915,16916,16919,16921],{},[144,16917,16918],{},"화면",[144,16920,4456],{},[144,16922,8295],{},[157,16924,16925,16943,16958,16978],{},[141,16926,16927,16932,16940],{},[162,16928,16929,16931],{},[16,16930,530],{}," 홈",[162,16933,16934,2367,16937],{},[28,16935,16936],{},"신규",[16,16938,16939],{},"GET \u002Fadmin\u002Fkpi",[162,16941,16942],{},"실 KPI 4 카드 (표준답변·이미지·평가·이번 달 비용) + 최근 활동 10건",[141,16944,16945,16949,16955],{},[162,16946,16947],{},[16,16948,836],{},[162,16950,16951,16952],{},"기존 ",[16,16953,16954],{},"GET \u002Fadmin\u002Fcost",[162,16956,16957],{},"7\u002F30\u002F90일 토글 + KPI 4 + 모델별 표 + 일별 추이 + 엔티티 분포 + 최근 호출 50건",[141,16959,16960,16964,16969],{},[162,16961,16962],{},[16,16963,642],{},[162,16965,16951,16966],{},[16,16967,16968],{},"GET \u002Fadmin\u002Fevals",[162,16970,16971,16972],{},"정렬 4종(최신·점수↑·점수↓·지연) + 빈 결과 필터. 행 클릭 → ",[28,16973,3970,16974,16977],{},[16,16975,16976],{},"\u002Fposts\u002F:id\u002Feval"," iframe 모달",[141,16979,16980,16984,16990],{},[162,16981,16982],{},[16,16983,754],{},[162,16985,16986,2367,16988],{},[28,16987,16936],{},[16,16989,2339],{},[162,16991,16992],{},"디바운스 검색 + source 필터 + 4:3 그리드 + 상세 모달(원본 + 메타)",[24,16994,16995,16996,105,16998,407],{},"API 신규 2개 — ",[16,16997,16939],{},[16,16999,17000],{},"GET \u002Fimage-assets(\u002F:id)",[215,17002,17004],{"id":17003},"_4-tb_user-통합-로그인-외부-sso-결정-tb_user-변경","4. tb_user 통합 로그인 (외부 SSO 결정 → tb_user 변경)",[24,17006,17007,17008,17020],{},"처음 외부 SSO 패턴 고려했다가 ",[28,17009,2731,17010,3351,17013,1524,17016,17019],{},[16,17011,17012],{},"tb_user",[16,17014,17015],{},"login_id",[16,17017,17018],{},"passwd"," SHA-256)를 그대로 사용","하는 통합 인증으로 결정.",[135,17022,17023,17031],{},[138,17024,17025],{},[141,17026,17027,17029],{},[144,17028,16825],{},[144,17030,10367],{},[157,17032,17033,17049,17062,17078,17095,17106,17122],{},[141,17034,17035,17040],{},[162,17036,17037],{},[16,17038,17039],{},"wrangler secret",[162,17041,17042,17045,17046,78],{},[16,17043,17044],{},"JWT_SECRET"," 등록 (",[16,17047,17048],{},"openssl rand -hex 32",[141,17050,17051,17054],{},[162,17052,17053],{},"CORS",[162,17055,17056,1524,17059,17061],{},[16,17057,17058],{},"credentials: true",[16,17060,15613],{}," 헤더 허용",[141,17063,17064,17067],{},[162,17065,17066],{},"API 엔드포인트",[162,17068,17069,2212,17072,2212,17075],{},[16,17070,17071],{},"POST \u002Fauth\u002Flogin",[16,17073,17074],{},"POST \u002Fauth\u002Flogout",[16,17076,17077],{},"GET \u002Fauth\u002Fme",[141,17079,17080,17083],{},[162,17081,17082],{},"검증 흐름",[162,17084,17085,17088,17089,17091,17092,78],{},[16,17086,17087],{},"tb_user.passwd === sha256(input)"," + 직원 룰(",[16,17090,128],{}," OR ",[16,17093,17094],{},"company='맑은소프트'",[141,17096,17097,17100],{},[162,17098,17099],{},"세션",[162,17101,17102,17103],{},"JWT 8h, ",[16,17104,17105],{},"Set-Cookie helper_session=...; HttpOnly; Secure; SameSite=None",[141,17107,17108,17110],{},[162,17109,171],{},[162,17111,17112,2212,17115,2212,17118,17121],{},[16,17113,17114],{},"composables\u002Fuse-auth.ts",[16,17116,17117],{},"middleware\u002Fauth.global.ts",[16,17119,17120],{},"pages\u002Flogin.vue"," · 사이드바·TopBar 실 사용자·로그아웃",[141,17123,17124,17127],{},[162,17125,17126],{},"역할 매핑",[162,17128,17129,17132,17133,17136],{},[16,17130,17131],{},"level ≥ 9"," admin \u002F ",[16,17134,17135],{},"≥ 5"," developer \u002F 그 외 agent",[24,17138,17139],{},"PMS는 인증 강제 X (현 흐름 유지).",[215,17141,12551],{"id":12550},[54,17143,17144,17151,17157,17160],{},[57,17145,17146,17147,17150],{},"외부 사이트 SSO 패턴 검토 후 ",[28,17148,17149],{},"tb_user 통합으로 전환"," — 인증 책임이 한 곳에 집중되어 일관성·관리성 ↑",[57,17152,17153,17156],{},[28,17154,17155],{},"SHA-256 단독 hash 약점"," 인지 — 운영 강화 시 bcrypt\u002Fargon2 마이그레이션 (첫 로그인 시 재해시) 권장 (보안 메모)",[57,17158,17159],{},"handoff_noti_admin 디자인을 admin 톤의 베이스로 차용 — 컴포넌트 룩앤필만, 콘텐츠는 우리 메뉴",[57,17161,17162],{},"미커버 질문 = 챗봇 운영 후 자동 수집 (Phase 2). 답변 없는 PMS 게시물(inquiry-only)과 별개임을 명확히",[215,17164,3763],{"id":3763},[54,17166,17167,17176],{},[57,17168,17169,1358,17172,17175],{},[16,17170,17171],{},"POST \u002Fauth\u002Flogin {\"loginId\":\"1\",\"password\":\"wrong\"}",[16,17173,17174],{},"{\"error\":\"invalid credentials\"}"," 401 ✅",[57,17177,17178,1358,17180,17183],{},[16,17179,16939],{},[16,17181,17182],{},"{ standardAnswers: 3, images: 24, evals: 35, avgScore: 3.7, monthCalls: 112 }"," 실데이터 ✅",[215,17185,15795],{"id":15794},[54,17187,17188,17206,17220,17230],{},[57,17189,17190,2448,17193,1524,17195,17197,17198,17200,17201,2212,17203,17205],{},[28,17191,17192],{},"2순위 마이그레이션",[16,17194,1619],{},[16,17196,1796],{}," 신설 + ",[16,17199,2125],{}," 컬럼 보강 → ",[16,17202,782],{},[16,17204,700],{}," 정식 활성",[57,17207,17208,17214,17215,2212,17217,17219],{},[28,17209,17210,1524,17212],{},[16,17211,2941],{},[16,17213,2947],{}," 신설 → admin ",[16,17216,1068],{},[16,17218,1095],{}," 동작",[57,17221,17222,17229],{},[28,17223,17224,17225,17228],{},"API 라우트별 ",[16,17226,17227],{},"requireAuth\u002FrequireRole"," 미들웨어 적용"," — 현재 인증 검증은 admin 측만, API는 무인증 호출 가능",[57,17231,17232,17235],{},[28,17233,17234],{},"SHA-256 → bcrypt 마이그레이션 계획"," (보안 강화)",[33,17237],{},[36,17239,11529],{"id":11529},[215,17241,17243,17244,11554],{"id":17242},"_1617-malgn-helper-admin-cloudflare-pages","16:17 — ",[16,17245,18],{},[54,17247,17248,17253,17256,17259,17262,17265,17268,17271,17274],{},[57,17249,11541,17250,11561],{},[16,17251,17252],{},"b3cfcad",[57,17254,17255],{},"메시지: feat(admin): 사이드바 메뉴 구조 + 레이아웃 + 17 페이지 stub (handoff_noti 디자인 톤 적용)",[57,17257,17258],{},"Nuxt UI v3 + Tailwind v4 + Lucide + DM Sans\u002FPretendard 도입",[57,17260,17261],{},"composables\u002Fuse-admin-menu.ts: 5 그룹 × 17 메뉴 + 권한·배지 정의",[57,17263,17264],{},"components\u002Fadmin\u002FSidebarMenu.vue: 256px LNB (브랜드·검색·그룹 접기·뱃지·사용자칩)",[57,17266,17267],{},"components\u002Fadmin\u002FTopBar.vue: 64px sticky (breadcrumb·검색·환경 토글·알림·로그아웃)",[57,17269,17270],{},"layouts\u002Fdefault.vue + app.vue 골격",[57,17272,17273],{},"pages\u002Findex.vue: 홈 KPI 4종 + 최근 활동 mockup",[57,17275,17276],{},"pages\u002F{16개} stub: AdminPagePlaceholder 컴포넌트로 통일",[215,17278,17280,17281,11536],{"id":17279},"_1642-malgn-helper-api-cloudflare-workers","16:42 — ",[16,17282,4404],{},[54,17284,17285,17290],{},[57,17286,11541,17287,11561],{},[16,17288,17289],{},"cc7fc47",[57,17291,17292],{},"메시지: feat(api): GET \u002Fimage-assets + GET \u002Fadmin\u002Fkpi — admin 1순위 화면 데이터 소스",[215,17294,17296,17297,11554],{"id":17295},"_1650-malgn-helper-admin-cloudflare-pages","16:50 — ",[16,17298,18],{},[54,17300,17301,17306],{},[57,17302,11541,17303,11561],{},[16,17304,17305],{},"69db1e8",[57,17307,17308],{},"메시지: feat(admin 1순위): 홈 KPI 실데이터 + \u002Fcost + \u002Fqa-evals(iframe 모달) + \u002Fimages 그리드",[215,17310,17312,17313,11536],{"id":17311},"_1737-malgn-helper-api-cloudflare-workers","17:37 — ",[16,17314,4404],{},[54,17316,17317,17322],{},[57,17318,11541,17319,11561],{},[16,17320,17321],{},"cfe84a4",[57,17323,17324],{},"메시지: feat(auth): \u002Fauth\u002Flogin·logout·me + JWT(8h httpOnly cookie) — tb_user 통합 인증",[215,17326,17328,17329,11554],{"id":17327},"_1740-malgn-helper-admin-cloudflare-pages","17:40 — ",[16,17330,18],{},[54,17332,17333,17338],{},[57,17334,11541,17335,11561],{},[16,17336,17337],{},"6f412e5",[57,17339,17340],{},"메시지: feat(auth): tb_user 통합 로그인 — \u002Flogin + auth.global 미들웨어 + JWT httpOnly cookie 세션 (8h)",{"title":423,"searchDepth":3342,"depth":3342,"links":17342},[17343,17352],{"id":15536,"depth":3335,"text":15536,"children":17344},[17345,17346,17347,17348,17349,17350,17351],{"id":16725,"depth":3342,"text":16726},{"id":16809,"depth":3342,"text":16810},{"id":16905,"depth":3342,"text":16906},{"id":17003,"depth":3342,"text":17004},{"id":12550,"depth":3342,"text":12551},{"id":3763,"depth":3342,"text":3763},{"id":15794,"depth":3342,"text":15795},{"id":11529,"depth":3335,"text":11529,"children":17353},[17354,17356,17358,17360,17362],{"id":17242,"depth":3342,"text":17355},"16:17 — malgn-helper-admin → Cloudflare Pages",{"id":17279,"depth":3342,"text":17357},"16:42 — malgn-helper-api → Cloudflare Workers",{"id":17295,"depth":3342,"text":17359},"16:50 — malgn-helper-admin → Cloudflare Pages",{"id":17311,"depth":3342,"text":17361},"17:37 — malgn-helper-api → Cloudflare Workers",{"id":17327,"depth":3342,"text":17363},"17:40 — malgn-helper-admin → Cloudflare Pages",{},"\u002Fhistory\u002Fhistory.20260608",{"title":16706,"description":423},"history\u002Fhistory.20260608","uyRjsN4uWp_k-2h9hkP-dhW3jfiPs8UU86wICzg63PE",{"id":17370,"title":17371,"body":17372,"description":17638,"extension":4340,"meta":17639,"navigation":3338,"path":17640,"seo":17641,"stem":17642,"__hash__":17643},"docs\u002Fhistory\u002FREADME.md","작업 이력 (doc\u002Fhistory\u002F)",{"type":8,"value":17373,"toc":17631},[17374,17381,17390,17394,17400,17407,17411,17414,17441,17444,17579,17583,17591,17593,17599,17628],[11,17375,17377,17378,78],{"id":17376},"작업-이력-dochistory","작업 이력 (",[16,17379,17380],{},"doc\u002Fhistory\u002F",[24,17382,17383,17385,17386,17389],{},[16,17384,47],{},"(고객상담 AI 챗봇) 프로젝트의 날짜별 작업 내역을 누적해 두는 폴더입니다. ",[28,17387,17388],{},"하루에 한 파일"," 원칙.",[36,17391,17393],{"id":17392},"파일명-규칙","파일명 규칙",[415,17395,17398],{"className":17396,"code":17397,"language":420},[418],"history.yyyyMMdd.md\n",[16,17399,17397],{"__ignoreMap":423},[24,17401,17402,17403,17406],{},"예: ",[16,17404,17405],{},"history.20260608.md",". 작업이 있는 날만 생성합니다.",[36,17408,17410],{"id":17409},"파일-구조-공통","파일 구조 (공통)",[24,17412,17413],{},"각 파일은 다음 순서를 따릅니다.",[1925,17415,17416,17422,17428,17436],{},[57,17417,17418,17421],{},[28,17419,17420],{},"종합 \u002F 요약"," — 그 날의 가장 큰 변화",[57,17423,17424,17427],{},[28,17425,17426],{},"번호별 작업 섹션"," — 결정 사항 \u002F 코드 변경 \u002F 검증",[57,17429,17430,2448,17432,17435],{},[28,17431,11529],{},[16,17433,17434],{},"deploy.sh","로 기록되는 repo별 배포 항목",[57,17437,17438],{},[28,17439,17440],{},"다음 작업 후보 \u002F 알려진 한계",[36,17442,17443],{"id":17443},"인덱스",[135,17445,17446,17455],{},[138,17447,17448],{},[141,17449,17450,17453],{},[144,17451,17452],{},"날짜",[144,17454,9923],{},[157,17456,17457,17499,17512,17528,17542,17552,17566],{},[141,17458,17459,17464],{},[162,17460,17461],{},[3257,17462,3945],{"href":17463},".\u002Fhistory.20260608",[162,17465,17466,17471,17472,2855,17474,17476,17477,17479,17480,2855,17482,17484,17485,17488,17489,17492,17493,530,17495,530,17497,78],{},[28,17467,16719,17468,17470],{},[16,17469,18],{},") 일괄 진입"," — ADMIN-PLAN 기획서(6 라운드, 5 그룹×17 메뉴) + admin 골격(256px LNB·64px TopBar·17 페이지 stub) + 1순위 4 화면 실데이터(홈 KPI·",[16,17473,836],{},[16,17475,642],{}," iframe 모달·",[16,17478,754],{}," 그리드) + API 신규 2(",[16,17481,16939],{},[16,17483,2339],{},") + ",[28,17486,17487],{},"tb_user 통합 로그인","(JWT 8h httpOnly · ",[16,17490,17491],{},"\u002Fauth\u002Flogin·logout·me"," · 역할 ",[16,17494,171],{},[16,17496,189],{},[16,17498,207],{},[141,17500,17501,17507],{},[162,17502,17503],{},[3257,17504,17506],{"href":17505},".\u002Fhistory.20260605","2026-06-05",[162,17508,17509,17511],{},[28,17510,16309],{}," + inquiry-only 모드(답변 없는 문의는 5축 평가 생략·추천 답변 6종만) + PMS UI 폴리시 다회",[141,17513,17514,17520],{},[162,17515,17516],{},[3257,17517,17519],{"href":17518},".\u002Fhistory.20260604","2026-06-04",[162,17521,17522,17523,530,17525,17527],{},"PMS 분석 모달 UX + 임베드 인터페이스(",[16,17524,16034],{},[16,17526,16038],{},") + GPT-4.1-mini Vision 이미지 URL 절대화·안정화",[141,17529,17530,17536],{},[162,17531,17532],{},[3257,17533,17535],{"href":17534},".\u002Fhistory.20260602","2026-06-02",[162,17537,17538,17539,17541],{},"WBS 페이지 라이트 톤 강제(",[16,17540,15550],{}," body bg 일원화) + 4 repo nuxt.config colorMode 정리",[141,17543,17544,17549],{},[162,17545,17546],{},[3257,17547,15433],{"href":17548},".\u002Fhistory.20260601",[162,17550,17551],{},"문서 현행화 — 인프라 활성화(Hyperdrive·R2·AI Gateway) + API 22+ 엔드포인트를 WBS.md에 일괄 반영",[141,17553,17554,17559],{},[162,17555,17556],{},[3257,17557,15428],{"href":17558},".\u002Fhistory.20260529",[162,17560,17561,17562,17565],{},"스토리보드 PMS 데모 → ",[28,17563,17564],{},"동작하는 LLM 기반 CS 헬퍼 백엔드\u002F관리자","로 도약 (브리핑·Q&A 평가·표준답변·캐시·감사)",[141,17567,17568,17573],{},[162,17569,17570],{},[3257,17571,9087],{"href":17572},".\u002Fhistory.20260528",[162,17574,17575,17576,17578],{},"프로젝트 착수 — ",[16,17577,4588],{}," 정의 추가 + 4개 GitHub repo 연결 + Cloudflare Workers\u002FPages 보일러플레이트 + 다중 계정(account_id 명시)",[36,17580,17582],{"id":17581},"작성-시점","작성 시점",[54,17584,17585,17588],{},[57,17586,17587],{},"큰 마일스톤 마무리 직후",[57,17589,17590],{},"그날 끝낼 때 짧게라도 한 줄 요약 + 산출물 목록만이라도",[36,17592,1182],{"id":1182},[24,17594,17595,17596,3360],{},"특정 결정을 언제 했는지 찾을 때 ",[16,17597,17598],{},"grep",[415,17600,17602],{"className":4632,"code":17601,"language":4634,"meta":423,"style":423},"grep -rn \"hp_image_asset\" doc\u002Fhistory\u002F\ngrep -rn \"tb_user 통합\" doc\u002Fhistory\u002F\n",[16,17603,17604,17617],{"__ignoreMap":423},[2166,17605,17606,17608,17611,17614],{"class":3301,"line":3302},[2166,17607,17598],{"class":3309},[2166,17609,17610],{"class":3402}," -rn",[2166,17612,17613],{"class":3316}," \"hp_image_asset\"",[2166,17615,17616],{"class":3316}," doc\u002Fhistory\u002F\n",[2166,17618,17619,17621,17623,17626],{"class":3301,"line":3335},[2166,17620,17598],{"class":3309},[2166,17622,17610],{"class":3402},[2166,17624,17625],{"class":3316}," \"tb_user 통합\"",[2166,17627,17616],{"class":3316},[4258,17629,17630],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":423,"searchDepth":3342,"depth":3342,"links":17632},[17633,17634,17635,17636,17637],{"id":17392,"depth":3335,"text":17393},{"id":17409,"depth":3335,"text":17410},{"id":17443,"depth":3335,"text":17443},{"id":17581,"depth":3335,"text":17582},{"id":1182,"depth":3335,"text":1182},"malgn-helper(고객상담 AI 챗봇) 프로젝트의 날짜별 작업 내역을 누적해 두는 폴더입니다. 하루에 한 파일 원칙.",{},"\u002Fhistory\u002Freadme",{"title":17371,"description":17638},"history\u002FREADME","emGkajWcHDUf1hckN_WHdRPhbtgyCUuPRvVSCUJp8sE",{"id":17645,"title":17646,"body":17647,"description":19546,"extension":4340,"meta":19547,"navigation":3338,"path":19548,"seo":19549,"stem":19550,"__hash__":19551},"docs\u002FHP-SCHEMA.md","Malgn Helper — DB 스키마 설계 (hp_* 테이블)",{"type":8,"value":17648,"toc":19521},[17649,17656,17670,17687,17689,17693,17754,17756,17760,17766,17768,17772,17779,17958,17962,17976,17988,17990,17997,18176,18180,18197,18199,18206,18212,18377,18381,18406,18408,18415,18418,18585,18589,18602,18604,18611,18622,18789,18793,18812,18814,18818,19341,19343,19347,19351,19357,19361,19367,19371,19377,19381,19387,19389,19393,19396,19430,19436,19438,19442,19519],[11,17650,17652,17653,17655],{"id":17651},"malgn-helper-db-스키마-설계-hp_-테이블","Malgn Helper — DB 스키마 설계 (",[16,17654,12167],{}," 테이블)",[24,17657,17658,17659,17665,17666,17669],{},"PMS DB 안에 ",[28,17660,17661,17664],{},[16,17662,17663],{},"hp_"," 접두사","로 헬퍼 전용 테이블을 둔다. 운영 PMS 테이블(",[16,17667,17668],{},"tb_*",")과 명확히 격리되며, 추후 별도 DB로 마이그레이션할 때도 검색·이전이 쉽다.",[21,17671,17672],{},[24,17673,17674,17675,17678,17679,17682,17683,17686],{},"약어 ",[16,17676,17677],{},"hp"," = ",[28,17680,17681],{},"H","elper ",[28,17684,17685],{},"P","roject. 모든 헬퍼 테이블 공통 접두사.",[33,17688],{},[36,17690,17692],{"id":17691},"_1-설계-원칙","1. 설계 원칙",[1925,17694,17695,17704,17714,17726,17735,17744],{},[57,17696,17697,17703],{},[28,17698,17699,17700,17702],{},"PMS 운영 테이블(",[16,17701,17668],{},")에는 외래키 걸지 않는다."," 참조만 하고 검증은 애플리케이션 레벨에서. PMS 스키마 변경에 영향받지 않기 위해.",[57,17705,17706,17713],{},[28,17707,17708,17709,17712],{},"모든 테이블에 ",[16,17710,17711],{},"status TINYINT"," (1=활성, -1=삭제)"," — soft delete 통일.",[57,17715,17716,1305,17723,17725],{},[28,17717,17718,17719,17722],{},"시간 컬럼은 ",[16,17720,17721],{},"DATETIME"," 사용",[16,17724,17668],{},"은 varchar(14) 레거시. 신규 테이블은 표준형).",[57,17727,17728,3351,17731,17734],{},[28,17729,17730],{},"LLM 결과는 통째로 JSON 컬럼에",[16,17732,17733],{},"LONGTEXT"," + JSON serialization). 향후 스키마 진화에 유연.",[57,17736,17737,17740,17741,133],{},[28,17738,17739],{},"자주 정렬·조회되는 핵심 값은 별도 컬럼","으로 빼서 인덱스 (예: ",[16,17742,17743],{},"hp_qa_eval.overall_score",[57,17745,17746,17749,17750,17753],{},[28,17747,17748],{},"버전 이력 보존"," — 같은 프로젝트\u002F게시글의 재생성은 같은 row 갱신이 아니라 ",[28,17751,17752],{},"새 row append",". 시계열 분석·되돌리기 가능.",[33,17755],{},[36,17757,17759],{"id":17758},"_2-erd-텍스트","2. ERD (텍스트)",[415,17761,17764],{"className":17762,"code":17763,"language":420},[418],"tb_project   tb_post\n   │            │\n   │ project_id │ post_id\n   ▼            ▼\n┌─────────────────────┐    ┌─────────────────────┐\n│  hp_briefing        │    │  hp_qa_eval         │\n│  (프로젝트 브리핑   │    │  (게시글 Q&A 평가   │\n│   여러 버전 누적)   │    │   여러 버전 누적)   │\n└──────────┬──────────┘    └──────────┬──────────┘\n           │                          │\n           │  saved_from              │  source_post_id\n           ▼                          ▼\n        ┌─────────────────────────────────┐\n        │  hp_standard_answer             │\n        │  (표준 답변 카탈로그            │\n        │   — 챗봇 응답 1순위 소스)       │\n        └─────────────────────────────────┘\n\n  (모든 LLM 호출은 hp_llm_log로 집계 — entity_type\u002Fid로 위 3개 테이블과 느슨 연결)\n",[16,17765,17763],{"__ignoreMap":423},[33,17767],{},[36,17769,17771],{"id":17770},"_3-테이블-상세","3. 테이블 상세",[215,17773,17775,17776,17778],{"id":17774},"_3-1-hp_briefing-프로젝트-브리핑-카드-캐시","3-1. ",[16,17777,2854],{}," — 프로젝트 브리핑 카드 캐시",[135,17780,17781,17793],{},[138,17782,17783],{},[141,17784,17785,17788,17791],{},[144,17786,17787],{},"컬럼",[144,17789,17790],{},"타입",[144,17792,1292],{},[157,17794,17795,17806,17822,17835,17856,17871,17883,17895,17906,17917,17933,17946],{},[141,17796,17797,17801,17804],{},[162,17798,17799],{},[16,17800,11737],{},[162,17802,17803],{},"INT PK AI",[162,17805],{},[141,17807,17808,17813,17816],{},[162,17809,17810],{},[16,17811,17812],{},"project_id",[162,17814,17815],{},"INT NOT NULL",[162,17817,17818,17821],{},[16,17819,17820],{},"tb_project.id"," (FK 없음)",[141,17823,17824,17829,17832],{},[162,17825,17826],{},[16,17827,17828],{},"generated_at",[162,17830,17831],{},"DATETIME NOT NULL",[162,17833,17834],{},"LLM 생성 시각",[141,17836,17837,17842,17845],{},[162,17838,17839],{},[16,17840,17841],{},"generator",[162,17843,17844],{},"VARCHAR(20) NOT NULL",[162,17846,17847,1365,17850,1365,17853],{},[16,17848,17849],{},"db_only",[16,17851,17852],{},"llm",[16,17854,17855],{},"hybrid",[141,17857,17858,17863,17866],{},[162,17859,17860],{},[16,17861,17862],{},"llm_model",[162,17864,17865],{},"VARCHAR(50) NULL",[162,17867,17402,17868],{},[16,17869,17870],{},"claude-sonnet-4-6",[141,17872,17873,17877,17880],{},[162,17874,17875],{},[16,17876,2800],{},[162,17878,17879],{},"CHAR(64) NULL",[162,17881,17882],{},"동일 입력 캐시 키 (project state SHA-256)",[141,17884,17885,17890,17893],{},[162,17886,17887],{},[16,17888,17889],{},"prompt_tokens",[162,17891,17892],{},"INT NULL",[162,17894],{},[141,17896,17897,17902,17904],{},[162,17898,17899],{},[16,17900,17901],{},"completion_tokens",[162,17903,17892],{},[162,17905],{},[141,17907,17908,17913,17915],{},[162,17909,17910],{},[16,17911,17912],{},"latency_ms",[162,17914,17892],{},[162,17916],{},[141,17918,17919,17924,17927],{},[162,17920,17921],{},[16,17922,17923],{},"briefing_json",[162,17925,17926],{},"LONGTEXT NOT NULL",[162,17928,17929,17932],{},[16,17930,17931],{},"Briefing"," 객체 전체",[141,17934,17935,17940,17943],{},[162,17936,17937],{},[16,17938,17939],{},"status",[162,17941,17942],{},"TINYINT NOT NULL DEFAULT 1",[162,17944,17945],{},"1=활성 \u002F -1=삭제",[141,17947,17948,17953,17956],{},[162,17949,17950],{},[16,17951,17952],{},"created_at",[162,17954,17955],{},"DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP",[162,17957],{},[24,17959,17960],{},[28,17961,17443],{},[54,17963,17964,17970],{},[57,17965,17966,17969],{},[16,17967,17968],{},"idx_project_status_gen (project_id, status, generated_at DESC)"," — 프로젝트별 최신 N건",[57,17971,17972,17975],{},[16,17973,17974],{},"idx_input_hash (llm_input_hash)"," — 캐시 lookup",[24,17977,17978,17981,17982,17984,17985,17987],{},[28,17979,17980],{},"캐시 정책",": 같은 ",[16,17983,17812],{}," + 같은 ",[16,17986,2800],{},"가 24시간 이내면 재사용. 그 외엔 새 LLM 호출.",[33,17989],{},[215,17991,17993,17994,17996],{"id":17992},"_3-2-hp_qa_eval-게시글-qa-평가-캐시","3-2. ",[16,17995,2858],{}," — 게시글 Q&A 평가 캐시",[135,17998,17999,18009],{},[138,18000,18001],{},[141,18002,18003,18005,18007],{},[144,18004,17787],{},[144,18006,17790],{},[144,18008,1292],{},[157,18010,18011,18021,18035,18046,18056,18066,18076,18087,18097,18107,18117,18131,18144,18156,18166],{},[141,18012,18013,18017,18019],{},[162,18014,18015],{},[16,18016,11737],{},[162,18018,17803],{},[162,18020],{},[141,18022,18023,18028,18030],{},[162,18024,18025],{},[16,18026,18027],{},"post_id",[162,18029,17815],{},[162,18031,18032],{},[16,18033,18034],{},"tb_post.id",[141,18036,18037,18041,18043],{},[162,18038,18039],{},[16,18040,17812],{},[162,18042,17815],{},[162,18044,18045],{},"조회 편의(중복 저장)",[141,18047,18048,18052,18054],{},[162,18049,18050],{},[16,18051,17828],{},[162,18053,17831],{},[162,18055],{},[141,18057,18058,18062,18064],{},[162,18059,18060],{},[16,18061,17841],{},[162,18063,17844],{},[162,18065],{},[141,18067,18068,18072,18074],{},[162,18069,18070],{},[16,18071,17862],{},[162,18073,17865],{},[162,18075],{},[141,18077,18078,18082,18084],{},[162,18079,18080],{},[16,18081,2800],{},[162,18083,17879],{},[162,18085,18086],{},"post + 댓글 본문 해시",[141,18088,18089,18093,18095],{},[162,18090,18091],{},[16,18092,17889],{},[162,18094,17892],{},[162,18096],{},[141,18098,18099,18103,18105],{},[162,18100,18101],{},[16,18102,17901],{},[162,18104,17892],{},[162,18106],{},[141,18108,18109,18113,18115],{},[162,18110,18111],{},[16,18112,17912],{},[162,18114,17892],{},[162,18116],{},[141,18118,18119,18124,18126],{},[162,18120,18121],{},[16,18122,18123],{},"eval_json",[162,18125,17926],{},[162,18127,18128,17932],{},[16,18129,18130],{},"QaEval",[141,18132,18133,18138,18141],{},[162,18134,18135],{},[16,18136,18137],{},"overall_score",[162,18139,18140],{},"DECIMAL(3,2) NULL",[162,18142,18143],{},"정렬·필터용 (예: 4.20)",[141,18145,18146,18150,18153],{},[162,18147,18148],{},[16,18149,15640],{},[162,18151,18152],{},"VARCHAR(100) NULL",[162,18154,18155],{},"표시용 한 줄 평 (예: \"알림톡 기능 추가 절차를 명확하게 안내함\") — 2026-05-29 VARCHAR(20)→100 마이그레이션",[141,18157,18158,18162,18164],{},[162,18159,18160],{},[16,18161,17939],{},[162,18163,17942],{},[162,18165],{},[141,18167,18168,18172,18174],{},[162,18169,18170],{},[16,18171,17952],{},[162,18173,17955],{},[162,18175],{},[24,18177,18178],{},[28,18179,17443],{},[54,18181,18182,18187,18193],{},[57,18183,18184],{},[16,18185,18186],{},"idx_post_status_gen (post_id, status, generated_at DESC)",[57,18188,18189,18192],{},[16,18190,18191],{},"idx_project_score (project_id, overall_score DESC)"," — 프로젝트별 우수\u002F취약 응대 정렬",[57,18194,18195],{},[16,18196,17974],{},[33,18198],{},[215,18200,18202,18203,18205],{"id":18201},"_3-3-hp_standard_answer-표준-답변-카탈로그","3-3. ",[16,18204,2125],{}," — 표준 답변 카탈로그",[24,18207,18208,18209,407],{},"QaEval 카드에서 \"표준답변으로 저장\" 액션 → 이 테이블에 누적. ",[28,18210,18211],{},"챗봇 응답의 1순위 소스",[135,18213,18214,18224],{},[138,18215,18216],{},[141,18217,18218,18220,18222],{},[144,18219,17787],{},[144,18221,17790],{},[144,18223,1292],{},[157,18225,18226,18236,18248,18261,18273,18284,18296,18309,18321,18333,18345,18355,18365],{},[141,18227,18228,18232,18234],{},[162,18229,18230],{},[16,18231,11737],{},[162,18233,17803],{},[162,18235],{},[141,18237,18238,18242,18245],{},[162,18239,18240],{},[16,18241,3022],{},[162,18243,18244],{},"VARCHAR(100) NOT NULL",[162,18246,18247],{},"카드\u002F탭 헤더",[141,18249,18250,18255,18258],{},[162,18251,18252],{},[16,18253,18254],{},"question",[162,18256,18257],{},"TEXT NOT NULL",[162,18259,18260],{},"다루는 질문 패턴",[141,18262,18263,18268,18270],{},[162,18264,18265],{},[16,18266,18267],{},"answer",[162,18269,18257],{},[162,18271,18272],{},"답변 본문",[141,18274,18275,18279,18281],{},[162,18276,18277],{},[16,18278,17812],{},[162,18280,17892],{},[162,18282,18283],{},"NULL = 전사 공통, 값 있으면 해당 프로젝트 전용",[141,18285,18286,18291,18293],{},[162,18287,18288],{},[16,18289,18290],{},"source_post_id",[162,18292,17892],{},[162,18294,18295],{},"출처 게시글",[141,18297,18298,18303,18306],{},[162,18299,18300],{},[16,18301,18302],{},"source_axis",[162,18304,18305],{},"VARCHAR(10) NULL",[162,18307,18308],{},"QaEval 축 (A\u002FB\u002FC\u002FD\u002FE)",[141,18310,18311,18316,18318],{},[162,18312,18313],{},[16,18314,18315],{},"created_by",[162,18317,18152],{},[162,18319,18320],{},"저장한 직원 이메일 (인증 도입 후)",[141,18322,18323,18327,18330],{},[162,18324,18325],{},[16,18326,1958],{},[162,18328,18329],{},"INT NOT NULL DEFAULT 0",[162,18331,18332],{},"챗봇이 사용한 횟수",[141,18334,18335,18340,18343],{},[162,18336,18337],{},[16,18338,18339],{},"last_used_at",[162,18341,18342],{},"DATETIME NULL",[162,18344],{},[141,18346,18347,18351,18353],{},[162,18348,18349],{},[16,18350,17939],{},[162,18352,17942],{},[162,18354],{},[141,18356,18357,18361,18363],{},[162,18358,18359],{},[16,18360,17952],{},[162,18362,17955],{},[162,18364],{},[141,18366,18367,18372,18375],{},[162,18368,18369],{},[16,18370,18371],{},"updated_at",[162,18373,18374],{},"DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP",[162,18376],{},[24,18378,18379],{},[28,18380,17443],{},[54,18382,18383,18388,18394,18400],{},[57,18384,18385],{},[16,18386,18387],{},"idx_project_status (project_id, status)",[57,18389,18390,18393],{},[16,18391,18392],{},"idx_usage (status, usage_count DESC)"," — 인기 답변 순회",[57,18395,18396,18399],{},[16,18397,18398],{},"idx_source_post (source_post_id)"," — 출처 역추적",[57,18401,18402,18405],{},[16,18403,18404],{},"FULLTEXT idx_qa (question, answer)"," — InnoDB FULLTEXT (MySQL 5.6.4+ 지원)",[33,18407],{},[215,18409,18411,18412,18414],{"id":18410},"_3-4-hp_llm_log-llm-호출-감사-로그","3-4. ",[16,18413,12177],{}," — LLM 호출 감사 로그",[24,18416,18417],{},"비용·지연·실패 추적. 전 엔티티 공통.",[135,18419,18420,18430],{},[138,18421,18422],{},[141,18423,18424,18426,18428],{},[144,18425,17787],{},[144,18427,17790],{},[144,18429,1292],{},[157,18431,18432,18443,18457,18479,18491,18503,18513,18523,18533,18545,18561,18574],{},[141,18433,18434,18438,18441],{},[162,18435,18436],{},[16,18437,11737],{},[162,18439,18440],{},"BIGINT PK AI",[162,18442],{},[141,18444,18445,18450,18452],{},[162,18446,18447],{},[16,18448,18449],{},"route",[162,18451,18244],{},[162,18453,18454,18455,78],{},"호출 라우트 (예: ",[16,18456,12185],{},[141,18458,18459,18464,18467],{},[162,18460,18461],{},[16,18462,18463],{},"entity_type",[162,18465,18466],{},"VARCHAR(30) NOT NULL",[162,18468,18469,1365,18472,1365,18475,18478],{},[16,18470,18471],{},"briefing",[16,18473,18474],{},"qa_eval",[16,18476,18477],{},"chat"," 등",[141,18480,18481,18486,18488],{},[162,18482,18483],{},[16,18484,18485],{},"entity_id",[162,18487,17892],{},[162,18489,18490],{},"위 3개 테이블의 id (생성 후 채움)",[141,18492,18493,18498,18501],{},[162,18494,18495],{},[16,18496,18497],{},"model",[162,18499,18500],{},"VARCHAR(50) NOT NULL",[162,18502],{},[141,18504,18505,18509,18511],{},[162,18506,18507],{},[16,18508,17889],{},[162,18510,17892],{},[162,18512],{},[141,18514,18515,18519,18521],{},[162,18516,18517],{},[16,18518,17901],{},[162,18520,17892],{},[162,18522],{},[141,18524,18525,18529,18531],{},[162,18526,18527],{},[16,18528,17912],{},[162,18530,17892],{},[162,18532],{},[141,18534,18535,18540,18543],{},[162,18536,18537],{},[16,18538,18539],{},"cost_usd",[162,18541,18542],{},"DECIMAL(10,6) NULL",[162,18544],{},[141,18546,18547,18552,18555],{},[162,18548,18549],{},[16,18550,18551],{},"cache_hit",[162,18553,18554],{},"TINYINT NOT NULL DEFAULT 0",[162,18556,18557,18558,18560],{},"1 = ",[16,18559,2800],{}," 매치로 LLM 미호출",[141,18562,18563,18568,18571],{},[162,18564,18565],{},[16,18566,18567],{},"error",[162,18569,18570],{},"TEXT NULL",[162,18572,18573],{},"실패 시 메시지",[141,18575,18576,18581,18583],{},[162,18577,18578],{},[16,18579,18580],{},"request_at",[162,18582,17955],{},[162,18584],{},[24,18586,18587],{},[28,18588,17443],{},[54,18590,18591,18596],{},[57,18592,18593],{},[16,18594,18595],{},"idx_entity (entity_type, entity_id, request_at)",[57,18597,18598,18601],{},[16,18599,18600],{},"idx_request_at (request_at)"," — 일별 비용 집계",[33,18603],{},[215,18605,18607,18608,18610],{"id":18606},"_3-5-hp_image_asset-pms-자산-이미지-메타-vision-자동-분석","3-5. ",[16,18609,77],{}," — PMS 자산 이미지 메타 (Vision 자동 분석)",[24,18612,18613,18614,18617,18618,18621],{},"게시물 본문·답변에서 발견된 ",[16,18615,18616],{},"\u002Fdata\u002F..."," 이미지의 자동 캡션·설명. ",[28,18619,18620],{},"src_path 기준 UNIQUE","라 한 이미지는 한 번만 분석되고 이후 재사용. 챗봇·표준답변 생성 시 이미지 문맥을 텍스트로 인용 가능.",[135,18623,18624,18634],{},[138,18625,18626],{},[141,18627,18628,18630,18632],{},[144,18629,17787],{},[144,18631,17790],{},[144,18633,1292],{},[157,18635,18636,18646,18662,18674,18685,18698,18711,18723,18734,18745,18757,18768,18779],{},[141,18637,18638,18642,18644],{},[162,18639,18640],{},[16,18641,11737],{},[162,18643,17803],{},[162,18645],{},[141,18647,18648,18652,18655],{},[162,18649,18650],{},[16,18651,16372],{},[162,18653,18654],{},"VARCHAR(500) NOT NULL",[162,18656,18657,18658,18661],{},"원본 src (예: ",[16,18659,18660],{},"\u002Fdata\u002F1\u002Fc52ef0c2....png",") — 절대 URL은 코드에서 prefix",[141,18663,18664,18668,18671],{},[162,18665,18666],{},[16,18667,2286],{},[162,18669,18670],{},"VARCHAR(200) NOT NULL",[162,18672,18673],{},"Vision이 생성한 짧은 제목 (예: \"알림톡 코드 확인 화면\")",[141,18675,18676,18680,18682],{},[162,18677,18678],{},[16,18679,2289],{},[162,18681,18257],{},[162,18683,18684],{},"Vision이 생성한 본문 설명 (메뉴\u002F버튼\u002F필드명·맥락)",[141,18686,18687,18691,18693],{},[162,18688,18689],{},[16,18690,2303],{},[162,18692,17892],{},[162,18694,18695,18696],{},"처음 발견된 ",[16,18697,18034],{},[141,18699,18700,18705,18707],{},[162,18701,18702],{},[16,18703,18704],{},"first_seen_project_id",[162,18706,17892],{},[162,18708,18695,18709],{},[16,18710,17820],{},[141,18712,18713,18717,18720],{},[162,18714,18715],{},[16,18716,2296],{},[162,18718,18719],{},"ENUM('inquiry','reply') NULL",[162,18721,18722],{},"문의 본문 \u002F 답변 어느 쪽에서 발견",[141,18724,18725,18729,18731],{},[162,18726,18727],{},[16,18728,17862],{},[162,18730,17865],{},[162,18732,18733],{},"분석에 사용한 모델",[141,18735,18736,18741,18743],{},[162,18737,18738],{},[16,18739,18740],{},"analyzed_at",[162,18742,17955],{},[162,18744],{},[141,18746,18747,18751,18754],{},[162,18748,18749],{},[16,18750,1958],{},[162,18752,18753],{},"INT NOT NULL DEFAULT 1",[162,18755,18756],{},"같은 src가 다른 게시물에서 재발견된 횟수",[141,18758,18759,18763,18765],{},[162,18760,18761],{},[16,18762,18339],{},[162,18764,18342],{},[162,18766,18767],{},"재발견 시 갱신",[141,18769,18770,18774,18776],{},[162,18771,18772],{},[16,18773,17939],{},[162,18775,17942],{},[162,18777,18778],{},"1=활성, -1=숨김",[141,18780,18781,18785,18787],{},[162,18782,18783],{},[16,18784,17952],{},[162,18786,17955],{},[162,18788],{},[24,18790,18791],{},[28,18792,17443],{},[54,18794,18795,18801,18806],{},[57,18796,18797,18800],{},[16,18798,18799],{},"UNIQUE KEY uk_src_path (src_path)"," — 중복 분석 방지",[57,18802,18803],{},[16,18804,18805],{},"KEY idx_project (first_seen_project_id, analyzed_at)",[57,18807,18808,18811],{},[16,18809,18810],{},"KEY idx_usage (status, usage_count DESC)"," — 자주 쓰이는 이미지 순회",[33,18813],{},[36,18815,18817],{"id":18816},"_4-ddl-한-파일로-일괄-실행","4. DDL (한 파일로 일괄 실행)",[415,18819,18821],{"className":8581,"code":18820,"language":8583,"meta":423,"style":423},"-- malgn-helper-api\u002Fmigrations\u002F001_init_hp_tables.sql\n-- 실행 위치: PMS DB (pms)\n-- 안전: 기존 tb_* 테이블에 영향 없음. CREATE TABLE IF NOT EXISTS 사용.\n\nCREATE TABLE IF NOT EXISTS hp_briefing (\n  id                INT NOT NULL AUTO_INCREMENT,\n  project_id        INT NOT NULL,\n  generated_at      DATETIME NOT NULL,\n  generator         VARCHAR(20) NOT NULL,\n  llm_model         VARCHAR(50) NULL,\n  llm_input_hash    CHAR(64) NULL,\n  prompt_tokens     INT NULL,\n  completion_tokens INT NULL,\n  latency_ms        INT NULL,\n  briefing_json     LONGTEXT NOT NULL,\n  status            TINYINT NOT NULL DEFAULT 1,\n  created_at        DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  PRIMARY KEY (id),\n  KEY idx_project_status_gen (project_id, status, generated_at),\n  KEY idx_input_hash (llm_input_hash)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\n\nCREATE TABLE IF NOT EXISTS hp_qa_eval (\n  id                INT NOT NULL AUTO_INCREMENT,\n  post_id           INT NOT NULL,\n  project_id        INT NOT NULL,\n  generated_at      DATETIME NOT NULL,\n  generator         VARCHAR(20) NOT NULL,\n  llm_model         VARCHAR(50) NULL,\n  llm_input_hash    CHAR(64) NULL,\n  prompt_tokens     INT NULL,\n  completion_tokens INT NULL,\n  latency_ms        INT NULL,\n  eval_json         LONGTEXT NOT NULL,\n  overall_score     DECIMAL(3,2) NULL,\n  overall_verdict   VARCHAR(100) NULL,\n  status            TINYINT NOT NULL DEFAULT 1,\n  created_at        DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  PRIMARY KEY (id),\n  KEY idx_post_status_gen (post_id, status, generated_at),\n  KEY idx_project_score (project_id, overall_score),\n  KEY idx_input_hash (llm_input_hash)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\n\nCREATE TABLE IF NOT EXISTS hp_standard_answer (\n  id              INT NOT NULL AUTO_INCREMENT,\n  label           VARCHAR(100) NOT NULL,\n  question        TEXT NOT NULL,\n  answer          TEXT NOT NULL,\n  project_id      INT NULL,\n  source_post_id  INT NULL,\n  source_axis     VARCHAR(10) NULL,\n  created_by      VARCHAR(100) NULL,\n  usage_count     INT NOT NULL DEFAULT 0,\n  last_used_at    DATETIME NULL,\n  status          TINYINT NOT NULL DEFAULT 1,\n  created_at      DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  updated_at      DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n  PRIMARY KEY (id),\n  KEY idx_project_status (project_id, status),\n  KEY idx_usage (status, usage_count),\n  KEY idx_source_post (source_post_id),\n  FULLTEXT KEY idx_qa (question, answer)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\n\nCREATE TABLE IF NOT EXISTS hp_llm_log (\n  id                BIGINT NOT NULL AUTO_INCREMENT,\n  route             VARCHAR(100) NOT NULL,\n  entity_type       VARCHAR(30) NOT NULL,\n  entity_id         INT NULL,\n  model             VARCHAR(50) NOT NULL,\n  prompt_tokens     INT NULL,\n  completion_tokens INT NULL,\n  latency_ms        INT NULL,\n  cost_usd          DECIMAL(10,6) NULL,\n  cache_hit         TINYINT NOT NULL DEFAULT 0,\n  error             TEXT NULL,\n  request_at        DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  PRIMARY KEY (id),\n  KEY idx_entity (entity_type, entity_id, request_at),\n  KEY idx_request_at (request_at)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\n\nCREATE TABLE IF NOT EXISTS hp_image_asset (\n  id                       INT NOT NULL AUTO_INCREMENT,\n  src_path                 VARCHAR(500) NOT NULL,\n  title                    VARCHAR(200) NOT NULL,\n  description              TEXT NOT NULL,\n  first_seen_post_id       INT NULL,\n  first_seen_project_id    INT NULL,\n  source                   ENUM('inquiry','reply') NULL,\n  llm_model                VARCHAR(50) NULL,\n  analyzed_at              DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  usage_count              INT NOT NULL DEFAULT 1,\n  last_used_at             DATETIME NULL,\n  status                   TINYINT NOT NULL DEFAULT 1,\n  created_at               DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  PRIMARY KEY (id),\n  UNIQUE KEY uk_src_path (src_path),\n  KEY idx_project (first_seen_project_id, analyzed_at),\n  KEY idx_usage (status, usage_count)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\n",[16,18822,18823,18828,18833,18838,18842,18847,18852,18857,18862,18867,18872,18877,18882,18887,18892,18897,18902,18907,18912,18917,18922,18927,18931,18936,18940,18945,18949,18953,18957,18961,18965,18969,18973,18977,18982,18987,18992,18996,19000,19004,19009,19014,19018,19022,19026,19031,19036,19041,19046,19051,19056,19061,19066,19071,19076,19081,19086,19091,19096,19100,19105,19110,19115,19120,19124,19128,19133,19139,19145,19151,19157,19163,19168,19173,19178,19184,19190,19196,19202,19207,19213,19219,19224,19229,19235,19241,19247,19253,19259,19265,19271,19277,19283,19289,19295,19301,19307,19313,19318,19324,19330,19336],{"__ignoreMap":423},[2166,18824,18825],{"class":3301,"line":3302},[2166,18826,18827],{},"-- malgn-helper-api\u002Fmigrations\u002F001_init_hp_tables.sql\n",[2166,18829,18830],{"class":3301,"line":3335},[2166,18831,18832],{},"-- 실행 위치: PMS DB (pms)\n",[2166,18834,18835],{"class":3301,"line":3342},[2166,18836,18837],{},"-- 안전: 기존 tb_* 테이블에 영향 없음. CREATE TABLE IF NOT EXISTS 사용.\n",[2166,18839,18840],{"class":3301,"line":3368},[2166,18841,3339],{"emptyLinePlaceholder":3338},[2166,18843,18844],{"class":3301,"line":3396},[2166,18845,18846],{},"CREATE TABLE IF NOT EXISTS hp_briefing (\n",[2166,18848,18849],{"class":3301,"line":3426},[2166,18850,18851],{},"  id                INT NOT NULL AUTO_INCREMENT,\n",[2166,18853,18854],{"class":3301,"line":3463},[2166,18855,18856],{},"  project_id        INT NOT NULL,\n",[2166,18858,18859],{"class":3301,"line":3504},[2166,18860,18861],{},"  generated_at      DATETIME NOT NULL,\n",[2166,18863,18864],{"class":3301,"line":3538},[2166,18865,18866],{},"  generator         VARCHAR(20) NOT NULL,\n",[2166,18868,18869],{"class":3301,"line":3550},[2166,18870,18871],{},"  llm_model         VARCHAR(50) NULL,\n",[2166,18873,18874],{"class":3301,"line":3556},[2166,18875,18876],{},"  llm_input_hash    CHAR(64) NULL,\n",[2166,18878,18879],{"class":3301,"line":5367},[2166,18880,18881],{},"  prompt_tokens     INT NULL,\n",[2166,18883,18884],{"class":3301,"line":5375},[2166,18885,18886],{},"  completion_tokens INT NULL,\n",[2166,18888,18889],{"class":3301,"line":5392},[2166,18890,18891],{},"  latency_ms        INT NULL,\n",[2166,18893,18894],{"class":3301,"line":5404},[2166,18895,18896],{},"  briefing_json     LONGTEXT NOT NULL,\n",[2166,18898,18899],{"class":3301,"line":5415},[2166,18900,18901],{},"  status            TINYINT NOT NULL DEFAULT 1,\n",[2166,18903,18904],{"class":3301,"line":5421},[2166,18905,18906],{},"  created_at        DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,\n",[2166,18908,18909],{"class":3301,"line":5432},[2166,18910,18911],{},"  PRIMARY KEY (id),\n",[2166,18913,18914],{"class":3301,"line":5453},[2166,18915,18916],{},"  KEY idx_project_status_gen (project_id, status, generated_at),\n",[2166,18918,18919],{"class":3301,"line":5459},[2166,18920,18921],{},"  KEY idx_input_hash (llm_input_hash)\n",[2166,18923,18924],{"class":3301,"line":8686},[2166,18925,18926],{},") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\n",[2166,18928,18929],{"class":3301,"line":8692},[2166,18930,3339],{"emptyLinePlaceholder":3338},[2166,18932,18933],{"class":3301,"line":8698},[2166,18934,18935],{},"CREATE TABLE IF NOT EXISTS hp_qa_eval (\n",[2166,18937,18938],{"class":3301,"line":8704},[2166,18939,18851],{},[2166,18941,18942],{"class":3301,"line":8710},[2166,18943,18944],{},"  post_id           INT NOT NULL,\n",[2166,18946,18947],{"class":3301,"line":8716},[2166,18948,18856],{},[2166,18950,18951],{"class":3301,"line":8721},[2166,18952,18861],{},[2166,18954,18955],{"class":3301,"line":8727},[2166,18956,18866],{},[2166,18958,18959],{"class":3301,"line":8733},[2166,18960,18871],{},[2166,18962,18963],{"class":3301,"line":8739},[2166,18964,18876],{},[2166,18966,18967],{"class":3301,"line":8745},[2166,18968,18881],{},[2166,18970,18971],{"class":3301,"line":8751},[2166,18972,18886],{},[2166,18974,18975],{"class":3301,"line":8756},[2166,18976,18891],{},[2166,18978,18979],{"class":3301,"line":8762},[2166,18980,18981],{},"  eval_json         LONGTEXT NOT NULL,\n",[2166,18983,18984],{"class":3301,"line":8767},[2166,18985,18986],{},"  overall_score     DECIMAL(3,2) NULL,\n",[2166,18988,18989],{"class":3301,"line":8773},[2166,18990,18991],{},"  overall_verdict   VARCHAR(100) NULL,\n",[2166,18993,18994],{"class":3301,"line":8779},[2166,18995,18901],{},[2166,18997,18998],{"class":3301,"line":8785},[2166,18999,18906],{},[2166,19001,19002],{"class":3301,"line":8791},[2166,19003,18911],{},[2166,19005,19006],{"class":3301,"line":8797},[2166,19007,19008],{},"  KEY idx_post_status_gen (post_id, status, generated_at),\n",[2166,19010,19011],{"class":3301,"line":8803},[2166,19012,19013],{},"  KEY idx_project_score (project_id, overall_score),\n",[2166,19015,19016],{"class":3301,"line":8809},[2166,19017,18921],{},[2166,19019,19020],{"class":3301,"line":8815},[2166,19021,18926],{},[2166,19023,19024],{"class":3301,"line":8821},[2166,19025,3339],{"emptyLinePlaceholder":3338},[2166,19027,19028],{"class":3301,"line":8827},[2166,19029,19030],{},"CREATE TABLE IF NOT EXISTS hp_standard_answer (\n",[2166,19032,19033],{"class":3301,"line":8832},[2166,19034,19035],{},"  id              INT NOT NULL AUTO_INCREMENT,\n",[2166,19037,19038],{"class":3301,"line":8838},[2166,19039,19040],{},"  label           VARCHAR(100) NOT NULL,\n",[2166,19042,19043],{"class":3301,"line":8844},[2166,19044,19045],{},"  question        TEXT NOT NULL,\n",[2166,19047,19048],{"class":3301,"line":8849},[2166,19049,19050],{},"  answer          TEXT NOT NULL,\n",[2166,19052,19053],{"class":3301,"line":8855},[2166,19054,19055],{},"  project_id      INT NULL,\n",[2166,19057,19058],{"class":3301,"line":8860},[2166,19059,19060],{},"  source_post_id  INT NULL,\n",[2166,19062,19063],{"class":3301,"line":8866},[2166,19064,19065],{},"  source_axis     VARCHAR(10) NULL,\n",[2166,19067,19068],{"class":3301,"line":8871},[2166,19069,19070],{},"  created_by      VARCHAR(100) NULL,\n",[2166,19072,19073],{"class":3301,"line":8877},[2166,19074,19075],{},"  usage_count     INT NOT NULL DEFAULT 0,\n",[2166,19077,19078],{"class":3301,"line":8883},[2166,19079,19080],{},"  last_used_at    DATETIME NULL,\n",[2166,19082,19083],{"class":3301,"line":8888},[2166,19084,19085],{},"  status          TINYINT NOT NULL DEFAULT 1,\n",[2166,19087,19088],{"class":3301,"line":8894},[2166,19089,19090],{},"  created_at      DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,\n",[2166,19092,19093],{"class":3301,"line":8899},[2166,19094,19095],{},"  updated_at      DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n",[2166,19097,19098],{"class":3301,"line":8905},[2166,19099,18911],{},[2166,19101,19102],{"class":3301,"line":8911},[2166,19103,19104],{},"  KEY idx_project_status (project_id, status),\n",[2166,19106,19107],{"class":3301,"line":8917},[2166,19108,19109],{},"  KEY idx_usage (status, usage_count),\n",[2166,19111,19112],{"class":3301,"line":8923},[2166,19113,19114],{},"  KEY idx_source_post (source_post_id),\n",[2166,19116,19117],{"class":3301,"line":8929},[2166,19118,19119],{},"  FULLTEXT KEY idx_qa (question, answer)\n",[2166,19121,19122],{"class":3301,"line":8935},[2166,19123,18926],{},[2166,19125,19126],{"class":3301,"line":8941},[2166,19127,3339],{"emptyLinePlaceholder":3338},[2166,19129,19130],{"class":3301,"line":8947},[2166,19131,19132],{},"CREATE TABLE IF NOT EXISTS hp_llm_log (\n",[2166,19134,19136],{"class":3301,"line":19135},67,[2166,19137,19138],{},"  id                BIGINT NOT NULL AUTO_INCREMENT,\n",[2166,19140,19142],{"class":3301,"line":19141},68,[2166,19143,19144],{},"  route             VARCHAR(100) NOT NULL,\n",[2166,19146,19148],{"class":3301,"line":19147},69,[2166,19149,19150],{},"  entity_type       VARCHAR(30) NOT NULL,\n",[2166,19152,19154],{"class":3301,"line":19153},70,[2166,19155,19156],{},"  entity_id         INT NULL,\n",[2166,19158,19160],{"class":3301,"line":19159},71,[2166,19161,19162],{},"  model             VARCHAR(50) NOT NULL,\n",[2166,19164,19166],{"class":3301,"line":19165},72,[2166,19167,18881],{},[2166,19169,19171],{"class":3301,"line":19170},73,[2166,19172,18886],{},[2166,19174,19176],{"class":3301,"line":19175},74,[2166,19177,18891],{},[2166,19179,19181],{"class":3301,"line":19180},75,[2166,19182,19183],{},"  cost_usd          DECIMAL(10,6) NULL,\n",[2166,19185,19187],{"class":3301,"line":19186},76,[2166,19188,19189],{},"  cache_hit         TINYINT NOT NULL DEFAULT 0,\n",[2166,19191,19193],{"class":3301,"line":19192},77,[2166,19194,19195],{},"  error             TEXT NULL,\n",[2166,19197,19199],{"class":3301,"line":19198},78,[2166,19200,19201],{},"  request_at        DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,\n",[2166,19203,19205],{"class":3301,"line":19204},79,[2166,19206,18911],{},[2166,19208,19210],{"class":3301,"line":19209},80,[2166,19211,19212],{},"  KEY idx_entity (entity_type, entity_id, request_at),\n",[2166,19214,19216],{"class":3301,"line":19215},81,[2166,19217,19218],{},"  KEY idx_request_at (request_at)\n",[2166,19220,19222],{"class":3301,"line":19221},82,[2166,19223,18926],{},[2166,19225,19227],{"class":3301,"line":19226},83,[2166,19228,3339],{"emptyLinePlaceholder":3338},[2166,19230,19232],{"class":3301,"line":19231},84,[2166,19233,19234],{},"CREATE TABLE IF NOT EXISTS hp_image_asset (\n",[2166,19236,19238],{"class":3301,"line":19237},85,[2166,19239,19240],{},"  id                       INT NOT NULL AUTO_INCREMENT,\n",[2166,19242,19244],{"class":3301,"line":19243},86,[2166,19245,19246],{},"  src_path                 VARCHAR(500) NOT NULL,\n",[2166,19248,19250],{"class":3301,"line":19249},87,[2166,19251,19252],{},"  title                    VARCHAR(200) NOT NULL,\n",[2166,19254,19256],{"class":3301,"line":19255},88,[2166,19257,19258],{},"  description              TEXT NOT NULL,\n",[2166,19260,19262],{"class":3301,"line":19261},89,[2166,19263,19264],{},"  first_seen_post_id       INT NULL,\n",[2166,19266,19268],{"class":3301,"line":19267},90,[2166,19269,19270],{},"  first_seen_project_id    INT NULL,\n",[2166,19272,19274],{"class":3301,"line":19273},91,[2166,19275,19276],{},"  source                   ENUM('inquiry','reply') NULL,\n",[2166,19278,19280],{"class":3301,"line":19279},92,[2166,19281,19282],{},"  llm_model                VARCHAR(50) NULL,\n",[2166,19284,19286],{"class":3301,"line":19285},93,[2166,19287,19288],{},"  analyzed_at              DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,\n",[2166,19290,19292],{"class":3301,"line":19291},94,[2166,19293,19294],{},"  usage_count              INT NOT NULL DEFAULT 1,\n",[2166,19296,19298],{"class":3301,"line":19297},95,[2166,19299,19300],{},"  last_used_at             DATETIME NULL,\n",[2166,19302,19304],{"class":3301,"line":19303},96,[2166,19305,19306],{},"  status                   TINYINT NOT NULL DEFAULT 1,\n",[2166,19308,19310],{"class":3301,"line":19309},97,[2166,19311,19312],{},"  created_at               DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,\n",[2166,19314,19316],{"class":3301,"line":19315},98,[2166,19317,18911],{},[2166,19319,19321],{"class":3301,"line":19320},99,[2166,19322,19323],{},"  UNIQUE KEY uk_src_path (src_path),\n",[2166,19325,19327],{"class":3301,"line":19326},100,[2166,19328,19329],{},"  KEY idx_project (first_seen_project_id, analyzed_at),\n",[2166,19331,19333],{"class":3301,"line":19332},101,[2166,19334,19335],{},"  KEY idx_usage (status, usage_count)\n",[2166,19337,19339],{"class":3301,"line":19338},102,[2166,19340,18926],{},[33,19342],{},[36,19344,19346],{"id":19345},"_5-사용-흐름","5. 사용 흐름",[215,19348,19350],{"id":19349},"_5-1-브리핑-카드-생성","5-1. 브리핑 카드 생성",[415,19352,19355],{"className":19353,"code":19354,"language":420},[418],"화면: [AI 요약 카드 생성하기] 클릭\n    │\n    ▼\nAPI: POST \u002Fpms\u002Fprojects\u002F:id\u002Fbriefing\u002Fgenerate\n    │\n    ├─ 1. DB 집계 → input 객체 구성 (현재 GET \u002Fbriefing 로직 재사용)\n    ├─ 2. input SHA-256 = input_hash\n    ├─ 3. hp_briefing에 input_hash 매치 + 24h 이내 활성 row 있나?\n    │      ├─ YES → 그 row 반환 (cache_hit=1, hp_llm_log 기록)\n    │      └─ NO  → LLM 호출\n    │              ├─ Claude → hotTopics\u002Ffaq\u002Fpolicies\u002FoneLine 요약 생성\n    │              ├─ DB 집계 + LLM 결과 병합한 briefing_json 저장 (status=1)\n    │              └─ hp_llm_log 기록 (cache_hit=0, 토큰·지연·비용)\n    └─ 4. 응답: { briefing }\n",[16,19356,19354],{"__ignoreMap":423},[215,19358,19360],{"id":19359},"_5-2-qa-평가-생성","5-2. Q&A 평가 생성",[415,19362,19365],{"className":19363,"code":19364,"language":420},[418],"화면: 게시글 상세에서 [평가 카드 생성]\n    │\n    ▼\nAPI: POST \u002Fpms\u002Fposts\u002F:id\u002Feval\u002Fgenerate\n    │\n    ├─ 1. tb_post + tb_post_comment + tb_user로 input 구성\n    ├─ 2. input_hash 계산\n    ├─ 3. hp_qa_eval 캐시 lookup (post_id + input_hash)\n    │      └─ HIT 또는 MISS → LLM 호출 후 새 row append\n    └─ 4. overall_score를 별도 컬럼으로 추출 저장\n",[16,19366,19364],{"__ignoreMap":423},[215,19368,19370],{"id":19369},"_5-3-표준답변-저장-사용자-액션","5-3. 표준답변 저장 (사용자 액션)",[415,19372,19375],{"className":19373,"code":19374,"language":420},[418],"QaEval 카드의 \"이 템플릿을 표준답변으로 저장\" 버튼\n    │\n    ▼\nAPI: POST \u002Fstandard-answers\n  body: { label, question, answer, projectId?, sourcePostId, sourceAxis }\n    │\n    └─ hp_standard_answer INSERT (status=1, usage_count=0)\n",[16,19376,19374],{"__ignoreMap":423},[215,19378,19380],{"id":19379},"_5-4-표준답변-검색-챗봇-응답-1순위","5-4. 표준답변 검색 (챗봇 응답 1순위)",[415,19382,19385],{"className":19383,"code":19384,"language":420},[418],"챗봇 질의 → API: GET \u002Fstandard-answers\u002Fmatch?q=...\n    │\n    ├─ FULLTEXT MATCH (question, answer) AGAINST (?)\n    ├─ 같은 project_id 우선, 그 다음 NULL(전사 공통)\n    ├─ usage_count 증가 + last_used_at 업데이트\n    └─ 챗봇 응답 컴포저로 전달\n",[16,19386,19384],{"__ignoreMap":423},[33,19388],{},[36,19390,19392],{"id":19391},"_6-향후-분리-시나리오","6. 향후 분리 시나리오",[24,19394,19395],{},"PMS 운영팀과 분리 협의가 필요해지면:",[1925,19397,19398,19405,19412,19418,19424],{},[57,19399,19400,19401,19404],{},"새 Aurora MySQL DB(",[16,19402,19403],{},"malgn_helper",") 구축",[57,19406,19407,19408,19411],{},"Hyperdrive에 새 connection string 등록 (",[16,19409,19410],{},"HYPERDRIVE_HELPER"," 바인딩 추가)",[57,19413,19414,19417],{},[16,19415,19416],{},"mysqldump --tables hp_*"," → 새 DB 로드",[57,19419,19420,19421,19423],{},"API 코드에서 ",[16,19422,12167],{}," 쿼리만 새 바인딩으로 전환",[57,19425,19426,19427,19429],{},"PMS DB의 ",[16,19428,12167],{}," 테이블은 1주일 보존 후 DROP",[24,19431,19432,19433,407],{},"테이블 접두사를 일관되게 둔 이유 = ",[28,19434,19435],{},"이 단계를 단순화하기 위함",[33,19437],{},[36,19439,19441],{"id":19440},"_7-보안운영-메모","7. 보안·운영 메모",[135,19443,19444,19453],{},[138,19445,19446],{},[141,19447,19448,19450],{},[144,19449,4143],{},[144,19451,19452],{},"방침",[157,19454,19455,19469,19479,19488,19499,19511],{},[141,19456,19457,19463],{},[162,19458,19459,19460,78],{},"비공개 댓글 본문(",[16,19461,19462],{},"tb_post_comment.private_yn='Y'",[162,19464,19465,19468],{},[16,19466,19467],{},"hp_qa_eval.eval_json","에 절대 저장 금지. LLM 입력 단계에서 필터링",[141,19470,19471,19474],{},[162,19472,19473],{},"직원\u002F고객 분류",[162,19475,19476,19478],{},[16,19477,128],{}," 매칭 결과만 저장. PII는 추가 저장 안 함",[141,19480,19481,19485],{},[162,19482,19483],{},[16,19484,18315],{},[162,19486,19487],{},"인증 도입 전까지는 NULL. 도입 후엔 직원 이메일 필수",[141,19489,19490,19493],{},[162,19491,19492],{},"비용 추적",[162,19494,19495,19498],{},[16,19496,19497],{},"hp_llm_log.cost_usd","를 일별 GROUP BY로 대시보드 (별도 페이지)",[141,19500,19501,19504],{},[162,19502,19503],{},"캐시 무효화",[162,19505,19506,19507,19510],{},"화면의 \"새 카드 생성\" 버튼 = ",[16,19508,19509],{},"?force=1"," 쿼리로 캐시 우회",[141,19512,19513,19516],{},[162,19514,19515],{},"백업",[162,19517,19518],{},"PMS DB 전체 백업에 포함 (별도 백업 불필요 — 분리 전까지)",[4258,19520,8979],{},{"title":423,"searchDepth":3342,"depth":3342,"links":19522},[19523,19524,19525,19537,19538,19544,19545],{"id":17691,"depth":3335,"text":17692},{"id":17758,"depth":3335,"text":17759},{"id":17770,"depth":3335,"text":17771,"children":19526},[19527,19529,19531,19533,19535],{"id":17774,"depth":3342,"text":19528},"3-1. hp_briefing — 프로젝트 브리핑 카드 캐시",{"id":17992,"depth":3342,"text":19530},"3-2. hp_qa_eval — 게시글 Q&A 평가 캐시",{"id":18201,"depth":3342,"text":19532},"3-3. hp_standard_answer — 표준 답변 카탈로그",{"id":18410,"depth":3342,"text":19534},"3-4. hp_llm_log — LLM 호출 감사 로그",{"id":18606,"depth":3342,"text":19536},"3-5. hp_image_asset — PMS 자산 이미지 메타 (Vision 자동 분석)",{"id":18816,"depth":3335,"text":18817},{"id":19345,"depth":3335,"text":19346,"children":19539},[19540,19541,19542,19543],{"id":19349,"depth":3342,"text":19350},{"id":19359,"depth":3342,"text":19360},{"id":19369,"depth":3342,"text":19370},{"id":19379,"depth":3342,"text":19380},{"id":19391,"depth":3335,"text":19392},{"id":19440,"depth":3335,"text":19441},"PMS DB 안에 hp_ 접두사로 헬퍼 전용 테이블을 둔다. 운영 PMS 테이블(tb_*)과 명확히 격리되며, 추후 별도 DB로 마이그레이션할 때도 검색·이전이 쉽다.",{},"\u002Fhp-schema",{"title":17646,"description":19546},"HP-SCHEMA","tvO7CBQ3rJaCFEUlze0Sos7g50dvAm-fk7X0OZD62ic",{"id":19553,"title":19554,"body":19555,"description":423,"extension":4340,"meta":22252,"navigation":3338,"path":22253,"seo":22254,"stem":22255,"__hash__":22256},"docs\u002FLEGACY-DB-INVENTORY.md","레거시 DB 인벤토리 — pms (테스트 서버)",{"type":8,"value":19556,"toc":22220},[19557,19564,19573,19576,19578,19582,19615,19617,19621,19665,19667,19671,20073,20080,20082,20086,20092,20292,20298,20403,20414,20419,20421,20425,20429,20474,20476,20526,20534,20536,20540,20721,20724,20737,20799,20804,20826,20832,20835,20838,20909,20915,20925,21021,21027,21030,21039,21049,21054,21088,21095,21152,21157,21199,21205,21208,21217,21253,21259,21360,21373,21377,21495,21498,21573,21577,21654,21659,21661,21672,21674,21678,21685,22022,22035,22051,22053,22057,22080,22082,22086,22166,22168,22172,22179,22209,22218],[11,19558,19560,19561,19563],{"id":19559},"레거시-db-인벤토리-pms-테스트-서버","레거시 DB 인벤토리 — ",[16,19562,12085],{}," (테스트 서버)",[21,19565,19566],{},[24,19567,19568,19569,19572],{},"조사일: 2026-05-18\n대상: ",[16,19570,19571],{},"db.malgn.co.kr:3306\u002Fpms"," (테스트 서버, 읽기 권한 계정)\n목적: AI 챗봇 학습 자산화 가능성 평가 및 인제스트 매핑 정의",[24,19574,19575],{},"자격 증명은 본 문서에 기록하지 않는다. 운영 시크릿 채널로 관리.",[33,19577],{},[36,19579,19581],{"id":19580},"_1-결론-요약","1. 결론 요약",[54,19583,19584,19590,19605,19612],{},[57,19585,19586,19587,407],{},"이 DB는 ",[28,19588,19589],{},"CS 전용 DB가 아니라 맑은소프트의 사내 PMS(프로젝트 관리 시스템)",[57,19591,19592,19593,1524,19595,10238,19597,19600,19601,19604],{},"그러나 ",[16,19594,11093],{},[16,19596,15316],{},[28,19598,19599],{},"고객 문의와 맑은소프트 직원의 답변이 함께 누적","되어 있어 ",[28,19602,19603],{},"CS Q&A 자산","으로 가치가 있다.",[57,19606,19607,19608,19611],{},"합리적 필터를 적용하면 ",[28,19609,19610],{},"약 1,358건의 Q&A 후보","가 확보된다 (Site 1: 1,146, Site 2: 212).",[57,19613,19614],{},"HTML 본문·테스트 글·이미지 전용 글 등 정제가 필요. 정제 후 OpenSearch 인덱싱 대상으로 활용 가능.",[33,19616],{},[36,19618,19620],{"id":19619},"_2-db-메타","2. DB 메타",[135,19622,19623,19631],{},[138,19624,19625],{},[141,19626,19627,19629],{},[144,19628,4143],{},[144,19630,1540],{},[157,19632,19633,19641,19649,19657],{},[141,19634,19635,19638],{},[162,19636,19637],{},"Engine",[162,19639,19640],{},"MySQL 8.0.42",[141,19642,19643,19646],{},[162,19644,19645],{},"Charset",[162,19647,19648],{},"utf8mb3",[141,19650,19651,19654],{},[162,19652,19653],{},"Tables",[162,19655,19656],{},"26개",[141,19658,19659,19662],{},[162,19660,19661],{},"성격",[162,19663,19664],{},"PMS(게시판·프로젝트·채팅·일정·투표 통합)",[33,19666],{},[36,19668,19670],{"id":19669},"_3-테이블-인벤토리-행수-기준-상위","3. 테이블 인벤토리 (행수 기준 상위)",[135,19672,19673,19688],{},[138,19674,19675],{},[141,19676,19677,19679,19682,19685],{},[144,19678,2973],{},[144,19680,19681],{},"행수",[144,19683,19684],{},"용도 추정",[144,19686,19687],{},"CS AI 활용성",[157,19689,19690,19706,19722,19737,19752,19767,19790,19806,19821,19836,19858,19873,19889,19904,19919,19934,19949,19965,19979,19994,20010,20025,20040,20058],{},[141,19691,19692,19697,19700,19703],{},[162,19693,19694],{},[16,19695,19696],{},"tb_post_read",[162,19698,19699],{},"364,140",[162,19701,19702],{},"게시글 읽음 처리",[162,19704,19705],{},"✕ 사용 안 함",[141,19707,19708,19713,19716,19719],{},[162,19709,19710],{},[16,19711,19712],{},"tb_post_file",[162,19714,19715],{},"79,180",[162,19717,19718],{},"게시글 첨부파일 메타",[162,19720,19721],{},"◎ 텍스트 문서는 본문 부착, 이미지\u002F동영상은 별도 정책 (§6 첨부파일 처리 전략)",[141,19723,19724,19729,19732,19735],{},[162,19725,19726],{},[16,19727,19728],{},"tb_post_share",[162,19730,19731],{},"68,380",[162,19733,19734],{},"게시글 공유 이력",[162,19736,7348],{},[141,19738,19739,19744,19747,19750],{},[162,19740,19741],{},[16,19742,19743],{},"tb_project_user",[162,19745,19746],{},"22,292",[162,19748,19749],{},"프로젝트-사용자 매핑",[162,19751,7348],{},[141,19753,19754,19759,19762,19765],{},[162,19755,19756],{},[16,19757,19758],{},"tb_diligence",[162,19760,19761],{},"7,137",[162,19763,19764],{},"근태\u002F근면 데이터",[162,19766,7348],{},[141,19768,19769,19775,19780,19785],{},[162,19770,19771],{},[28,19772,19773],{},[16,19774,15316],{},[162,19776,19777],{},[28,19778,19779],{},"5,684",[162,19781,19782],{},[28,19783,19784],{},"게시글 댓글 (답변 본문)",[162,19786,19787],{},[28,19788,19789],{},"◎ 핵심 자산",[141,19791,19792,19797,19800,19803],{},[162,19793,19794],{},[16,19795,19796],{},"tb_project",[162,19798,19799],{},"4,448",[162,19801,19802],{},"프로젝트 메타",[162,19804,19805],{},"△ 컨텍스트 (project_id 매핑)",[141,19807,19808,19812,19815,19818],{},[162,19809,19810],{},[16,19811,7368],{},[162,19813,19814],{},"3,778",[162,19816,19817],{},"게시글 라벨(태그)",[162,19819,19820],{},"△ 카테고리 후보",[141,19822,19823,19827,19830,19833],{},[162,19824,19825],{},[16,19826,17012],{},[162,19828,19829],{},"3,037",[162,19831,19832],{},"사용자",[162,19834,19835],{},"△ 작성자 메타용",[141,19837,19838,19844,19849,19854],{},[162,19839,19840],{},[28,19841,19842],{},[16,19843,11093],{},[162,19845,19846],{},[28,19847,19848],{},"2,437",[162,19850,19851],{},[28,19852,19853],{},"게시글 본문 (질문\u002F요청)",[162,19855,19856],{},[28,19857,19789],{},[141,19859,19860,19865,19868,19871],{},[162,19861,19862],{},[16,19863,19864],{},"tb_post_bookmark",[162,19866,19867],{},"2,046",[162,19869,19870],{},"즐겨찾기",[162,19872,7348],{},[141,19874,19875,19880,19883,19886],{},[162,19876,19877],{},[16,19878,19879],{},"tb_chat_message",[162,19881,19882],{},"1,814",[162,19884,19885],{},"사내 실시간 채팅",[162,19887,19888],{},"✕ CS와 무관, 짧은 잡담 위주",[141,19890,19891,19896,19899,19902],{},[162,19892,19893],{},[16,19894,19895],{},"tb_post_task",[162,19897,19898],{},"1,464",[162,19900,19901],{},"게시글 → 작업 변환",[162,19903,7348],{},[141,19905,19906,19911,19914,19917],{},[162,19907,19908],{},[16,19909,19910],{},"tb_session",[162,19912,19913],{},"686",[162,19915,19916],{},"로그인 세션",[162,19918,7348],{},[141,19920,19921,19926,19929,19932],{},[162,19922,19923],{},[16,19924,19925],{},"tb_user_log",[162,19927,19928],{},"457",[162,19930,19931],{},"사용자 활동 로그",[162,19933,7348],{},[141,19935,19936,19941,19944,19947],{},[162,19937,19938],{},[16,19939,19940],{},"tb_post_alram",[162,19942,19943],{},"187",[162,19945,19946],{},"게시글 알림",[162,19948,7348],{},[141,19950,19951,19956,19959,19962],{},[162,19952,19953],{},[16,19954,19955],{},"tb_post_template",[162,19957,19958],{},"90",[162,19960,19961],{},"문서 템플릿 (회의록\u002F보고서 등)",[162,19963,19964],{},"△ 양식이라 답변 데이터는 아님",[141,19966,19967,19972,19974,19977],{},[162,19968,19969],{},[16,19970,19971],{},"tb_post_poll_user",[162,19973,19958],{},[162,19975,19976],{},"투표 응답",[162,19978,7348],{},[141,19980,19981,19986,19989,19992],{},[162,19982,19983],{},[16,19984,19985],{},"tb_chat_file",[162,19987,19988],{},"81",[162,19990,19991],{},"채팅 첨부",[162,19993,7348],{},[141,19995,19996,20001,20004,20007],{},[162,19997,19998],{},[16,19999,20000],{},"tb_site",[162,20002,20003],{},"63",[162,20005,20006],{},"사이트(테넌트) 정보",[162,20008,20009],{},"○ 필터 키",[141,20011,20012,20017,20020,20023],{},[162,20013,20014],{},[16,20015,20016],{},"tb_post_poll",[162,20018,20019],{},"33",[162,20021,20022],{},"게시글 투표",[162,20024,7348],{},[141,20026,20027,20032,20035,20038],{},[162,20028,20029],{},[16,20030,20031],{},"tb_sequence",[162,20033,20034],{},"22",[162,20036,20037],{},"시퀀스 카운터",[162,20039,7348],{},[141,20041,20042,20050,20053,20056],{},[162,20043,20044,105,20047],{},[16,20045,20046],{},"tb_group_user",[16,20048,20049],{},"tb_group",[162,20051,20052],{},"8\u002F6",[162,20054,20055],{},"그룹",[162,20057,7348],{},[141,20059,20060,20065,20068,20071],{},[162,20061,20062],{},[16,20063,20064],{},"tb_post_confirm",[162,20066,20067],{},"0",[162,20069,20070],{},"(미사용)",[162,20072,7348],{},[21,20074,20075],{},[24,20076,20077,20079],{},[16,20078,19879],{}," 샘플: \"네~^^\", \"감사합니다ㅎㅎ\" 등 사내 메신저 대화 — CS 자산으로 활용 부적합.",[33,20081],{},[36,20083,20085],{"id":20084},"_4-핵심-테이블-스키마-관련-컬럼만","4. 핵심 테이블 스키마 (관련 컬럼만)",[215,20087,20089,20091],{"id":20088},"tb_post-질문요청-본문",[16,20090,11093],{}," (질문\u002F요청 본문)",[135,20093,20094,20105],{},[138,20095,20096],{},[141,20097,20098,20100,20102],{},[144,20099,17787],{},[144,20101,17790],{},[144,20103,20104],{},"의미 \u002F 활용",[157,20106,20107,20119,20131,20142,20156,20168,20183,20196,20211,20226,20238,20256,20268,20281],{},[141,20108,20109,20113,20116],{},[162,20110,20111],{},[16,20112,11737],{},[162,20114,20115],{},"int",[162,20117,20118],{},"게시글 PK",[141,20120,20121,20126,20128],{},[162,20122,20123],{},[16,20124,20125],{},"site_id",[162,20127,20115],{},[162,20129,20130],{},"테넌트(사이트) — 필터 키",[141,20132,20133,20137,20139],{},[162,20134,20135],{},[16,20136,17812],{},[162,20138,20115],{},[162,20140,20141],{},"프로젝트 컨텍스트",[141,20143,20144,20151,20153],{},[162,20145,20146,105,20148],{},[16,20147,3306],{},[16,20149,20150],{},"ctype",[162,20152,20115],{},[162,20154,20155],{},"게시글 구분 — 필터 후보",[141,20157,20158,20163,20165],{},[162,20159,20160],{},[16,20161,20162],{},"template_id",[162,20164,20115],{},[162,20166,20167],{},"사용된 템플릿",[141,20169,20170,20177,20180],{},[162,20171,20172,105,20175],{},[16,20173,20174],{},"label_id",[16,20176,3022],{},[162,20178,20179],{},"int\u002Fvarchar",[162,20181,20182],{},"카테고리 후보",[141,20184,20185,20190,20193],{},[162,20186,20187],{},[16,20188,20189],{},"writer",[162,20191,20192],{},"varchar",[162,20194,20195],{},"작성자(질문자)",[141,20197,20198,20203,20206],{},[162,20199,20200],{},[16,20201,20202],{},"subject",[162,20204,20205],{},"varchar(255)",[162,20207,20208],{},[28,20209,20210],{},"제목 = 질문 요약",[141,20212,20213,20218,20221],{},[162,20214,20215],{},[16,20216,20217],{},"content",[162,20219,20220],{},"longtext",[162,20222,20223],{},[28,20224,20225],{},"본문 = 질문 상세 (HTML)",[141,20227,20228,20233,20235],{},[162,20229,20230],{},[16,20231,20232],{},"is_notice",[162,20234,20115],{},[162,20236,20237],{},"공지 여부 — 제외",[141,20239,20240,20251,20253],{},[162,20241,20242,530,20245,530,20248],{},[16,20243,20244],{},"is_task",[16,20246,20247],{},"is_schedule",[16,20249,20250],{},"is_poll",[162,20252,20115],{},[162,20254,20255],{},"작업\u002F일정\u002F투표 — 제외",[141,20257,20258,20263,20265],{},[162,20259,20260],{},[16,20261,20262],{},"comm_cnt",[162,20264,20115],{},[162,20266,20267],{},"댓글 수 — Q&A 페어 여부",[141,20269,20270,20275,20278],{},[162,20271,20272],{},[16,20273,20274],{},"reg_date",[162,20276,20277],{},"varchar(14)",[162,20279,20280],{},"YYYYMMDDHHMMSS — 신선도",[141,20282,20283,20287,20289],{},[162,20284,20285],{},[16,20286,17939],{},[162,20288,20115],{},[162,20290,20291],{},"1 = 정상",[215,20293,20295,20297],{"id":20294},"tb_post_comment-답변-본문",[16,20296,15316],{}," (답변 본문)",[135,20299,20300,20310],{},[138,20301,20302],{},[141,20303,20304,20306,20308],{},[144,20305,17787],{},[144,20307,17790],{},[144,20309,20104],{},[157,20311,20312,20323,20334,20345,20358,20371,20382,20392],{},[141,20313,20314,20318,20320],{},[162,20315,20316],{},[16,20317,11737],{},[162,20319,20115],{},[162,20321,20322],{},"댓글 PK",[141,20324,20325,20329,20331],{},[162,20326,20327],{},[16,20328,18027],{},[162,20330,20115],{},[162,20332,20333],{},"부모 게시글 FK",[141,20335,20336,20340,20342],{},[162,20337,20338],{},[16,20339,20189],{},[162,20341,20192],{},[162,20343,20344],{},"작성자(답변자)",[141,20346,20347,20351,20353],{},[162,20348,20349],{},[16,20350,20217],{},[162,20352,20220],{},[162,20354,20355],{},[28,20356,20357],{},"답변 본문 (HTML)",[141,20359,20360,20365,20368],{},[162,20361,20362],{},[16,20363,20364],{},"private_yn",[162,20366,20367],{},"char(1)",[162,20369,20370],{},"'Y' 비공개 댓글 — 제외",[141,20372,20373,20377,20379],{},[162,20374,20375],{},[16,20376,20274],{},[162,20378,20277],{},[162,20380,20381],{},"등록일",[141,20383,20384,20388,20390],{},[162,20385,20386],{},[16,20387,17939],{},[162,20389,20115],{},[162,20391,20291],{},[141,20393,20394,20398,20400],{},[162,20395,20396],{},[16,20397,20202],{},[162,20399,20192],{},[162,20401,20402],{},"보통 비어 있음",[215,20404,20406,105,20408,105,20410,105,20412],{"id":20405},"tb_site-tb_project-tb_user-tb_post_label",[16,20407,20000],{},[16,20409,19796],{},[16,20411,17012],{},[16,20413,7368],{},[54,20415,20416],{},[57,20417,20418],{},"메타데이터 결합용 — 작성자명·사이트명·프로젝트명·라벨명을 인덱스 메타 필드로 첨부.",[33,20420],{},[36,20422,20424],{"id":20423},"_5-qa-후보-데이터-규모","5. Q&A 후보 데이터 규모",[215,20426,20428],{"id":20427},"적용-필터","적용 필터",[415,20430,20432],{"className":8581,"code":20431,"language":8583,"meta":423,"style":423},"WHERE p.status = 1\n  AND p.comm_cnt >= 1\n  AND p.is_task = 0\n  AND p.is_schedule = 0\n  AND p.is_poll = 0\n  AND p.is_notice = 0\n  AND p.subject NOT LIKE '테스트%'\n  AND CHAR_LENGTH(p.content) >= 20\n",[16,20433,20434,20439,20444,20449,20454,20459,20464,20469],{"__ignoreMap":423},[2166,20435,20436],{"class":3301,"line":3302},[2166,20437,20438],{},"WHERE p.status = 1\n",[2166,20440,20441],{"class":3301,"line":3335},[2166,20442,20443],{},"  AND p.comm_cnt >= 1\n",[2166,20445,20446],{"class":3301,"line":3342},[2166,20447,20448],{},"  AND p.is_task = 0\n",[2166,20450,20451],{"class":3301,"line":3368},[2166,20452,20453],{},"  AND p.is_schedule = 0\n",[2166,20455,20456],{"class":3301,"line":3396},[2166,20457,20458],{},"  AND p.is_poll = 0\n",[2166,20460,20461],{"class":3301,"line":3426},[2166,20462,20463],{},"  AND p.is_notice = 0\n",[2166,20465,20466],{"class":3301,"line":3463},[2166,20467,20468],{},"  AND p.subject NOT LIKE '테스트%'\n",[2166,20470,20471],{"class":3301,"line":3504},[2166,20472,20473],{},"  AND CHAR_LENGTH(p.content) >= 20\n",[215,20475,11180],{"id":11180},[135,20477,20478,20490],{},[138,20479,20480],{},[141,20481,20482,20484,20487],{},[144,20483,5830],{},[144,20485,20486],{},"Site 이름",[144,20488,20489],{},"후보 게시글",[157,20491,20492,20502,20512],{},[141,20493,20494,20496,20499],{},[162,20495,6055],{},[162,20497,20498],{},"(주)맑은소프트",[162,20500,20501],{},"1,146",[141,20503,20504,20506,20509],{},[162,20505,7685],{},[162,20507,20508],{},"맑은소프트 내부",[162,20510,20511],{},"212",[141,20513,20514,20516,20521],{},[162,20515,538],{},[162,20517,20518],{},[28,20519,20520],{},"합계",[162,20522,20523],{},[28,20524,20525],{},"1,358",[21,20527,20528],{},[24,20529,20530,20531,407],{},"Site 1이 외부 고객 문의 + 내부 글이 섞여 있을 가능성 있음. ",[28,20532,20533],{},"표본 검수 후 site별 채택 여부 재결정 필요",[33,20535],{},[36,20537,20539],{"id":20538},"_6-데이터-품질-이슈","6. 데이터 품질 이슈",[135,20541,20542,20551],{},[138,20543,20544],{},[141,20545,20546,20548],{},[144,20547,6149],{},[144,20549,20550],{},"처리 방안",[157,20552,20553,20567,20583,20594,20606,20619,20638,20650,20658,20669,20677,20685,20696,20710],{},[141,20554,20555,20561],{},[162,20556,20557,20558,78],{},"본문이 HTML (",[16,20559,20560],{},"\u003Cp>...",[162,20562,20563,20564,20566],{},"인덱싱 전 HTML 정제 (태그 제거, 엔티티 디코드, ",[16,20565,14934],{}," 제거 후 alt만 보존)",[141,20568,20569,20576],{},[162,20570,20571,20572,20575],{},"일부 글은 ",[28,20573,20574],{},"이미지만"," 있음 (스크린샷 캡처)",[162,20577,20578,20579,20582],{},"아래 ",[28,20580,20581],{},"이미지 처리 전략"," 참조 — 단계별 도입",[141,20584,20585,20591],{},[162,20586,20587,20590],{},[16,20588,20589],{},"\u003Cimg src=\"\u002Fdata\u002F...\">"," 내부 경로",[162,20592,20593],{},"메타 필드로 보존 후 외부 접근 가능한 URL로 치환 (R2 서명 URL 또는 프록시)",[141,20595,20596,20603],{},[162,20597,20598,20599,20602],{},"테스트 글(",[16,20600,20601],{},"테스트%",")이 많음",[162,20604,20605],{},"제목·작성자·날짜 기반 필터, 화이트리스트 검토",[141,20607,20608,20614],{},[162,20609,20610,20613],{},[16,20611,20612],{},"private_yn = 'Y'"," 비공개 댓글",[162,20615,20616],{},[28,20617,20618],{},"반드시 제외",[141,20620,20621,20629],{},[162,20622,20623,20625,20626,20628],{},[16,20624,20274],{},"가 ",[16,20627,20277],{}," (YYYYMMDDHHMMSS)",[162,20630,20631,20632,530,20634,20637],{},"인덱싱 시 ",[16,20633,17721],{},[16,20635,20636],{},"epoch"," 변환, 신선도 가중치 적용",[141,20639,20640,20643],{},[162,20641,20642],{},"동일 질문에 여러 댓글",[162,20644,20645,20646,20649],{},"모든 댓글을 후보로 보되 ",[28,20647,20648],{},"마지막 답변 또는 staff 답변 우선"," 등 정책 결정 필요",[141,20651,20652,20655],{},[162,20653,20654],{},"작성자가 동일한 Q&A (자기 답변)",[162,20656,20657],{},"셀프 답변은 신뢰도 낮춤 또는 제외",[141,20659,20660,20663],{},[162,20661,20662],{},"PII 가능성 (이메일·전화·이름)",[162,20664,20665,20666],{},"인제스트 단계에서 마스킹 또는 사내용으로만 사용. ",[28,20667,20668],{},"공개 챗봇에 그대로 노출 금지",[141,20670,20671,20674],{},[162,20672,20673],{},"사용자 작성 IP 컬럼 보유",[162,20675,20676],{},"인덱싱 대상에서 제외",[141,20678,20679,20682],{},[162,20680,20681],{},"Site별로 도메인이 다를 수 있음",[162,20683,20684],{},"사이트 1(맑은소프트 운영)만 우선 채택 후 확장",[141,20686,20687,20690],{},[162,20688,20689],{},"댓글이 1건 ↔ 다건(스레드)으로 섞임",[162,20691,20578,20692,20695],{},[28,20693,20694],{},"스레드 처리 전략"," 참조",[141,20697,20698,20704],{},[162,20699,20700,20701,20703],{},"비공개 댓글(",[16,20702,20612],{},")이 9.3% 존재",[162,20705,20578,20706,20709],{},[28,20707,20708],{},"비공개 댓글 처리 전략"," 참조 — 단순 제외 아님",[141,20711,20712,20715],{},[162,20713,20714],{},"첨부파일이 Q&A 후보 64.9%에 존재 (총 78,784건)",[162,20716,20578,20717,20720],{},[28,20718,20719],{},"첨부파일 처리 전략"," 참조 — 파일 종류별 분기",[215,20722,20581],{"id":20723},"이미지-처리-전략",[24,20725,20726,20727,20729,20730,20732,20733,20736],{},"본 DB의 게시글 본문은 ",[16,20728,12304],{}," 텍스트와 ",[16,20731,20589],{}," 이미지가 함께 들어 있다. 가치 있는 Q&A는 보통 텍스트 본문이 충분하고, 이미지만 있는 글은 테스트·사내 스크린샷이 대부분이라 ",[28,20734,20735],{},"단계별 도입","으로 비용과 복잡도를 통제한다.",[135,20738,20739,20753],{},[138,20740,20741],{},[141,20742,20743,20745,20748,20750],{},[144,20744,2976],{},[144,20746,20747],{},"처리 방식",[144,20749,5701],{},[144,20751,20752],{},"적용 시점",[157,20754,20755,20771,20785],{},[141,20756,20757,20760,20766,20768],{},[162,20758,20759],{},"A. 텍스트만 (MVP)",[162,20761,20762,20763,20765],{},"HTML·",[16,20764,14934],{}," 태그 제거 후 본문 길이가 임계값(예: 30자) 미만이면 인덱싱 제외. 이미지 URL은 메타 필드로만 보존",[162,20767,20067],{},[162,20769,20770],{},"Phase 1 즉시",[141,20772,20773,20776,20779,20782],{},[162,20774,20775],{},"B. OCR 추가",[162,20777,20778],{},"텍스트와 이미지가 함께 있는 글에서 스크린샷의 텍스트(에러 메시지·관리자 화면 등)만 추출해 본문 뒤에 부착",[162,20780,20781],{},"낮음 (Cloudflare AI \u002F 외부 OCR)",[162,20783,20784],{},"Phase 1 후반 ~ Phase 2",[141,20786,20787,20790,20793,20796],{},[162,20788,20789],{},"C. Vision LLM 캡션",[162,20791,20792],{},"Claude Vision으로 이미지 내용 요약 캡션 생성 → 의미 검색 강화",[162,20794,20795],{},"중간 (토큰 비용)",[162,20797,20798],{},"Phase 2 품질 고도화",[24,20800,20801],{},[28,20802,20803],{},"공통 원칙",[54,20805,20806,20813,20819],{},[57,20807,20808,20809,20812],{},"모든 단계에서 ",[28,20810,20811],{},"이미지 URL을 메타 필드로 보존"," → 챗봇 답변에서 \"관련 화면 참고: \u003C링크>\"로 인용 가능.",[57,20814,20815,20816,20818],{},"이미지 경로(",[16,20817,18616],{},")는 외부 접근 가능한 URL로 치환 (R2 서명 URL 또는 프록시).",[57,20820,20821,20822,20825],{},"단계 전환은 ",[28,20823,20824],{},"미커버 질문 분석 결과","로 결정. 이미지 정보 없이 풀리지 않는 질문이 의미 있게 쌓이면 B 도입.",[24,20827,20828,20831],{},[28,20829,20830],{},"트레이드오프",": 텍스트만은 단순·저비용이지만 \"이 화면에서 어떻게 해요?\" 같은 시각 의존 질문을 놓침. OCR\u002FVision은 잡을 수 있지만 복잡도·비용 증가.",[215,20833,20694],{"id":20834},"스레드-처리-전략",[24,20836,20837],{},"게시글당 댓글 수 분포 (status=1 + 테스트 제외 후, 1,358건 후보 기준):",[135,20839,20840,20853],{},[138,20841,20842],{},[141,20843,20844,20847,20850],{},[144,20845,20846],{},"댓글 수",[144,20848,20849],{},"게시글 수",[144,20851,20852],{},"비율",[157,20854,20855,20866,20876,20887,20898],{},[141,20856,20857,20860,20863],{},[162,20858,20859],{},"1 (단일 응답)",[162,20861,20862],{},"487",[162,20864,20865],{},"36%",[141,20867,20868,20871,20874],{},[162,20869,20870],{},"2~3 (짧은 스레드)",[162,20872,20873],{},"486",[162,20875,20865],{},[141,20877,20878,20881,20884],{},[162,20879,20880],{},"4~6 (중간 스레드)",[162,20882,20883],{},"238",[162,20885,20886],{},"18%",[141,20888,20889,20892,20895],{},[162,20890,20891],{},"7~15 (긴 스레드)",[162,20893,20894],{},"129",[162,20896,20897],{},"9%",[141,20899,20900,20903,20906],{},[162,20901,20902],{},"16+ (매우 긴)",[162,20904,20905],{},"18",[162,20907,20908],{},"1%",[24,20910,20911,20914],{},[28,20912,20913],{},"약 64%가 스레드형"," — 단일 Q&A 페어로 가정하면 안 된다. 후속 질의·재확인·해결 과정을 모두 활용해야 답변 품질이 살아난다.",[24,20916,20917,20920,20921,20924],{},[28,20918,20919],{},"원칙",": 스레드를 ",[28,20922,20923],{},"하나의 Q&A 도큐먼트로 압축","해서 인덱싱한다.",[135,20926,20927,20936],{},[138,20928,20929],{},[141,20930,20931,20933],{},[144,20932,4143],{},[144,20934,20935],{},"처리",[157,20937,20938,20946,20957,20972,20980,20988,20996,21008],{},[141,20939,20940,20943],{},[162,20941,20942],{},"단위",[162,20944,20945],{},"1개 게시글(+ 그 게시글의 모든 가시 댓글) = 1 도큐먼트",[141,20947,20948,20951],{},[162,20949,20950],{},"본문 구성",[162,20952,20953,20956],{},[16,20954,20955],{},"질문(Q) → 답변1(A) → 추가질문(Q2) → 답변2(A2) → ..."," 시간순 결합",[141,20958,20959,20962],{},[162,20960,20961],{},"화자 표기",[162,20963,20964,20965,105,20968,20971],{},"각 턴 앞에 작성자\u002F역할 라벨 (",[16,20966,20967],{},"고객:",[16,20969,20970],{},"상담사:"," 등) 부착 — LLM이 화자 추적 가능하게",[141,20973,20974,20977],{},[162,20975,20976],{},"잡담 필터",[162,20978,20979],{},"본문 길이 5자 미만, \"ddddd\" 같은 반복 문자 등 노이즈 댓글 제거 (post 94221 사례 참조)",[141,20981,20982,20985],{},[162,20983,20984],{},"임베딩 입력",[162,20986,20987],{},"결합된 전체 텍스트 (Q+A 누적)",[141,20989,20990,20993],{},[162,20991,20992],{},"BM25 인덱스",[162,20994,20995],{},"제목·질문·답변 분리 필드 + 결합 필드 둘 다 보유해 가중치 조절 가능",[141,20997,20998,21001],{},[162,20999,21000],{},"청킹",[162,21002,21003,21004,21007],{},"결합 본문이 임계값(예: 2000자) 초과 시 의미 단위 분할, 단 동일 ",[16,21005,21006],{},"doc_id","로 묶음",[141,21009,21010,21012],{},[162,21011,5798],{},[162,21013,21014,105,21017,21020],{},[16,21015,21016],{},"turn_count",[16,21018,21019],{},"last_reply_at"," 보존 → 신선도·복잡도 가중치",[24,21022,21023,21026],{},[28,21024,21025],{},"비잡담 검증",": 댓글 노이즈(\"ddddd\", \"xxxxxx\") 검출 룰 — 동일 문자 반복, 길이 5자 미만, 의미 없는 단일 단어 등.",[215,21028,20708],{"id":21029},"비공개-댓글-처리-전략",[24,21031,21032,21035,21036,407],{},[16,21033,21034],{},"tb_post_comment.private_yn = 'Y'"," 댓글은 활성 댓글 5,021건 중 ",[28,21037,21038],{},"513건 (약 9.3%)",[24,21040,21041,21044,21045,21048],{},[28,21042,21043],{},"관찰",": 일부 스레드는 ",[28,21046,21047],{},"알맹이 답변이 비공개에만 존재","한다 (예: post 94221 — 공개 댓글은 잡담, 비공개 댓글이 실제 답변). 따라서 단순 제외하면 답변 자산을 잃는다. 그러나 비공개는 의도적으로 고객 비노출이므로 챗봇 노출은 금지.",[24,21050,21051],{},[28,21052,21053],{},"해결: 가시성(visibility) 메타 필드로 계층 인덱싱.",[135,21055,21056,21066],{},[138,21057,21058],{},[141,21059,21060,21063],{},[144,21061,21062],{},"인덱스 도큐먼트의 visibility",[144,21064,21065],{},"포함 댓글",[157,21067,21068,21078],{},[141,21069,21070,21075],{},[162,21071,21072],{},[16,21073,21074],{},"internal",[162,21076,21077],{},"공개 + 비공개 댓글 모두 결합",[141,21079,21080,21085],{},[162,21081,21082],{},[16,21083,21084],{},"public",[162,21086,21087],{},"공개 댓글만 결합",[24,21089,21090,21091,21094],{},"같은 게시글에 대해 두 개 변형을 만들지 않고, ",[28,21092,21093],{},"하나의 도큐먼트에 두 본문 필드","를 유지하는 방식도 가능:",[135,21096,21097,21107],{},[138,21098,21099],{},[141,21100,21101,21104],{},[144,21102,21103],{},"인덱스 필드",[144,21105,21106],{},"내용",[157,21108,21109,21119,21129,21142],{},[141,21110,21111,21116],{},[162,21112,21113],{},[16,21114,21115],{},"body_public",[162,21117,21118],{},"공개 댓글만으로 구성한 결합 본문 (Phase 2 챗봇용 BM25\u002F임베딩)",[141,21120,21121,21126],{},[162,21122,21123],{},[16,21124,21125],{},"body_internal",[162,21127,21128],{},"비공개 포함 결합 본문 (Phase 1 상담사 보조용 BM25\u002F임베딩)",[141,21130,21131,21139],{},[162,21132,21133,1365,21136],{},[16,21134,21135],{},"embedding_public",[16,21137,21138],{},"embedding_internal",[162,21140,21141],{},"각 본문 기준 벡터",[141,21143,21144,21149],{},[162,21145,21146],{},[16,21147,21148],{},"has_internal_only_answer",[162,21150,21151],{},"공개 본문에는 답이 없고 비공개에만 있는 경우 표시 (Phase 2에서 자동 에스컬레이션 후보)",[24,21153,21154,3360],{},[28,21155,21156],{},"Phase별 사용",[135,21158,21159,21169],{},[138,21160,21161],{},[141,21162,21163,21166],{},[144,21164,21165],{},"Phase",[144,21167,21168],{},"검색 대상",[157,21170,21171,21183],{},[141,21172,21173,21176],{},[162,21174,21175],{},"Phase 1 (상담사 보조)",[162,21177,21178,1365,21180,21182],{},[16,21179,21125],{},[16,21181,21138],{}," — 내부 지식 활용 정당",[141,21184,21185,21188],{},[162,21186,21187],{},"Phase 2 (고객 챗봇)",[162,21189,21190,1365,21192,21194,21195,21198],{},[16,21191,21115],{},[16,21193,21135],{}," — 공개 자산만 사용. ",[16,21196,21197],{},"has_internal_only_answer = true","인 케이스는 \"확인 후 답변 드리겠습니다\" 또는 에스컬레이션",[24,21200,21201,21204],{},[28,21202,21203],{},"금지",": 비공개 댓글 본문이 Phase 2 챗봇 응답에 직접 인용되거나 출처로 노출되어선 안 됨.",[215,21206,20719],{"id":21207},"첨부파일-처리-전략",[24,21209,21210,21212,21213,21216],{},[16,21211,19712],{},"은 게시글\u002F댓글에 첨부된 파일 메타. 활성 78,784건이 존재하고 ",[28,21214,21215],{},"Q&A 후보 1,358건 중 881건(64.9%)이 첨부 보유"," — 무시 시 답변 자산의 절반 손실.",[24,21218,21219,4664,21222,3351,21225,530,21228,17484,21231,21234,21235,21238,21239,3351,21242,530,21244,530,21247,17484,21250,407],{},[28,21220,21221],{},"스키마 핵심",[16,21223,21224],{},"module",[16,21226,21227],{},"post",[16,21229,21230],{},"editor",[16,21232,21233],{},"module_id","(게시글 id) + ",[16,21236,21237],{},"realname","(원본 파일명) + ",[16,21240,21241],{},"filetype",[16,21243,1308],{},[16,21245,21246],{},"image",[16,21248,21249],{},"movie",[16,21251,21252],{},"filesize",[24,21254,21255,21258],{},[28,21256,21257],{},"파일 종류 분포"," (확장자 상위):",[135,21260,21261,21275],{},[138,21262,21263],{},[141,21264,21265,21267,21270,21272],{},[144,21266,6779],{},[144,21268,21269],{},"확장자",[144,21271,5928],{},[144,21273,21274],{},"평균\u002F최대 크기",[157,21276,21277,21291,21305,21319,21333,21347],{},[141,21278,21279,21282,21285,21288],{},[162,21280,21281],{},"이미지",[162,21283,21284],{},"png, jpg, gif, jpeg, bmp",[162,21286,21287],{},"38,063",[162,21289,21290],{},"평균 ~수백KB",[141,21292,21293,21296,21299,21302],{},[162,21294,21295],{},"텍스트 문서",[162,21297,21298],{},"pdf(11k), pptx(7k), hwp(5k), xlsx(5k), docx(2k), ppt(1.4k), doc(0.7k), txt(0.3k), csv(0.2k)",[162,21300,21301],{},"34,125",[162,21303,21304],{},"pdf 평균 2.3MB, pptx 평균 6.7MB \u002F 최대 530MB",[141,21306,21307,21310,21313,21316],{},[162,21308,21309],{},"압축",[162,21311,21312],{},"zip",[162,21314,21315],{},"3,374",[162,21317,21318],{},"평균 35MB \u002F 최대 1.1GB",[141,21320,21321,21324,21327,21330],{},[162,21322,21323],{},"동영상",[162,21325,21326],{},"mp4, mov, swf",[162,21328,21329],{},"566",[162,21331,21332],{},"mp4 평균 113MB \u002F 최대 1.1GB",[141,21334,21335,21338,21341,21344],{},[162,21336,21337],{},"디자인",[162,21339,21340],{},"psd, ai",[162,21342,21343],{},"1,294",[162,21345,21346],{},"평균 수MB ~ 수십MB",[141,21348,21349,21352,21355,21358],{},[162,21350,21351],{},"기타",[162,21353,21354],{},"exe, sql, r, ttf 등",[162,21356,21357],{},"소량",[162,21359,538],{},[21,21361,21362],{},[24,21363,21364,21365,21368,21369,21372],{},"한국어 환경 특이점: ",[28,21366,21367],{},"HWP(한컴) 5,094건"," — 별도 추출기(",[16,21370,21371],{},"hwp.js"," 등) 필요.",[482,21374,21376],{"id":21375},"종류별-처리-정책","종류별 처리 정책",[135,21378,21379,21393],{},[138,21380,21381],{},[141,21382,21383,21386,21389,21391],{},[144,21384,21385],{},"파일 종류",[144,21387,21388],{},"Phase 1 MVP",[144,21390,2992],{},[144,21392,3088],{},[157,21394,21395,21412,21426,21444,21457,21471,21483],{},[141,21396,21397,21403,21406,21409],{},[162,21398,21399,21400,78],{},"인라인 이미지 (",[16,21401,21402],{},"module=editor",[162,21404,21405],{},"§6 이미지 처리 전략 Stage A",[162,21407,21408],{},"Stage B (OCR)",[162,21410,21411],{},"Stage C (Vision LLM)",[141,21413,21414,21417,21420,21423],{},[162,21415,21416],{},"이미지 첨부 (png\u002Fjpg\u002Fgif\u002Fjpeg\u002Fbmp)",[162,21418,21419],{},"동일 — 메타만 보존",[162,21421,21422],{},"OCR 텍스트 본문 부착",[162,21424,21425],{},"Vision 캡션",[141,21427,21428,21433,21439,21442],{},[162,21429,21430,21432],{},[28,21431,21295],{}," (pdf\u002Fdocx\u002Fhwp\u002Ftxt\u002Fcsv\u002Fxlsx)",[162,21434,21435,21438],{},[28,21436,21437],{},"추출 텍스트를 본문에 부착"," → 검색 대상",[162,21440,21441],{},"청킹·구조 보존 개선",[162,21443,538],{},[141,21445,21446,21449,21452,21455],{},[162,21447,21448],{},"슬라이드 (pptx\u002Fppt)",[162,21450,21451],{},"텍스트 추출 (크기 상한 50MB)",[162,21453,21454],{},"슬라이드 단위 청킹",[162,21456,538],{},[141,21458,21459,21462,21465,21468],{},[162,21460,21461],{},"압축파일 (zip)",[162,21463,21464],{},"미추출, 메타만",[162,21466,21467],{},"사례 검토 후 선택 도입",[162,21469,21470],{},"Queue로 처리 검토",[141,21472,21473,21476,21478,21480],{},[162,21474,21475],{},"동영상 (mp4\u002Fmov\u002Fswf)",[162,21477,21464],{},[162,21479,538],{},[162,21481,21482],{},"Queue + 트랜스크립트 (Whisper 등)",[141,21484,21485,21488,21491,21493],{},[162,21486,21487],{},"디자인\u002F실행 (psd\u002Fai\u002Fexe)",[162,21489,21490],{},"파일명만 메타",[162,21492,538],{},[162,21494,538],{},[482,21496,20803],{"id":21497},"공통-원칙",[54,21499,21500,21512,21540,21546,21556,21562],{},[57,21501,21502,21505,21506,530,21508,21511],{},[28,21503,21504],{},"원본은 R2에 보관",". DB의 ",[16,21507,21237],{},[16,21509,21510],{},"filename","을 R2 키로 매핑. 답변 인용 시 R2 서명 URL 발급.",[57,21513,21514,21517,21518,21520,21521],{},[28,21515,21516],{},"가시성 상속",": 댓글에 첨부된 파일은 그 댓글의 ",[16,21519,20364],{}," 값을 상속.\n",[54,21522,21523,21531,21537],{},[57,21524,21525,21526,2855,21528,21530],{},"공개 댓글 첨부 → 텍스트는 ",[16,21527,21115],{},[16,21529,21125],{}," 모두에 부착",[57,21532,21533,21534,21536],{},"비공개 댓글 첨부 → ",[16,21535,21125],{},"에만 부착, Phase 2 챗봇에서 노출 금지",[57,21538,21539],{},"게시글 본문 첨부 → 공개 취급",[57,21541,21542,21545],{},[28,21543,21544],{},"크기 상한",": Phase 1에서는 50MB 초과 파일은 Queue 도입 전까지 보류. 메타만 인덱스에 보존.",[57,21547,21548,21551,21552,21555],{},[28,21549,21550],{},"추출 실패 허용",": 손상된 파일·미지원 포맷은 메타만 남기고 ",[16,21553,21554],{},"extraction_status: failed",". 인덱싱 중단 사유 아님.",[57,21557,21558,21561],{},[28,21559,21560],{},"PII",": 추출 텍스트에도 PII 검출·마스킹 적용 (이메일·전화·주민번호).",[57,21563,21564,21567,21568,21572],{},[28,21565,21566],{},"챗봇 인용",": 답변에 \"참고: ",[3257,21569,21571],{"href":21570},"r2-url","filename.pdf","\" 형식으로 출처 첨부 명시.",[482,21574,21576],{"id":21575},"라이브러리-후보-선정-보류","라이브러리 후보 (선정 보류)",[135,21578,21579,21589],{},[138,21580,21581],{},[141,21582,21583,21586],{},[144,21584,21585],{},"포맷",[144,21587,21588],{},"후보",[157,21590,21591,21604,21617,21627,21638,21646],{},[141,21592,21593,21596],{},[162,21594,21595],{},"PDF",[162,21597,21598,105,21601],{},[16,21599,21600],{},"pdf-parse",[16,21602,21603],{},"pdfjs-dist",[141,21605,21606,21609],{},[162,21607,21608],{},"DOCX",[162,21610,21611,105,21614],{},[16,21612,21613],{},"mammoth",[16,21615,21616],{},"docx",[141,21618,21619,21622],{},[162,21620,21621],{},"HWP",[162,21623,21624,21626],{},[16,21625,21371],{}," (한국 환경 필수)",[141,21628,21629,21632],{},[162,21630,21631],{},"XLSX\u002FXLS",[162,21633,21634,21637],{},[16,21635,21636],{},"xlsx"," (SheetJS)",[141,21639,21640,21643],{},[162,21641,21642],{},"PPTX",[162,21644,21645],{},"자체 unzip + slide XML 파싱 또는 외부 변환 서비스",[141,21647,21648,21651],{},[162,21649,21650],{},"TXT\u002FCSV",[162,21652,21653],{},"직접 읽기",[21,21655,21656],{},[24,21657,21658],{},"Cloudflare Workers의 CPU\u002F메모리 제한으로 동기 추출은 일부 포맷·소형 파일만 가능. 대용량\u002F복잡 추출은 별도 인덱서(로컬 백필 스크립트 또는 Phase 2 Queue Worker)에서 처리.",[482,21660,20830],{"id":20830},[54,21662,21663,21666,21669],{},[57,21664,21665],{},"텍스트 문서 추출만 도입해도 답변 자산이 크게 늘어남(881건의 첨부 중 상당수가 매뉴얼·로그·샘플).",[57,21667,21668],{},"그러나 추출 라이브러리·실패 케이스·대용량 처리 인프라 비용 증가.",[57,21670,21671],{},"동영상 트랜스크립트는 즉시 도입 시 비용이 가장 크므로 Phase 2 Queue 도입과 정합.",[33,21673],{},[36,21675,21677],{"id":21676},"_7-권장-인제스트-매핑-초안","7. 권장 인제스트 매핑 (초안)",[24,21679,21680,21681,21684],{},"OpenSearch ",[16,21682,21683],{},"chunks"," 인덱스 한 도큐먼트당:",[135,21686,21687,21698],{},[138,21688,21689],{},[141,21690,21691,21693,21696],{},[144,21692,21103],{},[144,21694,21695],{},"출처",[144,21697,2979],{},[157,21699,21700,21714,21729,21749,21769,21782,21796,21812,21824,21836,21851,21865,21880,21893,21909,21922,21938,21950,21962,21976,21988,22008],{},[141,21701,21702,21706,21711],{},[162,21703,21704],{},[16,21705,21006],{},[162,21707,21708],{},[16,21709,21710],{},"legacy:post:{tb_post.id}",[162,21712,21713],{},"안정적 식별자",[141,21715,21716,21721,21726],{},[162,21717,21718],{},[16,21719,21720],{},"source_type",[162,21722,21723],{},[16,21724,21725],{},"\"legacy_pms_qna\"",[162,21727,21728],{},"출처 구분",[141,21730,21731,21738,21746],{},[162,21732,21733,1365,21735],{},[16,21734,20125],{},[16,21736,21737],{},"site_name",[162,21739,21740,1524,21743],{},[16,21741,21742],{},"tb_post.site_id",[16,21744,21745],{},"tb_site.name",[162,21747,21748],{},"필터·메타",[141,21750,21751,21758,21766],{},[162,21752,21753,1365,21755],{},[16,21754,17812],{},[16,21756,21757],{},"project_name",[162,21759,21760,1524,21763],{},[16,21761,21762],{},"tb_post.project_id",[16,21764,21765],{},"tb_project.name",[162,21767,21768],{},"컨텍스트",[141,21770,21771,21775,21780],{},[162,21772,21773],{},[16,21774,3022],{},[162,21776,21777],{},[16,21778,21779],{},"tb_post_label.name",[162,21781,5925],{},[141,21783,21784,21788,21793],{},[162,21785,21786],{},[16,21787,2286],{},[162,21789,21790],{},[16,21791,21792],{},"tb_post.subject",[162,21794,21795],{},"제목",[141,21797,21798,21803,21809],{},[162,21799,21800],{},[16,21801,21802],{},"question_text",[162,21804,21805,21806],{},"정제된 ",[16,21807,21808],{},"tb_post.content",[162,21810,21811],{},"질문 본문",[141,21813,21814,21818,21821],{},[162,21815,21816],{},[16,21817,21115],{},[162,21819,21820],{},"공개 댓글만으로 구성한 스레드 결합 본문 (Q→A→Q2→A2…, 화자 라벨 포함)",[162,21822,21823],{},"Phase 2 검색·임베딩",[141,21825,21826,21830,21833],{},[162,21827,21828],{},[16,21829,21125],{},[162,21831,21832],{},"비공개 포함 스레드 결합 본문",[162,21834,21835],{},"Phase 1 검색·임베딩",[141,21837,21838,21842,21848],{},[162,21839,21840],{},[16,21841,21135],{},[162,21843,21844,21847],{},[16,21845,21846],{},"title + question_text + body_public"," 기준 벡터",[162,21849,21850],{},"Phase 2 k-NN",[141,21852,21853,21857,21862],{},[162,21854,21855],{},[16,21856,21138],{},[162,21858,21859,21847],{},[16,21860,21861],{},"title + question_text + body_internal",[162,21863,21864],{},"Phase 1 k-NN",[141,21866,21867,21871,21877],{},[162,21868,21869],{},[16,21870,21148],{},[162,21872,21873,21874],{},"공개 본문에는 답이 없고 비공개에만 있는 경우 ",[16,21875,21876],{},"true",[162,21878,21879],{},"Phase 2 자동 에스컬레이션 트리거",[141,21881,21882,21887,21890],{},[162,21883,21884],{},[16,21885,21886],{},"image_urls",[162,21888,21889],{},"본문\u002F댓글에서 추출한 이미지 URL 배열",[162,21891,21892],{},"인용용 메타 (외부 접근 URL로 치환)",[141,21894,21895,21900,21906],{},[162,21896,21897],{},[16,21898,21899],{},"attachments_public",[162,21901,21902,21903],{},"공개 영역(게시글 본문\u002F공개 댓글)의 첨부 배열 — ",[16,21904,21905],{},"{filename, r2_url, filetype, size, visibility, extraction_status}",[162,21907,21908],{},"Phase 2 인용 가능",[141,21910,21911,21916,21919],{},[162,21912,21913],{},[16,21914,21915],{},"attachments_internal",[162,21917,21918],{},"비공개 댓글 첨부까지 포함한 전체 배열",[162,21920,21921],{},"Phase 1 전용",[141,21923,21924,21929,21935],{},[162,21925,21926],{},[16,21927,21928],{},"extracted_text_public",[162,21930,21931,21932,21934],{},"공개 첨부에서 추출한 텍스트(",[16,21933,21115],{},"에 부착 전 원본)",[162,21936,21937],{},"청킹·재처리 용",[141,21939,21940,21945,21948],{},[162,21941,21942],{},[16,21943,21944],{},"extracted_text_internal",[162,21946,21947],{},"비공개 포함 첨부 추출 텍스트",[162,21949,21921],{},[141,21951,21952,21956,21959],{},[162,21953,21954],{},[16,21955,21016],{},[162,21957,21958],{},"게시글 + 가시 댓글 수",[162,21960,21961],{},"가중치·신선도 보조",[141,21963,21964,21969,21974],{},[162,21965,21966],{},[16,21967,21968],{},"asker",[162,21970,21971],{},[16,21972,21973],{},"tb_post.writer",[162,21975,5798],{},[141,21977,21978,21983,21986],{},[162,21979,21980],{},[16,21981,21982],{},"answerers",[162,21984,21985],{},"가시 댓글 작성자 배열",[162,21987,5798],{},[141,21989,21990,21997,22006],{},[162,21991,21992,1365,21995],{},[16,21993,21994],{},"reg_date_at",[16,21996,21019],{},[162,21998,21999,22002,22003,22005],{},[16,22000,22001],{},"tb_post.reg_date"," \u002F 마지막 댓글 ",[16,22004,20274],{}," 변환",[162,22007,6313],{},[141,22009,22010,22015,22020],{},[162,22011,22012],{},[16,22013,22014],{},"comment_count",[162,22016,22017],{},[16,22018,22019],{},"tb_post.comm_cnt",[162,22021,5798],{},[24,22023,22024,22027,22028,22030,22031,22034],{},[28,22025,22026],{},"청킹 전략",": 스레드를 1 도큐먼트로 압축. 결합 본문(스레드 + 추출 첨부 텍스트)이 2000자 이상이면 의미 단위 분할 (동일 ",[16,22029,21006],{}," 유지). 짧은 단일 Q&A는 분할 없이 그대로. 첨부 추출 텍스트는 본문 결합 시 ",[16,22032,22033],{},"[첨부:{filename}]"," 헤더 뒤에 부착해 LLM이 출처를 인지 가능하게.",[24,22036,22037,22040,22041,1524,22043,22045,22046,1524,22048,22050],{},[28,22038,22039],{},"Phase별 쿼리",": Phase 1은 ",[16,22042,21125],{},[16,22044,21138],{},", Phase 2는 ",[16,22047,21115],{},[16,22049,21135],{},"을 검색 대상으로. 색인은 같은 도큐먼트라 운영 동기화 비용 1배수.",[33,22052],{},[36,22054,22056],{"id":22055},"_8-표준-답변-후보-식별-전략","8. 표준 답변 후보 식별 전략",[54,22058,22059,22065,22071],{},[57,22060,22061,22062,22064],{},"동일\u002F유사 질문에 같은 답변이 반복 등장 → ",[28,22063,6326],{},"로 자동 추출.",[57,22066,22067,22068,22070],{},"댓글 작성자가 맑은소프트 직원(",[16,22069,17012],{},"에서 staff 플래그\u002F도메인으로 식별) → 신뢰도 가중치 상향.",[57,22072,22073,22074,2367,22077,22079],{},"후보 답변은 ",[3257,22075,6981],{"href":22076},"ROADMAP",[28,22078,6984],{},"의 자동 추천 흐름과 연결.",[33,22081],{},[36,22083,22085],{"id":22084},"_9-다음-단계-실행-항목","9. 다음 단계 (실행 항목)",[1925,22087,22088,22098,22104,22114,22120,22126,22132,22138,22147,22153],{},[57,22089,22090,22093,22094,22097],{},[28,22091,22092],{},"표본 검수",": site 1의 Q&A 후보 30~50건 추출 → 실제 CS 답변\u002F내부 잡담 비율 확인 → 추가 필터 도출. ",[28,22095,22096],{},"스레드형\u002F단일형 분포와 비공개 댓글 영향","도 함께 평가.",[57,22099,22100,22103],{},[28,22101,22102],{},"HTML 정제 PoC",": 5건 정도를 직접 정제해서 토큰 수·내용 유효성 측정.",[57,22105,22106,22109,22110,22113],{},[28,22107,22108],{},"노이즈 댓글 필터 룰"," 작성: 5자 미만, 동일 문자 반복(",[16,22111,22112],{},"ddddd"," 등), 의미 없는 단일 단어 탐지.",[57,22115,22116,22119],{},[28,22117,22118],{},"PII 검출 룰"," 작성: 이메일\u002F전화\u002F주민번호 정규식 + 마스킹 규칙.",[57,22121,22122,22125],{},[28,22123,22124],{},"가시성 정책 합의",": Phase 1에서 비공개 댓글 활용 범위·노출 경로(상담사 화면에서만) 명문화. 첨부파일도 동일 정책 상속.",[57,22127,22128,22131],{},[28,22129,22130],{},"첨부 추출기 선정 PoC",": PDF\u002FDOCX\u002FHWP\u002FXLSX 추출 라이브러리 후보 평가 (한국어·표·이미지 포함 PDF에서의 정확도, Worker 적합성).",[57,22133,22134,22137],{},[28,22135,22136],{},"R2 마이그레이션 계획",": 78,784개 첨부의 R2 이관 전략 (전체 백필? 인덱싱 대상만? URL 매핑 테이블 유지?).",[57,22139,22140,22143,22144,22146],{},[28,22141,22142],{},"인제스트 파이프라인 설계",": 일회성 백필 + 증분 동기화 (",[16,22145,20274],{}," 기준) 정책. 스레드는 마지막 댓글 갱신 시 재인덱싱. 첨부 추출 실패는 메타만 보존.",[57,22148,22149,22152],{},[28,22150,22151],{},"사이트 채택 범위"," 합의: site 1만? 1+2? 다른 site는 외부 고객사 데이터라 사용 가능 여부 별도 확인 필요.",[57,22154,22155,22158,22159,105,22162,22165],{},[28,22156,22157],{},"법적\u002F내부 검토",": 고객 문의 본문에 포함된 회사명·개인정보 사용 가능 범위, ",[28,22160,22161],{},"비공개 댓글의 학습 자산화 가능 여부",[28,22163,22164],{},"첨부 파일(특히 고객사 자료) 활용 가능 범위"," 확인.",[33,22167],{},[36,22169,22171],{"id":22170},"_10-미사용-결정","10. 미사용 결정",[24,22173,22174,22175,22178],{},"다음은 본 DB에서 ",[28,22176,22177],{},"사용하지 않음","으로 결론:",[54,22180,22181,22186,22191,22197,22203],{},[57,22182,22183,22185],{},[16,22184,19879],{}," — 짧은 사내 메신저, CS 자산 아님",[57,22187,22188,22190],{},[16,22189,19955],{}," — 양식\u002F템플릿이라 답변 데이터 부재",[57,22192,22193,22196],{},[28,22194,22195],{},"이미지만 있는 게시글"," (Stage A 한정) — §6 이미지 처리 전략 참조. Stage B\u002FC 도입 시 재평가",[57,22198,22199,22202],{},[28,22200,22201],{},"노이즈 댓글"," (5자 미만, 동일 문자 반복 등) — §6 스레드 처리 전략의 노이즈 필터로 제외",[57,22204,22205,22208],{},[28,22206,22207],{},"압축파일(zip)·동영상·디자인\u002F실행 파일"," (Phase 1 MVP 한정) — §6 첨부파일 처리 전략 참조. zip은 검토 후 결정, 동영상은 Phase 2 Queue 도입 시 트랜스크립트 처리",[21,22210,22211],{},[24,22212,22213,22214,22217],{},"비공개 댓글·첨부는 ",[28,22215,22216],{},"사용하지 않음이 아님",". Phase 1 한정으로 활용. §6 비공개 댓글 \u002F 첨부파일 처리 전략 참조.",[4258,22219,8979],{},{"title":423,"searchDepth":3342,"depth":3342,"links":22221},[22222,22223,22224,22225,22233,22237,22248,22249,22250,22251],{"id":19580,"depth":3335,"text":19581},{"id":19619,"depth":3335,"text":19620},{"id":19669,"depth":3335,"text":19670},{"id":20084,"depth":3335,"text":20085,"children":22226},[22227,22229,22231],{"id":20088,"depth":3342,"text":22228},"tb_post (질문\u002F요청 본문)",{"id":20294,"depth":3342,"text":22230},"tb_post_comment (답변 본문)",{"id":20405,"depth":3342,"text":22232},"tb_site, tb_project, tb_user, tb_post_label",{"id":20423,"depth":3335,"text":20424,"children":22234},[22235,22236],{"id":20427,"depth":3342,"text":20428},{"id":11180,"depth":3342,"text":11180},{"id":20538,"depth":3335,"text":20539,"children":22238},[22239,22240,22241,22242],{"id":20723,"depth":3342,"text":20581},{"id":20834,"depth":3342,"text":20694},{"id":21029,"depth":3342,"text":20708},{"id":21207,"depth":3342,"text":20719,"children":22243},[22244,22245,22246,22247],{"id":21375,"depth":3368,"text":21376},{"id":21497,"depth":3368,"text":20803},{"id":21575,"depth":3368,"text":21576},{"id":20830,"depth":3368,"text":20830},{"id":21676,"depth":3335,"text":21677},{"id":22055,"depth":3335,"text":22056},{"id":22084,"depth":3335,"text":22085},{"id":22170,"depth":3335,"text":22171},{},"\u002Flegacy-db-inventory",{"title":19554,"description":423},"LEGACY-DB-INVENTORY","MVuHo3jfJLkG6636XqgrMRYQqAP8eWNZzepIP9DcbCY",{"id":22258,"title":22259,"body":22260,"description":22267,"extension":4340,"meta":22789,"navigation":3338,"path":22790,"seo":22791,"stem":22792,"__hash__":22793},"docs\u002FMYSQL-INDEXES.md","PMS DB 인덱스 추천 (브리핑 카드 쿼리 부하 절감)",{"type":8,"value":22261,"toc":22776},[22262,22265,22268,22294,22311,22313,22317,22321,22330,22336,22374,22379,22383,22398,22402,22419,22424,22426,22430,22599,22601,22605,22608,22614,22631,22635,22641,22658,22660,22664,22697,22699,22703,22773],[11,22263,22259],{"id":22264},"pms-db-인덱스-추천-브리핑-카드-쿼리-부하-절감",[24,22266,22267],{},"브리핑 카드 생성 시 MySQL 부하 원인은 두 가지:",[1925,22269,22270,22285],{},[57,22271,22272,1358,22277,22284],{},[12602,22273,22274],{},[16,22275,22276],{},"email LIKE '%@malgnsoft.com'",[28,22278,22279,22280,22283],{},"이미 코드에서 ",[16,22281,22282],{},"staff user_id IN (...)"," 으로 교체"," (별도 작업 불요)",[57,22286,22287,22288,22290,22291],{},"큰 프로젝트(post 수천 건)에서 ",[16,22289,11093],{}," 스캔 — ",[28,22292,22293],{},"복합 인덱스 추가 필요",[24,22295,22296,22298,22299,22302,22303,22310],{},[16,22297,12167],{}," 헬퍼 테이블 인덱스는 이미 ",[16,22300,22301],{},"001_init_hp_tables.sql","에 정의돼 있으니 여기서는 ",[28,22304,22305,1365,22307,22309],{},[16,22306,11093],{},[16,22308,15316],{}," 운영 테이블"," 만 다룹니다.",[33,22312],{},[36,22314,22316],{"id":22315},"추천-인덱스","추천 인덱스",[215,22318,22320],{"id":22319},"_1-tb_post-최우선","1. tb_post — 최우선",[415,22322,22324],{"className":8581,"code":22323,"language":8583,"meta":423,"style":423},"ALTER TABLE tb_post ADD INDEX idx_project_status_regdate (project_id, status, reg_date);\n",[16,22325,22326],{"__ignoreMap":423},[2166,22327,22328],{"class":3301,"line":3302},[2166,22329,22323],{},[24,22331,22332,22335],{},[28,22333,22334],{},"효과",": 다음 6개 쿼리가 모두 인덱스 한 번으로 결정됨",[54,22337,22338,22344,22350,22356,22362,22368],{},[57,22339,22340,22343],{},[16,22341,22342],{},"COUNT(*) WHERE project_id=? AND status=1"," (누적·180일 통계)",[57,22345,22346,22349],{},[16,22347,22348],{},"MIN\u002FMAX(reg_date) WHERE project_id=? AND status=1"," (빠른 quick check)",[57,22351,22352,22355],{},[16,22353,22354],{},"SELECT subject ... ORDER BY reg_date DESC LIMIT 100"," (제목 군집화)",[57,22357,22358,22361],{},[16,22359,22360],{},"WHERE project_id=? AND status=1 AND reg_date >= ?"," (180일 cutoff)",[57,22363,22364,22367],{},[16,22365,22366],{},"WHERE project_id=? AND status=1 AND p.user_id NOT IN (...)"," (미응답·고객 메시지)",[57,22369,22370,22373],{},[16,22371,22372],{},"WHERE project_id=? AND label IS NOT NULL GROUP BY label"," (라벨 분포)",[24,22375,22376,22378],{},[28,22377,5701],{},": 추가 디스크 \u003C 1% (PMS tb_post 행 사이즈 작음). 쓰기 부하 무시 가능.",[215,22380,22382],{"id":22381},"_2-tb_post_comment","2. tb_post_comment",[415,22384,22386],{"className":8581,"code":22385,"language":8583,"meta":423,"style":423},"ALTER TABLE tb_post_comment ADD INDEX idx_postid_status_regdate (post_id, status, reg_date);\nALTER TABLE tb_post_comment ADD INDEX idx_postid_userid_status (post_id, user_id, status);\n",[16,22387,22388,22393],{"__ignoreMap":423},[2166,22389,22390],{"class":3301,"line":3302},[2166,22391,22392],{},"ALTER TABLE tb_post_comment ADD INDEX idx_postid_status_regdate (post_id, status, reg_date);\n",[2166,22394,22395],{"class":3301,"line":3335},[2166,22396,22397],{},"ALTER TABLE tb_post_comment ADD INDEX idx_postid_userid_status (post_id, user_id, status);\n",[24,22399,22400,3360],{},[28,22401,22334],{},[54,22403,22404,22410,22416],{},[57,22405,22406,22409],{},[16,22407,22408],{},"NOT EXISTS (SELECT 1 FROM tb_post_comment WHERE post_id = p.id AND status = 1 AND user_id IN (...))"," (미응답 판정)",[57,22411,22412,22415],{},[16,22413,22414],{},"MIN(reg_date) WHERE post_id = ? AND user_id IN (...)"," (FRT 첫 응답 시각)",[57,22417,22418],{},"가장 비싼 NOT EXISTS 상관 서브쿼리가 인덱스 한 번으로 끝남",[24,22420,22421,22423],{},[28,22422,5701],{},": 댓글 테이블이 크면 디스크 사용 약간 증가 (1~2%). 그래도 NOT EXISTS 풀스캔 대비 압도적 이득.",[33,22425],{},[36,22427,22429],{"id":22428},"적용-절차-운영팀-검토","적용 절차 (운영팀 검토)",[1925,22431,22432,22438,22590],{},[57,22433,22434,22437],{},[28,22435,22436],{},"백업 또는 dry run"," — 운영 PMS에 적용 전 테스트 서버에서 EXPLAIN 비교",[57,22439,22440,22443,22444,22447,22450,22470,22472,22479,22497,22502,22504,22510,22528,22536,22538,22541,22581],{},[28,22441,22442],{},"온라인 ALTER 시도"," — MySQL 5.6 InnoDB는 환경에 따라 옵션 제약. 단계적으로:",[22445,22446],"br",{},[28,22448,22449],{},"1단계 — LOCK 옵션 생략 (대부분 OK)",[415,22451,22453],{"className":8581,"code":22452,"language":8583,"meta":423,"style":423},"ALTER TABLE tb_post\n  ADD INDEX idx_project_status_regdate (project_id, status, reg_date),\n  ALGORITHM=INPLACE;\n",[16,22454,22455,22460,22465],{"__ignoreMap":423},[2166,22456,22457],{"class":3301,"line":3302},[2166,22458,22459],{},"ALTER TABLE tb_post\n",[2166,22461,22462],{"class":3301,"line":3335},[2166,22463,22464],{},"  ADD INDEX idx_project_status_regdate (project_id, status, reg_date),\n",[2166,22466,22467],{"class":3301,"line":3342},[2166,22468,22469],{},"  ALGORITHM=INPLACE;\n",[22445,22471],{},[28,22473,22474,22475,22478],{},"2단계 — ",[16,22476,22477],{},"LOCK=NONE"," 미지원 에러(2A000\u002F1845) 시",[415,22480,22482],{"className":8581,"code":22481,"language":8583,"meta":423,"style":423},"ALTER TABLE tb_post\n  ADD INDEX idx_project_status_regdate (project_id, status, reg_date),\n  ALGORITHM=INPLACE, LOCK=SHARED;\n",[16,22483,22484,22488,22492],{"__ignoreMap":423},[2166,22485,22486],{"class":3301,"line":3302},[2166,22487,22459],{},[2166,22489,22490],{"class":3301,"line":3335},[2166,22491,22464],{},[2166,22493,22494],{"class":3301,"line":3342},[2166,22495,22496],{},"  ALGORITHM=INPLACE, LOCK=SHARED;\n",[54,22498,22499],{},[57,22500,22501],{},"읽기 허용, 쓰기만 짧게 차단",[22445,22503],{},[28,22505,22506,22507],{},"3단계 — 그래도 안 되면 점검 시간에 ",[16,22508,22509],{},"ALGORITHM=COPY",[415,22511,22513],{"className":8581,"code":22512,"language":8583,"meta":423,"style":423},"ALTER TABLE tb_post\n  ADD INDEX idx_project_status_regdate (project_id, status, reg_date),\n  ALGORITHM=COPY;\n",[16,22514,22515,22519,22523],{"__ignoreMap":423},[2166,22516,22517],{"class":3301,"line":3302},[2166,22518,22459],{},[2166,22520,22521],{"class":3301,"line":3335},[2166,22522,22464],{},[2166,22524,22525],{"class":3301,"line":3342},[2166,22526,22527],{},"  ALGORITHM=COPY;\n",[54,22529,22530,22533],{},[57,22531,22532],{},"테이블 복사 (쓰기 차단). tb_post 크기에 따라 수 분",[57,22534,22535],{},"점검 윈도 확보 후",[22445,22537],{},[28,22539,22540],{},"4단계 — 무중단 필수면 외부 도구",[415,22542,22544],{"className":4632,"code":22543,"language":4634,"meta":423,"style":423},"# Percona toolkit\npt-online-schema-change \\\n  --alter \"ADD INDEX idx_project_status_regdate (project_id, status, reg_date)\" \\\n  D=pms,t=tb_post \\\n  --execute\n",[16,22545,22546,22551,22559,22569,22576],{"__ignoreMap":423},[2166,22547,22548],{"class":3301,"line":3302},[2166,22549,22550],{"class":3422},"# Percona toolkit\n",[2166,22552,22553,22556],{"class":3301,"line":3335},[2166,22554,22555],{"class":3309},"pt-online-schema-change",[2166,22557,22558],{"class":3402}," \\\n",[2166,22560,22561,22564,22567],{"class":3301,"line":3342},[2166,22562,22563],{"class":3402},"  --alter",[2166,22565,22566],{"class":3316}," \"ADD INDEX idx_project_status_regdate (project_id, status, reg_date)\"",[2166,22568,22558],{"class":3402},[2166,22570,22571,22574],{"class":3301,"line":3368},[2166,22572,22573],{"class":3316},"  D=pms,t=tb_post",[2166,22575,22558],{"class":3402},[2166,22577,22578],{"class":3301,"line":3396},[2166,22579,22580],{"class":3402},"  --execute\n",[54,22582,22583],{},[57,22584,22585,22586,22589],{},"또는 ",[16,22587,22588],{},"gh-ost"," (GitHub)",[57,22591,22592,22594,22595,22598],{},[28,22593,3763],{},": 적용 후 첫 브리핑 카드 호출(",[16,22596,22597],{},"force=1",")이 5~10배 빨라지면 OK",[33,22600],{},[36,22602,22604],{"id":22603},"explain-비교-참고","EXPLAIN 비교 (참고)",[215,22606,15339],{"id":22607},"before",[415,22609,22612],{"className":22610,"code":22611,"language":420},[418],"SELECT COUNT(*) FROM tb_post p\nJOIN tb_user pu ON pu.id = p.user_id\nWHERE p.project_id = 1528 AND p.status = 1 AND p.reg_date >= '20251130000000'\n  AND pu.email NOT LIKE '%@malgnsoft.com'\n  AND NOT EXISTS (SELECT 1 FROM tb_post_comment c JOIN tb_user cu ...)\n",[16,22613,22611],{"__ignoreMap":423},[54,22615,22616,22621,22626],{},[57,22617,22618,22620],{},[16,22619,11093],{}," Using where, rows = N (project_id 인덱스만 활용)",[57,22622,22623,22625],{},[16,22624,15316],{}," ALL (풀스캔, 매 row마다)",[57,22627,22628,22630],{},[16,22629,17012],{}," Using where (email LIKE 풀스캔)",[215,22632,22634],{"id":22633},"after-코드-변경-인덱스-추가","After (코드 변경 + 인덱스 추가)",[415,22636,22639],{"className":22637,"code":22638,"language":420},[418],"SELECT COUNT(*) FROM tb_post p\nWHERE p.project_id = 1528 AND p.status = 1 AND p.reg_date >= '20251130000000'\n  AND p.user_id NOT IN (1, 2, 3, ...)\n  AND NOT EXISTS (SELECT 1 FROM tb_post_comment c\n                   WHERE c.post_id = p.id AND c.status = 1 AND c.user_id IN (1, 2, ...))\n",[16,22640,22638],{"__ignoreMap":423},[54,22642,22643,22648,22653],{},[57,22644,22645,22647],{},[16,22646,11093],{}," Using index for group-by, range 한정",[57,22649,22650,22652],{},[16,22651,15316],{}," Using index, ref (post_id) — 인덱스 lookup만",[57,22654,22655,22657],{},[16,22656,17012],{}," 안 봄 (LIKE 제거됨)",[33,22659],{},[36,22661,22663],{"id":22662},"코드-측에서-한-일","코드 측에서 한 일",[1925,22665,22666,22679,22691],{},[57,22667,22668,22671,22672,530,22675,22678],{},[28,22669,22670],{},"staff user_id를 한 번에 가져와 캐시"," — 모든 후속 쿼리에서 ",[16,22673,22674],{},"IN",[16,22676,22677],{},"NOT IN","으로 사용",[57,22680,22681,2448,22684,1524,22687,22690],{},[28,22682,22683],{},"캐시 키를 quick check 2개로 변경",[16,22685,22686],{},"MAX(tb_post.reg_date)",[16,22688,22689],{},"MAX(tb_post_comment.reg_date)","로 데이터 변동 감지. 같으면 13개 SQL 안 침",[57,22692,22693,22696],{},[28,22694,22695],{},"24시간 hp_briefing 캐시 적중률 상승"," — 데이터 안 바뀌면 매번 캐시 그대로 반환",[33,22698],{},[36,22700,22702],{"id":22701},"적용-후-기대-효과","적용 후 기대 효과",[135,22704,22705,22718],{},[138,22706,22707],{},[141,22708,22709,22712,22715],{},[144,22710,22711],{},"지표",[144,22713,22714],{},"적용 전",[144,22716,22717],{},"적용 후",[157,22719,22720,22733,22743,22754],{},[141,22721,22722,22725,22728],{},[162,22723,22724],{},"캐시 hit 시 SQL 쿼리 수",[162,22726,22727],{},"13~14",[162,22729,22730,22732],{},[28,22731,7685],{}," (quick check만)",[141,22734,22735,22738,22740],{},[162,22736,22737],{},"캐시 miss 시 SQL 쿼리 수",[162,22739,22727],{},[162,22741,22742],{},"13~14 (동일하나 각 쿼리가 빨라짐)",[141,22744,22745,22748,22751],{},[162,22746,22747],{},"가장 비싼 unanswered 쿼리 지연",[162,22749,22750],{},"수백 ms ~ 수 초",[162,22752,22753],{},"수십 ms",[141,22755,22756,22762,22765],{},[162,22757,22758,22761],{},[16,22759,22760],{},"email LIKE"," 풀스캔",[162,22763,22764],{},"매 호출마다 N회",[162,22766,22767,1305,22770,22772],{},[28,22768,22769],{},"0회",[16,22771,22674],{}," 사용)",[4258,22774,22775],{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":423,"searchDepth":3342,"depth":3342,"links":22777},[22778,22782,22783,22787,22788],{"id":22315,"depth":3335,"text":22316,"children":22779},[22780,22781],{"id":22319,"depth":3342,"text":22320},{"id":22381,"depth":3342,"text":22382},{"id":22428,"depth":3335,"text":22429},{"id":22603,"depth":3335,"text":22604,"children":22784},[22785,22786],{"id":22607,"depth":3342,"text":15339},{"id":22633,"depth":3342,"text":22634},{"id":22662,"depth":3335,"text":22663},{"id":22701,"depth":3335,"text":22702},{},"\u002Fmysql-indexes",{"title":22259,"description":22267},"MYSQL-INDEXES","VXq31GglrcgYeVnwarbrD88e5Cqb3xVRcDlzFskxSBI",{"id":22795,"title":22796,"body":22797,"description":423,"extension":4340,"meta":24050,"navigation":3338,"path":24051,"seo":24052,"stem":24053,"__hash__":24054},"docs\u002FPROJECT-INQUIRY-ANALYSIS.md","프로젝트별(업체별) 문의 분석",{"type":8,"value":22798,"toc":24026},[22799,22802,22812,22814,22818,22858,22860,22864,22906,22918,22920,22924,23029,23031,23035,23427,23429,23433,23627,23636,23638,23642,23646,23657,23661,23672,23676,23687,23691,23702,23706,23723,23727,23738,23742,23754,23758,23763,23769,23784,23797,23805,23807,23811,23938,23940,23944,23993,23995,23997],[11,22800,22796],{"id":22801},"프로젝트별업체별-문의-분석",[21,22803,22804],{},[24,22805,19568,22806,22809,22810],{},[16,22807,22808],{},"pms.tb_post"," Q&A 후보 1,358건 (status=1, 댓글≥1, 비-Task\u002F일정\u002F투표\u002F공지, 테스트 제외, 본문≥20자)\n출처 메타: ",[3257,22811,6360],{"href":22255},[33,22813],{},[36,22815,22817],{"id":22816},"_1-요약-tldr","1. 요약 (TL;DR)",[54,22819,22820,22831,22838,22845,22855],{},[57,22821,22822,22823,22827,22828,22830],{},"실제 업체 구분은 ",[28,22824,22825],{},[16,22826,21765],{}," 단위. ",[16,22829,20125],{},"는 의미 없음(활동 사이트는 Site 1·2 두 곳뿐).",[57,22832,22833,22834,22837],{},"Q&A 후보 1,358건이 약 200여 프로젝트에 분포 — ",[28,22835,22836],{},"상위 25개 프로젝트가 약 50%"," 차지.",[57,22839,22840,22841,22844],{},"도메인은 ",[28,22842,22843],{},"LMS(학습관리시스템) 운영 지원이 압도적"," — 교육원·대학교·기업교육 위주.",[57,22846,22847,22848,22851,22852,407],{},"시점은 대부분 ",[28,22849,22850],{},"2022년 상반기(3~6월)",", 극소수만 2026년. ",[28,22853,22854],{},"답변 노후화 위험",[57,22856,22857],{},"빈출 주제: 일반 문의 > 오류 신고 > 진도\u002F수강\u002F학습 > 회원\u002F계정 > 콘텐츠\u002F영상 > SMS\u002F메일 > 견적\u002F정산 > 평가\u002F시험 > 수료증 > 도메인 > 결제\u002FPG.",[33,22859],{},[36,22861,22863],{"id":22862},"_2-분류-단위-사이트-업체","2. 분류 단위 — 사이트 ≠ 업체",[135,22865,22866,22877],{},[138,22867,22868],{},[141,22869,22870,22872,22874],{},[144,22871,20942],{},[144,22873,1543],{},[144,22875,22876],{},"Q&A 분포",[157,22878,22879,22894],{},[141,22880,22881,22885,22888],{},[162,22882,22883],{},[16,22884,20000],{},[162,22886,22887],{},"시스템 인스턴스",[162,22889,22890,22891],{},"Site 1(맑은소프트) 1,146 \u002F Site 2(맑은소프트 내부) 212. ",[28,22892,22893],{},"나머지 61개 사이트는 활동 없음",[141,22895,22896,22900,22903],{},[162,22897,22898],{},[16,22899,19796],{},[162,22901,22902],{},"실제 업체·업무 단위",[162,22904,22905],{},"1,358 전부 프로젝트 매핑됨",[24,22907,22908,22910,22911,11190,22915,22917],{},[28,22909,4789],{},": 업체별 자료 격리·필터·접근 제어의 기본 키는 ",[28,22912,22913],{},[16,22914,17812],{},[16,22916,20125],{},"는 외부 vs 내부 1차 분류용 정도.",[33,22919],{},[36,22921,22923],{"id":22922},"_3-프로젝트-이름-패턴","3. 프로젝트 이름 패턴",[135,22925,22926,22938],{},[138,22927,22928],{},[141,22929,22930,22933,22935],{},[144,22931,22932],{},"패턴",[144,22934,1543],{},[144,22936,22937],{},"예",[157,22939,22940,22957,22974,22992,23008],{},[141,22941,22942,22947,22950],{},[162,22943,22944],{},[16,22945,22946],{},"*업체명",[162,22948,22949],{},"종료\u002F완료 프로젝트",[162,22951,22952,105,22955],{},[16,22953,22954],{},"*경복대학교",[16,22956,9239],{},[141,22958,22959,22964,22967],{},[162,22960,22961],{},[16,22962,22963],{},"# 업체명",[162,22965,22966],{},"활성·특별 표시",[162,22968,22969,105,22971],{},[16,22970,9076],{},[16,22972,22973],{},"# 한국세무사회",[141,22975,22976,22981,22984],{},[162,22977,22978],{},[16,22979,22980],{},"업체명",[162,22982,22983],{},"일반 진행 중",[162,22985,22986,105,22989],{},[16,22987,22988],{},"주식회사 웅진",[16,22990,22991],{},"명지대학교",[141,22993,22994,22999,23005],{},[162,22995,22996],{},[16,22997,22998],{},"[영업] 일반LMS",[162,23000,23001,23004],{},[28,23002,23003],{},"영업 단계 잠재 고객"," 모음 — 회사명별 1~3건",[162,23006,23007],{},"\"함께일하는재단\", \"듀잇\", \"SK\" 등",[141,23009,23010,23015,23021],{},[162,23011,23012],{},[16,23013,23014],{},"01.\u002F02.\u002F09. ...",[162,23016,23017,23020],{},[28,23018,23019],{},"사내 업무 게시판"," — CS 자산 아님",[162,23022,23023,105,23026],{},[16,23024,23025],{},"01. 결재_월차 및 휴가",[16,23027,23028],{},"09. 대표님께 요청하기",[33,23030],{},[36,23032,23034],{"id":23033},"_4-상위-업체-top-25","4. 상위 업체 Top 25",[135,23036,23037,23054],{},[138,23038,23039],{},[141,23040,23041,23043,23046,23049,23052],{},[144,23042,497],{},[144,23044,23045],{},"프로젝트",[144,23047,23048],{},"site",[144,23050,23051],{},"Q&A",[144,23053,19661],{},[157,23055,23056,23074,23088,23102,23117,23132,23147,23161,23175,23192,23208,23222,23238,23252,23267,23283,23298,23312,23328,23341,23355,23370,23384,23398,23412],{},[141,23057,23058,23060,23066,23068,23071],{},[162,23059,6055],{},[162,23061,23062,23065],{},[2166,23063,23064],{},"영업"," 일반LMS",[162,23067,7685],{},[162,23069,23070],{},"103",[162,23072,23073],{},"신규 영업 잠재 고객 (회사명별 글)",[141,23075,23076,23078,23080,23082,23085],{},[162,23077,7685],{},[162,23079,9239],{},[162,23081,6055],{},[162,23083,23084],{},"88",[162,23086,23087],{},"HRD 직업훈련 LMS",[141,23089,23090,23092,23094,23096,23099],{},[162,23091,6004],{},[162,23093,22988],{},[162,23095,6055],{},[162,23097,23098],{},"53",[162,23100,23101],{},"일반 기업 교육",[141,23103,23104,23106,23109,23111,23114],{},[162,23105,5963],{},[162,23107,23108],{},"*프라임에듀넷",[162,23110,6055],{},[162,23112,23113],{},"51",[162,23115,23116],{},"에듀테크",[141,23118,23119,23121,23124,23126,23129],{},[162,23120,5952],{},[162,23122,23123],{},"*케이에이치정보교육원",[162,23125,6055],{},[162,23127,23128],{},"46",[162,23130,23131],{},"직업훈련 교육원",[141,23133,23134,23136,23139,23141,23144],{},[162,23135,6066],{},[162,23137,23138],{},"엘삭아트스쿨",[162,23140,6055],{},[162,23142,23143],{},"44",[162,23145,23146],{},"예술 교육",[141,23148,23149,23151,23153,23155,23158],{},[162,23150,15746],{},[162,23152,22954],{},[162,23154,6055],{},[162,23156,23157],{},"43",[162,23159,23160],{},"대학교 LMS",[141,23162,23163,23165,23167,23169,23172],{},[162,23164,5941],{},[162,23166,5820],{},[162,23168,6055],{},[162,23170,23171],{},"48",[162,23173,23174],{},"HRD 공공",[141,23176,23177,23180,23182,23184,23187],{},[162,23178,23179],{},"9",[162,23181,23028],{},[162,23183,7685],{},[162,23185,23186],{},"29",[162,23188,23189],{},[28,23190,23191],{},"사내",[141,23193,23194,23197,23200,23202,23205],{},[162,23195,23196],{},"10",[162,23198,23199],{},"구)몽땅뚝딱 현)갤러리티",[162,23201,6055],{},[162,23203,23204],{},"28",[162,23206,23207],{},"일반 기업",[141,23209,23210,23213,23215,23217,23220],{},[162,23211,23212],{},"11",[162,23214,22991],{},[162,23216,6055],{},[162,23218,23219],{},"27",[162,23221,23160],{},[141,23223,23224,23227,23230,23232,23235],{},[162,23225,23226],{},"12",[162,23228,23229],{},"*구)유니윌 현)아이티윌",[162,23231,6055],{},[162,23233,23234],{},"26",[162,23236,23237],{},"훈련기관",[141,23239,23240,23243,23246,23248,23250],{},[162,23241,23242],{},"13",[162,23244,23245],{},"*피아스페이스(주)",[162,23247,6055],{},[162,23249,20034],{},[162,23251,23207],{},[141,23253,23254,23257,23260,23262,23264],{},[162,23255,23256],{},"14",[162,23258,23259],{},"*언더독스",[162,23261,6055],{},[162,23263,20034],{},[162,23265,23266],{},"스타트업 교육",[141,23268,23269,23272,23275,23277,23280],{},[162,23270,23271],{},"15",[162,23273,23274],{},"국토안전관리원",[162,23276,6055],{},[162,23278,23279],{},"20",[162,23281,23282],{},"공공기관 교육",[141,23284,23285,23288,23290,23292,23295],{},[162,23286,23287],{},"16",[162,23289,9076],{},[162,23291,6055],{},[162,23293,23294],{},"19",[162,23296,23297],{},"대기업 인하우스 LMS",[141,23299,23300,23303,23305,23307,23309],{},[162,23301,23302],{},"17",[162,23304,22973],{},[162,23306,6055],{},[162,23308,23294],{},[162,23310,23311],{},"협회 교육",[141,23313,23314,23316,23319,23321,23323],{},[162,23315,20905],{},[162,23317,23318],{},"몽골개발팀",[162,23320,7685],{},[162,23322,23302],{},[162,23324,23325],{},[28,23326,23327],{},"사내 개발팀",[141,23329,23330,23332,23335,23337,23339],{},[162,23331,23294],{},[162,23333,23334],{},"안경공장 아이데코 안경체인",[162,23336,6055],{},[162,23338,23271],{},[162,23340,23207],{},[141,23342,23343,23345,23348,23350,23352],{},[162,23344,23279],{},[162,23346,23347],{},"기아 주식회사",[162,23349,6055],{},[162,23351,23271],{},[162,23353,23354],{},"대기업",[141,23356,23357,23360,23362,23364,23366],{},[162,23358,23359],{},"21",[162,23361,23025],{},[162,23363,7685],{},[162,23365,23271],{},[162,23367,23368],{},[28,23369,23191],{},[141,23371,23372,23374,23377,23379,23381],{},[162,23373,20034],{},[162,23375,23376],{},"*한솔아카데미",[162,23378,6055],{},[162,23380,23256],{},[162,23382,23383],{},"자격증 교육",[141,23385,23386,23389,23392,23394,23396],{},[162,23387,23388],{},"23",[162,23390,23391],{},"케이잡스 주식회사",[162,23393,6055],{},[162,23395,23242],{},[162,23397,23207],{},[141,23399,23400,23403,23406,23408,23410],{},[162,23401,23402],{},"24",[162,23404,23405],{},"# 오름에듀테크",[162,23407,6055],{},[162,23409,23226],{},[162,23411,23116],{},[141,23413,23414,23417,23420,23422,23424],{},[162,23415,23416],{},"25",[162,23418,23419],{},"*천재교육",[162,23421,6055],{},[162,23423,23226],{},[162,23425,23426],{},"대형 교육사",[33,23428],{},[36,23430,23432],{"id":23431},"_5-주제별-키워드-빈도-제목-기준","5. 주제별 키워드 빈도 (제목 기준)",[135,23434,23435,23449],{},[138,23436,23437],{},[141,23438,23439,23441,23444,23446],{},[144,23440,5925],{},[144,23442,23443],{},"키워드",[144,23445,5928],{},[144,23447,23448],{},"비중",[157,23450,23451,23465,23478,23492,23505,23518,23531,23544,23556,23568,23580,23591,23603,23615],{},[141,23452,23453,23456,23459,23462],{},[162,23454,23455],{},"일반 문의",[162,23457,23458],{},"문의",[162,23460,23461],{},"266",[162,23463,23464],{},"~20%",[141,23466,23467,23469,23472,23475],{},[162,23468,6821],{},[162,23470,23471],{},"오류",[162,23473,23474],{},"119",[162,23476,23477],{},"~9%",[141,23479,23480,23483,23486,23489],{},[162,23481,23482],{},"진도·수강·학습",[162,23484,23485],{},"진도\u002F수강\u002F학습",[162,23487,23488],{},"105",[162,23490,23491],{},"~8%",[141,23493,23494,23497,23500,23503],{},[162,23495,23496],{},"회원·계정",[162,23498,23499],{},"회원\u002F계정\u002F로그인\u002F비밀번호",[162,23501,23502],{},"69",[162,23504],{},[141,23506,23507,23510,23513,23516],{},[162,23508,23509],{},"콘텐츠·영상",[162,23511,23512],{},"WBT\u002F콘텐츠\u002F영상",[162,23514,23515],{},"66",[162,23517],{},[141,23519,23520,23523,23526,23529],{},[162,23521,23522],{},"알림·발송",[162,23524,23525],{},"SMS\u002F메일\u002F문자",[162,23527,23528],{},"52",[162,23530],{},[141,23532,23533,23536,23539,23542],{},[162,23534,23535],{},"정산·견적",[162,23537,23538],{},"견적\u002F계산서\u002F세금\u002F거래명세",[162,23540,23541],{},"47",[162,23543],{},[141,23545,23546,23549,23552,23554],{},[162,23547,23548],{},"평가·시험",[162,23550,23551],{},"평가\u002F시험\u002F퀴즈",[162,23553,23143],{},[162,23555],{},[141,23557,23558,23561,23564,23566],{},[162,23559,23560],{},"수료증",[162,23562,23563],{},"수료",[162,23565,20019],{},[162,23567],{},[141,23569,23570,23573,23575,23578],{},[162,23571,23572],{},"인프라",[162,23574,1650],{},[162,23576,23577],{},"30",[162,23579],{},[141,23581,23582,23585,23587,23589],{},[162,23583,23584],{},"결제",[162,23586,23584],{},[162,23588,23204],{},[162,23590],{},[141,23592,23593,23596,23599,23601],{},[162,23594,23595],{},"LMS 명시",[162,23597,23598],{},"LMS",[162,23600,23388],{},[162,23602],{},[141,23604,23605,23608,23611,23613],{},[162,23606,23607],{},"학습독려",[162,23609,23610],{},"독려\u002F알림\u002F알람",[162,23612,23359],{},[162,23614],{},[141,23616,23617,23620,23623,23625],{},[162,23618,23619],{},"결제 시스템",[162,23621,23622],{},"PG",[162,23624,23212],{},[162,23626],{},[24,23628,23629,23631,23632,23635],{},[28,23630,8295],{},": LMS 학사·운영 지원(진도·수료·평가·콘텐츠·회원·알림·결제·도메인)이 전체의 ",[28,23633,23634],{},"약 70%"," 추정.",[33,23637],{},[36,23639,23641],{"id":23640},"_6-주요-업체별-문의-성격-요약","6. 주요 업체별 문의 성격 요약",[215,23643,23645],{"id":23644},"현대엔지비-lms-19건","# 현대엔지비 LMS (19건)",[54,23647,23648,23654],{},[57,23649,23650,23653],{},[28,23651,23652],{},"운영 중 LMS의 유지보수·콘텐츠 관리"," 중심.",[57,23655,23656],{},"빈출 주제: 콘텐츠 재생 오류, 상시학습 데이터 추출, 수료증 양식 수정, 게이트페이지 권한, 학습자 일괄 등록 오류, 디자인 견적\u002F배너 제작.",[215,23658,23660],{"id":23659},"에듀야-88건","*에듀야 (88건)",[54,23662,23663,23669],{},[57,23664,23665,23666,407],{},"HRD\u002F직업훈련 LMS — ",[28,23667,23668],{},"카테고리가 가장 다양",[57,23670,23671],{},"평가·퀴즈, SMS\u002F메일 발송, 학습독려, WBT 콘텐츠, Q&A 알람, 모바일 팝업, 회원정보 수정, 강사·심사관 계정, 심사용 서류, 나이스평가정보 코드.",[215,23673,23675],{"id":23674},"케이에이치정보교육원-46건","*케이에이치정보교육원 (46건)",[54,23677,23678,23684],{},[57,23679,23680,23683],{},[28,23681,23682],{},"직업훈련 + HRD 심사 관련"," 특화.",[57,23685,23686],{},"WBT\u002FPWBT, 산인공 API, K-디지털 모니터링, 수료처리, 환불, PG 결제, 도메인 A레코드, 영상 업로드 CDN, mOTP.",[215,23688,23690],{"id":23689},"경복대학교-43건","*경복대학교 (43건)",[54,23692,23693,23699],{},[57,23694,23695,23698],{},[28,23696,23697],{},"대학 LMS 구축·운영 초기 단계"," 문의.",[57,23700,23701],{},"도메인 포워딩·소유권 이전·A레코드, PG 심사, 월 사용료\u002F거래명세서, 홈페이지 디자인·오타, 진도율 오류, 대면교육 일정.",[215,23703,23705],{"id":23704},"안전보건진흥원-48건","*안전보건진흥원 (48건)",[54,23707,23708,23711,23714],{},[57,23709,23710],{},"HRD 공공기관 콘텐츠 운영.",[57,23712,23713],{},"MP4 진도제어 불가, 회원탈퇴 시 교육 데이터 삭제 정책, 온라인 컨텐츠 반영 방법.",[57,23715,23716,23719,23720,23722],{},[28,23717,23718],{},"일부 답변이 비공개에만 존재"," (예: post 94221) — ",[3257,23721,6360],{"href":22255}," §6 비공개 댓글 처리 전략 참조.",[215,23724,23726],{"id":23725},"구유니윌-현아이티윌-26건","*구)유니윌 현)아이티윌 (26건)",[54,23728,23729,23735],{},[57,23730,23731,23734],{},[28,23732,23733],{},"결제·API 통합 이슈"," 빈출.",[57,23736,23737],{},"산인공 LMS API 오류, 결제 누락\u002F오류, PG 코드 변경, 수료처리 API, 도메인 설정, 자동메일 조건부 발송.",[215,23739,23741],{"id":23740},"언더독스-22건","*언더독스 (22건)",[54,23743,23744,23751],{},[57,23745,23746,23747,23750],{},"스타트업 교육 LMS — ",[28,23748,23749],{},"기능 개선·운영 정책"," 비중 큼.",[57,23752,23753],{},"수강종료\u002F수료 기준, 학습독려 알림, 과제 미제출자 처리, 쿠폰 발행, 코칭권 업데이트.",[215,23755,23757],{"id":23756},"프라임에듀넷-51건명지대학교-27건한솔아카데미-14건-등","*프라임에듀넷 (51건)·명지대학교 (27건)·*한솔아카데미 (14건) 등",[54,23759,23760],{},[57,23761,23762],{},"LMS 일반 운영(학습독려·수료증·FTP·서버 세팅).",[215,23764,23766,23768],{"id":23765},"영업-일반lms-103건",[2166,23767,23064],{}," 일반LMS (103건)",[54,23770,23771,23777],{},[57,23772,23773,23776],{},[28,23774,23775],{},"신규 영업 단계"," 게시판. 회사명 자체가 글 제목.",[57,23778,23779,23780,23783],{},"답변\u002F제안서 작성 협업용 — Q&A 형식이 아니라 ",[28,23781,23782],{},"영업 메모"," 성격.",[215,23785,23787,23788,105,23791,105,23794,23796],{"id":23786},"사내-프로젝트-01-09-몽골개발팀-등","사내 프로젝트 (",[16,23789,23790],{},"01.~",[16,23792,23793],{},"09.~",[16,23795,23318],{}," 등)",[54,23798,23799],{},[57,23800,23801,23802,407],{},"결재(월차\u002F휴가), 회의록, 대표 요청, 사내 개발팀 — ",[28,23803,23804],{},"CS 자산 아님",[33,23806],{},[36,23808,23810],{"id":23809},"_7-ai-데이터-활용-시사점","7. AI 데이터 활용 시사점",[135,23812,23813,23822],{},[138,23814,23815],{},[141,23816,23817,23819],{},[144,23818,6304],{},[144,23820,23821],{},"적용 방안",[157,23823,23824,23834,23858,23875,23885,23898,23911,23928],{},[141,23825,23826,23831],{},[162,23827,23828,23829],{},"인덱스 분리 키 = ",[16,23830,17812],{},[162,23832,23833],{},"업체별 자료 격리·필터·접근 제어의 기본 단위",[141,23835,23836,23841],{},[162,23837,23838],{},[28,23839,23840],{},"사내 프로젝트 제외 룰",[162,23842,23843,23844,23847,23848,105,23851,23854,23855,23857],{},"이름 패턴 ",[16,23845,23846],{},"^[0-9]+\\."," (예: ",[16,23849,23850],{},"01. ...",[16,23852,23853],{},"09. ...",") + Site 2 일부 + ",[16,23856,23318],{}," 등 화이트리스트 검증 후 제외",[141,23859,23860,23865],{},[162,23861,23862],{},[28,23863,23864],{},"영업 일반LMS 별도 처리",[162,23866,23867,23868,394,23871,23874],{},"project_id=153. Q&A 형식 깨짐 → 챗봇 답변 자산보다는 ",[28,23869,23870],{},"영업 사례 메타",[28,23872,23873],{},"표준 답변 트리거"," 검토 대상",[141,23876,23877,23882],{},[162,23878,23879],{},[28,23880,23881],{},"표준 답변 자동 후보화",[162,23883,23884],{},"키워드 빈도(진도\u002F수료\u002F평가\u002FSMS\u002F도메인\u002FPG 등)에서 반복 답변 다수 → 제목·본문 임베딩 클러스터링으로 표준 답변 후보 추출",[141,23886,23887,23892],{},[162,23888,23889],{},[28,23890,23891],{},"업체별 답변 분리",[162,23893,23894,23895,23897],{},"같은 \"수료 처리\"라도 업체별 정책·세팅 상이 → 검색 시 ",[16,23896,17812],{}," 필터 + 전사 공통 결과 병합 전략",[141,23899,23900,23905],{},[162,23901,23902],{},[28,23903,23904],{},"답변 노후화 가중치",[162,23906,23907,23908,23910],{},"데이터 대부분 2022년 → ",[16,23909,20274],{}," 기반 신선도 가중치 + 정기 검토 워크플로 필수",[141,23912,23913,23921],{},[162,23914,23915],{},[28,23916,23917,23918,23920],{},"종료 프로젝트(",[16,23919,5824],{},") 가드",[162,23922,23923,23924,23927],{},"학습 자산으로는 유효하나 ",[28,23925,23926],{},"\"현재 시스템과 다를 수 있다\""," 가드 필요",[141,23929,23930,23935],{},[162,23931,23932],{},[28,23933,23934],{},"HRD 특화 카테고리",[162,23936,23937],{},"산인공 API, K-디지털, mOTP, WBT\u002FPWBT, 나이스평가정보 등은 별도 표준 답변 카테고리로 구축 가치",[33,23939],{},[36,23941,23943],{"id":23942},"_8-권장-후속-작업","8. 권장 후속 작업",[1925,23945,23946,23955,23961,23967,23973,23981,23987],{},[57,23947,23948,4664,23951,23954],{},[28,23949,23950],{},"사내 프로젝트 필터 룰 SQL 작성",[16,23952,23953],{},"project.name REGEXP '^[0-9]+\\\\.'"," + 수동 화이트리스트 검토 → CS 자산만 남김.",[57,23956,23957,23960],{},[28,23958,23959],{},"Top 5 프로젝트 표본 검수"," (에듀야·웅진·프라임에듀넷·케이에이치·경복대 각 30건) → 답변 품질·신선도 평가.",[57,23962,23963,23966],{},[28,23964,23965],{},"주제 카테고리 클러스터링 PoC",": 제목 임베딩으로 자동 분류, 표준 답변 후보 추출.",[57,23968,23969,23972],{},[28,23970,23971],{},"영업 일반LMS(project_id=153) 활용 방안 결정",": 챗봇 학습 자산 \u002F 영업 메모 \u002F 미사용 중 택일.",[57,23974,23975,23980],{},[28,23976,23917,23977,23979],{},[16,23978,5824],{},") 노출 정책 합의",": Phase 2 챗봇에서 어디까지 답변 자산으로 쓸지.",[57,23982,23983,23986],{},[28,23984,23985],{},"공공\u002FHRD 도메인 별도 표준 답변 트랙"," 운영 검토 (산인공·K-디지털 등 규제 변동성 큰 영역).",[57,23988,23989,23992],{},[28,23990,23991],{},"2026년 활동 데이터 추출",": 1.7만 게시글 중 2026년 데이터만 별도 분석 — 현재 운영 흐름과 차이 검증.",[33,23994],{},[36,23996,8956],{"id":8955},[54,23998,23999,24012,24019],{},[57,24000,24001,24002,530,24004,530,24006,24008,24009,24011],{},"인덱스 메타 필드(",[16,24003,17812],{},[16,24005,21757],{},[16,24007,20125],{},")·가시성 정책: ",[3257,24010,6360],{"href":22255}," §7",[57,24013,24014,24015,2367,24017],{},"표준 답변 후보 자동 추출 흐름: ",[3257,24016,6981],{"href":22076},[28,24018,6984],{},[57,24020,24021,24022,24025],{},"WBS 1-4 기본자료 검토 입력 자료: ",[3257,24023,10422],{"href":24024},"WBS"," Phase 1",{"title":423,"searchDepth":3342,"depth":3342,"links":24027},[24028,24029,24030,24031,24032,24033,24047,24048,24049],{"id":22816,"depth":3335,"text":22817},{"id":22862,"depth":3335,"text":22863},{"id":22922,"depth":3335,"text":22923},{"id":23033,"depth":3335,"text":23034},{"id":23431,"depth":3335,"text":23432},{"id":23640,"depth":3335,"text":23641,"children":24034},[24035,24036,24037,24038,24039,24040,24041,24042,24043,24045],{"id":23644,"depth":3342,"text":23645},{"id":23659,"depth":3342,"text":23660},{"id":23674,"depth":3342,"text":23675},{"id":23689,"depth":3342,"text":23690},{"id":23704,"depth":3342,"text":23705},{"id":23725,"depth":3342,"text":23726},{"id":23740,"depth":3342,"text":23741},{"id":23756,"depth":3342,"text":23757},{"id":23765,"depth":3342,"text":24044},"영업 일반LMS (103건)",{"id":23786,"depth":3342,"text":24046},"사내 프로젝트 (01.~, 09.~, 몽골개발팀 등)",{"id":23809,"depth":3335,"text":23810},{"id":23942,"depth":3335,"text":23943},{"id":8955,"depth":3335,"text":8956},{},"\u002Fproject-inquiry-analysis",{"title":22796,"description":423},"PROJECT-INQUIRY-ANALYSIS","TPbMF5BDlOtWucg24FVpofG7oHuqvJ1gGAEAGH4oy9A",{"id":24056,"title":24057,"body":24058,"description":423,"extension":4340,"meta":26812,"navigation":3338,"path":26813,"seo":26814,"stem":26815,"__hash__":26816},"docs\u002FPROJECT_MANAGEMENT_BLUEPRINT.md","프로젝트 관리 앱 블루프린트 (재사용 가이드)",{"type":8,"value":24059,"toc":26778},[24060,24063,24108,24110,24114,24121,24206,24222,24224,24228,24331,24336,24424,24426,24430,24434,24468,24470,24476,24491,24495,24501,24503,24507,24514,24520,24580,24582,24586,24593,24633,24639,24664,24671,24754,24764,24792,24798,24805,24807,24811,24817,25542,25561,25567,25749,25751,25755,25844,25847,25974,26000,26002,26006,26013,26021,26066,26070,26076,26092,26094,26098,26182,26184,26188,26285,26289,26345,26349,26455,26460,26511,26513,26517,26590,26615,26617,26621,26659,26661,26665,26672,26766,26775],[11,24061,24057],{"id":24062},"프로젝트-관리-앱-블루프린트-재사용-가이드",[21,24064,24065,24080],{},[24,24066,24067,24068,24071,24072,24075,24076,24079],{},"이 문서는 ",[16,24069,24070],{},"malgn-noti-mng","로 구현한 ",[28,24073,24074],{},"프로젝트 관리 허브 앱","의 일반화된 설계도다.\n특정 프로젝트의 데이터·문구·도메인 내용은 제외하고, ",[28,24077,24078],{},"다른 프로젝트에 그대로 이식·구현","할 수 있는\n아키텍처 · 메뉴 · 화면 · 스키마 · 디자인 토큰 · 셋업\u002F배포 절차만 담는다.\nClaude Code가 이 문서만 보고 새 프로젝트용 관리 앱을 처음부터 구축할 수 있도록 작성했다.",[24,24081,24082,4664,24085,24088,24089,467,24092,24095,24096,24099,24100,24103,24104,24107],{},[28,24083,24084],{},"치환 토큰",[16,24086,24087],{},"{APP}","=앱\u002FPages 프로젝트명(예: ",[16,24090,24091],{},"myproj-mng",[16,24093,24094],{},"{PROJECT}","=대상 프로젝트 표시명 ·\n",[16,24097,24098],{},"{D1_NAME}","=D1 DB명 · ",[16,24101,24102],{},"{D1_ID}","=D1 database_id · ",[16,24105,24106],{},"{REPO}","=GitHub 레포 URL.",[33,24109],{},[36,24111,24113],{"id":24112},"_1-이-앱은-무엇인가-목적","1. 이 앱은 무엇인가 (목적)",[24,24115,24116,24117,24120],{},"하나의 프로젝트를 운영·조망하는 ",[28,24118,24119],{},"단일 관리 허브",". 5개 영역으로 구성:",[135,24122,24123,24134],{},[138,24124,24125],{},[141,24126,24127,24129,24131],{},[144,24128,16825],{},[144,24130,503],{},[144,24132,24133],{},"한 줄 정의",[157,24135,24136,24148,24161,24177,24193],{},[141,24137,24138,24141,24145],{},[162,24139,24140],{},"대시보드",[162,24142,24143],{},[16,24144,530],{},[162,24146,24147],{},"프로젝트 개요(목표·방향) + 진척 요약 + 바로가기",[141,24149,24150,24153,24158],{},[162,24151,24152],{},"현황판",[162,24154,24155],{},[16,24156,24157],{},"\u002Fboard",[162,24159,24160],{},"단계\u002F작업 진척을 시각 카드·행으로 보는 상태 보드",[141,24162,24163,24166,24170],{},[162,24164,24165],{},"WBS(간트)",[162,24167,24168],{},[16,24169,12910],{},[162,24171,24172,24173,24176],{},"일 단위 간트 차트 + 작업 ",[28,24174,24175],{},"등록\u002F수정\u002F삭제","(CRUD)",[141,24178,24179,24182,24187],{},[162,24180,24181],{},"문서",[162,24183,24184],{},[16,24185,24186],{},"\u002Fdocs",[162,24188,24189,24192],{},[16,24190,24191],{},"doc\u002F"," 마크다운 트리 뷰어",[141,24194,24195,24198,24203],{},[162,24196,24197],{},"작업 이력",[162,24199,24200],{},[16,24201,24202],{},"\u002Fhistory",[162,24204,24205],{},"일자별 작업 이력 타임라인",[24,24207,24208,24211,24212,24215,24216,24221],{},[28,24209,24210],{},"데이터 정본 2종",": ① 구조화 데이터(진척·작업·단계)는 ",[28,24213,24214],{},"Cloudflare D1",", ② 문서\u002F이력은 ",[28,24217,24218,24220],{},[16,24219,24191],{}," 마크다운","(@nuxt\u002Fcontent).\n자체 완결형 — 외부 API 의존 없음(원하면 외부 API도 붙일 수 있으나 기본은 자급).",[33,24223],{},[36,24225,24227],{"id":24226},"_2-기술-스택","2. 기술 스택",[54,24229,24230,24243,24253,24262,24275,24294,24307,24316,24322],{},[57,24231,24232,24235,24236,105,24239,24242],{},[28,24233,24234],{},"프레임워크",": Nuxt 3 (",[16,24237,24238],{},"future.compatibilityVersion: 4",[16,24240,24241],{},"\u003Cscript setup lang=\"ts\">",", strict TS)",[57,24244,24245,24248,24249,24252],{},[28,24246,24247],{},"UI",": Nuxt UI v3 (Reka UI + Tailwind CSS v4). ",[16,24250,24251],{},"@nuxtjs\u002Ftailwindcss","는 설치 금지(Nuxt UI가 통합 관리)",[57,24254,24255,24257,24258,24261],{},[28,24256,7333],{},": Pinia (",[16,24259,24260],{},"@pinia\u002Fnuxt",") — 필요 시",[57,24263,24264,4664,24267,24270,24271,24274],{},[28,24265,24266],{},"콘텐츠",[16,24268,24269],{},"@nuxt\u002Fcontent"," v3 + ",[16,24272,24273],{},"better-sqlite3","(빌드 타임 SQLite 어댑터)",[57,24276,24277,24280,24281,1524,24284,3351,24287,17484,24290,24293],{},[28,24278,24279],{},"DB\u002FORM",": Cloudflare ",[28,24282,24283],{},"D1",[28,24285,24286],{},"Drizzle ORM",[16,24288,24289],{},"drizzle-orm\u002Fd1",[16,24291,24292],{},"drizzle-kit","(마이그레이션)",[57,24295,24296,4664,24298,105,24301,1305,24304,78],{},[28,24297,506],{},[16,24299,24300],{},"@iconify-json\u002Flucide",[16,24302,24303],{},"@iconify-json\u002Fheroicons",[16,24305,24306],{},"i-lucide-*",[57,24308,24309,4664,24312,24315],{},[28,24310,24311],{},"린트",[16,24313,24314],{},"@nuxt\u002Feslint"," + ESLint",[57,24317,24318,24321],{},[28,24319,24320],{},"패키지 매니저",": pnpm",[57,24323,24324,24326,24327,24330],{},[28,24325,11529],{},": Cloudflare Pages (Functions\u002FSSR) — Nitro ",[16,24328,24329],{},"cloudflare-pages"," 프리셋",[24,24332,24333,24335],{},[16,24334,10090],{}," 핵심:",[415,24337,24339],{"className":13086,"code":24338,"language":13088,"meta":423,"style":423},"{\n  \"scripts\": {\n    \"dev\": \"nuxt dev\", \"build\": \"nuxt build\", \"preview\": \"nuxt preview\",\n    \"postinstall\": \"nuxt prepare\", \"typecheck\": \"nuxt typecheck\", \"lint\": \"eslint .\",\n    \"db:generate\": \"drizzle-kit generate\",\n    \"db:apply\": \"wrangler d1 migrations apply {D1_NAME} --remote\",\n    \"db:seed\": \"wrangler d1 execute {D1_NAME} --remote --file=server\u002Fdb\u002Fseed.sql\"\n  },\n  \"dependencies\": [\n    \"@iconify-json\u002Fheroicons\",\"@iconify-json\u002Flucide\",\"@nuxt\u002Fcontent\",\"@nuxt\u002Fui\",\n    \"@pinia\u002Fnuxt\",\"better-sqlite3\",\"drizzle-orm\",\"nuxt\",\"pinia\",\"vue\",\"vue-router\"\n  ],\n  \"devDependencies\": [\"@nuxt\u002Feslint\",\"drizzle-kit\",\"eslint\",\"typescript\",\"vue-tsc\"],\n  \u002F\u002F 네이티브 빌드 허용 (pnpm v10 비대화형 설치 필수)\n  \"pnpm\": { \"onlyBuiltDependencies\":\n    [\"@parcel\u002Fwatcher\",\"better-sqlite3\",\"esbuild\",\"unrs-resolver\",\"vue-demi\"] }\n}\n",[16,24340,24341,24345,24350,24355,24360,24365,24370,24375,24380,24385,24390,24395,24400,24405,24410,24415,24420],{"__ignoreMap":423},[2166,24342,24343],{"class":3301,"line":3302},[2166,24344,13095],{},[2166,24346,24347],{"class":3301,"line":3335},[2166,24348,24349],{},"  \"scripts\": {\n",[2166,24351,24352],{"class":3301,"line":3342},[2166,24353,24354],{},"    \"dev\": \"nuxt dev\", \"build\": \"nuxt build\", \"preview\": \"nuxt preview\",\n",[2166,24356,24357],{"class":3301,"line":3368},[2166,24358,24359],{},"    \"postinstall\": \"nuxt prepare\", \"typecheck\": \"nuxt typecheck\", \"lint\": \"eslint .\",\n",[2166,24361,24362],{"class":3301,"line":3396},[2166,24363,24364],{},"    \"db:generate\": \"drizzle-kit generate\",\n",[2166,24366,24367],{"class":3301,"line":3426},[2166,24368,24369],{},"    \"db:apply\": \"wrangler d1 migrations apply {D1_NAME} --remote\",\n",[2166,24371,24372],{"class":3301,"line":3463},[2166,24373,24374],{},"    \"db:seed\": \"wrangler d1 execute {D1_NAME} --remote --file=server\u002Fdb\u002Fseed.sql\"\n",[2166,24376,24377],{"class":3301,"line":3504},[2166,24378,24379],{},"  },\n",[2166,24381,24382],{"class":3301,"line":3538},[2166,24383,24384],{},"  \"dependencies\": [\n",[2166,24386,24387],{"class":3301,"line":3550},[2166,24388,24389],{},"    \"@iconify-json\u002Fheroicons\",\"@iconify-json\u002Flucide\",\"@nuxt\u002Fcontent\",\"@nuxt\u002Fui\",\n",[2166,24391,24392],{"class":3301,"line":3556},[2166,24393,24394],{},"    \"@pinia\u002Fnuxt\",\"better-sqlite3\",\"drizzle-orm\",\"nuxt\",\"pinia\",\"vue\",\"vue-router\"\n",[2166,24396,24397],{"class":3301,"line":5367},[2166,24398,24399],{},"  ],\n",[2166,24401,24402],{"class":3301,"line":5375},[2166,24403,24404],{},"  \"devDependencies\": [\"@nuxt\u002Feslint\",\"drizzle-kit\",\"eslint\",\"typescript\",\"vue-tsc\"],\n",[2166,24406,24407],{"class":3301,"line":5392},[2166,24408,24409],{},"  \u002F\u002F 네이티브 빌드 허용 (pnpm v10 비대화형 설치 필수)\n",[2166,24411,24412],{"class":3301,"line":5404},[2166,24413,24414],{},"  \"pnpm\": { \"onlyBuiltDependencies\":\n",[2166,24416,24417],{"class":3301,"line":5415},[2166,24418,24419],{},"    [\"@parcel\u002Fwatcher\",\"better-sqlite3\",\"esbuild\",\"unrs-resolver\",\"vue-demi\"] }\n",[2166,24421,24422],{"class":3301,"line":5421},[2166,24423,3559],{},[33,24425],{},[36,24427,24429],{"id":24428},"_3-시스템-아키텍처","3. 시스템 아키텍처",[215,24431,24433],{"id":24432},"렌더링-전략-프리렌더-vs-ssr-핵심-결정","렌더링 전략 (프리렌더 vs SSR) — 핵심 결정",[54,24435,24436,24453],{},[57,24437,24438,4664,24446,24449,24450,24452],{},[28,24439,24440,24441,105,24444,78],{},"문서\u002F이력 페이지(",[16,24442,24443],{},"\u002Fdocs\u002F**",[16,24445,24202],{},[28,24447,24448],{},"프리렌더(정적)",". 빌드 타임에 ",[16,24451,24269],{},"가 마크다운을 HTML로 구워 베이크 → 런타임 DB 불필요.",[57,24454,24455,4664,24464,24467],{},[28,24456,24457,24458,105,24460,105,24462,78],{},"대시보드\u002F현황판\u002FWBS(",[16,24459,530],{},[16,24461,24157],{},[16,24463,12910],{},[28,24465,24466],{},"SSR(Pages Functions)",". 런타임에 D1을 조회하므로 프리렌더하지 않는다.",[215,24469,4549],{"id":4548},[415,24471,24474],{"className":24472,"code":24473,"language":420},[418],"브라우저\n  ├─ \u002Fdocs, \u002Fhistory        → (프리렌더 HTML, @nuxt\u002Fcontent 빌드 산출)\n  └─ \u002F, \u002Fboard, \u002Fwbs (SSR)  → useFetch('\u002Fapi\u002F*') → server\u002Fapi\u002F* (Pages Function)\n                                                      └─ useDb(event) → Drizzle → D1({D1_NAME})\n",[16,24475,24473],{"__ignoreMap":423},[54,24477,24478,24488],{},[57,24479,24480,24483,24484,24487],{},[28,24481,24482],{},"브라우저는 D1에 직접 접근 불가",". 반드시 서버 한 겹(Pages Function + ",[16,24485,24486],{},"env.DB"," 바인딩) 경유.",[57,24489,24490],{},"데이터 편집(CRUD)도 같은 API 경유.",[215,24492,24494],{"id":24493},"디렉터리-구조","디렉터리 구조",[415,24496,24499],{"className":24497,"code":24498,"language":420},[418],"app\u002F\n  app.vue                     # \u003CUApp>\u003CNuxtLayout>\u003CNuxtPage\u002F>\n  app.config.ts               # Nuxt UI 색상 매핑(primary\u002Fneutral)\n  assets\u002Fcss\u002Fmain.css         # 디자인 시스템 토큰(전역)\n  assets\u002Fcss\u002Fprose.css        # 마크다운 prose 스타일(전역 — §9 주의)\n  layouts\u002Fdefault.vue         # GNB(상단 네비) + 푸터\n  components\u002F\n    AppLogoMark.vue           # 로고 마크(인라인 SVG)\n    AppWbsOverview.vue        # 대시보드\u002F현황판 공용 진척 요약(전체% + 단계 박스\u002F행)\n  composables\u002F\n    useDocs.ts                # doc\u002F 콘텐츠 조회 + history 판별·날짜 포맷\n    useWbs.ts                 # \u002Fapi\u002Fboard 조회 + 파생 통계(가중평균·카운트·상태)\n  pages\u002F\n    index.vue                 # 대시보드\n    board.vue                 # 현황판\n    wbs.vue                   # 간트 WBS (+ CRUD UI)\n    docs\u002Findex.vue            # 문서 목록\n    docs\u002F[...slug].vue        # 문서 렌더(ContentRenderer)\n    history\u002Findex.vue         # 작업 이력 타임라인\n  utils\u002FwbsData.ts            # WBS 정적 메타(단계명·가중치) + dev 시드 폴백\nserver\u002F\n  api\u002Fboard.get.ts            # 현황판 데이터(GET)\n  api\u002Fwbs.get.ts              # WBS 목록(GET)\n  api\u002Fwbs.post.ts             # WBS 등록(POST)\n  api\u002Fwbs\u002F[id].patch.ts       # WBS 수정(PATCH)\n  api\u002Fwbs\u002F[id].delete.ts      # WBS 삭제(DELETE)\n  db\u002Fschema.ts                # Drizzle 스키마(정본)\n  db\u002Fmigrations\u002F*             # drizzle-kit 생성 마이그레이션\n  db\u002Fseed.sql                 # 시드(초기 데이터)\n  utils\u002Fdb.ts                 # useDb(event) → Drizzle\u002FD1\n  utils\u002FboardSeed.ts          # dev(D1 없음) 폴백 시드\ncontent.config.ts             # @nuxt\u002Fcontent: 소스를 doc\u002F 로 매핑\nnuxt.config.ts                # 프리렌더 라우트 열거 + cloudflare-pages 프리셋\nwrangler.toml                 # D1 바인딩 + migrations_dir\ndoc\u002F                          # 마크다운 문서 + history\u002F\n",[16,24500,24498],{"__ignoreMap":423},[33,24502],{},[36,24504,24506],{"id":24505},"_4-메뉴-구성도-ia","4. 메뉴 구성도 (IA)",[24,24508,24509,24510,24513],{},"상단 GNB(고정 56px): ",[16,24511,24512],{},"[로고]"," + 네비 + (우측) GitHub 링크.",[415,24515,24518],{"className":24516,"code":24517,"language":420},[418],"[로고 {PROJECT}]   대시보드 · 현황판 · WBS · 문서 · 작업 이력            GitHub↗\n",[16,24519,24517],{"__ignoreMap":423},[54,24521,24522,24577],{},[57,24523,24524,4708,24527,24530,24531,24534,24535],{},[16,24525,24526],{},"default.vue",[16,24528,24529],{},"nav"," 배열로 정의: ",[16,24532,24533],{},"{ to, label, icon }",".\n",[54,24536,24537,24545,24553,24561,24569],{},[57,24538,24539,24540,2367,24542],{},"대시보드 ",[16,24541,530],{},[16,24543,24544],{},"i-lucide-layout-dashboard",[57,24546,24547,24548,2367,24550],{},"현황판 ",[16,24549,24157],{},[16,24551,24552],{},"i-lucide-gauge",[57,24554,24555,24556,2367,24558],{},"WBS ",[16,24557,12910],{},[16,24559,24560],{},"i-lucide-gantt-chart",[57,24562,24563,24564,2367,24566],{},"문서 ",[16,24565,24186],{},[16,24567,24568],{},"i-lucide-book-text",[57,24570,24571,24572,2367,24574],{},"작업 이력 ",[16,24573,24202],{},[16,24575,24576],{},"i-lucide-history",[57,24578,24579],{},"푸터: 한 줄 카피라이트\u002F설명.",[33,24581],{},[36,24583,24585],{"id":24584},"_5-화면별-명세-일반","5. 화면별 명세 (일반)",[215,24587,24589,24590,24592],{"id":24588},"_51-대시보드-ssr","5.1 대시보드 ",[16,24591,530],{}," (SSR)",[54,24594,24595,24601,24618,24624],{},[57,24596,24597,24600],{},[28,24598,24599],{},"프로젝트 개요",": 목표 카드(한 줄 목표 + 핵심 키워드 칩) + 방향 카드(불릿). 데이터는 페이지 내 배열 또는 별도 doc.",[57,24602,24603,4664,24606,24609,24610,24613,24614,24617],{},[28,24604,24605],{},"프로젝트 현황 요약",[16,24607,24608],{},"AppWbsOverview","(전체 진척% + 단계 박스) — ",[16,24611,24612],{},"useWbs()","로 ",[16,24615,24616],{},"\u002Fapi\u002Fboard"," 조회.",[57,24619,24620,24623],{},[28,24621,24622],{},"바로가기",": 외부 링크 카드(라벨 + URL). 배열로 관리.",[57,24625,24626,4664,24629,24632],{},[28,24627,24628],{},"문서 \u002F 최근 작업 이력",[16,24630,24631],{},"useDocs()","로 doc 목록·최근 history N개 카드.",[215,24634,24636,24637,24592],{"id":24635},"_52-현황판-board-ssr","5.2 현황판 ",[16,24638,24157],{},[54,24640,24641,24644,24647],{},[57,24642,24643],{},"상단: 전체 진척률(가중평균) + 완료\u002F진행 중 카운터.",[57,24645,24646],{},"단계별 진척률(행 스타일) + 단계 상세(그룹\u002F작업 표: 상태·담당·목표\u002F완료일).",[57,24648,24649,24650,1358,24652,24654,24655,530,24658,530,24661,133],{},"데이터: ",[16,24651,24612],{},[16,24653,24616],{},"(D1 ",[16,24656,24657],{},"board_meta",[16,24659,24660],{},"stage",[16,24662,24663],{},"task",[215,24665,24667,24668,24670],{"id":24666},"_53-wbs-간트-wbs-ssr-핵심","5.3 WBS 간트 ",[16,24669,12910],{}," (SSR) — 핵심",[54,24672,24673,24679,24688,24694,24711,24724,24744],{},[57,24674,24675,24678],{},[28,24676,24677],{},"상단 KPI",": 전체 진척 미터 + 완료\u002F진행중\u002F지연\u002F예정 카운트.",[57,24680,24681,24684,24685,407],{},[28,24682,24683],{},"툴바",": 담당 칩(다중 필터) · 상태 세그먼트 · 검색 · 모두 접기\u002F펼치기 · 범례 · ",[28,24686,24687],{},"＋작업 추가",[57,24689,24690,24693],{},[28,24691,24692],{},"3계층 트리",": Step → 구분(Category) → 작업(Task), 셰브론 접기.",[57,24695,24696,24699,24700,24703,24704,24707,24708,407],{},[28,24697,24698],{},"간트",": 일 단위 헤더(월\u002F일\u002F요일, 주말 음영, 오늘 기준선) + 상태색 ",[28,24701,24702],{},"진척 막대","(채움+%) · 1일=마일스톤(다이아몬드) · 구분\u002FStep ",[28,24705,24706],{},"롤업 막대"," · 막대 ",[28,24709,24710],{},"호버 툴팁",[57,24712,24713,24716,24717,24720,24721,407],{},[28,24714,24715],{},"CRUD",": 행 hover 시 수정\u002F삭제, ＋추가 → 등록\u002F수정 모달. ",[16,24718,24719],{},"\u002Fapi\u002Fwbs"," 호출 후 ",[16,24722,24723],{},"refresh()",[57,24725,24726,4664,24729,24731,24732,24735,24736,24739,24740,24743],{},[28,24727,24728],{},"상태 규칙",[16,24730,1427],{},"(progress≥100) · ",[16,24733,24734],{},"plan","(시작 없음\u002F미래) · ",[16,24737,24738],{},"late","(종료\u003C오늘 & \u003C100%) · ",[16,24741,24742],{},"active","(그 외).",[57,24745,24746,24749,24750,24753],{},[28,24747,24748],{},"진척 집계 규칙(중요)",": 전체\u002F단계 진척은 ",[28,24751,24752],{},"단계 가중평균","(보드와 일치)으로, 작업 카운트·구분 롤업은 작업 기준. (단순 평균은 화면 단위가 잘게 쪼개진 경우 과소평가됨 — 가중치 권장.)",[215,24755,24757,24758,105,24760,24763],{"id":24756},"_54-문서-docs-docsslug-프리렌더","5.4 문서 ",[16,24759,24186],{},[16,24761,24762],{},"\u002Fdocs\u002F[...slug]"," (프리렌더)",[54,24765,24766,24781],{},[57,24767,24768,4664,24770,24772,24773,4664,24775,1358,24778,407],{},[16,24769,24186],{},[16,24771,24631],{},"로 doc 목록. ",[16,24774,24762],{},[16,24776,24777],{},"queryCollection('docs').path('\u002F'+slug)",[16,24779,24780],{},"\u003CContentRenderer>",[57,24782,24783,24784,24787,24788,24791],{},"링크는 콘텐츠 ",[16,24785,24786],{},"path","를 그대로 사용(",[16,24789,24790],{},"\u002Fdocs${doc.path}",")해 대소문자 일관 유지.",[215,24793,24795,24796,24763],{"id":24794},"_55-작업-이력-history-프리렌더","5.5 작업 이력 ",[16,24797,24202],{},[54,24799,24800],{},[57,24801,24802,24804],{},[16,24803,10501],{},"를 타임라인으로. 파일명에서 날짜 파싱.",[33,24806],{},[36,24808,24810],{"id":24809},"_6-데이터-모델-테이블-스키마-d1-drizzle","6. 데이터 모델 · 테이블 스키마 (D1 \u002F Drizzle)",[24,24812,24813,24816],{},[16,24814,24815],{},"server\u002Fdb\u002Fschema.ts"," (구조만 — 데이터 내용 제외):",[415,24818,24820],{"className":3294,"code":24819,"language":3296,"meta":423,"style":423},"import { sqliteTable, text, integer } from 'drizzle-orm\u002Fsqlite-core'\n\n\u002F\u002F 현황판(board) — 프로젝트 메타 + 단계 + 작업\nexport const boardMeta = sqliteTable('board_meta', {\n  id: integer('id').primaryKey(),            \u002F\u002F 단일 행 = 1\n  projectName: text('project_name').notNull(),\n  lastUpdated: text('last_updated').notNull(),\u002F\u002F YYYY-MM-DD\n})\nexport const stage = sqliteTable('stage', {\n  id: text('id').primaryKey(),               \u002F\u002F step-1 …\n  no: text('no').notNull(), name: text('name').notNull(),\n  emoji: text('emoji'), summary: text('summary'),\n  weight: integer('weight').notNull().default(0),     \u002F\u002F 가중치(%)\n  progress: integer('progress').notNull().default(0), \u002F\u002F 진행률(%)\n  sort: integer('sort').notNull().default(0),\n})\nexport const task = sqliteTable('task', {\n  id: text('id').primaryKey(), stageId: text('stage_id').notNull(),\n  grp: text('grp'), title: text('title').notNull(),\n  status: text('status').notNull().default('pending'), \u002F\u002F done|in_progress|pending|blocked\n  owner: text('owner'), note: text('note'),\n  targetDate: text('target_date'), completionDate: text('completion_date'),\n  href: text('href'), sort: integer('sort').notNull().default(0),\n})\n\n\u002F\u002F WBS 간트 항목 — 등록\u002F수정\u002F삭제 대상\nexport const wbsItem = sqliteTable('wbs_item', {\n  id: integer('id').primaryKey({ autoIncrement: true }),\n  step: integer('step').notNull(), grp: text('grp').notNull(),\n  name: text('name').notNull(), owner: text('owner').notNull().default(''),\n  start: text('start'), end: text('end'),               \u002F\u002F YYYY-MM-DD | null\n  progress: integer('progress').notNull().default(0),\n  note: text('note'), href: text('href'),\n  sort: integer('sort').notNull().default(0),\n})\n",[16,24821,24822,24834,24838,24843,24865,24889,24909,24931,24936,24956,24976,25008,25032,25064,25094,25120,25124,25144,25174,25202,25232,25256,25280,25315,25319,25323,25328,25348,25370,25401,25440,25468,25492,25514,25538],{"__ignoreMap":423},[2166,24823,24824,24826,24829,24831],{"class":3301,"line":3302},[2166,24825,5214],{"class":3305},[2166,24827,24828],{"class":3331}," { sqliteTable, text, integer } ",[2166,24830,5220],{"class":3305},[2166,24832,24833],{"class":3316}," 'drizzle-orm\u002Fsqlite-core'\n",[2166,24835,24836],{"class":3301,"line":3335},[2166,24837,3339],{"emptyLinePlaceholder":3338},[2166,24839,24840],{"class":3301,"line":3342},[2166,24841,24842],{"class":3422},"\u002F\u002F 현황판(board) — 프로젝트 메타 + 단계 + 작업\n",[2166,24844,24845,24847,24850,24853,24855,24858,24860,24863],{"class":3301,"line":3368},[2166,24846,5292],{"class":3305},[2166,24848,24849],{"class":3305}," const",[2166,24851,24852],{"class":3402}," boardMeta",[2166,24854,3313],{"class":3305},[2166,24856,24857],{"class":3309}," sqliteTable",[2166,24859,3351],{"class":3331},[2166,24861,24862],{"class":3316},"'board_meta'",[2166,24864,5389],{"class":3331},[2166,24866,24867,24870,24873,24875,24878,24880,24883,24886],{"class":3301,"line":3396},[2166,24868,24869],{"class":3331},"  id: ",[2166,24871,24872],{"class":3309},"integer",[2166,24874,3351],{"class":3331},[2166,24876,24877],{"class":3316},"'id'",[2166,24879,133],{"class":3331},[2166,24881,24882],{"class":3309},"primaryKey",[2166,24884,24885],{"class":3331},"(),            ",[2166,24887,24888],{"class":3422},"\u002F\u002F 단일 행 = 1\n",[2166,24890,24891,24894,24896,24898,24901,24903,24906],{"class":3301,"line":3426},[2166,24892,24893],{"class":3331},"  projectName: ",[2166,24895,420],{"class":3309},[2166,24897,3351],{"class":3331},[2166,24899,24900],{"class":3316},"'project_name'",[2166,24902,133],{"class":3331},[2166,24904,24905],{"class":3309},"notNull",[2166,24907,24908],{"class":3331},"(),\n",[2166,24910,24911,24914,24916,24918,24921,24923,24925,24928],{"class":3301,"line":3463},[2166,24912,24913],{"class":3331},"  lastUpdated: ",[2166,24915,420],{"class":3309},[2166,24917,3351],{"class":3331},[2166,24919,24920],{"class":3316},"'last_updated'",[2166,24922,133],{"class":3331},[2166,24924,24905],{"class":3309},[2166,24926,24927],{"class":3331},"(),",[2166,24929,24930],{"class":3422},"\u002F\u002F YYYY-MM-DD\n",[2166,24932,24933],{"class":3301,"line":3504},[2166,24934,24935],{"class":3331},"})\n",[2166,24937,24938,24940,24942,24945,24947,24949,24951,24954],{"class":3301,"line":3538},[2166,24939,5292],{"class":3305},[2166,24941,24849],{"class":3305},[2166,24943,24944],{"class":3402}," stage",[2166,24946,3313],{"class":3305},[2166,24948,24857],{"class":3309},[2166,24950,3351],{"class":3331},[2166,24952,24953],{"class":3316},"'stage'",[2166,24955,5389],{"class":3331},[2166,24957,24958,24960,24962,24964,24966,24968,24970,24973],{"class":3301,"line":3550},[2166,24959,24869],{"class":3331},[2166,24961,420],{"class":3309},[2166,24963,3351],{"class":3331},[2166,24965,24877],{"class":3316},[2166,24967,133],{"class":3331},[2166,24969,24882],{"class":3309},[2166,24971,24972],{"class":3331},"(),               ",[2166,24974,24975],{"class":3422},"\u002F\u002F step-1 …\n",[2166,24977,24978,24981,24983,24985,24988,24990,24992,24995,24997,24999,25002,25004,25006],{"class":3301,"line":3556},[2166,24979,24980],{"class":3331},"  no: ",[2166,24982,420],{"class":3309},[2166,24984,3351],{"class":3331},[2166,24986,24987],{"class":3316},"'no'",[2166,24989,133],{"class":3331},[2166,24991,24905],{"class":3309},[2166,24993,24994],{"class":3331},"(), name: ",[2166,24996,420],{"class":3309},[2166,24998,3351],{"class":3331},[2166,25000,25001],{"class":3316},"'name'",[2166,25003,133],{"class":3331},[2166,25005,24905],{"class":3309},[2166,25007,24908],{"class":3331},[2166,25009,25010,25013,25015,25017,25020,25023,25025,25027,25030],{"class":3301,"line":5367},[2166,25011,25012],{"class":3331},"  emoji: ",[2166,25014,420],{"class":3309},[2166,25016,3351],{"class":3331},[2166,25018,25019],{"class":3316},"'emoji'",[2166,25021,25022],{"class":3331},"), summary: ",[2166,25024,420],{"class":3309},[2166,25026,3351],{"class":3331},[2166,25028,25029],{"class":3316},"'summary'",[2166,25031,5261],{"class":3331},[2166,25033,25034,25037,25039,25041,25044,25046,25048,25051,25054,25056,25058,25061],{"class":3301,"line":5375},[2166,25035,25036],{"class":3331},"  weight: ",[2166,25038,24872],{"class":3309},[2166,25040,3351],{"class":3331},[2166,25042,25043],{"class":3316},"'weight'",[2166,25045,133],{"class":3331},[2166,25047,24905],{"class":3309},[2166,25049,25050],{"class":3331},"().",[2166,25052,25053],{"class":3309},"default",[2166,25055,3351],{"class":3331},[2166,25057,20067],{"class":3402},[2166,25059,25060],{"class":3331},"),     ",[2166,25062,25063],{"class":3422},"\u002F\u002F 가중치(%)\n",[2166,25065,25066,25069,25071,25073,25076,25078,25080,25082,25084,25086,25088,25091],{"class":3301,"line":5392},[2166,25067,25068],{"class":3331},"  progress: ",[2166,25070,24872],{"class":3309},[2166,25072,3351],{"class":3331},[2166,25074,25075],{"class":3316},"'progress'",[2166,25077,133],{"class":3331},[2166,25079,24905],{"class":3309},[2166,25081,25050],{"class":3331},[2166,25083,25053],{"class":3309},[2166,25085,3351],{"class":3331},[2166,25087,20067],{"class":3402},[2166,25089,25090],{"class":3331},"), ",[2166,25092,25093],{"class":3422},"\u002F\u002F 진행률(%)\n",[2166,25095,25096,25099,25101,25103,25106,25108,25110,25112,25114,25116,25118],{"class":3301,"line":5404},[2166,25097,25098],{"class":3331},"  sort: ",[2166,25100,24872],{"class":3309},[2166,25102,3351],{"class":3331},[2166,25104,25105],{"class":3316},"'sort'",[2166,25107,133],{"class":3331},[2166,25109,24905],{"class":3309},[2166,25111,25050],{"class":3331},[2166,25113,25053],{"class":3309},[2166,25115,3351],{"class":3331},[2166,25117,20067],{"class":3402},[2166,25119,5261],{"class":3331},[2166,25121,25122],{"class":3301,"line":5415},[2166,25123,24935],{"class":3331},[2166,25125,25126,25128,25130,25133,25135,25137,25139,25142],{"class":3301,"line":5421},[2166,25127,5292],{"class":3305},[2166,25129,24849],{"class":3305},[2166,25131,25132],{"class":3402}," task",[2166,25134,3313],{"class":3305},[2166,25136,24857],{"class":3309},[2166,25138,3351],{"class":3331},[2166,25140,25141],{"class":3316},"'task'",[2166,25143,5389],{"class":3331},[2166,25145,25146,25148,25150,25152,25154,25156,25158,25161,25163,25165,25168,25170,25172],{"class":3301,"line":5432},[2166,25147,24869],{"class":3331},[2166,25149,420],{"class":3309},[2166,25151,3351],{"class":3331},[2166,25153,24877],{"class":3316},[2166,25155,133],{"class":3331},[2166,25157,24882],{"class":3309},[2166,25159,25160],{"class":3331},"(), stageId: ",[2166,25162,420],{"class":3309},[2166,25164,3351],{"class":3331},[2166,25166,25167],{"class":3316},"'stage_id'",[2166,25169,133],{"class":3331},[2166,25171,24905],{"class":3309},[2166,25173,24908],{"class":3331},[2166,25175,25176,25179,25181,25183,25186,25189,25191,25193,25196,25198,25200],{"class":3301,"line":5453},[2166,25177,25178],{"class":3331},"  grp: ",[2166,25180,420],{"class":3309},[2166,25182,3351],{"class":3331},[2166,25184,25185],{"class":3316},"'grp'",[2166,25187,25188],{"class":3331},"), title: ",[2166,25190,420],{"class":3309},[2166,25192,3351],{"class":3331},[2166,25194,25195],{"class":3316},"'title'",[2166,25197,133],{"class":3331},[2166,25199,24905],{"class":3309},[2166,25201,24908],{"class":3331},[2166,25203,25204,25207,25209,25211,25214,25216,25218,25220,25222,25224,25227,25229],{"class":3301,"line":5459},[2166,25205,25206],{"class":3331},"  status: ",[2166,25208,420],{"class":3309},[2166,25210,3351],{"class":3331},[2166,25212,25213],{"class":3316},"'status'",[2166,25215,133],{"class":3331},[2166,25217,24905],{"class":3309},[2166,25219,25050],{"class":3331},[2166,25221,25053],{"class":3309},[2166,25223,3351],{"class":3331},[2166,25225,25226],{"class":3316},"'pending'",[2166,25228,25090],{"class":3331},[2166,25230,25231],{"class":3422},"\u002F\u002F done|in_progress|pending|blocked\n",[2166,25233,25234,25237,25239,25241,25244,25247,25249,25251,25254],{"class":3301,"line":8686},[2166,25235,25236],{"class":3331},"  owner: ",[2166,25238,420],{"class":3309},[2166,25240,3351],{"class":3331},[2166,25242,25243],{"class":3316},"'owner'",[2166,25245,25246],{"class":3331},"), note: ",[2166,25248,420],{"class":3309},[2166,25250,3351],{"class":3331},[2166,25252,25253],{"class":3316},"'note'",[2166,25255,5261],{"class":3331},[2166,25257,25258,25261,25263,25265,25268,25271,25273,25275,25278],{"class":3301,"line":8692},[2166,25259,25260],{"class":3331},"  targetDate: ",[2166,25262,420],{"class":3309},[2166,25264,3351],{"class":3331},[2166,25266,25267],{"class":3316},"'target_date'",[2166,25269,25270],{"class":3331},"), completionDate: ",[2166,25272,420],{"class":3309},[2166,25274,3351],{"class":3331},[2166,25276,25277],{"class":3316},"'completion_date'",[2166,25279,5261],{"class":3331},[2166,25281,25282,25285,25287,25289,25292,25295,25297,25299,25301,25303,25305,25307,25309,25311,25313],{"class":3301,"line":8698},[2166,25283,25284],{"class":3331},"  href: ",[2166,25286,420],{"class":3309},[2166,25288,3351],{"class":3331},[2166,25290,25291],{"class":3316},"'href'",[2166,25293,25294],{"class":3331},"), sort: ",[2166,25296,24872],{"class":3309},[2166,25298,3351],{"class":3331},[2166,25300,25105],{"class":3316},[2166,25302,133],{"class":3331},[2166,25304,24905],{"class":3309},[2166,25306,25050],{"class":3331},[2166,25308,25053],{"class":3309},[2166,25310,3351],{"class":3331},[2166,25312,20067],{"class":3402},[2166,25314,5261],{"class":3331},[2166,25316,25317],{"class":3301,"line":8704},[2166,25318,24935],{"class":3331},[2166,25320,25321],{"class":3301,"line":8710},[2166,25322,3339],{"emptyLinePlaceholder":3338},[2166,25324,25325],{"class":3301,"line":8716},[2166,25326,25327],{"class":3422},"\u002F\u002F WBS 간트 항목 — 등록\u002F수정\u002F삭제 대상\n",[2166,25329,25330,25332,25334,25337,25339,25341,25343,25346],{"class":3301,"line":8721},[2166,25331,5292],{"class":3305},[2166,25333,24849],{"class":3305},[2166,25335,25336],{"class":3402}," wbsItem",[2166,25338,3313],{"class":3305},[2166,25340,24857],{"class":3309},[2166,25342,3351],{"class":3331},[2166,25344,25345],{"class":3316},"'wbs_item'",[2166,25347,5389],{"class":3331},[2166,25349,25350,25352,25354,25356,25358,25360,25362,25365,25367],{"class":3301,"line":8727},[2166,25351,24869],{"class":3331},[2166,25353,24872],{"class":3309},[2166,25355,3351],{"class":3331},[2166,25357,24877],{"class":3316},[2166,25359,133],{"class":3331},[2166,25361,24882],{"class":3309},[2166,25363,25364],{"class":3331},"({ autoIncrement: ",[2166,25366,21876],{"class":3402},[2166,25368,25369],{"class":3331}," }),\n",[2166,25371,25372,25375,25377,25379,25382,25384,25386,25389,25391,25393,25395,25397,25399],{"class":3301,"line":8733},[2166,25373,25374],{"class":3331},"  step: ",[2166,25376,24872],{"class":3309},[2166,25378,3351],{"class":3331},[2166,25380,25381],{"class":3316},"'step'",[2166,25383,133],{"class":3331},[2166,25385,24905],{"class":3309},[2166,25387,25388],{"class":3331},"(), grp: ",[2166,25390,420],{"class":3309},[2166,25392,3351],{"class":3331},[2166,25394,25185],{"class":3316},[2166,25396,133],{"class":3331},[2166,25398,24905],{"class":3309},[2166,25400,24908],{"class":3331},[2166,25402,25403,25406,25408,25410,25412,25414,25416,25419,25421,25423,25425,25427,25429,25431,25433,25435,25438],{"class":3301,"line":8739},[2166,25404,25405],{"class":3331},"  name: ",[2166,25407,420],{"class":3309},[2166,25409,3351],{"class":3331},[2166,25411,25001],{"class":3316},[2166,25413,133],{"class":3331},[2166,25415,24905],{"class":3309},[2166,25417,25418],{"class":3331},"(), owner: ",[2166,25420,420],{"class":3309},[2166,25422,3351],{"class":3331},[2166,25424,25243],{"class":3316},[2166,25426,133],{"class":3331},[2166,25428,24905],{"class":3309},[2166,25430,25050],{"class":3331},[2166,25432,25053],{"class":3309},[2166,25434,3351],{"class":3331},[2166,25436,25437],{"class":3316},"''",[2166,25439,5261],{"class":3331},[2166,25441,25442,25445,25447,25449,25452,25455,25457,25459,25462,25465],{"class":3301,"line":8745},[2166,25443,25444],{"class":3331},"  start: ",[2166,25446,420],{"class":3309},[2166,25448,3351],{"class":3331},[2166,25450,25451],{"class":3316},"'start'",[2166,25453,25454],{"class":3331},"), end: ",[2166,25456,420],{"class":3309},[2166,25458,3351],{"class":3331},[2166,25460,25461],{"class":3316},"'end'",[2166,25463,25464],{"class":3331},"),               ",[2166,25466,25467],{"class":3422},"\u002F\u002F YYYY-MM-DD | null\n",[2166,25469,25470,25472,25474,25476,25478,25480,25482,25484,25486,25488,25490],{"class":3301,"line":8751},[2166,25471,25068],{"class":3331},[2166,25473,24872],{"class":3309},[2166,25475,3351],{"class":3331},[2166,25477,25075],{"class":3316},[2166,25479,133],{"class":3331},[2166,25481,24905],{"class":3309},[2166,25483,25050],{"class":3331},[2166,25485,25053],{"class":3309},[2166,25487,3351],{"class":3331},[2166,25489,20067],{"class":3402},[2166,25491,5261],{"class":3331},[2166,25493,25494,25497,25499,25501,25503,25506,25508,25510,25512],{"class":3301,"line":8756},[2166,25495,25496],{"class":3331},"  note: ",[2166,25498,420],{"class":3309},[2166,25500,3351],{"class":3331},[2166,25502,25253],{"class":3316},[2166,25504,25505],{"class":3331},"), href: ",[2166,25507,420],{"class":3309},[2166,25509,3351],{"class":3331},[2166,25511,25291],{"class":3316},[2166,25513,5261],{"class":3331},[2166,25515,25516,25518,25520,25522,25524,25526,25528,25530,25532,25534,25536],{"class":3301,"line":8762},[2166,25517,25098],{"class":3331},[2166,25519,24872],{"class":3309},[2166,25521,3351],{"class":3331},[2166,25523,25105],{"class":3316},[2166,25525,133],{"class":3331},[2166,25527,24905],{"class":3309},[2166,25529,25050],{"class":3331},[2166,25531,25053],{"class":3309},[2166,25533,3351],{"class":3331},[2166,25535,20067],{"class":3402},[2166,25537,5261],{"class":3331},[2166,25539,25540],{"class":3301,"line":8767},[2166,25541,24935],{"class":3331},[54,25543,25544,25554],{},[57,25545,25546,25547,25550,25551,407],{},"마이그레이션은 ",[16,25548,25549],{},"pnpm db:generate","(drizzle-kit) → ",[16,25552,25553],{},"server\u002Fdb\u002Fmigrations\u002F",[57,25555,25556,25557,25560],{},"신규 D1엔 ",[16,25558,25559],{},"wrangler d1 migrations apply {D1_NAME} --remote","로 적용. (기존 테이블이 있으면 충돌하므로, 처음 구축 시 migrations apply 사용 권장.)",[24,25562,25563,25566],{},[16,25564,25565],{},"server\u002Futils\u002Fdb.ts"," (공용 D1 접근):",[415,25568,25570],{"className":3294,"code":25569,"language":3296,"meta":423,"style":423},"import { drizzle } from 'drizzle-orm\u002Fd1'\nimport type { H3Event } from 'h3'\nimport * as schema from '..\u002Fdb\u002Fschema'\ntype D1Client = Parameters\u003Ctypeof drizzle>[0]\nexport function useDb(event: H3Event) {\n  const env = event.context.cloudflare?.env as { DB?: unknown } | undefined\n  const d1 = env?.DB\n  return d1 ? drizzle(d1 as D1Client, { schema }) : null   \u002F\u002F dev(바인딩 없음) → null → 시드 폴백\n}\n",[16,25571,25572,25584,25599,25617,25642,25663,25699,25714,25745],{"__ignoreMap":423},[2166,25573,25574,25576,25579,25581],{"class":3301,"line":3302},[2166,25575,5214],{"class":3305},[2166,25577,25578],{"class":3331}," { drizzle } ",[2166,25580,5220],{"class":3305},[2166,25582,25583],{"class":3316}," 'drizzle-orm\u002Fd1'\n",[2166,25585,25586,25588,25591,25594,25596],{"class":3301,"line":3335},[2166,25587,5214],{"class":3305},[2166,25589,25590],{"class":3305}," type",[2166,25592,25593],{"class":3331}," { H3Event } ",[2166,25595,5220],{"class":3305},[2166,25597,25598],{"class":3316}," 'h3'\n",[2166,25600,25601,25603,25606,25609,25612,25614],{"class":3301,"line":3342},[2166,25602,5214],{"class":3305},[2166,25604,25605],{"class":3402}," *",[2166,25607,25608],{"class":3305}," as",[2166,25610,25611],{"class":3331}," schema ",[2166,25613,5220],{"class":3305},[2166,25615,25616],{"class":3316}," '..\u002Fdb\u002Fschema'\n",[2166,25618,25619,25621,25624,25626,25629,25631,25634,25637,25639],{"class":3301,"line":3368},[2166,25620,3306],{"class":3305},[2166,25622,25623],{"class":3309}," D1Client",[2166,25625,3313],{"class":3305},[2166,25627,25628],{"class":3309}," Parameters",[2166,25630,4732],{"class":3331},[2166,25632,25633],{"class":3305},"typeof",[2166,25635,25636],{"class":3331}," drizzle>[",[2166,25638,20067],{"class":3402},[2166,25640,25641],{"class":3331},"]\n",[2166,25643,25644,25646,25648,25651,25653,25656,25658,25661],{"class":3301,"line":3396},[2166,25645,5292],{"class":3305},[2166,25647,5297],{"class":3305},[2166,25649,25650],{"class":3309}," useDb",[2166,25652,3351],{"class":3331},[2166,25654,25655],{"class":3356},"event",[2166,25657,3360],{"class":3305},[2166,25659,25660],{"class":3309}," H3Event",[2166,25662,5312],{"class":3331},[2166,25664,25665,25667,25670,25672,25675,25678,25681,25684,25687,25690,25693,25696],{"class":3301,"line":3426},[2166,25666,5317],{"class":3305},[2166,25668,25669],{"class":3402}," env",[2166,25671,3313],{"class":3305},[2166,25673,25674],{"class":3331}," event.context.cloudflare?.env ",[2166,25676,25677],{"class":3305},"as",[2166,25679,25680],{"class":3331}," { ",[2166,25682,25683],{"class":3356},"DB",[2166,25685,25686],{"class":3305},"?:",[2166,25688,25689],{"class":3402}," unknown",[2166,25691,25692],{"class":3331}," } ",[2166,25694,25695],{"class":3305},"|",[2166,25697,25698],{"class":3402}," undefined\n",[2166,25700,25701,25703,25706,25708,25711],{"class":3301,"line":3463},[2166,25702,5317],{"class":3305},[2166,25704,25705],{"class":3402}," d1",[2166,25707,3313],{"class":3305},[2166,25709,25710],{"class":3331}," env?.",[2166,25712,25713],{"class":3402},"DB\n",[2166,25715,25716,25718,25721,25724,25727,25730,25732,25734,25737,25739,25742],{"class":3301,"line":3504},[2166,25717,3371],{"class":3305},[2166,25719,25720],{"class":3331}," d1 ",[2166,25722,25723],{"class":3305},"?",[2166,25725,25726],{"class":3309}," drizzle",[2166,25728,25729],{"class":3331},"(d1 ",[2166,25731,25677],{"class":3305},[2166,25733,25623],{"class":3309},[2166,25735,25736],{"class":3331},", { schema }) ",[2166,25738,3360],{"class":3305},[2166,25740,25741],{"class":3402}," null",[2166,25743,25744],{"class":3422},"   \u002F\u002F dev(바인딩 없음) → null → 시드 폴백\n",[2166,25746,25747],{"class":3301,"line":3538},[2166,25748,3559],{"class":3331},[33,25750],{},[36,25752,25754],{"id":25753},"_7-api-엔드포인트","7. API 엔드포인트",[135,25756,25757,25768],{},[138,25758,25759],{},[141,25760,25761,25764,25766],{},[144,25762,25763],{},"메서드\u002F경로",[144,25765,1292],{},[144,25767,2979],{},[157,25769,25770,25787,25800,25819,25832],{},[141,25771,25772,25777,25780],{},[162,25773,25774],{},[16,25775,25776],{},"GET \u002Fapi\u002Fboard",[162,25778,25779],{},"현황판 문서(meta+stages+tasks) 조립",[162,25781,25782,25783,25786],{},"dev는 ",[16,25784,25785],{},"boardSeed"," 폴백",[141,25788,25789,25794,25797],{},[162,25790,25791],{},[16,25792,25793],{},"GET \u002Fapi\u002Fwbs",[162,25795,25796],{},"WBS 항목 목록",[162,25798,25799],{},"dev는 정적 시드 폴백",[141,25801,25802,25807,25810],{},[162,25803,25804],{},[16,25805,25806],{},"POST \u002Fapi\u002Fwbs",[162,25808,25809],{},"항목 등록",[162,25811,25812,25815,25816],{},[16,25813,25814],{},"readBody"," 검증 후 insert·",[16,25817,25818],{},"returning()",[141,25820,25821,25826,25829],{},[162,25822,25823],{},[16,25824,25825],{},"PATCH \u002Fapi\u002Fwbs\u002F:id",[162,25827,25828],{},"항목 수정",[162,25830,25831],{},"부분 업데이트",[141,25833,25834,25839,25842],{},[162,25835,25836],{},[16,25837,25838],{},"DELETE \u002Fapi\u002Fwbs\u002F:id",[162,25840,25841],{},"항목 삭제",[162,25843],{},[24,25845,25846],{},"패턴(예 — GET):",[415,25848,25850],{"className":3294,"code":25849,"language":3296,"meta":423,"style":423},"export default defineEventHandler(async (event) => {\n  const db = useDb(event)\n  if (!db) return { data: \u002F* 정적 시드 *\u002F }\n  const rows = await db.select().from(wbsItem).orderBy(asc(wbsItem.sort), asc(wbsItem.id))\n  return { data: rows.map(\u002F* DB컬럼 grp→group 등 매핑 *\u002F) }\n})\n",[16,25851,25852,25876,25890,25912,25952,25970],{"__ignoreMap":423},[2166,25853,25854,25856,25859,25862,25864,25866,25868,25870,25872,25874],{"class":3301,"line":3302},[2166,25855,5292],{"class":3305},[2166,25857,25858],{"class":3305}," default",[2166,25860,25861],{"class":3309}," defineEventHandler",[2166,25863,3351],{"class":3331},[2166,25865,5487],{"class":3305},[2166,25867,1305],{"class":3331},[2166,25869,25655],{"class":3356},[2166,25871,3387],{"class":3331},[2166,25873,3390],{"class":3305},[2166,25875,3393],{"class":3331},[2166,25877,25878,25880,25883,25885,25887],{"class":3301,"line":3335},[2166,25879,5317],{"class":3305},[2166,25881,25882],{"class":3402}," db",[2166,25884,3313],{"class":3305},[2166,25886,25650],{"class":3309},[2166,25888,25889],{"class":3331},"(event)\n",[2166,25891,25892,25894,25896,25898,25901,25903,25906,25909],{"class":3301,"line":3342},[2166,25893,5340],{"class":3305},[2166,25895,1305],{"class":3331},[2166,25897,3434],{"class":3305},[2166,25899,25900],{"class":3331},"db) ",[2166,25902,3440],{"class":3305},[2166,25904,25905],{"class":3331}," { data: ",[2166,25907,25908],{"class":3422},"\u002F* 정적 시드 *\u002F",[2166,25910,25911],{"class":3331}," }\n",[2166,25913,25914,25916,25919,25921,25923,25926,25929,25931,25933,25936,25939,25941,25944,25947,25949],{"class":3301,"line":3368},[2166,25915,5317],{"class":3305},[2166,25917,25918],{"class":3402}," rows",[2166,25920,3313],{"class":3305},[2166,25922,5513],{"class":3305},[2166,25924,25925],{"class":3331}," db.",[2166,25927,25928],{"class":3309},"select",[2166,25930,25050],{"class":3331},[2166,25932,5220],{"class":3309},[2166,25934,25935],{"class":3331},"(wbsItem).",[2166,25937,25938],{"class":3309},"orderBy",[2166,25940,3351],{"class":3331},[2166,25942,25943],{"class":3309},"asc",[2166,25945,25946],{"class":3331},"(wbsItem.sort), ",[2166,25948,25943],{"class":3309},[2166,25950,25951],{"class":3331},"(wbsItem.id))\n",[2166,25953,25954,25956,25959,25962,25964,25967],{"class":3301,"line":3396},[2166,25955,3371],{"class":3305},[2166,25957,25958],{"class":3331}," { data: rows.",[2166,25960,25961],{"class":3309},"map",[2166,25963,3351],{"class":3331},[2166,25965,25966],{"class":3422},"\u002F* DB컬럼 grp→group 등 매핑 *\u002F",[2166,25968,25969],{"class":3331},") }\n",[2166,25971,25972],{"class":3301,"line":3426},[2166,25973,24935],{"class":3331},[54,25975,25976,25989],{},[57,25977,25978,25979,25982,25983,25986,25987,407],{},"페이지는 ",[16,25980,25981],{},"useFetch('\u002Fapi\u002F...')","로 조회, 변경은 ",[16,25984,25985],{},"$fetch(..., { method })"," 후 ",[16,25988,24723],{},[57,25990,25991,25992,25995,25996,25999],{},"컬럼명(",[16,25993,25994],{},"grp",")과 화면 키(",[16,25997,25998],{},"group",")는 API 레이어에서 매핑.",[33,26001],{},[36,26003,26005],{"id":26004},"_8-디자인-가이드-토큰","8. 디자인 가이드 (토큰)",[24,26007,26008,26009,26012],{},"두 개의 토큰 세트를 쓴다. ",[28,26010,26011],{},"둘 다 전역 CSS","로 둔다(§9 주의).",[215,26014,26016,26017,26020],{"id":26015},"_81-앱-전반-appassetscssmaincss-relay-inspired-저밀도-라이트","8.1 앱 전반 — ",[16,26018,26019],{},"app\u002Fassets\u002Fcss\u002Fmain.css"," (Relay-inspired 저밀도 라이트)",[54,26022,26023,26046,26056,26063],{},[57,26024,26025,26026,26029,26030,105,26033,105,26036,26039,26040,105,26043,133],{},"무채색 ink 11단(",[16,26027,26028],{},"--ink-900","…",[16,26031,26032],{},"--ink-50",[16,26034,26035],{},"--paper",[16,26037,26038],{},"--line",") + 단일 그린 액센트(",[16,26041,26042],{},"--accent #00DC82",[16,26044,26045],{},"--accent-ink",[57,26047,26048,26049,1524,26052,26055],{},"폰트: Inter(UI) + JetBrains Mono(숫자\u002FID) + Pretendard(한국어). ",[16,26050,26051],{},"@import \"tailwindcss\"; @import \"@nuxt\u002Fui\";",[16,26053,26054],{},"@theme","로 토큰 노출.",[57,26057,26058,4664,26060,407],{},[16,26059,10934],{},[16,26061,26062],{},"ui.colors.primary\u002Fneutral = 'zinc'",[57,26064,26065],{},"1px hairline, radius 카드 12px, 저밀도.",[215,26067,26069],{"id":26068},"_82-간트-전용-데이터-대시보드-토큰-컴포넌트-스코프-라이트","8.2 간트 전용 — 데이터 대시보드 토큰 (컴포넌트 스코프, 라이트)",[415,26071,26074],{"className":26072,"code":26073,"language":420},[418],"--bg #f4f6f8 · --surface #fff · --surface-2 #f8fafc · --band #eef1f5 · --band-2 #e7ebf0\n--line #e3e8ee · --line-2 #eef1f5 · --ink #1b2330 · --ink-2 #5a6675 · --ink-3 #8a93a3 · --accent #2563eb\n상태: 완료 #16a34a\u002F#d7f0de · 진행중 #2563eb\u002F#d6e4fd · 예정 #94a3b8\u002F#e6eaf0 · 지연 #e0524d\u002F#fadcd9\n주말 #f3f5f8 · 오늘 #f59e0b\n레이아웃: --col-name 300 · --col-who 84 · --col-s\u002Fe 50 · --col-done 56 · --col-prog 86\n--day-w 26 · --row-h 30 · --grp-h 34 · --step-h 38\n담당자 아바타 색: 사람별 고정 색 맵(예: #2563eb\u002F#7c3aed\u002F#0d9488\u002F#d97706\u002F#db2777, 미정 #94a3b8)\n",[16,26075,26073],{"__ignoreMap":423},[54,26077,26078,26081],{},[57,26079,26080],{},"막대 = 트랙(연한 상태색) + 채움(진한 상태색, width=progress%). 1일짜리는 다이아몬드. 그룹\u002FStep은 롤업 막대.",[57,26082,26083,26084,26087,26088,26091],{},"고정 좌측 정보 패널(",[16,26085,26086],{},"position:sticky; left:0",") + 고정 헤더(",[16,26089,26090],{},"top:0","), 좌상단 코너는 left+top 동시 고정. z-index: 코너>헤더>좌측열>본문.",[33,26093],{},[36,26095,26097],{"id":26096},"_9-환경구현-주의사항-실전-함정","9. 환경·구현 주의사항 (실전 함정)",[1925,26099,26100,26119,26138,26150,26156,26162,26176],{},[57,26101,26102,26105,26106,11190,26109,26112,26113,4708,26116,26118],{},[28,26103,26104],{},"prose 스타일은 전역 CSS로"," — 컴포넌트 scoped로 두면 별도 CSS 청크로 분리돼 프리렌더된 문서 페이지가 그 청크를 링크하지 않아 ",[28,26107,26108],{},"스타일이 안 먹는다",[16,26110,26111],{},"app\u002Fassets\u002Fcss\u002Fprose.css","를 ",[16,26114,26115],{},"nuxt.config",[16,26117,11238],{},"에 등록.",[57,26120,26121,2448,26124,1524,26127,26130,26131,26133,26134,26137],{},[28,26122,26123],{},"프리렌더 크롤 끄기",[16,26125,26126],{},"nitro.prerender.crawlLinks: false",[16,26128,26129],{},"routes","를 직접 열거. 마크다운 내부 상대 링크를 크롤하면 404·대문자 디렉터리(케이스 민감 Cloudflare에서 404)를 만든다. 라우트는 ",[16,26132,24191],{}," 트리를 재귀 순회해 ",[28,26135,26136],{},"소문자","로 생성.",[57,26139,26140,2448,26143,26146,26147,26149],{},[28,26141,26142],{},"better-sqlite3 네이티브 빌드",[16,26144,26145],{},"pnpm.onlyBuiltDependencies","에 등록해야 비대화형 설치에서 빌드된다. ",[16,26148,24269],{},"가 SQLite 어댑터로 사용.",[57,26151,26152,26155],{},[28,26153,26154],{},"@nuxt\u002Fcontent + Cloudflare"," — 문서 페이지를 전부 프리렌더하면 런타임 콘텐츠 DB가 필요 없다(런타임 콘텐츠 쿼리를 하지 않도록 유지).",[57,26157,26158,26161],{},[28,26159,26160],{},"D1 진위 확인"," — 배포 후 D1 값 1건을 바꿔 응답에 반영되는지로 \"폴백이 아닌 실제 D1\" 확인.",[57,26163,26164,26167,26168,26171,26172,26175],{},[28,26165,26166],{},"로컬 dev 소켓 이슈(특정 샌드박스 한정)"," — macOS 기본 ",[16,26169,26170],{},"$TMPDIR","가 길어 Nuxt vite-node Unix 소켓이 104자 제한 초과 시 ",[16,26173,26174],{},"TMPDIR=\u002Ftmp\u002Fx pnpm dev","로 우회(일반 환경은 불필요).",[57,26177,26178,26181],{},[28,26179,26180],{},"진척 집계 일관성"," — 현황판\u002F대시보드\u002FWBS의 \"전체 진척\"은 동일 산식(가중평균) 사용. 화면을 잘게 쪼갠 WBS의 단순 평균과 단계 가중평균은 크게 달라질 수 있음.",[33,26183],{},[36,26185,26187],{"id":26186},"_10-셋업-절차-claude-code-실행-순서","10. 셋업 절차 (Claude Code 실행 순서)",[415,26189,26191],{"className":4632,"code":26190,"language":4634,"meta":423,"style":423},"# 0) Nuxt 앱 생성 후 의존성(§2) 설치, pnpm.onlyBuiltDependencies 설정\n# 1) D1 생성\nwrangler d1 create {D1_NAME}     # → database_id 확보 → wrangler.toml 작성\n# 2) 설정 파일: nuxt.config.ts(cloudflare-pages 프리셋 + prerender routes),\n#    content.config.ts(doc\u002F 매핑), app.config.ts, wrangler.toml(D1 바인딩 DB),\n#    main.css \u002F prose.css 등록\n# 3) 스키마 작성(server\u002Fdb\u002Fschema.ts) → 마이그레이션 생성·적용\npnpm db:generate\nwrangler d1 migrations apply {D1_NAME} --remote\n# 4) 시드 작성(server\u002Fdb\u002Fseed.sql) → 적용\npnpm db:seed\n# 5) server\u002Futils\u002Fdb.ts, server\u002Fapi\u002F*, app\u002F* (레이아웃·페이지·컴포넌트·컴포저블) 구현\n# 6) 빌드·배포(§11)\n",[16,26192,26193,26198,26203,26219,26224,26229,26234,26239,26246,26263,26268,26275,26280],{"__ignoreMap":423},[2166,26194,26195],{"class":3301,"line":3302},[2166,26196,26197],{"class":3422},"# 0) Nuxt 앱 생성 후 의존성(§2) 설치, pnpm.onlyBuiltDependencies 설정\n",[2166,26199,26200],{"class":3301,"line":3335},[2166,26201,26202],{"class":3422},"# 1) D1 생성\n",[2166,26204,26205,26208,26210,26213,26216],{"class":3301,"line":3342},[2166,26206,26207],{"class":3309},"wrangler",[2166,26209,25705],{"class":3316},[2166,26211,26212],{"class":3316}," create",[2166,26214,26215],{"class":3316}," {D1_NAME}",[2166,26217,26218],{"class":3422},"     # → database_id 확보 → wrangler.toml 작성\n",[2166,26220,26221],{"class":3301,"line":3368},[2166,26222,26223],{"class":3422},"# 2) 설정 파일: nuxt.config.ts(cloudflare-pages 프리셋 + prerender routes),\n",[2166,26225,26226],{"class":3301,"line":3396},[2166,26227,26228],{"class":3422},"#    content.config.ts(doc\u002F 매핑), app.config.ts, wrangler.toml(D1 바인딩 DB),\n",[2166,26230,26231],{"class":3301,"line":3426},[2166,26232,26233],{"class":3422},"#    main.css \u002F prose.css 등록\n",[2166,26235,26236],{"class":3301,"line":3463},[2166,26237,26238],{"class":3422},"# 3) 스키마 작성(server\u002Fdb\u002Fschema.ts) → 마이그레이션 생성·적용\n",[2166,26240,26241,26243],{"class":3301,"line":3504},[2166,26242,4778],{"class":3309},[2166,26244,26245],{"class":3316}," db:generate\n",[2166,26247,26248,26250,26252,26255,26258,26260],{"class":3301,"line":3538},[2166,26249,26207],{"class":3309},[2166,26251,25705],{"class":3316},[2166,26253,26254],{"class":3316}," migrations",[2166,26256,26257],{"class":3316}," apply",[2166,26259,26215],{"class":3316},[2166,26261,26262],{"class":3402}," --remote\n",[2166,26264,26265],{"class":3301,"line":3550},[2166,26266,26267],{"class":3422},"# 4) 시드 작성(server\u002Fdb\u002Fseed.sql) → 적용\n",[2166,26269,26270,26272],{"class":3301,"line":3556},[2166,26271,4778],{"class":3309},[2166,26273,26274],{"class":3316}," db:seed\n",[2166,26276,26277],{"class":3301,"line":5367},[2166,26278,26279],{"class":3422},"# 5) server\u002Futils\u002Fdb.ts, server\u002Fapi\u002F*, app\u002F* (레이아웃·페이지·컴포넌트·컴포저블) 구현\n",[2166,26281,26282],{"class":3301,"line":5375},[2166,26283,26284],{"class":3422},"# 6) 빌드·배포(§11)\n",[24,26286,26287,3360],{},[16,26288,4701],{},[415,26290,26294],{"className":26291,"code":26292,"language":26293,"meta":423,"style":423},"language-toml shiki shiki-themes github-light github-dark","name = \"{APP}\"\ncompatibility_date = \"2025-01-01\"\ncompatibility_flags = [\"nodejs_compat\"]\npages_build_output_dir = \"dist\"\n\n[[d1_databases]]\nbinding = \"DB\"\ndatabase_name = \"{D1_NAME}\"\ndatabase_id = \"{D1_ID}\"\nmigrations_dir = \"server\u002Fdb\u002Fmigrations\"\n","toml",[16,26295,26296,26301,26306,26311,26316,26320,26325,26330,26335,26340],{"__ignoreMap":423},[2166,26297,26298],{"class":3301,"line":3302},[2166,26299,26300],{},"name = \"{APP}\"\n",[2166,26302,26303],{"class":3301,"line":3335},[2166,26304,26305],{},"compatibility_date = \"2025-01-01\"\n",[2166,26307,26308],{"class":3301,"line":3342},[2166,26309,26310],{},"compatibility_flags = [\"nodejs_compat\"]\n",[2166,26312,26313],{"class":3301,"line":3368},[2166,26314,26315],{},"pages_build_output_dir = \"dist\"\n",[2166,26317,26318],{"class":3301,"line":3396},[2166,26319,3339],{"emptyLinePlaceholder":3338},[2166,26321,26322],{"class":3301,"line":3426},[2166,26323,26324],{},"[[d1_databases]]\n",[2166,26326,26327],{"class":3301,"line":3463},[2166,26328,26329],{},"binding = \"DB\"\n",[2166,26331,26332],{"class":3301,"line":3504},[2166,26333,26334],{},"database_name = \"{D1_NAME}\"\n",[2166,26336,26337],{"class":3301,"line":3538},[2166,26338,26339],{},"database_id = \"{D1_ID}\"\n",[2166,26341,26342],{"class":3301,"line":3550},[2166,26343,26344],{},"migrations_dir = \"server\u002Fdb\u002Fmigrations\"\n",[24,26346,26347,24335],{},[16,26348,10093],{},[415,26350,26352],{"className":3294,"code":26351,"language":3296,"meta":423,"style":423},"export default defineNuxtConfig({\n  future: { compatibilityVersion: 4 },\n  modules: ['@nuxt\u002Fui', '@nuxt\u002Fcontent', '@nuxt\u002Feslint', '@pinia\u002Fnuxt'],\n  css: ['~\u002Fassets\u002Fcss\u002Fmain.css', '~\u002Fassets\u002Fcss\u002Fprose.css'],\n  nitro: { preset: 'cloudflare-pages',\n    prerender: { crawlLinks: false, failOnError: false, routes: prerenderRoutes } }, \u002F\u002F '\u002Fdocs','\u002Fhistory',+doc 트리\n  \u002F\u002F '\u002F', '\u002Fboard', '\u002Fwbs' 는 프리렌더 제외(SSR)\n})\n",[16,26353,26354,26366,26376,26402,26417,26427,26446,26451],{"__ignoreMap":423},[2166,26355,26356,26358,26360,26363],{"class":3301,"line":3302},[2166,26357,5292],{"class":3305},[2166,26359,25858],{"class":3305},[2166,26361,26362],{"class":3309}," defineNuxtConfig",[2166,26364,26365],{"class":3331},"({\n",[2166,26367,26368,26371,26373],{"class":3301,"line":3335},[2166,26369,26370],{"class":3331},"  future: { compatibilityVersion: ",[2166,26372,5963],{"class":3402},[2166,26374,26375],{"class":3331}," },\n",[2166,26377,26378,26381,26384,26386,26389,26391,26394,26396,26399],{"class":3301,"line":3342},[2166,26379,26380],{"class":3331},"  modules: [",[2166,26382,26383],{"class":3316},"'@nuxt\u002Fui'",[2166,26385,105],{"class":3331},[2166,26387,26388],{"class":3316},"'@nuxt\u002Fcontent'",[2166,26390,105],{"class":3331},[2166,26392,26393],{"class":3316},"'@nuxt\u002Feslint'",[2166,26395,105],{"class":3331},[2166,26397,26398],{"class":3316},"'@pinia\u002Fnuxt'",[2166,26400,26401],{"class":3331},"],\n",[2166,26403,26404,26407,26410,26412,26415],{"class":3301,"line":3368},[2166,26405,26406],{"class":3331},"  css: [",[2166,26408,26409],{"class":3316},"'~\u002Fassets\u002Fcss\u002Fmain.css'",[2166,26411,105],{"class":3331},[2166,26413,26414],{"class":3316},"'~\u002Fassets\u002Fcss\u002Fprose.css'",[2166,26416,26401],{"class":3331},[2166,26418,26419,26422,26425],{"class":3301,"line":3396},[2166,26420,26421],{"class":3331},"  nitro: { preset: ",[2166,26423,26424],{"class":3316},"'cloudflare-pages'",[2166,26426,5401],{"class":3331},[2166,26428,26429,26432,26435,26438,26440,26443],{"class":3301,"line":3426},[2166,26430,26431],{"class":3331},"    prerender: { crawlLinks: ",[2166,26433,26434],{"class":3402},"false",[2166,26436,26437],{"class":3331},", failOnError: ",[2166,26439,26434],{"class":3402},[2166,26441,26442],{"class":3331},", routes: prerenderRoutes } }, ",[2166,26444,26445],{"class":3422},"\u002F\u002F '\u002Fdocs','\u002Fhistory',+doc 트리\n",[2166,26447,26448],{"class":3301,"line":3463},[2166,26449,26450],{"class":3422},"  \u002F\u002F '\u002F', '\u002Fboard', '\u002Fwbs' 는 프리렌더 제외(SSR)\n",[2166,26452,26453],{"class":3301,"line":3504},[2166,26454,24935],{"class":3331},[24,26456,26457,3360],{},[16,26458,26459],{},"content.config.ts",[415,26461,26463],{"className":3294,"code":26462,"language":3296,"meta":423,"style":423},"export default defineContentConfig({ collections: {\n  docs: defineCollection({ type: 'page', source: { cwd: '\u003Cdoc 절대경로>', include: '**\u002F*.md' } }),\n} })\n",[16,26464,26465,26477,26506],{"__ignoreMap":423},[2166,26466,26467,26469,26471,26474],{"class":3301,"line":3302},[2166,26468,5292],{"class":3305},[2166,26470,25858],{"class":3305},[2166,26472,26473],{"class":3309}," defineContentConfig",[2166,26475,26476],{"class":3331},"({ collections: {\n",[2166,26478,26479,26482,26485,26488,26491,26494,26497,26500,26503],{"class":3301,"line":3335},[2166,26480,26481],{"class":3331},"  docs: ",[2166,26483,26484],{"class":3309},"defineCollection",[2166,26486,26487],{"class":3331},"({ type: ",[2166,26489,26490],{"class":3316},"'page'",[2166,26492,26493],{"class":3331},", source: { cwd: ",[2166,26495,26496],{"class":3316},"'\u003Cdoc 절대경로>'",[2166,26498,26499],{"class":3331},", include: ",[2166,26501,26502],{"class":3316},"'**\u002F*.md'",[2166,26504,26505],{"class":3331}," } }),\n",[2166,26507,26508],{"class":3301,"line":3342},[2166,26509,26510],{"class":3331},"} })\n",[33,26512],{},[36,26514,26516],{"id":26515},"_11-배포-cloudflare-pages-d1","11. 배포 (Cloudflare Pages + D1)",[415,26518,26520],{"className":4632,"code":26519,"language":4634,"meta":423,"style":423},"pnpm build                                  # nitro cloudflare-pages → dist\u002F (_worker.js + 프리렌더)\nwrangler pages project create {APP} --production-branch=main   # 최초 1회\nwrangler pages deploy dist --project-name={APP} --branch=main \\\n  --commit-dirty=true --commit-message \"\u003Cascii>\"\n",[16,26521,26522,26532,26553,26579],{"__ignoreMap":423},[2166,26523,26524,26526,26529],{"class":3301,"line":3302},[2166,26525,4778],{"class":3309},[2166,26527,26528],{"class":3316}," build",[2166,26530,26531],{"class":3422},"                                  # nitro cloudflare-pages → dist\u002F (_worker.js + 프리렌더)\n",[2166,26533,26534,26536,26539,26542,26544,26547,26550],{"class":3301,"line":3335},[2166,26535,26207],{"class":3309},[2166,26537,26538],{"class":3316}," pages",[2166,26540,26541],{"class":3316}," project",[2166,26543,26212],{"class":3316},[2166,26545,26546],{"class":3316}," {APP}",[2166,26548,26549],{"class":3402}," --production-branch=main",[2166,26551,26552],{"class":3422},"   # 최초 1회\n",[2166,26554,26555,26557,26559,26562,26565,26568,26571,26574,26577],{"class":3301,"line":3342},[2166,26556,26207],{"class":3309},[2166,26558,26538],{"class":3316},[2166,26560,26561],{"class":3316}," deploy",[2166,26563,26564],{"class":3316}," dist",[2166,26566,26567],{"class":3402}," --project-name=",[2166,26569,26570],{"class":3331},"{",[2166,26572,26573],{"class":3309},"APP}",[2166,26575,26576],{"class":3402}," --branch=main",[2166,26578,22558],{"class":3402},[2166,26580,26581,26584,26587],{"class":3301,"line":3368},[2166,26582,26583],{"class":3402},"  --commit-dirty=true",[2166,26585,26586],{"class":3402}," --commit-message",[2166,26588,26589],{"class":3316}," \"\u003Cascii>\"\n",[54,26591,26592,26599,26608],{},[57,26593,26594,26595,26598],{},"인증: wrangler OAuth. ",[16,26596,26597],{},"--commit-message","는 ASCII로 명시(한글 커밋이면 wrangler가 UTF-8 에러).",[57,26600,26601,26602,4708,26604,26607],{},"D1 바인딩은 ",[16,26603,4701],{},[16,26605,26606],{},"[[d1_databases]]","로 Pages 배포에 자동 연결.",[57,26609,26610,26611,26614],{},"배포 후 검증: 라우트 200 + ",[16,26612,26613],{},"\u002Fapi\u002F*"," 응답이 D1 기준인지 + 프리렌더 문서 렌더.",[33,26616],{},[36,26618,26620],{"id":26619},"_12-운영-컨벤션-선택","12. 운영 컨벤션 (선택)",[54,26622,26623,26634,26644,26654],{},[57,26624,26625,4664,26627,26629,26630,26633],{},[28,26626,24197],{},[16,26628,10501],{}," — 하루 한 파일, ① 한 줄 요약 → ② 번호 섹션 → ③ 산출물 → ④ 다음 단계. ",[16,26631,26632],{},"doc\u002Fhistory\u002FREADME.md"," 인덱스 갱신.",[57,26635,26636,26639,26640,26643],{},[28,26637,26638],{},"Git",": 단일 ",[16,26641,26642],{},"main",", 커밋·푸시는 요청 시. 무관 파일은 끌어들이지 않기.",[57,26645,26646,26649,26650,26653],{},[28,26647,26648],{},"문서 정본 동기화",": 코드\u002F구조가 바뀌면 관련 ",[16,26651,26652],{},"doc\u002F*.md"," 현행화.",[57,26655,26656,26658],{},[28,26657,9949],{},": 레포 루트에 프로젝트 목적·스택·구조·컨벤션 요약(이 블루프린트와 별개).",[33,26660],{},[36,26662,26664],{"id":26663},"_13-새-프로젝트로-가져갈-때-치환-체크리스트","13. 새 프로젝트로 가져갈 때 — 치환 체크리스트",[24,26666,26667,26668,26671],{},"이식 시 ",[28,26669,26670],{},"내용만"," 바꾸면 됨(구조·코드·디자인은 재사용):",[54,26673,26675,26694,26709,26715,26730,26740,26749,26757],{"className":26674},[10401],[57,26676,26678,2367,26680,2855,26682,2855,26684,2855,26686,26688,26689,105,26691,26693],{"className":26677},[10405],[10407,26679],{"disabled":3338,"type":10409},[16,26681,24087],{},[16,26683,24098],{},[16,26685,24102],{},[16,26687,24106],{}," 치환 (",[16,26690,4701],{},[16,26692,10090],{}," db 스크립트, GNB GitHub 링크)",[57,26695,26697,26699,26700,105,26703,26705,26706,26708],{"className":26696},[10405],[10407,26698],{"disabled":3338,"type":10409}," 로고\u002F브랜드(",[16,26701,26702],{},"AppLogoMark.vue",[16,26704,24526],{}," 브랜드 텍스트), 앱 타이틀(",[16,26707,26115],{}," head)",[57,26710,26712,26714],{"className":26711},[10405],[10407,26713],{"disabled":3338,"type":10409}," 대시보드 목표·기획 방향·바로가기 링크 배열",[57,26716,26718,26720,26721,530,26723,26725,26726,26729],{"className":26717},[10405],[10407,26719],{"disabled":3338,"type":10409}," 단계 정의(",[16,26722,24657],{},[16,26724,24660],{}," 시드 + ",[16,26727,26728],{},"wbsData.ts","의 단계명·가중치 메타)",[57,26731,26733,26735,26736,26739],{"className":26732},[10405],[10407,26734],{"disabled":3338,"type":10409}," WBS 초기 작업(",[16,26737,26738],{},"wbs_item"," 시드) — 또는 빈 상태로 시작해 화면에서 CRUD",[57,26741,26743,26745,26746,26748],{"className":26742},[10405],[10407,26744],{"disabled":3338,"type":10409}," 담당자 목록·아바타 색 맵(",[16,26747,12910],{}," 페이지 상수)",[57,26750,26752,2367,26754,26756],{"className":26751},[10405],[10407,26753],{"disabled":3338,"type":10409},[16,26755,24191],{}," 문서 트리(이 프로젝트의 문서로 교체)",[57,26758,26760,26762,26763,26765],{"className":26759},[10405],[10407,26761],{"disabled":3338,"type":10409}," 디자인 액센트색(필요 시 ",[16,26764,15550],{},"\u002F간트 토큰)",[21,26767,26768],{},[24,26769,26770,26771,26774],{},"구조·아키텍처·스키마·API·디자인 토큰·셋업\u002F배포 절차는 그대로 두고, 위 목록의 ",[28,26772,26773],{},"데이터·문구·브랜드","만 교체하면 새 프로젝트 관리 앱이 된다.",[4258,26776,26777],{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":423,"searchDepth":3342,"depth":3342,"links":26779},[26780,26781,26782,26787,26788,26800,26801,26802,26807,26808,26809,26810,26811],{"id":24112,"depth":3335,"text":24113},{"id":24226,"depth":3335,"text":24227},{"id":24428,"depth":3335,"text":24429,"children":26783},[26784,26785,26786],{"id":24432,"depth":3342,"text":24433},{"id":4548,"depth":3342,"text":4549},{"id":24493,"depth":3342,"text":24494},{"id":24505,"depth":3335,"text":24506},{"id":24584,"depth":3335,"text":24585,"children":26789},[26790,26792,26794,26796,26798],{"id":24588,"depth":3342,"text":26791},"5.1 대시보드 \u002F (SSR)",{"id":24635,"depth":3342,"text":26793},"5.2 현황판 \u002Fboard (SSR)",{"id":24666,"depth":3342,"text":26795},"5.3 WBS 간트 \u002Fwbs (SSR) — 핵심",{"id":24756,"depth":3342,"text":26797},"5.4 문서 \u002Fdocs, \u002Fdocs\u002F[...slug] (프리렌더)",{"id":24794,"depth":3342,"text":26799},"5.5 작업 이력 \u002Fhistory (프리렌더)",{"id":24809,"depth":3335,"text":24810},{"id":25753,"depth":3335,"text":25754},{"id":26004,"depth":3335,"text":26005,"children":26803},[26804,26806],{"id":26015,"depth":3342,"text":26805},"8.1 앱 전반 — app\u002Fassets\u002Fcss\u002Fmain.css (Relay-inspired 저밀도 라이트)",{"id":26068,"depth":3342,"text":26069},{"id":26096,"depth":3335,"text":26097},{"id":26186,"depth":3335,"text":26187},{"id":26515,"depth":3335,"text":26516},{"id":26619,"depth":3335,"text":26620},{"id":26663,"depth":3335,"text":26664},{},"\u002Fproject_management_blueprint",{"title":24057,"description":423},"PROJECT_MANAGEMENT_BLUEPRINT","E7V0WU5T8PztVAbrhqycauFOCCpy_4Ti_qLZiUcAqfs",{"id":26818,"title":26819,"body":26820,"description":423,"extension":4340,"meta":28151,"navigation":3338,"path":28152,"seo":28153,"stem":28154,"__hash__":28155},"docs\u002Fprompts\u002Fcs-evaluation.md","CS 평가 프롬프트 (재사용 템플릿)",{"type":8,"value":26821,"toc":28130},[26822,26825,26834,26837,26865,26867,26871,26882,26887,26933,26939,26963,26969,26997,27000,27026,27032,27037,27767,27773,27776,27780,27783,27803,27807,27810,27814,27817,27821,27824,27829,27833,27836,27840,27843,27865,27871,27875,27878,27900,27911,27915,27917,27939,27952,27958,28040,28047,28094,28096,28099,28128],[11,26823,26819],{"id":26824},"cs-평가-프롬프트-재사용-템플릿",[21,26826,26827],{},[24,26828,26829,26830],{},"임의의 프로젝트(고객사)에 대해 동일 양식의 CS·챗봇·고객사 평가 보고서를 AI에게 생성시키기 위한 프롬프트.\n산출 예시: ",[3257,26831,26832],{"href":10875},[16,26833,9047],{},[36,26835,26836],{"id":26836},"사용법",[1925,26838,26839,26845,26855,26858],{},[57,26840,20578,26841,26844],{},[28,26842,26843],{},"§ 프롬프트 본문","을 복사.",[57,26846,26847,26848,4708,26851,26854],{},"상단 ",[16,26849,26850],{},"[입력]",[16,26852,26853],{},"{{...}}"," 자리에 실제 값을 채움.",[57,26856,26857],{},"AI(또는 DB 접근 가능한 에이전트)에게 전달.",[57,26859,26860,26861,26864],{},"산출물은 ",[16,26862,26863],{},"doc\u002Fexamples\u002F{{PROJECT_NAME}}.md","로 저장.",[33,26866],{},[11,26868,26870],{"id":26869},"프롬프트-본문-이-아래를-그대로-ai에게-전달","§ 프롬프트 본문 (이 아래를 그대로 AI에게 전달)",[24,26872,26873,26874,26877,26878,26881],{},"당신은 ",[28,26875,26876],{},"CS 운영 데이터 분석가","입니다.\n아래 입력과 평가 프레임을 사용해 단일 프로젝트(고객사)에 대한 종합 평가 보고서를 작성하세요.\n산출물은 마크다운이며, 표 위주로 구성합니다. 측정되지 않은 항목은 추측하지 말고 ",[16,26879,26880],{},"ㅡ(정보 부족)","으로 표기하세요.",[36,26883,26885],{"id":26884},"입력",[2166,26886,26884],{},[54,26888,26889,26899,26909,26917,26925],{},[57,26890,26891,17678,26894,23847,26897,78],{},[16,26892,26893],{},"PROJECT_ID",[16,26895,26896],{},"{{PROJECT_ID}}",[16,26898,5810],{},[57,26900,26901,17678,26904,23847,26907,78],{},[16,26902,26903],{},"PROJECT_NAME",[16,26905,26906],{},"{{PROJECT_NAME}}",[16,26908,5820],{},[57,26910,26911,17678,26913,26916],{},[16,26912,11358],{},[16,26914,26915],{},"{{YYYY-MM-DD}}"," (평가 기준일)",[57,26918,26919,17678,26922],{},[16,26920,26921],{},"DB_CONNECTION",[16,26923,26924],{},"{{호스트·계정 — 별도 시크릿 채널}}",[57,26926,26927,17678,26930],{},[16,26928,26929],{},"SCOPE",[16,26931,26932],{},"{{선택: 기간\u002F사이트\u002F필터 추가 조건}}",[36,26934,26936,26938],{"id":26935},"분류-규칙-필수-준수",[2166,26937,5893],{}," — 필수 준수",[54,26940,26941,26949,26954,26957],{},[57,26942,26943],{},[28,26944,26945,26948],{},[16,26946,26947],{},"tb_user.email LIKE '%@malgnsoft.com'"," → 직원 (staff)",[57,26950,26951],{},[28,26952,26953],{},"그 외 도메인 → 고객사·협력사 (customer\u002Fpartner)",[57,26955,26956],{},"이메일이 없거나 NULL이면 별도 검수 (분류 불명)",[57,26958,26959,26962],{},[28,26960,26961],{},"이름·게시판 패턴·작성 빈도로 추정 금지",". 분류는 반드시 이메일 도메인으로 결정.",[36,26964,26966],{"id":26965},"출처-데이터-모델",[2166,26967,26968],{},"출처 데이터 모델",[24,26970,26971,26973,26974,26976,26977,26979,26980,26982,26983,26985,26986,26988,26989,26991,26992,9048],{},[16,26972,12085],{}," DB의 ",[16,26975,11093],{},"(게시글) + ",[16,26978,15316],{},"(댓글) + ",[16,26981,19712],{},"(첨부) + ",[16,26984,19796],{},"(고객사) + ",[16,26987,20000],{},"(사이트) + ",[16,26990,17012],{},"(사용자). 자세한 스키마·정제 정책은 ",[3257,26993,26994],{"href":6359},[16,26995,26996],{},"doc\u002FLEGACY-DB-INVENTORY.md",[24,26998,26999],{},"기본 Q&A 후보 필터:",[415,27001,27003],{"className":8581,"code":27002,"language":8583,"meta":423,"style":423},"WHERE p.status = 1\n  AND p.comm_cnt >= 1\n  AND p.is_task = 0 AND p.is_schedule = 0 AND p.is_poll = 0 AND p.is_notice = 0\n  AND p.subject NOT LIKE '테스트%'\n  AND CHAR_LENGTH(p.content) >= 20\n",[16,27004,27005,27009,27013,27018,27022],{"__ignoreMap":423},[2166,27006,27007],{"class":3301,"line":3302},[2166,27008,20438],{},[2166,27010,27011],{"class":3301,"line":3335},[2166,27012,20443],{},[2166,27014,27015],{"class":3301,"line":3342},[2166,27016,27017],{},"  AND p.is_task = 0 AND p.is_schedule = 0 AND p.is_poll = 0 AND p.is_notice = 0\n",[2166,27019,27020],{"class":3301,"line":3368},[2166,27021,20468],{},[2166,27023,27024],{"class":3301,"line":3396},[2166,27025,20473],{},[36,27027,27029],{"id":27028},"필수-데이터-수집-쿼리-그대로-실행-가능",[2166,27030,27031],{},"필수 데이터 수집 쿼리 — 그대로 실행 가능",[24,27033,27034,27036],{},[16,27035,26896],{},"만 치환해서 실행. 결과를 평가 프레임에 매핑.",[415,27038,27040],{"className":8581,"code":27039,"language":8583,"meta":423,"style":423},"-- D1. 게시글·댓글·비공개 분포 (이메일 도메인 기반)\nSELECT 'posts' kind,\n  SUM(u.email LIKE '%@malgnsoft.com') staff,\n  SUM(u.email IS NULL OR u.email NOT LIKE '%@malgnsoft.com') customer,\n  COUNT(*) total\nFROM tb_post p LEFT JOIN tb_user u ON u.id = p.user_id\nWHERE p.project_id = {{PROJECT_ID}} AND p.status = 1\nUNION ALL SELECT 'comments',\n  SUM(u.email LIKE '%@malgnsoft.com'),\n  SUM(u.email IS NULL OR u.email NOT LIKE '%@malgnsoft.com'),\n  COUNT(*)\nFROM tb_post_comment c JOIN tb_post p ON p.id = c.post_id LEFT JOIN tb_user u ON u.id = c.user_id\nWHERE p.project_id = {{PROJECT_ID}} AND p.status = 1 AND c.status = 1\nUNION ALL SELECT 'private_comments',\n  SUM(c.private_yn='Y' AND u.email LIKE '%@malgnsoft.com'),\n  SUM(c.private_yn='Y' AND (u.email IS NULL OR u.email NOT LIKE '%@malgnsoft.com')),\n  SUM(c.private_yn='Y')\nFROM tb_post_comment c JOIN tb_post p ON p.id = c.post_id LEFT JOIN tb_user u ON u.id = c.user_id\nWHERE p.project_id = {{PROJECT_ID}} AND p.status = 1 AND c.status = 1;\n\n-- D2. Q&A 후보 \u002F 본문 통계 \u002F 첨부\nSELECT COUNT(*) qna_candidates,\n  ROUND(AVG(CHAR_LENGTH(p.content))) avg_body_len,\n  SUM(p.subject LIKE CONCAT('[', '{{PROJECT_NAME_BARE}}', ']%')) structured_title\nFROM tb_post p\nWHERE p.project_id = {{PROJECT_ID}} AND p.status = 1\n  AND p.comm_cnt >= 1 AND p.is_task=0 AND p.is_schedule=0 AND p.is_poll=0 AND p.is_notice=0\n  AND p.subject NOT LIKE '테스트%' AND CHAR_LENGTH(p.content) >= 20;\n\nSELECT COUNT(DISTINCT p.id) total,\n  COUNT(DISTINCT IF(f.id IS NOT NULL, p.id, NULL)) with_attachment\nFROM tb_post p LEFT JOIN tb_post_file f ON f.module='post' AND f.module_id = p.id AND f.status=1\nWHERE p.project_id = {{PROJECT_ID}} AND p.status = 1;\n\n-- D3. 응답 시간 (FRT)\nSELECT ROUND(AVG(frt)) avg_min,\n  SUM(frt \u003C= 60) within_1h, SUM(frt \u003C= 240) within_4h, SUM(frt \u003C= 1440) within_1d, COUNT(*) total\nFROM (\n  SELECT TIMESTAMPDIFF(MINUTE,\n    STR_TO_DATE(p.reg_date,'%Y%m%d%H%i%s'),\n    STR_TO_DATE(MIN(c.reg_date),'%Y%m%d%H%i%s')) frt\n  FROM tb_post p JOIN tb_post_comment c ON c.post_id=p.id\n  WHERE p.project_id={{PROJECT_ID}} AND p.status=1 AND c.status=1\n  GROUP BY p.id\n) t;\n\n-- D4. FCR (직원 단일 답변 후 종결)\nWITH staff_replies AS (\n  SELECT c.post_id, COUNT(*) n\n  FROM tb_post_comment c JOIN tb_post p ON p.id=c.post_id LEFT JOIN tb_user u ON u.id=c.user_id\n  WHERE p.project_id={{PROJECT_ID}} AND p.status=1 AND c.status=1 AND u.email LIKE '%@malgnsoft.com'\n  GROUP BY c.post_id\n)\nSELECT COUNT(*) total, SUM(n=1) single, ROUND(100.0*SUM(n=1)\u002FCOUNT(*),1) fcr_pct\nFROM staff_replies;\n\n-- D5. 인력 분담 (직원 only)\nSELECT u.name, u.email, COUNT(*) replies,\n  ROUND(100.0*COUNT(*)\u002FSUM(COUNT(*)) OVER (),1) pct,\n  SUM(c.private_yn='Y') private_cnt\nFROM tb_post_comment c JOIN tb_post p ON p.id=c.post_id LEFT JOIN tb_user u ON u.id=c.user_id\nWHERE p.project_id={{PROJECT_ID}} AND p.status=1 AND c.status=1 AND u.email LIKE '%@malgnsoft.com'\nGROUP BY u.name, u.email ORDER BY replies DESC;\n\n-- D6. 고객 매너 키워드\nSELECT SUM(c.content LIKE '%감사%') thanks,\n  SUM(c.content LIKE '%확인%') confirm,\n  SUM(c.content LIKE '%부탁%') please,\n  SUM(c.content LIKE '%죄송%') apology,\n  COUNT(*) customer_comments\nFROM tb_post_comment c JOIN tb_post p ON p.id=c.post_id LEFT JOIN tb_user u ON u.id=c.user_id\nWHERE p.project_id={{PROJECT_ID}} AND p.status=1 AND c.status=1\n  AND (u.email IS NULL OR u.email NOT LIKE '%@malgnsoft.com');\n\n-- D7. 종결 멘트 작성자\nWITH last_c AS (\n  SELECT c.post_id, u.email, c.content,\n    ROW_NUMBER() OVER (PARTITION BY c.post_id ORDER BY c.reg_date DESC) rn\n  FROM tb_post_comment c JOIN tb_post p ON p.id=c.post_id LEFT JOIN tb_user u ON u.id=c.user_id\n  WHERE p.project_id={{PROJECT_ID}} AND p.status=1 AND c.status=1\n)\nSELECT IF(email LIKE '%@malgnsoft.com','staff','customer') who, COUNT(*) total,\n  SUM(content LIKE '%감사%' OR content LIKE '%확인했%' OR content LIKE '%잘 받았%') closed\nFROM last_c WHERE rn=1 GROUP BY 1;\n\n-- D8. 영업시간\u002F주말 응답 (직원)\nSELECT SUM(HOUR(STR_TO_DATE(c.reg_date,'%Y%m%d%H%i%s')) BETWEEN 9 AND 18) biz_hours,\n  SUM(HOUR(STR_TO_DATE(c.reg_date,'%Y%m%d%H%i%s')) NOT BETWEEN 9 AND 18) off_hours,\n  SUM(DAYOFWEEK(STR_TO_DATE(c.reg_date,'%Y%m%d%H%i%s')) IN (1,7)) weekend,\n  COUNT(*) total\nFROM tb_post_comment c JOIN tb_post p ON p.id=c.post_id LEFT JOIN tb_user u ON u.id=c.user_id\nWHERE p.project_id={{PROJECT_ID}} AND p.status=1 AND c.status=1 AND u.email LIKE '%@malgnsoft.com';\n\n-- D9. 주제 키워드 빈도 (제목 기준)\nSELECT 'LMS' kw, COUNT(*) cnt FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND subject LIKE '%LMS%'\nUNION ALL SELECT '오류', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND subject LIKE '%오류%'\nUNION ALL SELECT '문의', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND subject LIKE '%문의%'\nUNION ALL SELECT '결제', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND subject LIKE '%결제%'\nUNION ALL SELECT '도메인', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND subject LIKE '%도메인%'\nUNION ALL SELECT 'SMS·문자', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND (subject LIKE '%SMS%' OR subject LIKE '%문자%' OR subject LIKE '%메일%')\nUNION ALL SELECT '회원·계정', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND (subject LIKE '%회원%' OR subject LIKE '%계정%' OR subject LIKE '%로그인%' OR subject LIKE '%비밀번호%')\nUNION ALL SELECT '진도·수강', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND (subject LIKE '%진도%' OR subject LIKE '%수강%' OR subject LIKE '%학습%')\nUNION ALL SELECT '수료증', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND subject LIKE '%수료%'\nUNION ALL SELECT '평가·시험', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND (subject LIKE '%평가%' OR subject LIKE '%시험%' OR subject LIKE '%퀴즈%')\nUNION ALL SELECT '콘텐츠·영상', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND (subject LIKE '%WBT%' OR subject LIKE '%콘텐츠%' OR subject LIKE '%컨텐츠%' OR subject LIKE '%영상%')\nORDER BY 2 DESC;\n\n-- D10. 시기별 분포 (월 단위)\nSELECT SUBSTRING(reg_date,1,6) ym, COUNT(*) cnt\nFROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1\nGROUP BY ym ORDER BY ym;\n\n-- D11. 본문에 포함된 답변 본문 키워드 (에스컬레이션·거절 시그널)\nSELECT\n  SUM(c.content LIKE '%개발팀%') dev_handoff,\n  SUM(c.content LIKE '%유선%' OR c.content LIKE '%전화%') phone,\n  SUM(c.content LIKE '%확인 후%' OR c.content LIKE '%확인하고%') check_back,\n  SUM(c.content LIKE '%죄송%') apology,\n  SUM(c.content LIKE '%감사%') thanks,\n  SUM(c.content LIKE '%개발 어려%' OR c.content LIKE '%지원되지 않%' OR c.content LIKE '%제공되지 않%' OR c.content LIKE '%불가%') rejection,\n  COUNT(*) total\nFROM tb_post_comment c JOIN tb_post p ON p.id=c.post_id\nWHERE p.project_id={{PROJECT_ID}} AND p.status=1 AND c.status=1;\n\n-- D12. PII 의심 패턴\nSELECT\n  SUM(c.content REGEXP '[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+') email_like,\n  SUM(c.content REGEXP '010[-]?[0-9]{4}[-]?[0-9]{4}') phone_010,\n  SUM(c.content REGEXP '[0-9]{2,3}-[0-9]{3,4}-[0-9]{4}') tel_dash,\n  COUNT(*) total\nFROM tb_post_comment c JOIN tb_post p ON p.id=c.post_id\nWHERE p.project_id={{PROJECT_ID}} AND p.status=1 AND c.status=1;\n\n-- D13. 자동화 적합성 분류 (제목 키워드 기반)\nSELECT '위탁·협업 요청' kind, COUNT(*) cnt FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1\n  AND (subject LIKE '%모니터링%' OR subject LIKE '%작업%' OR subject LIKE '%세팅%' OR subject LIKE '%확인 요청%' OR subject LIKE '%발송%' OR subject LIKE '%체크%')\nUNION ALL SELECT '기능 질의', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1\n  AND (subject LIKE '%질의%' OR subject LIKE '%여부%' OR subject LIKE '%가능한지%' OR subject LIKE '%관련 문의%')\nUNION ALL SELECT '오류 신고', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1\n  AND (subject LIKE '%오류%' OR subject LIKE '%작동%' OR subject LIKE '%안되%' OR subject LIKE '%풀려%')\nUNION ALL SELECT '개발 요청', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1\n  AND (subject LIKE '%기능개발%' OR subject LIKE '%개발 요청%' OR subject LIKE '%추가 제작%' OR subject LIKE '%반영%')\nUNION ALL SELECT '긴급', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1\n  AND (subject LIKE '%긴급%' OR subject LIKE '%★%');\n",[16,27041,27042,27047,27052,27057,27062,27066,27071,27076,27081,27086,27091,27096,27101,27106,27111,27116,27121,27126,27130,27135,27139,27144,27149,27154,27159,27163,27167,27172,27177,27181,27186,27191,27196,27201,27205,27210,27215,27220,27224,27228,27232,27237,27242,27247,27251,27256,27260,27265,27270,27275,27280,27285,27289,27293,27298,27303,27307,27312,27317,27322,27327,27332,27337,27342,27346,27351,27356,27361,27366,27371,27376,27380,27385,27389,27393,27398,27403,27408,27413,27417,27421,27425,27430,27435,27440,27444,27449,27454,27459,27464,27468,27472,27477,27481,27486,27491,27496,27501,27506,27511,27516,27521,27526,27532,27538,27544,27550,27555,27561,27567,27573,27579,27584,27590,27595,27601,27607,27613,27618,27624,27630,27635,27641,27647,27652,27658,27663,27669,27675,27681,27686,27691,27696,27701,27707,27713,27719,27725,27731,27737,27743,27749,27755,27761],{"__ignoreMap":423},[2166,27043,27044],{"class":3301,"line":3302},[2166,27045,27046],{},"-- D1. 게시글·댓글·비공개 분포 (이메일 도메인 기반)\n",[2166,27048,27049],{"class":3301,"line":3335},[2166,27050,27051],{},"SELECT 'posts' kind,\n",[2166,27053,27054],{"class":3301,"line":3342},[2166,27055,27056],{},"  SUM(u.email LIKE '%@malgnsoft.com') staff,\n",[2166,27058,27059],{"class":3301,"line":3368},[2166,27060,27061],{},"  SUM(u.email IS NULL OR u.email NOT LIKE '%@malgnsoft.com') customer,\n",[2166,27063,27064],{"class":3301,"line":3396},[2166,27065,8794],{},[2166,27067,27068],{"class":3301,"line":3426},[2166,27069,27070],{},"FROM tb_post p LEFT JOIN tb_user u ON u.id = p.user_id\n",[2166,27072,27073],{"class":3301,"line":3463},[2166,27074,27075],{},"WHERE p.project_id = {{PROJECT_ID}} AND p.status = 1\n",[2166,27077,27078],{"class":3301,"line":3504},[2166,27079,27080],{},"UNION ALL SELECT 'comments',\n",[2166,27082,27083],{"class":3301,"line":3538},[2166,27084,27085],{},"  SUM(u.email LIKE '%@malgnsoft.com'),\n",[2166,27087,27088],{"class":3301,"line":3550},[2166,27089,27090],{},"  SUM(u.email IS NULL OR u.email NOT LIKE '%@malgnsoft.com'),\n",[2166,27092,27093],{"class":3301,"line":3556},[2166,27094,27095],{},"  COUNT(*)\n",[2166,27097,27098],{"class":3301,"line":5367},[2166,27099,27100],{},"FROM tb_post_comment c JOIN tb_post p ON p.id = c.post_id LEFT JOIN tb_user u ON u.id = c.user_id\n",[2166,27102,27103],{"class":3301,"line":5375},[2166,27104,27105],{},"WHERE p.project_id = {{PROJECT_ID}} AND p.status = 1 AND c.status = 1\n",[2166,27107,27108],{"class":3301,"line":5392},[2166,27109,27110],{},"UNION ALL SELECT 'private_comments',\n",[2166,27112,27113],{"class":3301,"line":5404},[2166,27114,27115],{},"  SUM(c.private_yn='Y' AND u.email LIKE '%@malgnsoft.com'),\n",[2166,27117,27118],{"class":3301,"line":5415},[2166,27119,27120],{},"  SUM(c.private_yn='Y' AND (u.email IS NULL OR u.email NOT LIKE '%@malgnsoft.com')),\n",[2166,27122,27123],{"class":3301,"line":5421},[2166,27124,27125],{},"  SUM(c.private_yn='Y')\n",[2166,27127,27128],{"class":3301,"line":5432},[2166,27129,27100],{},[2166,27131,27132],{"class":3301,"line":5453},[2166,27133,27134],{},"WHERE p.project_id = {{PROJECT_ID}} AND p.status = 1 AND c.status = 1;\n",[2166,27136,27137],{"class":3301,"line":5459},[2166,27138,3339],{"emptyLinePlaceholder":3338},[2166,27140,27141],{"class":3301,"line":8686},[2166,27142,27143],{},"-- D2. Q&A 후보 \u002F 본문 통계 \u002F 첨부\n",[2166,27145,27146],{"class":3301,"line":8692},[2166,27147,27148],{},"SELECT COUNT(*) qna_candidates,\n",[2166,27150,27151],{"class":3301,"line":8698},[2166,27152,27153],{},"  ROUND(AVG(CHAR_LENGTH(p.content))) avg_body_len,\n",[2166,27155,27156],{"class":3301,"line":8704},[2166,27157,27158],{},"  SUM(p.subject LIKE CONCAT('[', '{{PROJECT_NAME_BARE}}', ']%')) structured_title\n",[2166,27160,27161],{"class":3301,"line":8710},[2166,27162,8605],{},[2166,27164,27165],{"class":3301,"line":8716},[2166,27166,27075],{},[2166,27168,27169],{"class":3301,"line":8721},[2166,27170,27171],{},"  AND p.comm_cnt >= 1 AND p.is_task=0 AND p.is_schedule=0 AND p.is_poll=0 AND p.is_notice=0\n",[2166,27173,27174],{"class":3301,"line":8727},[2166,27175,27176],{},"  AND p.subject NOT LIKE '테스트%' AND CHAR_LENGTH(p.content) >= 20;\n",[2166,27178,27179],{"class":3301,"line":8733},[2166,27180,3339],{"emptyLinePlaceholder":3338},[2166,27182,27183],{"class":3301,"line":8739},[2166,27184,27185],{},"SELECT COUNT(DISTINCT p.id) total,\n",[2166,27187,27188],{"class":3301,"line":8745},[2166,27189,27190],{},"  COUNT(DISTINCT IF(f.id IS NOT NULL, p.id, NULL)) with_attachment\n",[2166,27192,27193],{"class":3301,"line":8751},[2166,27194,27195],{},"FROM tb_post p LEFT JOIN tb_post_file f ON f.module='post' AND f.module_id = p.id AND f.status=1\n",[2166,27197,27198],{"class":3301,"line":8756},[2166,27199,27200],{},"WHERE p.project_id = {{PROJECT_ID}} AND p.status = 1;\n",[2166,27202,27203],{"class":3301,"line":8762},[2166,27204,3339],{"emptyLinePlaceholder":3338},[2166,27206,27207],{"class":3301,"line":8767},[2166,27208,27209],{},"-- D3. 응답 시간 (FRT)\n",[2166,27211,27212],{"class":3301,"line":8773},[2166,27213,27214],{},"SELECT ROUND(AVG(frt)) avg_min,\n",[2166,27216,27217],{"class":3301,"line":8779},[2166,27218,27219],{},"  SUM(frt \u003C= 60) within_1h, SUM(frt \u003C= 240) within_4h, SUM(frt \u003C= 1440) within_1d, COUNT(*) total\n",[2166,27221,27222],{"class":3301,"line":8785},[2166,27223,8800],{},[2166,27225,27226],{"class":3301,"line":8791},[2166,27227,8806],{},[2166,27229,27230],{"class":3301,"line":8797},[2166,27231,8812],{},[2166,27233,27234],{"class":3301,"line":8803},[2166,27235,27236],{},"    STR_TO_DATE(MIN(c.reg_date),'%Y%m%d%H%i%s')) frt\n",[2166,27238,27239],{"class":3301,"line":8809},[2166,27240,27241],{},"  FROM tb_post p JOIN tb_post_comment c ON c.post_id=p.id\n",[2166,27243,27244],{"class":3301,"line":8815},[2166,27245,27246],{},"  WHERE p.project_id={{PROJECT_ID}} AND p.status=1 AND c.status=1\n",[2166,27248,27249],{"class":3301,"line":8821},[2166,27250,8835],{},[2166,27252,27253],{"class":3301,"line":8827},[2166,27254,27255],{},") t;\n",[2166,27257,27258],{"class":3301,"line":8832},[2166,27259,3339],{"emptyLinePlaceholder":3338},[2166,27261,27262],{"class":3301,"line":8838},[2166,27263,27264],{},"-- D4. FCR (직원 단일 답변 후 종결)\n",[2166,27266,27267],{"class":3301,"line":8844},[2166,27268,27269],{},"WITH staff_replies AS (\n",[2166,27271,27272],{"class":3301,"line":8849},[2166,27273,27274],{},"  SELECT c.post_id, COUNT(*) n\n",[2166,27276,27277],{"class":3301,"line":8855},[2166,27278,27279],{},"  FROM tb_post_comment c JOIN tb_post p ON p.id=c.post_id LEFT JOIN tb_user u ON u.id=c.user_id\n",[2166,27281,27282],{"class":3301,"line":8860},[2166,27283,27284],{},"  WHERE p.project_id={{PROJECT_ID}} AND p.status=1 AND c.status=1 AND u.email LIKE '%@malgnsoft.com'\n",[2166,27286,27287],{"class":3301,"line":8866},[2166,27288,8713],{},[2166,27290,27291],{"class":3301,"line":8871},[2166,27292,4527],{},[2166,27294,27295],{"class":3301,"line":8877},[2166,27296,27297],{},"SELECT COUNT(*) total, SUM(n=1) single, ROUND(100.0*SUM(n=1)\u002FCOUNT(*),1) fcr_pct\n",[2166,27299,27300],{"class":3301,"line":8883},[2166,27301,27302],{},"FROM staff_replies;\n",[2166,27304,27305],{"class":3301,"line":8888},[2166,27306,3339],{"emptyLinePlaceholder":3338},[2166,27308,27309],{"class":3301,"line":8894},[2166,27310,27311],{},"-- D5. 인력 분담 (직원 only)\n",[2166,27313,27314],{"class":3301,"line":8899},[2166,27315,27316],{},"SELECT u.name, u.email, COUNT(*) replies,\n",[2166,27318,27319],{"class":3301,"line":8905},[2166,27320,27321],{},"  ROUND(100.0*COUNT(*)\u002FSUM(COUNT(*)) OVER (),1) pct,\n",[2166,27323,27324],{"class":3301,"line":8911},[2166,27325,27326],{},"  SUM(c.private_yn='Y') private_cnt\n",[2166,27328,27329],{"class":3301,"line":8917},[2166,27330,27331],{},"FROM tb_post_comment c JOIN tb_post p ON p.id=c.post_id LEFT JOIN tb_user u ON u.id=c.user_id\n",[2166,27333,27334],{"class":3301,"line":8923},[2166,27335,27336],{},"WHERE p.project_id={{PROJECT_ID}} AND p.status=1 AND c.status=1 AND u.email LIKE '%@malgnsoft.com'\n",[2166,27338,27339],{"class":3301,"line":8929},[2166,27340,27341],{},"GROUP BY u.name, u.email ORDER BY replies DESC;\n",[2166,27343,27344],{"class":3301,"line":8935},[2166,27345,3339],{"emptyLinePlaceholder":3338},[2166,27347,27348],{"class":3301,"line":8941},[2166,27349,27350],{},"-- D6. 고객 매너 키워드\n",[2166,27352,27353],{"class":3301,"line":8947},[2166,27354,27355],{},"SELECT SUM(c.content LIKE '%감사%') thanks,\n",[2166,27357,27358],{"class":3301,"line":19135},[2166,27359,27360],{},"  SUM(c.content LIKE '%확인%') confirm,\n",[2166,27362,27363],{"class":3301,"line":19141},[2166,27364,27365],{},"  SUM(c.content LIKE '%부탁%') please,\n",[2166,27367,27368],{"class":3301,"line":19147},[2166,27369,27370],{},"  SUM(c.content LIKE '%죄송%') apology,\n",[2166,27372,27373],{"class":3301,"line":19153},[2166,27374,27375],{},"  COUNT(*) customer_comments\n",[2166,27377,27378],{"class":3301,"line":19159},[2166,27379,27331],{},[2166,27381,27382],{"class":3301,"line":19165},[2166,27383,27384],{},"WHERE p.project_id={{PROJECT_ID}} AND p.status=1 AND c.status=1\n",[2166,27386,27387],{"class":3301,"line":19170},[2166,27388,8950],{},[2166,27390,27391],{"class":3301,"line":19175},[2166,27392,3339],{"emptyLinePlaceholder":3338},[2166,27394,27395],{"class":3301,"line":19180},[2166,27396,27397],{},"-- D7. 종결 멘트 작성자\n",[2166,27399,27400],{"class":3301,"line":19186},[2166,27401,27402],{},"WITH last_c AS (\n",[2166,27404,27405],{"class":3301,"line":19192},[2166,27406,27407],{},"  SELECT c.post_id, u.email, c.content,\n",[2166,27409,27410],{"class":3301,"line":19198},[2166,27411,27412],{},"    ROW_NUMBER() OVER (PARTITION BY c.post_id ORDER BY c.reg_date DESC) rn\n",[2166,27414,27415],{"class":3301,"line":19204},[2166,27416,27279],{},[2166,27418,27419],{"class":3301,"line":19209},[2166,27420,27246],{},[2166,27422,27423],{"class":3301,"line":19215},[2166,27424,4527],{},[2166,27426,27427],{"class":3301,"line":19221},[2166,27428,27429],{},"SELECT IF(email LIKE '%@malgnsoft.com','staff','customer') who, COUNT(*) total,\n",[2166,27431,27432],{"class":3301,"line":19226},[2166,27433,27434],{},"  SUM(content LIKE '%감사%' OR content LIKE '%확인했%' OR content LIKE '%잘 받았%') closed\n",[2166,27436,27437],{"class":3301,"line":19231},[2166,27438,27439],{},"FROM last_c WHERE rn=1 GROUP BY 1;\n",[2166,27441,27442],{"class":3301,"line":19237},[2166,27443,3339],{"emptyLinePlaceholder":3338},[2166,27445,27446],{"class":3301,"line":19243},[2166,27447,27448],{},"-- D8. 영업시간\u002F주말 응답 (직원)\n",[2166,27450,27451],{"class":3301,"line":19249},[2166,27452,27453],{},"SELECT SUM(HOUR(STR_TO_DATE(c.reg_date,'%Y%m%d%H%i%s')) BETWEEN 9 AND 18) biz_hours,\n",[2166,27455,27456],{"class":3301,"line":19255},[2166,27457,27458],{},"  SUM(HOUR(STR_TO_DATE(c.reg_date,'%Y%m%d%H%i%s')) NOT BETWEEN 9 AND 18) off_hours,\n",[2166,27460,27461],{"class":3301,"line":19261},[2166,27462,27463],{},"  SUM(DAYOFWEEK(STR_TO_DATE(c.reg_date,'%Y%m%d%H%i%s')) IN (1,7)) weekend,\n",[2166,27465,27466],{"class":3301,"line":19267},[2166,27467,8794],{},[2166,27469,27470],{"class":3301,"line":19273},[2166,27471,27331],{},[2166,27473,27474],{"class":3301,"line":19279},[2166,27475,27476],{},"WHERE p.project_id={{PROJECT_ID}} AND p.status=1 AND c.status=1 AND u.email LIKE '%@malgnsoft.com';\n",[2166,27478,27479],{"class":3301,"line":19285},[2166,27480,3339],{"emptyLinePlaceholder":3338},[2166,27482,27483],{"class":3301,"line":19291},[2166,27484,27485],{},"-- D9. 주제 키워드 빈도 (제목 기준)\n",[2166,27487,27488],{"class":3301,"line":19297},[2166,27489,27490],{},"SELECT 'LMS' kw, COUNT(*) cnt FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND subject LIKE '%LMS%'\n",[2166,27492,27493],{"class":3301,"line":19303},[2166,27494,27495],{},"UNION ALL SELECT '오류', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND subject LIKE '%오류%'\n",[2166,27497,27498],{"class":3301,"line":19309},[2166,27499,27500],{},"UNION ALL SELECT '문의', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND subject LIKE '%문의%'\n",[2166,27502,27503],{"class":3301,"line":19315},[2166,27504,27505],{},"UNION ALL SELECT '결제', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND subject LIKE '%결제%'\n",[2166,27507,27508],{"class":3301,"line":19320},[2166,27509,27510],{},"UNION ALL SELECT '도메인', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND subject LIKE '%도메인%'\n",[2166,27512,27513],{"class":3301,"line":19326},[2166,27514,27515],{},"UNION ALL SELECT 'SMS·문자', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND (subject LIKE '%SMS%' OR subject LIKE '%문자%' OR subject LIKE '%메일%')\n",[2166,27517,27518],{"class":3301,"line":19332},[2166,27519,27520],{},"UNION ALL SELECT '회원·계정', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND (subject LIKE '%회원%' OR subject LIKE '%계정%' OR subject LIKE '%로그인%' OR subject LIKE '%비밀번호%')\n",[2166,27522,27523],{"class":3301,"line":19338},[2166,27524,27525],{},"UNION ALL SELECT '진도·수강', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND (subject LIKE '%진도%' OR subject LIKE '%수강%' OR subject LIKE '%학습%')\n",[2166,27527,27529],{"class":3301,"line":27528},103,[2166,27530,27531],{},"UNION ALL SELECT '수료증', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND subject LIKE '%수료%'\n",[2166,27533,27535],{"class":3301,"line":27534},104,[2166,27536,27537],{},"UNION ALL SELECT '평가·시험', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND (subject LIKE '%평가%' OR subject LIKE '%시험%' OR subject LIKE '%퀴즈%')\n",[2166,27539,27541],{"class":3301,"line":27540},105,[2166,27542,27543],{},"UNION ALL SELECT '콘텐츠·영상', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND (subject LIKE '%WBT%' OR subject LIKE '%콘텐츠%' OR subject LIKE '%컨텐츠%' OR subject LIKE '%영상%')\n",[2166,27545,27547],{"class":3301,"line":27546},106,[2166,27548,27549],{},"ORDER BY 2 DESC;\n",[2166,27551,27553],{"class":3301,"line":27552},107,[2166,27554,3339],{"emptyLinePlaceholder":3338},[2166,27556,27558],{"class":3301,"line":27557},108,[2166,27559,27560],{},"-- D10. 시기별 분포 (월 단위)\n",[2166,27562,27564],{"class":3301,"line":27563},109,[2166,27565,27566],{},"SELECT SUBSTRING(reg_date,1,6) ym, COUNT(*) cnt\n",[2166,27568,27570],{"class":3301,"line":27569},110,[2166,27571,27572],{},"FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1\n",[2166,27574,27576],{"class":3301,"line":27575},111,[2166,27577,27578],{},"GROUP BY ym ORDER BY ym;\n",[2166,27580,27582],{"class":3301,"line":27581},112,[2166,27583,3339],{"emptyLinePlaceholder":3338},[2166,27585,27587],{"class":3301,"line":27586},113,[2166,27588,27589],{},"-- D11. 본문에 포함된 답변 본문 키워드 (에스컬레이션·거절 시그널)\n",[2166,27591,27593],{"class":3301,"line":27592},114,[2166,27594,8724],{},[2166,27596,27598],{"class":3301,"line":27597},115,[2166,27599,27600],{},"  SUM(c.content LIKE '%개발팀%') dev_handoff,\n",[2166,27602,27604],{"class":3301,"line":27603},116,[2166,27605,27606],{},"  SUM(c.content LIKE '%유선%' OR c.content LIKE '%전화%') phone,\n",[2166,27608,27610],{"class":3301,"line":27609},117,[2166,27611,27612],{},"  SUM(c.content LIKE '%확인 후%' OR c.content LIKE '%확인하고%') check_back,\n",[2166,27614,27616],{"class":3301,"line":27615},118,[2166,27617,27370],{},[2166,27619,27621],{"class":3301,"line":27620},119,[2166,27622,27623],{},"  SUM(c.content LIKE '%감사%') thanks,\n",[2166,27625,27627],{"class":3301,"line":27626},120,[2166,27628,27629],{},"  SUM(c.content LIKE '%개발 어려%' OR c.content LIKE '%지원되지 않%' OR c.content LIKE '%제공되지 않%' OR c.content LIKE '%불가%') rejection,\n",[2166,27631,27633],{"class":3301,"line":27632},121,[2166,27634,8794],{},[2166,27636,27638],{"class":3301,"line":27637},122,[2166,27639,27640],{},"FROM tb_post_comment c JOIN tb_post p ON p.id=c.post_id\n",[2166,27642,27644],{"class":3301,"line":27643},123,[2166,27645,27646],{},"WHERE p.project_id={{PROJECT_ID}} AND p.status=1 AND c.status=1;\n",[2166,27648,27650],{"class":3301,"line":27649},124,[2166,27651,3339],{"emptyLinePlaceholder":3338},[2166,27653,27655],{"class":3301,"line":27654},125,[2166,27656,27657],{},"-- D12. PII 의심 패턴\n",[2166,27659,27661],{"class":3301,"line":27660},126,[2166,27662,8724],{},[2166,27664,27666],{"class":3301,"line":27665},127,[2166,27667,27668],{},"  SUM(c.content REGEXP '[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+') email_like,\n",[2166,27670,27672],{"class":3301,"line":27671},128,[2166,27673,27674],{},"  SUM(c.content REGEXP '010[-]?[0-9]{4}[-]?[0-9]{4}') phone_010,\n",[2166,27676,27678],{"class":3301,"line":27677},129,[2166,27679,27680],{},"  SUM(c.content REGEXP '[0-9]{2,3}-[0-9]{3,4}-[0-9]{4}') tel_dash,\n",[2166,27682,27684],{"class":3301,"line":27683},130,[2166,27685,8794],{},[2166,27687,27689],{"class":3301,"line":27688},131,[2166,27690,27640],{},[2166,27692,27694],{"class":3301,"line":27693},132,[2166,27695,27646],{},[2166,27697,27699],{"class":3301,"line":27698},133,[2166,27700,3339],{"emptyLinePlaceholder":3338},[2166,27702,27704],{"class":3301,"line":27703},134,[2166,27705,27706],{},"-- D13. 자동화 적합성 분류 (제목 키워드 기반)\n",[2166,27708,27710],{"class":3301,"line":27709},135,[2166,27711,27712],{},"SELECT '위탁·협업 요청' kind, COUNT(*) cnt FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1\n",[2166,27714,27716],{"class":3301,"line":27715},136,[2166,27717,27718],{},"  AND (subject LIKE '%모니터링%' OR subject LIKE '%작업%' OR subject LIKE '%세팅%' OR subject LIKE '%확인 요청%' OR subject LIKE '%발송%' OR subject LIKE '%체크%')\n",[2166,27720,27722],{"class":3301,"line":27721},137,[2166,27723,27724],{},"UNION ALL SELECT '기능 질의', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1\n",[2166,27726,27728],{"class":3301,"line":27727},138,[2166,27729,27730],{},"  AND (subject LIKE '%질의%' OR subject LIKE '%여부%' OR subject LIKE '%가능한지%' OR subject LIKE '%관련 문의%')\n",[2166,27732,27734],{"class":3301,"line":27733},139,[2166,27735,27736],{},"UNION ALL SELECT '오류 신고', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1\n",[2166,27738,27740],{"class":3301,"line":27739},140,[2166,27741,27742],{},"  AND (subject LIKE '%오류%' OR subject LIKE '%작동%' OR subject LIKE '%안되%' OR subject LIKE '%풀려%')\n",[2166,27744,27746],{"class":3301,"line":27745},141,[2166,27747,27748],{},"UNION ALL SELECT '개발 요청', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1\n",[2166,27750,27752],{"class":3301,"line":27751},142,[2166,27753,27754],{},"  AND (subject LIKE '%기능개발%' OR subject LIKE '%개발 요청%' OR subject LIKE '%추가 제작%' OR subject LIKE '%반영%')\n",[2166,27756,27758],{"class":3301,"line":27757},143,[2166,27759,27760],{},"UNION ALL SELECT '긴급', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1\n",[2166,27762,27764],{"class":3301,"line":27763},144,[2166,27765,27766],{},"  AND (subject LIKE '%긴급%' OR subject LIKE '%★%');\n",[36,27768,27770],{"id":27769},"평가-프레임-8개-섹션-작성",[2166,27771,27772],{},"평가 프레임 — 8개 섹션 작성",[24,27774,27775],{},"다음 8개 섹션을 모두 작성하세요. 점수 체계: ★ 1~5, 판정 표시: ✓ 양호 \u002F ⚠ 주의 \u002F ✕ 문제 \u002F ㅡ 정보 부족.",[215,27777,27779],{"id":27778},"_1-메타-overview","§ 1. 메타 (overview)",[24,27781,27782],{},"다음 정보를 표로 정리:",[54,27784,27785,27788,27791,27794,27797,27800],{},[57,27786,27787],{},"Project ID \u002F Name \u002F Site",[57,27789,27790],{},"기간 (first_post ~ last_post)",[57,27792,27793],{},"전체 게시글 수 \u002F Q&A 후보 수",[57,27795,27796],{},"주 문의자 (이메일 도메인 포함)",[57,27798,27799],{},"응대자 (직원, 분담 비율)",[57,27801,27802],{},"케이스 성격 한 줄 요약",[215,27804,27806],{"id":27805},"_2-카테고리별-분포","§ 2. 카테고리별 분포",[24,27808,27809],{},"D9·D13 결과로 주요 주제 카테고리와 건수를 표로. 각 카테고리에 대표 문의 예시 1~2개를 함께.",[215,27811,27813],{"id":27812},"_3-시기별-흐름","§ 3. 시기별 흐름",[24,27815,27816],{},"D10 결과로 월별 추이 + 시기별 특징(도입 초기 \u002F 운영 중반 \u002F 정착기 등)을 정성 해석.",[215,27818,27820],{"id":27819},"_4-답변-결과로-본-핵심-시스템-이슈","§ 4. 답변 결과로 본 핵심 시스템 이슈",[24,27822,27823],{},"D11 결과 + 정성 분석. 정책 거절·미지원·개발 불가 답변에서 반복되는 시스템 이슈를 표로:",[54,27825,27826],{},[57,27827,27828],{},"이슈명 \u002F 결과(요약) \u002F 비공개 여부 \u002F 참조 post_id",[215,27830,27832],{"id":27831},"_5-케이스-특수성","§ 5. 케이스 특수성",[24,27834,27835],{},"이 프로젝트만의 도메인 특수성(공공\u002F대학\u002FHRD\u002F일반기업 등), 법령·규제, 운영 의존도, 답변 노출 민감성 등 4~6개 항목으로.",[215,27837,27839],{"id":27838},"_6-ai-챗봇-적합성-평가-5축","§ 6. AI 챗봇 적합성 평가 (5축)",[24,27841,27842],{},"각 축마다 체크 항목 표를 작성. 측정값 + 판정(✓\u002F⚠\u002F✕\u002Fㅡ).",[24,27844,27845,27847,27848,27850,27851,27854,27855,27857,27858,27861,27862],{},[28,27846,6411],{},": 정확도 · 현재 유효성(신선도) · 완결성(종결 멘트) · 일관성 · 출처·근거 인용\n",[28,27849,6490],{},": FRT 평균·분포(1h\u002F4h\u002F1d) · TTR · 재문의 패턴 · 긴급 처리 일관성\n",[28,27852,27853],{},"C. 응대 패턴",": 답변자 분포(이메일 기반) · 셀프 보완 · 에스컬레이션 시그널 · 응답 톤 정형성 · 반복 답변 가능성\n",[28,27856,6669],{},": 거절·미지원 답변 비율 · 비공개 댓글 비율 · 비공개에만 답 있는 글 · PII 의심 패턴 · 고객사 식별정보 · 법령 종속 답변 · 비공개 작성자 패턴\n",[28,27859,27860],{},"E. 자동화 적합성",": D13의 5분류(위탁·협업 \u002F 기능 질의 \u002F 오류 신고 \u002F 개발 요청 \u002F 긴급) 비중 → ",[28,27863,27864],{},"추정 자동 응답 가능 비중(%)",[24,27866,27867,27870],{},[28,27868,27869],{},"§6 종합 판정",": 5개 차원에 대한 ✓\u002F⚠\u002F✕ 판정 + 권장 후속 조치 5~7개.",[215,27872,27874],{"id":27873},"_7-순수-cs-운영-품질-평가-챗봇-분리","§ 7. 순수 CS 운영 품질 평가 (챗봇 분리)",[24,27876,27877],{},"5축 × ★ 1~5 점수.",[24,27879,27880,27883,27884,27887,27888,27891,27892,27895,27896,27899],{},[28,27881,27882],{},"A. 응답 신속성",": FRT 평균 · 1h\u002F4h\u002F1d 비율 · 영업시간 응답률 · 주말 응답 · 긴급 SLA 일관성\n",[28,27885,27886],{},"B. 해결 품질",": FCR(D4) · 평균 댓글 수 · 종결 시그널(D7) · 사과 사용 · 장기 미해결 · 반복 주제(D9)\n",[28,27889,27890],{},"C. 인력 운영",": 응답 인력 수(D5) · 주 응답자 집중도 · 역할 분담 패턴(공개\u002F비공개·테마별) · 백업 운영 · 야간 커버 · 표준답변·KMS 여부\n",[28,27893,27894],{},"D. 프로세스 성숙도",": 티켓 시스템 · 표준답변\u002FFAQ · 카테고리·태그 · 우선순위 분기 · 공개\u002F비공개 분리 · 지식 베이스 검색 · 에스컬레이션 경로 · 개발 환류 추적\n",[28,27897,27898],{},"E. 고객 경험",": 만족 시그널 · 사과 빈도 · 응답 톤 일관성 · 고객-담당자 관계 · 고객 측 능동성 · 긴급 대응 실패 사례 · 거절 답변 노출 통제",[24,27901,27902,27904,27905,27907,27908,27910],{},[28,27903,7532],{}," (5축 + 전체 평균)\n",[28,27906,7623],{}," (개선 우선순위 5~7개)\n",[28,27909,7750],{}," (다른 프로젝트로 일반화 가능 패턴)",[215,27912,27914],{"id":27913},"_8-고객사-평가-협업-행태","§ 8. 고객사 평가 (협업 행태)",[24,27916,27877],{},[24,27918,27919,27922,27923,27926,27927,27930,27931,27934,27935,27938],{},[28,27920,27921],{},"A. 문의 품질",": 제목 구조화 비율(D2) · 카테고리 라벨링 · 본문 길이(D2) · 컨텍스트 첨부(D2) · 재현 정보 명시\n",[28,27924,27925],{},"B. 컨택 일관성",": 주 담당자 단독\u002F복수 · 협업자·백업 유무 · 다중 채널(유선) 사용 · 응대 시간대 · 후속 응답 속도\n",[28,27928,27929],{},"C. 요청 합리성",": D13 분류의 위탁·협업 비중 · 단순 질의 비중 · 오류 신고 정상 비율 · 개발 요청 무리도 · 긴급 표기 남용 · 법령\u002F근거 인용\n",[28,27932,27933],{},"D. 협업 태도",": 종결 멘트 작성률(고객) · 매너 키워드(D6: 감사\u002F확인\u002F부탁\u002F죄송) · 회신 방향성 · 정책 거절 수용도 · 후속 정보 능동 제공\n",[28,27936,27937],{},"E. 운영 성숙도",": 기술 용어 정확도 · 자체 분류 운영 · FAQ 인지 · 동일 주제 반복 · 의사결정 일관성 · 도입 단계 · 장기 미종결 처리",[24,27940,27941,27904,27943,27945,27948,27949,27951],{},[28,27942,7532],{},[28,27944,8374],{},[28,27946,27947],{},"제공자 vs 고객사 매트릭스"," (5축 점수 비교 + 관계 진단 한 문단)\n",[28,27950,8548],{}," (신규 고객사 온보딩 가이드 · 위탁 비중 비교 · 고객사 SLA 자가진단 등)",[36,27953,27955],{"id":27954},"출력-형식-규칙",[2166,27956,27957],{},"출력 형식 규칙",[54,27959,27960,27966,27971,27977,27983,27992,28001,28019,28030],{},[57,27961,27962,27965],{},[28,27963,27964],{},"언어",": 한국어",[57,27967,27968,27970],{},[28,27969,21585],{},": 마크다운, 표 위주",[57,27972,27973,27976],{},[28,27974,27975],{},"점수",": ★ 1~5",[57,27978,27979,27982],{},[28,27980,27981],{},"판정 기호",": ✓ 양호 · ⚠ 주의 · ✕ 문제 · ㅡ 정보 부족",[57,27984,27985,27988,27989,27991],{},[28,27986,27987],{},"추측 금지",": 데이터로 측정·관찰되지 않은 항목은 반드시 ",[16,27990,6471],{},"로 표기.",[57,27993,27994,27997,27998,28000],{},[28,27995,27996],{},"분류 기준 명시",": §1 메타에 \"분류 규칙: 이메일 도메인 ",[16,27999,128],{}," 기준\" 한 줄 포함.",[57,28002,28003,28005,28006,105,28010,105,28014,28018],{},[28,28004,8956],{},": 결과 문서 하단에 ",[3257,28007,28008],{"href":6359},[16,28009,6360],{},[3257,28011,28012],{"href":5779},[16,28013,5780],{},[3257,28015,28016],{"href":6980},[16,28017,6981],{}," 링크.",[57,28020,28021,4664,28024,28026,28027,28029],{},[28,28022,28023],{},"저장 경로",[16,28025,26863],{},". (",[16,28028,5824],{}," 같은 접두 기호는 안전한 파일명으로 치환 가능)",[57,28031,28032,28035,28036,28039],{},[28,28033,28034],{},"추출 쿼리 섹션은 포함하지 않음"," — 본 프롬프트의 ",[2166,28037,28038],{},"필수 데이터 수집 쿼리"," 절을 재사용.",[36,28041,28043,28046],{"id":28042},"품질-체크리스트-보고서-제출-전-확인",[2166,28044,28045],{},"품질 체크리스트"," — 보고서 제출 전 확인",[54,28048,28050,28056,28062,28068,28074,28082,28088],{"className":28049},[10401],[57,28051,28053,28055],{"className":28052},[10405],[10407,28054],{"disabled":3338,"type":10409}," 메타에 이메일 도메인 분류 기준 명시",[57,28057,28059,28061],{"className":28058},[10405],[10407,28060],{"disabled":3338,"type":10409}," 모든 수치는 측정값 (가정·추정 금지)",[57,28063,28065,28067],{"className":28064},[10405],[10407,28066],{"disabled":3338,"type":10409}," §6·§7·§8 각각의 종합 점수표 포함",[57,28069,28071,28073],{"className":28070},[10405],[10407,28072],{"disabled":3338,"type":10409}," §8 끝의 제공자 vs 고객사 매트릭스 포함",[57,28075,28077,28079,28080,10639],{"className":28076},[10405],[10407,28078],{"disabled":3338,"type":10409}," 정보 부족 항목은 ",[16,28081,6471],{},[57,28083,28085,28087],{"className":28084},[10405],[10407,28086],{"disabled":3338,"type":10409}," 점수 산정 근거가 표 안에 들어 있음",[57,28089,28091,28093],{"className":28090},[10405],[10407,28092],{"disabled":3338,"type":10409}," 강점\u002F개선점\u002F후속 조치 모두 포함",[33,28095],{},[11,28097,28098],{"id":2393},"§ 참고",[54,28100,28101,28109,28116,28123],{},[57,28102,28103,28104,28108],{},"예시 산출물: ",[3257,28105,28106],{"href":10875},[16,28107,9047],{}," — 본 프롬프트로 만들 결과의 모범 형태",[57,28110,28111,28112],{},"DB 정책·정제 룰: ",[3257,28113,28114],{"href":6359},[16,28115,26996],{},[57,28117,28118,28119],{},"전체 업체 분포·필터 룰: ",[3257,28120,28121],{"href":5779},[16,28122,9184],{},[57,28124,28125,28126,9264],{},"분류 규칙 메모리 근거: 사용자 정책 (",[16,28127,128],{},[4258,28129,8979],{},{"title":423,"searchDepth":3342,"depth":3342,"links":28131},[28132,28133,28134,28136,28137,28138,28148,28149],{"id":26836,"depth":3335,"text":26836},{"id":26884,"depth":3335,"text":26884},{"id":26935,"depth":3335,"text":28135},"분류 규칙 — 필수 준수",{"id":26965,"depth":3335,"text":26968},{"id":27028,"depth":3335,"text":27031},{"id":27769,"depth":3335,"text":27772,"children":28139},[28140,28141,28142,28143,28144,28145,28146,28147],{"id":27778,"depth":3342,"text":27779},{"id":27805,"depth":3342,"text":27806},{"id":27812,"depth":3342,"text":27813},{"id":27819,"depth":3342,"text":27820},{"id":27831,"depth":3342,"text":27832},{"id":27838,"depth":3342,"text":27839},{"id":27873,"depth":3342,"text":27874},{"id":27913,"depth":3342,"text":27914},{"id":27954,"depth":3335,"text":27957},{"id":28042,"depth":3335,"text":28150},"품질 체크리스트 — 보고서 제출 전 확인",{},"\u002Fprompts\u002Fcs-evaluation",{"title":26819,"description":423},"prompts\u002Fcs-evaluation","pGF0pY2_hFnX6DbOr4_ufwdLHXq4jb2OxW_sEHbZGmw",{"id":28157,"title":28158,"body":28159,"description":423,"extension":4340,"meta":28962,"navigation":3338,"path":28963,"seo":28964,"stem":28965,"__hash__":28966},"docs\u002Fprompts\u002Fcustomer-briefing.md","고객사 브리핑 카드 프롬프트",{"type":8,"value":28160,"toc":28950},[28161,28164,28182,28184,28199,28203,28235,28237,28239,28253,28257,28287,28292,28310,28319,28736,28743,28749,28755,28834,28840,28854,28860,28862,28866,28914,28916,28948],[11,28162,28158],{"id":28163},"고객사-브리핑-카드-프롬프트",[21,28165,28166,28173],{},[24,28167,28168,28169,28172],{},"CS 상담자가 고객사 페이지를 열었을 때, 응대에 필요한 맥락을 ",[28,28170,28171],{},"10~30초 안에"," 파악할 수 있는 간결한 브리핑 카드를 AI에게 생성시키기 위한 프롬프트.\n산출물은 짧은 카드 한 장 (장문 분석 보고서가 아님).",[24,28174,28175,28176,28181],{},"비교: ",[3257,28177,28179],{"href":28178},"cs-evaluation",[16,28180,11383],{},"는 운영 진단용 장문 보고서, 본 프롬프트는 실시간 응대용 요약.",[36,28183,26836],{"id":26836},[1925,28185,28186,28189,28196],{},[57,28187,28188],{},"CS 관리자 사이트에서 고객사(프로젝트) 페이지 진입 시 호출.",[57,28190,20578,28191,4708,28193,28195],{},[28,28192,26843],{},[16,28194,26853],{},"를 치환해 AI에 전달.",[57,28197,28198],{},"산출물은 페이지 상단 카드로 렌더링. 저장은 선택 (캐시 용도).",[36,28200,28202],{"id":28201},"설계-원칙","설계 원칙",[1925,28204,28205,28211,28217,28223,28229],{},[57,28206,28207,28210],{},[28,28208,28209],{},"5초 \u002F 30초 \u002F 5분 레이어",": 헤더만 봐도 핵심 파악 → 표준답변까지 30초 → 상세는 별도 메뉴",[57,28212,28213,28216],{},[28,28214,28215],{},"위험 알림은 상단",": 미응답·긴급·정책 거절 후 재문의 등",[57,28218,28219,28222],{},[28,28220,28221],{},"표준답변·매뉴얼 직결 링크"," — 클릭 한 번에 사용",[57,28224,28225,28228],{},[28,28226,28227],{},"이미 거절된 요청 명시"," — 같은 답변 매번 새로 쓰지 않게",[57,28230,28231,28234],{},[28,28232,28233],{},"자동 산출 가능한 것만 표시"," — 사람이 채워야 하는 필드는 별도 메뉴",[33,28236],{},[11,28238,26870],{"id":26869},[24,28240,26873,28241,28244,28245,28248,28249,28252],{},[28,28242,28243],{},"CS 상담 지원 보조 AI","입니다.\n다음 데이터를 사용해 상담자가 고객사 페이지를 열 때 보여줄 ",[28,28246,28247],{},"간결한 브리핑 카드 하나","를 만드세요.\n보고서·평가서가 아닙니다. ",[28,28250,28251],{},"응대에 즉시 도움 되는 사실","만 담습니다.",[36,28254,28255],{"id":26884},[2166,28256,26884],{},[54,28258,28259,28265,28271,28279],{},[57,28260,28261,17678,28263],{},[16,28262,26893],{},[16,28264,26896],{},[57,28266,28267,17678,28269],{},[16,28268,26903],{},[16,28270,26906],{},[57,28272,28273,17678,28276,28278],{},[16,28274,28275],{},"CURRENT_DATE",[16,28277,26915],{}," (브리핑 기준일)",[57,28280,28281,17678,28284,28286],{},[16,28282,28283],{},"RECENT_WINDOW",[16,28285,23577],{}," (최근 활동 집계 기간, 일수)",[36,28288,28290],{"id":28289},"분류-규칙",[2166,28291,5893],{},[54,28293,28294,28301,28307],{},[57,28295,28296,1358,28298],{},[16,28297,26947],{},[28,28299,28300],{},"직원 (staff)",[57,28302,28303,28304],{},"그 외 → ",[28,28305,28306],{},"고객사·협력사 (customer)",[57,28308,28309],{},"이름·패턴으로 추정 금지",[36,28311,28313,2448,28316,28318],{"id":28312},"데이터-수집-쿼리-project_id만-치환",[2166,28314,28315],{},"데이터 수집 쿼리",[16,28317,26896],{},"만 치환",[415,28320,28322],{"className":8581,"code":28321,"language":8583,"meta":423,"style":423},"-- B1. 프로젝트 메타\nSELECT id, name, site_id, buyer, url, url2, start_date, end_date, status, reg_date\nFROM tb_project WHERE id = {{PROJECT_ID}};\n\n-- B2. 고객 측 주 담당자 (최근 90일 게시글 기준)\nSELECT u.name, u.email, COUNT(*) post_cnt, MAX(p.reg_date) last_post\nFROM tb_post p LEFT JOIN tb_user u ON u.id = p.user_id\nWHERE p.project_id = {{PROJECT_ID}} AND p.status = 1\n  AND (u.email IS NULL OR u.email NOT LIKE '%@malgnsoft.com')\n  AND p.reg_date >= DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 90 DAY), '%Y%m%d000000')\nGROUP BY u.name, u.email ORDER BY post_cnt DESC LIMIT 3;\n\n-- B3. 맑소 측 담당 (최근 90일 댓글 기준)\nSELECT u.name, u.email, COUNT(*) reply_cnt\nFROM tb_post_comment c JOIN tb_post p ON p.id = c.post_id LEFT JOIN tb_user u ON u.id = c.user_id\nWHERE p.project_id = {{PROJECT_ID}} AND p.status = 1 AND c.status = 1\n  AND u.email LIKE '%@malgnsoft.com'\n  AND c.reg_date >= DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 90 DAY), '%Y%m%d000000')\nGROUP BY u.name, u.email ORDER BY reply_cnt DESC LIMIT 5;\n\n-- B4. 최근 30일 활동\nSELECT COUNT(*) recent_posts,\n  SUM(p.comm_cnt = 0) AS no_reply,\n  SUM(p.subject LIKE '%긴급%' OR p.subject LIKE '%★%') AS urgent\nFROM tb_post p\nWHERE p.project_id = {{PROJECT_ID}} AND p.status = 1\n  AND p.reg_date >= DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 30 DAY), '%Y%m%d000000');\n\n-- B5. 미해결\u002F주의 필요 글 (최근 우선) — 직원 응답 없음 OR 종결 멘트 없음 OR 24h+ 미응답\nWITH last_comment AS (\n  SELECT c.post_id,\n    MAX(c.reg_date) last_reg,\n    MAX(CASE WHEN u.email LIKE '%@malgnsoft.com' THEN c.reg_date END) AS last_staff_reg,\n    MAX(c.content) last_content\n  FROM tb_post_comment c LEFT JOIN tb_user u ON u.id = c.user_id\n  WHERE c.status = 1\n  GROUP BY c.post_id\n)\nSELECT p.id, p.subject, p.writer, p.comm_cnt, p.reg_date,\n  CASE\n    WHEN p.comm_cnt = 0 THEN '미응답'\n    WHEN lc.last_staff_reg IS NULL THEN '직원 응답 없음'\n    WHEN lc.last_content NOT REGEXP '감사|확인했|잘 받았' THEN '종결 멘트 없음'\n    ELSE NULL\n  END AS flag\nFROM tb_post p LEFT JOIN last_comment lc ON lc.post_id = p.id\nWHERE p.project_id = {{PROJECT_ID}} AND p.status = 1\n  AND p.reg_date >= DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 60 DAY), '%Y%m%d000000')\nHAVING flag IS NOT NULL\nORDER BY p.reg_date DESC LIMIT 5;\n\n-- B6. 최근 30일 카테고리 분포 (라벨 또는 키워드)\nSELECT label, COUNT(*) cnt FROM tb_post\nWHERE project_id = {{PROJECT_ID}} AND status = 1\n  AND reg_date >= DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 30 DAY), '%Y%m%d000000')\n  AND label IS NOT NULL AND label != ''\nGROUP BY label ORDER BY cnt DESC LIMIT 5;\n\n-- B7. 자주 묻는 주제 Top 5 (전체 기간, 제목 키워드)\nSELECT '결제·납부' kw, COUNT(*) cnt FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND (subject LIKE '%결제%' OR subject LIKE '%납부%' OR subject LIKE '%계산서%')\nUNION ALL SELECT '수료증', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND subject LIKE '%수료%'\nUNION ALL SELECT '회원·계정', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND (subject LIKE '%회원%' OR subject LIKE '%계정%' OR subject LIKE '%로그인%' OR subject LIKE '%비밀번호%')\nUNION ALL SELECT 'SMS·메일', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND (subject LIKE '%SMS%' OR subject LIKE '%문자%' OR subject LIKE '%메일%')\nUNION ALL SELECT '진도·수강·평가', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND (subject LIKE '%진도%' OR subject LIKE '%수강%' OR subject LIKE '%평가%' OR subject LIKE '%시험%')\nUNION ALL SELECT '도메인·SSO·API', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND (subject LIKE '%도메인%' OR subject LIKE '%SSO%' OR subject LIKE '%API%')\nUNION ALL SELECT '콘텐츠·영상·WBT', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND (subject LIKE '%WBT%' OR subject LIKE '%콘텐츠%' OR subject LIKE '%컨텐츠%' OR subject LIKE '%영상%')\nORDER BY 2 DESC LIMIT 5;\n\n-- B8. 이미 거절된 요청 (정책상 불가 답변이 달린 게시글)\nSELECT p.id, p.subject, p.reg_date,\n  SUBSTRING(REGEXP_REPLACE(c.content, '\u003C[^>]+>', ''), 1, 120) excerpt\nFROM tb_post p JOIN tb_post_comment c ON c.post_id = p.id LEFT JOIN tb_user u ON u.id = c.user_id\nWHERE p.project_id = {{PROJECT_ID}} AND p.status = 1 AND c.status = 1\n  AND u.email LIKE '%@malgnsoft.com'\n  AND (c.content LIKE '%개발 어려%' OR c.content LIKE '%지원되지 않%' OR c.content LIKE '%제공되지 않%' OR c.content LIKE '%불가%' OR c.content LIKE '%규정상%')\nORDER BY p.reg_date DESC LIMIT 5;\n\n-- B9. 평균 FRT \u002F FCR (최근 90일)\nSELECT ROUND(AVG(frt)\u002F60, 1) avg_hours FROM (\n  SELECT TIMESTAMPDIFF(MINUTE,\n    STR_TO_DATE(p.reg_date,'%Y%m%d%H%i%s'),\n    STR_TO_DATE(MIN(c.reg_date),'%Y%m%d%H%i%s')) frt\n  FROM tb_post p JOIN tb_post_comment c ON c.post_id = p.id LEFT JOIN tb_user u ON u.id = c.user_id\n  WHERE p.project_id = {{PROJECT_ID}} AND p.status = 1 AND c.status = 1\n    AND u.email LIKE '%@malgnsoft.com'\n    AND p.reg_date >= DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 90 DAY), '%Y%m%d000000')\n  GROUP BY p.id\n) t;\n",[16,28323,28324,28329,28334,28339,28343,28348,28353,28357,28361,28366,28371,28376,28380,28385,28390,28394,28398,28403,28408,28413,28417,28422,28427,28432,28437,28441,28445,28450,28454,28459,28464,28469,28474,28479,28484,28489,28494,28498,28502,28507,28512,28517,28522,28527,28532,28537,28542,28546,28551,28556,28561,28565,28570,28575,28580,28585,28590,28595,28599,28604,28609,28613,28617,28622,28627,28632,28637,28642,28646,28651,28656,28661,28666,28670,28674,28679,28683,28687,28692,28697,28701,28705,28709,28714,28719,28723,28728,28732],{"__ignoreMap":423},[2166,28325,28326],{"class":3301,"line":3302},[2166,28327,28328],{},"-- B1. 프로젝트 메타\n",[2166,28330,28331],{"class":3301,"line":3335},[2166,28332,28333],{},"SELECT id, name, site_id, buyer, url, url2, start_date, end_date, status, reg_date\n",[2166,28335,28336],{"class":3301,"line":3342},[2166,28337,28338],{},"FROM tb_project WHERE id = {{PROJECT_ID}};\n",[2166,28340,28341],{"class":3301,"line":3368},[2166,28342,3339],{"emptyLinePlaceholder":3338},[2166,28344,28345],{"class":3301,"line":3396},[2166,28346,28347],{},"-- B2. 고객 측 주 담당자 (최근 90일 게시글 기준)\n",[2166,28349,28350],{"class":3301,"line":3426},[2166,28351,28352],{},"SELECT u.name, u.email, COUNT(*) post_cnt, MAX(p.reg_date) last_post\n",[2166,28354,28355],{"class":3301,"line":3463},[2166,28356,27070],{},[2166,28358,28359],{"class":3301,"line":3504},[2166,28360,27075],{},[2166,28362,28363],{"class":3301,"line":3538},[2166,28364,28365],{},"  AND (u.email IS NULL OR u.email NOT LIKE '%@malgnsoft.com')\n",[2166,28367,28368],{"class":3301,"line":3550},[2166,28369,28370],{},"  AND p.reg_date >= DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 90 DAY), '%Y%m%d000000')\n",[2166,28372,28373],{"class":3301,"line":3556},[2166,28374,28375],{},"GROUP BY u.name, u.email ORDER BY post_cnt DESC LIMIT 3;\n",[2166,28377,28378],{"class":3301,"line":5367},[2166,28379,3339],{"emptyLinePlaceholder":3338},[2166,28381,28382],{"class":3301,"line":5375},[2166,28383,28384],{},"-- B3. 맑소 측 담당 (최근 90일 댓글 기준)\n",[2166,28386,28387],{"class":3301,"line":5392},[2166,28388,28389],{},"SELECT u.name, u.email, COUNT(*) reply_cnt\n",[2166,28391,28392],{"class":3301,"line":5404},[2166,28393,27100],{},[2166,28395,28396],{"class":3301,"line":5415},[2166,28397,27105],{},[2166,28399,28400],{"class":3301,"line":5421},[2166,28401,28402],{},"  AND u.email LIKE '%@malgnsoft.com'\n",[2166,28404,28405],{"class":3301,"line":5432},[2166,28406,28407],{},"  AND c.reg_date >= DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 90 DAY), '%Y%m%d000000')\n",[2166,28409,28410],{"class":3301,"line":5453},[2166,28411,28412],{},"GROUP BY u.name, u.email ORDER BY reply_cnt DESC LIMIT 5;\n",[2166,28414,28415],{"class":3301,"line":5459},[2166,28416,3339],{"emptyLinePlaceholder":3338},[2166,28418,28419],{"class":3301,"line":8686},[2166,28420,28421],{},"-- B4. 최근 30일 활동\n",[2166,28423,28424],{"class":3301,"line":8692},[2166,28425,28426],{},"SELECT COUNT(*) recent_posts,\n",[2166,28428,28429],{"class":3301,"line":8698},[2166,28430,28431],{},"  SUM(p.comm_cnt = 0) AS no_reply,\n",[2166,28433,28434],{"class":3301,"line":8704},[2166,28435,28436],{},"  SUM(p.subject LIKE '%긴급%' OR p.subject LIKE '%★%') AS urgent\n",[2166,28438,28439],{"class":3301,"line":8710},[2166,28440,8605],{},[2166,28442,28443],{"class":3301,"line":8716},[2166,28444,27075],{},[2166,28446,28447],{"class":3301,"line":8721},[2166,28448,28449],{},"  AND p.reg_date >= DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 30 DAY), '%Y%m%d000000');\n",[2166,28451,28452],{"class":3301,"line":8727},[2166,28453,3339],{"emptyLinePlaceholder":3338},[2166,28455,28456],{"class":3301,"line":8733},[2166,28457,28458],{},"-- B5. 미해결\u002F주의 필요 글 (최근 우선) — 직원 응답 없음 OR 종결 멘트 없음 OR 24h+ 미응답\n",[2166,28460,28461],{"class":3301,"line":8739},[2166,28462,28463],{},"WITH last_comment AS (\n",[2166,28465,28466],{"class":3301,"line":8745},[2166,28467,28468],{},"  SELECT c.post_id,\n",[2166,28470,28471],{"class":3301,"line":8751},[2166,28472,28473],{},"    MAX(c.reg_date) last_reg,\n",[2166,28475,28476],{"class":3301,"line":8756},[2166,28477,28478],{},"    MAX(CASE WHEN u.email LIKE '%@malgnsoft.com' THEN c.reg_date END) AS last_staff_reg,\n",[2166,28480,28481],{"class":3301,"line":8762},[2166,28482,28483],{},"    MAX(c.content) last_content\n",[2166,28485,28486],{"class":3301,"line":8767},[2166,28487,28488],{},"  FROM tb_post_comment c LEFT JOIN tb_user u ON u.id = c.user_id\n",[2166,28490,28491],{"class":3301,"line":8773},[2166,28492,28493],{},"  WHERE c.status = 1\n",[2166,28495,28496],{"class":3301,"line":8779},[2166,28497,8713],{},[2166,28499,28500],{"class":3301,"line":8785},[2166,28501,4527],{},[2166,28503,28504],{"class":3301,"line":8791},[2166,28505,28506],{},"SELECT p.id, p.subject, p.writer, p.comm_cnt, p.reg_date,\n",[2166,28508,28509],{"class":3301,"line":8797},[2166,28510,28511],{},"  CASE\n",[2166,28513,28514],{"class":3301,"line":8803},[2166,28515,28516],{},"    WHEN p.comm_cnt = 0 THEN '미응답'\n",[2166,28518,28519],{"class":3301,"line":8809},[2166,28520,28521],{},"    WHEN lc.last_staff_reg IS NULL THEN '직원 응답 없음'\n",[2166,28523,28524],{"class":3301,"line":8815},[2166,28525,28526],{},"    WHEN lc.last_content NOT REGEXP '감사|확인했|잘 받았' THEN '종결 멘트 없음'\n",[2166,28528,28529],{"class":3301,"line":8821},[2166,28530,28531],{},"    ELSE NULL\n",[2166,28533,28534],{"class":3301,"line":8827},[2166,28535,28536],{},"  END AS flag\n",[2166,28538,28539],{"class":3301,"line":8832},[2166,28540,28541],{},"FROM tb_post p LEFT JOIN last_comment lc ON lc.post_id = p.id\n",[2166,28543,28544],{"class":3301,"line":8838},[2166,28545,27075],{},[2166,28547,28548],{"class":3301,"line":8844},[2166,28549,28550],{},"  AND p.reg_date >= DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 60 DAY), '%Y%m%d000000')\n",[2166,28552,28553],{"class":3301,"line":8849},[2166,28554,28555],{},"HAVING flag IS NOT NULL\n",[2166,28557,28558],{"class":3301,"line":8855},[2166,28559,28560],{},"ORDER BY p.reg_date DESC LIMIT 5;\n",[2166,28562,28563],{"class":3301,"line":8860},[2166,28564,3339],{"emptyLinePlaceholder":3338},[2166,28566,28567],{"class":3301,"line":8866},[2166,28568,28569],{},"-- B6. 최근 30일 카테고리 분포 (라벨 또는 키워드)\n",[2166,28571,28572],{"class":3301,"line":8871},[2166,28573,28574],{},"SELECT label, COUNT(*) cnt FROM tb_post\n",[2166,28576,28577],{"class":3301,"line":8877},[2166,28578,28579],{},"WHERE project_id = {{PROJECT_ID}} AND status = 1\n",[2166,28581,28582],{"class":3301,"line":8883},[2166,28583,28584],{},"  AND reg_date >= DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 30 DAY), '%Y%m%d000000')\n",[2166,28586,28587],{"class":3301,"line":8888},[2166,28588,28589],{},"  AND label IS NOT NULL AND label != ''\n",[2166,28591,28592],{"class":3301,"line":8894},[2166,28593,28594],{},"GROUP BY label ORDER BY cnt DESC LIMIT 5;\n",[2166,28596,28597],{"class":3301,"line":8899},[2166,28598,3339],{"emptyLinePlaceholder":3338},[2166,28600,28601],{"class":3301,"line":8905},[2166,28602,28603],{},"-- B7. 자주 묻는 주제 Top 5 (전체 기간, 제목 키워드)\n",[2166,28605,28606],{"class":3301,"line":8911},[2166,28607,28608],{},"SELECT '결제·납부' kw, COUNT(*) cnt FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND (subject LIKE '%결제%' OR subject LIKE '%납부%' OR subject LIKE '%계산서%')\n",[2166,28610,28611],{"class":3301,"line":8917},[2166,28612,27531],{},[2166,28614,28615],{"class":3301,"line":8923},[2166,28616,27520],{},[2166,28618,28619],{"class":3301,"line":8929},[2166,28620,28621],{},"UNION ALL SELECT 'SMS·메일', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND (subject LIKE '%SMS%' OR subject LIKE '%문자%' OR subject LIKE '%메일%')\n",[2166,28623,28624],{"class":3301,"line":8935},[2166,28625,28626],{},"UNION ALL SELECT '진도·수강·평가', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND (subject LIKE '%진도%' OR subject LIKE '%수강%' OR subject LIKE '%평가%' OR subject LIKE '%시험%')\n",[2166,28628,28629],{"class":3301,"line":8941},[2166,28630,28631],{},"UNION ALL SELECT '도메인·SSO·API', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND (subject LIKE '%도메인%' OR subject LIKE '%SSO%' OR subject LIKE '%API%')\n",[2166,28633,28634],{"class":3301,"line":8947},[2166,28635,28636],{},"UNION ALL SELECT '콘텐츠·영상·WBT', COUNT(*) FROM tb_post WHERE project_id={{PROJECT_ID}} AND status=1 AND (subject LIKE '%WBT%' OR subject LIKE '%콘텐츠%' OR subject LIKE '%컨텐츠%' OR subject LIKE '%영상%')\n",[2166,28638,28639],{"class":3301,"line":19135},[2166,28640,28641],{},"ORDER BY 2 DESC LIMIT 5;\n",[2166,28643,28644],{"class":3301,"line":19141},[2166,28645,3339],{"emptyLinePlaceholder":3338},[2166,28647,28648],{"class":3301,"line":19147},[2166,28649,28650],{},"-- B8. 이미 거절된 요청 (정책상 불가 답변이 달린 게시글)\n",[2166,28652,28653],{"class":3301,"line":19153},[2166,28654,28655],{},"SELECT p.id, p.subject, p.reg_date,\n",[2166,28657,28658],{"class":3301,"line":19159},[2166,28659,28660],{},"  SUBSTRING(REGEXP_REPLACE(c.content, '\u003C[^>]+>', ''), 1, 120) excerpt\n",[2166,28662,28663],{"class":3301,"line":19165},[2166,28664,28665],{},"FROM tb_post p JOIN tb_post_comment c ON c.post_id = p.id LEFT JOIN tb_user u ON u.id = c.user_id\n",[2166,28667,28668],{"class":3301,"line":19170},[2166,28669,27105],{},[2166,28671,28672],{"class":3301,"line":19175},[2166,28673,28402],{},[2166,28675,28676],{"class":3301,"line":19180},[2166,28677,28678],{},"  AND (c.content LIKE '%개발 어려%' OR c.content LIKE '%지원되지 않%' OR c.content LIKE '%제공되지 않%' OR c.content LIKE '%불가%' OR c.content LIKE '%규정상%')\n",[2166,28680,28681],{"class":3301,"line":19186},[2166,28682,28560],{},[2166,28684,28685],{"class":3301,"line":19192},[2166,28686,3339],{"emptyLinePlaceholder":3338},[2166,28688,28689],{"class":3301,"line":19198},[2166,28690,28691],{},"-- B9. 평균 FRT \u002F FCR (최근 90일)\n",[2166,28693,28694],{"class":3301,"line":19204},[2166,28695,28696],{},"SELECT ROUND(AVG(frt)\u002F60, 1) avg_hours FROM (\n",[2166,28698,28699],{"class":3301,"line":19209},[2166,28700,8806],{},[2166,28702,28703],{"class":3301,"line":19215},[2166,28704,8812],{},[2166,28706,28707],{"class":3301,"line":19221},[2166,28708,27236],{},[2166,28710,28711],{"class":3301,"line":19226},[2166,28712,28713],{},"  FROM tb_post p JOIN tb_post_comment c ON c.post_id = p.id LEFT JOIN tb_user u ON u.id = c.user_id\n",[2166,28715,28716],{"class":3301,"line":19231},[2166,28717,28718],{},"  WHERE p.project_id = {{PROJECT_ID}} AND p.status = 1 AND c.status = 1\n",[2166,28720,28721],{"class":3301,"line":19237},[2166,28722,8707],{},[2166,28724,28725],{"class":3301,"line":19243},[2166,28726,28727],{},"    AND p.reg_date >= DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 90 DAY), '%Y%m%d000000')\n",[2166,28729,28730],{"class":3301,"line":19249},[2166,28731,8835],{},[2166,28733,28734],{"class":3301,"line":19255},[2166,28735,27255],{},[36,28737,28739,28742],{"id":28738},"출력-양식-정확히-이-형식으로",[2166,28740,28741],{},"출력 양식"," — 정확히 이 형식으로",[415,28744,28747],{"className":28745,"code":28746,"language":420},[418],"┌─────────────────────────────────────────────────────────────────────────────┐\n│  {{PROJECT_NAME}}                                  {배지: ★우수\u002F⚠주의\u002F✕위험} │\n│  {프로젝트 유형}  ·  계약: {start_date} ~ {end_date or 진행}                 │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  👤 고객  {담당자명} ({이메일도메인} \u002F 직책 추정)                            │\n│  🛠 담당  PM {이름} · 기술 {이름} · {역할별 이름}                            │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  📨 최근 {RECENT_WINDOW}일  문의 {N}건 \u002F 평균 FRT {X}h \u002F 미응답 {N}건       │\n│  🔥 핫 카테고리 (최근 {RECENT_WINDOW}일)  {라벨1} {N} · {라벨2} {N} ...     │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  ⚠ 알림                                                                     │\n│   • {미해결\u002F미응답\u002F긴급 이슈, 최대 3건}                                      │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  📚 자주 묻는 주제 (참고)                                                    │\n│   1. {주제}                                                                  │\n│   2. {주제}                                                                  │\n│   3. {주제}                                                                  │\n│  🚫 이미 거절된 요청 (재문의 시 같은 답변)                                  │\n│   • {거절 이슈 요약} — {답변 일자} 안내 완료                                 │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  🔧 시스템 세팅 메모  (별도 등록된 메모가 있으면 표시, 없으면 생략)          │\n└─────────────────────────────────────────────────────────────────────────────┘\n",[16,28748,28746],{"__ignoreMap":423},[36,28750,28752],{"id":28751},"작성-규칙",[2166,28753,28754],{},"작성 규칙",[54,28756,28757,28763,28768,28773,28779,28789,28795,28801],{},[57,28758,28759,28762],{},[28,28760,28761],{},"분량",": 카드 한 장. 시스템 세팅 메모까지 포함해 약 20~25줄 이내.",[57,28764,28765,28767],{},[28,28766,27964],{},": 한국어. 격식체 유지.",[57,28769,28770,28772],{},[28,28771,27987],{},": 데이터에 없으면 해당 줄 자체를 생략. \"정보 없음\" 같은 빈 라인 출력 금지.",[57,28774,28775,28778],{},[28,28776,28777],{},"위험 알림 우선",": 미응답·긴급·정책 거절 후 재문의가 보이면 가장 위에.",[57,28780,28781,28784,28785,28788],{},[28,28782,28783],{},"고객 측 담당자 표기",": 이메일은 도메인만 표시 (예: ",[16,28786,28787],{},"@shai.or.kr",") — 전체 이메일 노출 금지.",[57,28790,28791,28794],{},[28,28792,28793],{},"거절 이슈",": B8 결과에서 거절 키워드 발견 시 1~2줄 요약. 본문 그대로 인용 금지(재해석).",[57,28796,28797,28800],{},[28,28798,28799],{},"누락",": 시스템 세팅 메모는 별도 메모가 등록된 경우에만. 자동 생성 금지.",[57,28802,28803,28806,28807],{},[28,28804,28805],{},"배지 규칙"," (헤더 우측):\n",[54,28808,28809,28815,28821,28827],{},[57,28810,28811,28814],{},[16,28812,28813],{},"★우수"," — 최근 30일 미응답 0건 & FRT 평균 \u003C 4h & 거절 후 재문의 0건",[57,28816,28817,28820],{},[16,28818,28819],{},"⚠주의"," — 미응답 1~2건 또는 종결 안 된 글 3건+ 또는 거절 재문의 1건+",[57,28822,28823,28826],{},[16,28824,28825],{},"✕위험"," — 미응답 3건+ 또는 24h+ 미응답 또는 긴급 미처리 또는 미수금\u002F계약 이슈",[57,28828,28829,28830,28833],{},"메모성 별도 배지(예: ",[16,28831,28832],{},"미수금",")는 추가 가능",[36,28835,28837],{"id":28836},"예시-출력",[2166,28838,28839],{},"예시 출력",[21,28841,28842],{},[24,28843,28844,28845,105,28848,105,28851],{},"입력: ",[16,28846,28847],{},"PROJECT_ID=1528",[16,28849,28850],{},"PROJECT_NAME=*안전보건진흥원",[16,28852,28853],{},"CURRENT_DATE=2026-05-18",[415,28855,28858],{"className":28856,"code":28857,"language":420},[418],"┌─────────────────────────────────────────────────────────────────────────────┐\n│  *안전보건진흥원                                              종료 프로젝트   │\n│  HRD 공공 + 다수 기업 B2B 교육 LMS  ·  계약: 종료 (2022-06 마지막 활동)      │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  👤 고객  고은비 (@shai.or.kr, 안전교육팀) — 1인 단독 컨택                   │\n│  🛠 담당  운영·회계 이영은 · 기술 김서연 · 정책 거절 엄정원·최종수            │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  📨 최근 30일  문의 0건 \u002F 평균 FRT 5h(과거 90일) \u002F 미응답 0건                │\n│  🔥 핫 카테고리 (역대)  SMS·메일 8 · SSO·API 7 · 도메인 7 · 수료증 4         │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  ⚠ 알림                                                                     │\n│   • 종료된 프로젝트 — 현행 정책·시스템과 다를 수 있음 (답변 시 주의)         │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  📚 자주 묻는 주제                                                           │\n│   1. 비즈뿌리오 SMS 발송·점검                                                │\n│   2. S-OIL\u002F알파코 SSO 연동                                                  │\n│   3. 도메인 포워딩·b2b 연동                                                  │\n│  🚫 이미 거절된 요청                                                         │\n│   • MP4 강의바 진도제어 — 미지원 (2022-06-23 안내, WBT로 우회)              │\n│   • 회원탈퇴 시 교육 데이터 자동 삭제 — 내부 규정상 개발 불가 (2022-06-24)  │\n└─────────────────────────────────────────────────────────────────────────────┘\n",[16,28859,28857],{"__ignoreMap":423},[33,28861],{},[11,28863,28865],{"id":28864},"구현-메모","§ 구현 메모",[54,28867,28868,28874,28880,28886,28892],{},[57,28869,28870,28873],{},[28,28871,28872],{},"실시간 호출",": 페이지 진입 시 매번 호출. 응답 캐시 5~15분 권장.",[57,28875,28876,28879],{},[28,28877,28878],{},"렌더링",": 텍스트 카드 또는 HTML 컴포넌트. 텍스트라면 위 박스 그대로, HTML이면 같은 정보 구조를 시각 컴포넌트로.",[57,28881,28882,28885],{},[28,28883,28884],{},"데이터 양",": 본 프롬프트의 9개 쿼리는 모두 짧음(LIMIT 5~10 + 집계). p95 응답 \u003C 1초 목표.",[57,28887,28888,28891],{},[28,28889,28890],{},"민감 정보",": 고객 이메일·연락처 전체값을 카드에 노출하지 말 것 — 도메인·뒷자리만.",[57,28893,28894,28897,28898,105,28901,105,28904,105,28907,105,28910,28913],{},[28,28895,28896],{},"거절 키워드",": B8의 패턴(",[16,28899,28900],{},"개발 어려",[16,28902,28903],{},"지원되지 않",[16,28905,28906],{},"제공되지 않",[16,28908,28909],{},"불가",[16,28911,28912],{},"규정상",")은 운영 결과로 보정 가능. 오탐 시 룰 갱신.",[11,28915,28098],{"id":2393},[54,28917,28918,28925,28932,28938],{},[57,28919,28920,28921],{},"장문 평가 프롬프트: ",[3257,28922,28923],{"href":28178},[16,28924,11383],{},[57,28926,28927,28928],{},"DB 정책: ",[3257,28929,28930],{"href":6359},[16,28931,6360],{},[57,28933,28934,28935,28937],{},"분류 규칙(메모리): ",[16,28936,128],{}," → 직원",[57,28939,8971,28940,2367,28944,28947],{},[3257,28941,28942],{"href":6980},[16,28943,6981],{},[28,28945,28946],{},"Phase 1 · 1.8 AI 추천 답변"," — 본 브리핑은 추천 답변의 진입 컨텍스트로도 사용",[4258,28949,8979],{},{"title":423,"searchDepth":3342,"depth":3342,"links":28951},[28952,28953,28954,28955,28956,28958,28960,28961],{"id":26836,"depth":3335,"text":26836},{"id":28201,"depth":3335,"text":28202},{"id":26884,"depth":3335,"text":26884},{"id":28289,"depth":3335,"text":5893},{"id":28312,"depth":3335,"text":28957},"데이터 수집 쿼리 — {{PROJECT_ID}}만 치환",{"id":28738,"depth":3335,"text":28959},"출력 양식 — 정확히 이 형식으로",{"id":28751,"depth":3335,"text":28754},{"id":28836,"depth":3335,"text":28839},{},"\u002Fprompts\u002Fcustomer-briefing",{"title":28158,"description":423},"prompts\u002Fcustomer-briefing","u8nuIcvjF4ZWTOyzmEoRUEx-VmemaZv_nX5VwvbLl2s",{"id":28968,"title":28969,"body":28970,"description":423,"extension":4340,"meta":30119,"navigation":3338,"path":30120,"seo":30121,"stem":30122,"__hash__":30123},"docs\u002Fprompts\u002Fqa-evaluation.md","단일 Q&A 요약·평가 프롬프트",{"type":8,"value":28971,"toc":30101},[28972,28975,29004,29006,29033,29035,29037,29047,29053,29057,29082,29086,29105,29112,29357,29363,29366,29370,29423,29427,29484,29488,29538,29542,29595,29599,29654,29660,29932,29936,30006,30011,30058,30060,30062,30099],[11,28973,28969],{"id":28974},"단일-qa-요약평가-프롬프트",[21,28976,28977,28984,28987],{},[24,28978,28979,28980],{},"게시판의 한 문의(post) + 답변(comment)에 대한 요약·5축 평가 보고서를 AI에게 생성시키기 위한 프롬프트.\n산출 예시: ",[3257,28981,28982],{"href":11318},[16,28983,11319],{},[24,28985,28986],{},"비교 — 다른 양식 프롬프트:",[54,28988,28989,28997],{},[57,28990,28991,28996],{},[3257,28992,28994],{"href":28993},"customer-briefing",[16,28995,10889],{},": 고객사(프로젝트) 단위 한 장 브리핑 카드",[57,28998,28999,29003],{},[3257,29000,29001],{"href":28178},[16,29002,11383],{},": 고객사(프로젝트) 단위 풀 평가 보고서",[36,29005,26836],{"id":26836},[1925,29007,29008,29012,29022,29024],{},[57,29009,20578,29010,26844],{},[28,29011,26843],{},[57,29013,26847,29014,4708,29016,29018,29019,29021],{},[16,29015,26850],{},[16,29017,26853],{}," 자리에 값 채움 (",[16,29020,11355],{},"만 필수).",[57,29023,26857],{},[57,29025,26860,29026,29029,29030,133],{},[16,29027,29028],{},"doc\u002Fexamples\u002Fqa-{{POST_ID}}-{슬러그}.md","로 저장 (예: ",[16,29031,29032],{},"qa-94227-사용자매뉴얼.md",[33,29034],{},[11,29036,26870],{"id":26869},[24,29038,26873,29039,29042,29043,29046],{},[28,29040,29041],{},"CS Q&A 품질 평가 보조 AI","입니다.\n게시판의 단일 문의(post) + 그에 달린 답변(comment) 한 건을 받아, ",[28,29044,29045],{},"요약 + 5축 평가 보고서","를 만드세요.",[24,29048,29049,29050,29052],{},"산출물은 마크다운, 표 위주. 측정되지 않은 항목은 추측하지 말고 ",[16,29051,26880],{},"으로 표기.",[36,29054,29055],{"id":26884},[2166,29056,26884],{},[54,29058,29059,29068,29074],{},[57,29060,29061,17678,29063,23847,29066,78],{},[16,29062,11355],{},[16,29064,29065],{},"{{POST_ID}}",[16,29067,9228],{},[57,29069,29070,17678,29072,26916],{},[16,29071,11358],{},[16,29073,26915],{},[57,29075,29076,17678,29078,29081],{},[16,29077,11362],{},[16,29079,29080],{},"{{COMMENT_ID}}"," (선택 — 게시글에 댓글이 여러 개일 때 특정 댓글 지정. 미지정 시 모두 또는 가장 의미 있는 댓글 자동 선택)",[36,29083,29084,26938],{"id":26935},[2166,29085,5893],{},[54,29087,29088,29094,29099,29102],{},[57,29089,29090,1358,29092],{},[16,29091,26947],{},[28,29093,28300],{},[57,29095,29096,29097],{},"그 외 도메인 → ",[28,29098,28306],{},[57,29100,29101],{},"이메일 NULL → 분류 불명 (별도 표기)",[57,29103,29104],{},"이름·게시판 패턴으로 추정 금지",[36,29106,29108,2448,29110,28318],{"id":29107},"데이터-수집-쿼리-post_id만-치환",[2166,29109,28315],{},[16,29111,29065],{},[415,29113,29115],{"className":8581,"code":29114,"language":8583,"meta":423,"style":423},"-- Q1. 게시글 메타·본문\nSELECT p.id, p.subject, p.writer, u.email AS writer_email,\n       pr.id AS project_id, pr.name AS project_name,\n       p.label, p.reg_date, p.comm_cnt, p.status,\n       REGEXP_REPLACE(p.content, '\u003C[^>]+>', '') AS body_clean,\n       CHAR_LENGTH(p.content) AS body_len\nFROM tb_post p\nJOIN tb_project pr ON pr.id = p.project_id\nLEFT JOIN tb_user u ON u.id = p.user_id\nWHERE p.id = {{POST_ID}};\n\n-- Q2. 댓글 전체 (시간순)\nSELECT c.id, c.writer, u.email AS writer_email,\n       c.private_yn, c.status, c.reg_date,\n       REGEXP_REPLACE(c.content, '\u003C[^>]+>', '') AS body_clean,\n       CHAR_LENGTH(c.content) AS body_len\nFROM tb_post_comment c LEFT JOIN tb_user u ON u.id = c.user_id\nWHERE c.post_id = {{POST_ID}}\nORDER BY c.reg_date;\n\n-- Q3. 타이밍 — FRT(분), 첫 직원 답변 지연(분), 총 해결 시간(시간)\nSELECT\n  STR_TO_DATE(p.reg_date,'%Y%m%d%H%i%s') AS post_at,\n  STR_TO_DATE(MIN(c.reg_date),'%Y%m%d%H%i%s') AS first_reply_at,\n  STR_TO_DATE(MAX(c.reg_date),'%Y%m%d%H%i%s') AS last_reply_at,\n  TIMESTAMPDIFF(MINUTE,\n    STR_TO_DATE(p.reg_date,'%Y%m%d%H%i%s'),\n    STR_TO_DATE(MIN(c.reg_date),'%Y%m%d%H%i%s')) AS frt_min,\n  TIMESTAMPDIFF(MINUTE,\n    STR_TO_DATE(p.reg_date,'%Y%m%d%H%i%s'),\n    STR_TO_DATE(MIN(CASE WHEN u.email LIKE '%@malgnsoft.com' THEN c.reg_date END),'%Y%m%d%H%i%s')) AS first_staff_reply_min,\n  TIMESTAMPDIFF(HOUR,\n    STR_TO_DATE(p.reg_date,'%Y%m%d%H%i%s'),\n    STR_TO_DATE(MAX(c.reg_date),'%Y%m%d%H%i%s')) AS ttr_hours\nFROM tb_post p\nLEFT JOIN tb_post_comment c ON c.post_id = p.id AND c.status = 1\nLEFT JOIN tb_user u ON u.id = c.user_id\nWHERE p.id = {{POST_ID}} GROUP BY p.id, p.reg_date;\n\n-- Q4. 첨부 파일 (게시글 + 댓글)\nSELECT f.id, f.module, f.module_id, f.realname, f.filetype,\n       ROUND(f.filesize\u002F1024, 1) AS size_kb\nFROM tb_post_file f\nWHERE f.status = 1\n  AND (\n    (f.module = 'post' AND f.module_id = {{POST_ID}})\n    OR (f.module = 'editor' AND f.module_id = {{POST_ID}})\n    OR (f.module = 'comment' AND f.module_id IN (\n        SELECT id FROM tb_post_comment WHERE post_id = {{POST_ID}}\n    ))\n  );\n",[16,29116,29117,29122,29126,29131,29136,29141,29146,29150,29154,29158,29163,29167,29172,29176,29181,29186,29191,29195,29200,29205,29209,29214,29218,29223,29228,29233,29238,29242,29247,29251,29255,29260,29265,29269,29274,29278,29283,29288,29293,29297,29302,29307,29312,29317,29322,29327,29332,29337,29342,29347,29352],{"__ignoreMap":423},[2166,29118,29119],{"class":3301,"line":3302},[2166,29120,29121],{},"-- Q1. 게시글 메타·본문\n",[2166,29123,29124],{"class":3301,"line":3335},[2166,29125,9795],{},[2166,29127,29128],{"class":3301,"line":3342},[2166,29129,29130],{},"       pr.id AS project_id, pr.name AS project_name,\n",[2166,29132,29133],{"class":3301,"line":3368},[2166,29134,29135],{},"       p.label, p.reg_date, p.comm_cnt, p.status,\n",[2166,29137,29138],{"class":3301,"line":3396},[2166,29139,29140],{},"       REGEXP_REPLACE(p.content, '\u003C[^>]+>', '') AS body_clean,\n",[2166,29142,29143],{"class":3301,"line":3426},[2166,29144,29145],{},"       CHAR_LENGTH(p.content) AS body_len\n",[2166,29147,29148],{"class":3301,"line":3463},[2166,29149,8605],{},[2166,29151,29152],{"class":3301,"line":3504},[2166,29153,9814],{},[2166,29155,29156],{"class":3301,"line":3538},[2166,29157,9819],{},[2166,29159,29160],{"class":3301,"line":3550},[2166,29161,29162],{},"WHERE p.id = {{POST_ID}};\n",[2166,29164,29165],{"class":3301,"line":3556},[2166,29166,3339],{"emptyLinePlaceholder":3338},[2166,29168,29169],{"class":3301,"line":5367},[2166,29170,29171],{},"-- Q2. 댓글 전체 (시간순)\n",[2166,29173,29174],{"class":3301,"line":5375},[2166,29175,9833],{},[2166,29177,29178],{"class":3301,"line":5392},[2166,29179,29180],{},"       c.private_yn, c.status, c.reg_date,\n",[2166,29182,29183],{"class":3301,"line":5404},[2166,29184,29185],{},"       REGEXP_REPLACE(c.content, '\u003C[^>]+>', '') AS body_clean,\n",[2166,29187,29188],{"class":3301,"line":5415},[2166,29189,29190],{},"       CHAR_LENGTH(c.content) AS body_len\n",[2166,29192,29193],{"class":3301,"line":5421},[2166,29194,9848],{},[2166,29196,29197],{"class":3301,"line":5432},[2166,29198,29199],{},"WHERE c.post_id = {{POST_ID}}\n",[2166,29201,29202],{"class":3301,"line":5453},[2166,29203,29204],{},"ORDER BY c.reg_date;\n",[2166,29206,29207],{"class":3301,"line":5459},[2166,29208,3339],{"emptyLinePlaceholder":3338},[2166,29210,29211],{"class":3301,"line":8686},[2166,29212,29213],{},"-- Q3. 타이밍 — FRT(분), 첫 직원 답변 지연(분), 총 해결 시간(시간)\n",[2166,29215,29216],{"class":3301,"line":8692},[2166,29217,8724],{},[2166,29219,29220],{"class":3301,"line":8698},[2166,29221,29222],{},"  STR_TO_DATE(p.reg_date,'%Y%m%d%H%i%s') AS post_at,\n",[2166,29224,29225],{"class":3301,"line":8704},[2166,29226,29227],{},"  STR_TO_DATE(MIN(c.reg_date),'%Y%m%d%H%i%s') AS first_reply_at,\n",[2166,29229,29230],{"class":3301,"line":8710},[2166,29231,29232],{},"  STR_TO_DATE(MAX(c.reg_date),'%Y%m%d%H%i%s') AS last_reply_at,\n",[2166,29234,29235],{"class":3301,"line":8716},[2166,29236,29237],{},"  TIMESTAMPDIFF(MINUTE,\n",[2166,29239,29240],{"class":3301,"line":8721},[2166,29241,8812],{},[2166,29243,29244],{"class":3301,"line":8727},[2166,29245,29246],{},"    STR_TO_DATE(MIN(c.reg_date),'%Y%m%d%H%i%s')) AS frt_min,\n",[2166,29248,29249],{"class":3301,"line":8733},[2166,29250,29237],{},[2166,29252,29253],{"class":3301,"line":8739},[2166,29254,8812],{},[2166,29256,29257],{"class":3301,"line":8745},[2166,29258,29259],{},"    STR_TO_DATE(MIN(CASE WHEN u.email LIKE '%@malgnsoft.com' THEN c.reg_date END),'%Y%m%d%H%i%s')) AS first_staff_reply_min,\n",[2166,29261,29262],{"class":3301,"line":8751},[2166,29263,29264],{},"  TIMESTAMPDIFF(HOUR,\n",[2166,29266,29267],{"class":3301,"line":8756},[2166,29268,8812],{},[2166,29270,29271],{"class":3301,"line":8762},[2166,29272,29273],{},"    STR_TO_DATE(MAX(c.reg_date),'%Y%m%d%H%i%s')) AS ttr_hours\n",[2166,29275,29276],{"class":3301,"line":8767},[2166,29277,8605],{},[2166,29279,29280],{"class":3301,"line":8773},[2166,29281,29282],{},"LEFT JOIN tb_post_comment c ON c.post_id = p.id AND c.status = 1\n",[2166,29284,29285],{"class":3301,"line":8779},[2166,29286,29287],{},"LEFT JOIN tb_user u ON u.id = c.user_id\n",[2166,29289,29290],{"class":3301,"line":8785},[2166,29291,29292],{},"WHERE p.id = {{POST_ID}} GROUP BY p.id, p.reg_date;\n",[2166,29294,29295],{"class":3301,"line":8791},[2166,29296,3339],{"emptyLinePlaceholder":3338},[2166,29298,29299],{"class":3301,"line":8797},[2166,29300,29301],{},"-- Q4. 첨부 파일 (게시글 + 댓글)\n",[2166,29303,29304],{"class":3301,"line":8803},[2166,29305,29306],{},"SELECT f.id, f.module, f.module_id, f.realname, f.filetype,\n",[2166,29308,29309],{"class":3301,"line":8809},[2166,29310,29311],{},"       ROUND(f.filesize\u002F1024, 1) AS size_kb\n",[2166,29313,29314],{"class":3301,"line":8815},[2166,29315,29316],{},"FROM tb_post_file f\n",[2166,29318,29319],{"class":3301,"line":8821},[2166,29320,29321],{},"WHERE f.status = 1\n",[2166,29323,29324],{"class":3301,"line":8827},[2166,29325,29326],{},"  AND (\n",[2166,29328,29329],{"class":3301,"line":8832},[2166,29330,29331],{},"    (f.module = 'post' AND f.module_id = {{POST_ID}})\n",[2166,29333,29334],{"class":3301,"line":8838},[2166,29335,29336],{},"    OR (f.module = 'editor' AND f.module_id = {{POST_ID}})\n",[2166,29338,29339],{"class":3301,"line":8844},[2166,29340,29341],{},"    OR (f.module = 'comment' AND f.module_id IN (\n",[2166,29343,29344],{"class":3301,"line":8849},[2166,29345,29346],{},"        SELECT id FROM tb_post_comment WHERE post_id = {{POST_ID}}\n",[2166,29348,29349],{"class":3301,"line":8855},[2166,29350,29351],{},"    ))\n",[2166,29353,29354],{"class":3301,"line":8860},[2166,29355,29356],{},"  );\n",[36,29358,29360],{"id":29359},"평가-프레임-5축",[2166,29361,29362],{},"평가 프레임 — 5축",[24,29364,29365],{},"각 축마다 점수 (★ 1~5) + 측정 근거 표.",[215,29367,29369],{"id":29368},"a-답변-정확성완결성","A. 답변 정확성·완결성",[135,29371,29372,29382],{},[138,29373,29374],{},[141,29375,29376,29379],{},[144,29377,29378],{},"체크 항목",[144,29380,29381],{},"측정 방법",[157,29383,29384,29391,29399,29407,29415],{},[141,29385,29386,29388],{},[162,29387,9373],{},[162,29389,29390],{},"답변 본문이 질문 의도를 해소했는가",[141,29392,29393,29396],{},[162,29394,29395],{},"이유·근거 설명",[162,29397,29398],{},"정책·규정·시스템 근거 제시 여부",[141,29400,29401,29404],{},[162,29402,29403],{},"대안·우회 제시",[162,29405,29406],{},"직접 답변 불가 시 대안 안내 여부",[141,29408,29409,29412],{},[162,29410,29411],{},"구체적 안내 (링크·경로·매뉴얼)",[162,29413,29414],{},"후속 액션 가능한 정보 포함 여부",[141,29416,29417,29420],{},[162,29418,29419],{},"출처 인용",[162,29421,29422],{},"매뉴얼\u002F정책 문서 링크 포함 여부",[215,29424,29426],{"id":29425},"b-응대-시간턴-효율성","B. 응대 시간·턴 효율성",[135,29428,29429,29437],{},[138,29430,29431],{},[141,29432,29433,29435],{},[144,29434,29378],{},[144,29436,29381],{},[157,29438,29439,29447,29461,29469,29476],{},[141,29440,29441,29444],{},[162,29442,29443],{},"FRT (First Response Time)",[162,29445,29446],{},"일반 첫 응답 시간 (분)",[141,29448,29449,29456],{},[162,29450,29451,29452,29455],{},"첫 ",[28,29453,29454],{},"직원"," 응답 시간",[162,29457,29458,29460],{},[16,29459,128],{}," 기준 첫 응답까지 분",[141,29462,29463,29466],{},[162,29464,29465],{},"FCR (단일 응답 종결)",[162,29467,29468],{},"직원 응답 1회로 종결 여부",[141,29470,29471,29473],{},[162,29472,9455],{},[162,29474,29475],{},"고객 측 추가 질의 여부",[141,29477,29478,29481],{},[162,29479,29480],{},"긴급 표기 여부",[162,29482,29483],{},"제목에 \"긴급\"\u002F\"★\" 포함 시 SLA 일치성",[215,29485,29487],{"id":29486},"c-톤친절도","C. 톤·친절도",[135,29489,29490,29498],{},[138,29491,29492],{},[141,29493,29494,29496],{},[144,29495,29378],{},[144,29497,29381],{},[157,29499,29500,29507,29515,29522,29530],{},[141,29501,29502,29504],{},[162,29503,9483],{},[162,29505,29506],{},"정형 응대 패턴 일관성",[141,29508,29509,29512],{},[162,29510,29511],{},"사과·공감 표현",[162,29513,29514],{},"\"죄송\", \"불편하시더라도\", \"양해\" 등",[141,29516,29517,29519],{},[162,29518,9503],{},[162,29520,29521],{},"고객의 다음 액션을 명확히 제시",[141,29523,29524,29527],{},[162,29525,29526],{},"부정문 사용 빈도",[162,29528,29529],{},"거절성 표현의 톤(완곡 vs 직설)",[141,29531,29532,29535],{},[162,29533,29534],{},"격식 일관성",[162,29536,29537],{},"공공\u002F대학\u002F기업별 톤 적합성",[215,29539,29541],{"id":29540},"d-표준답변화-가능성","D. 표준답변화 가능성",[135,29543,29544,29552],{},[138,29545,29546],{},[141,29547,29548,29550],{},[144,29549,29378],{},[144,29551,29381],{},[157,29553,29554,29562,29570,29578,29587],{},[141,29555,29556,29559],{},[162,29557,29558],{},"반복 가능성",[162,29560,29561],{},"다른 고객·다른 시점에도 동일 질의 예상 여부",[141,29563,29564,29567],{},[162,29565,29566],{},"정책 의존도",[162,29568,29569],{},"개별 고객 환경 무관한 일반 답변인가",[141,29571,29572,29575],{},[162,29573,29574],{},"시간 무관성",[162,29576,29577],{},"시스템·법령 변경 영향 적은가",[141,29579,29580,29584],{},[162,29581,29582],{},[28,29583,9601],{},[162,29585,29586],{},"비공개 답변이면 별도 공개판 필요",[141,29588,29589,29592],{},[162,29590,29591],{},"권장 표준답변 템플릿",[162,29593,29594],{},"1~3 단락 초안 작성",[215,29596,29598],{"id":29597},"e-챗봇-자동화-적합성-가시성","E. 챗봇 자동화 적합성 + 가시성",[135,29600,29601,29609],{},[138,29602,29603],{},[141,29604,29605,29607],{},[144,29606,29378],{},[144,29608,29381],{},[157,29610,29611,29618,29630,29638,29646],{},[141,29612,29613,29615],{},[162,29614,9566],{},[162,29616,29617],{},"정책성·일반화 가능 여부",[141,29619,29620,29627],{},[162,29621,29622],{},[28,29623,29624,29625,78],{},"가시성 (",[16,29626,20364],{},[162,29628,29629],{},"공개 \u002F 비공개 — Phase 2 챗봇 노출 가부 결정",[141,29631,29632,29635],{},[162,29633,29634],{},"거절성 답변 분류",[162,29636,29637],{},"\"불가\", \"지원하지 않음\" 등 정책 거절 패턴",[141,29639,29640,29643],{},[162,29641,29642],{},"민감 정보 포함",[162,29644,29645],{},"이메일·전화·내부 시스템명·고객사 식별정보",[141,29647,29648,29651],{},[162,29649,29650],{},"PII \u002F 보안 위험",[162,29652,29653],{},"마스킹 필요 항목 식별",[36,29655,29657,29659],{"id":29656},"출력-양식-정확히-이-구조",[2166,29658,28741],{}," — 정확히 이 구조",[415,29661,29665],{"className":29662,"code":29663,"language":29664,"meta":423,"style":423},"language-markdown shiki shiki-themes github-light github-dark","# Q&A 요약·평가 예시 — post {{POST_ID}} \"{제목}\"\n\n> (한 줄 설명)\n\n| 메타 | 값 |\n| --- | --- |\n| Post ID | **{{POST_ID}}** |\n| Project | {project_id} · `{project_name}` ({성격 요약}) |\n| 문의자 | {writer} (`{email_domain}` → 고객\u002F직원) |\n| 응대자 | {comment_writer} (`{email_domain}` → 고객\u002F직원) |\n| 일시 | 문의 {YYYY-MM-DD HH:MM} · 응답 {YYYY-MM-DD HH:MM} |\n| FRT | **{N분\u002F시}** |\n| 가시성 | 공개 \u002F **비공개** |\n| 분류 규칙 | `@malgnsoft.com` = 직원 · 그 외 = 고객\u002F협력사 |\n\n---\n\n## 1. 문의 본문\n\n> {정제된 본문 — HTML 제거}\n\n## 2. 답변 본문 ({공개\u002F비공개})\n\n> {정제된 답변 본문}\n\n## 3. 한 줄 요약\n\n> **{1~2 문장 요약 — 질의·답·결과}**\n\n---\n\n## 4. 평가 (5축)\n\n(범례, 그리고 §4-A ~ §4-E 각 5축의 표 + 평)\n\n## 5. 종합 점수표\n\n(★ × 5축 + 전체 평균)\n\n## 6. 후속 조치 권장\n\n(번호 매긴 액션 3~5개)\n\n## 7. 관찰 (선택)\n\n(비공개 패턴·정책 거절 일관성 등 발견 사항)\n\n## 8. 추출 쿼리 (재현용)\n\n(위 Q1·Q2 SQL)\n\n---\n\n## Cross-link\n\n- 정책: [LEGACY-DB-INVENTORY.md](..\u002FLEGACY-DB-INVENTORY.md) §6 (해당 시)\n- 평가 양식 (장문): [prompts\u002Fcs-evaluation.md](..\u002Fprompts\u002Fcs-evaluation.md)\n- 브리핑 카드 양식: [prompts\u002Fcustomer-briefing.md](..\u002Fprompts\u002Fcustomer-briefing.md)\n","markdown",[16,29666,29667,29672,29676,29681,29685,29690,29695,29700,29705,29710,29715,29720,29725,29730,29735,29739,29744,29748,29753,29757,29762,29766,29771,29775,29780,29784,29789,29793,29798,29802,29806,29810,29815,29819,29824,29828,29833,29837,29842,29846,29851,29855,29860,29864,29869,29873,29878,29882,29887,29891,29896,29900,29904,29908,29913,29917,29922,29927],{"__ignoreMap":423},[2166,29668,29669],{"class":3301,"line":3302},[2166,29670,29671],{},"# Q&A 요약·평가 예시 — post {{POST_ID}} \"{제목}\"\n",[2166,29673,29674],{"class":3301,"line":3335},[2166,29675,3339],{"emptyLinePlaceholder":3338},[2166,29677,29678],{"class":3301,"line":3342},[2166,29679,29680],{},"> (한 줄 설명)\n",[2166,29682,29683],{"class":3301,"line":3368},[2166,29684,3339],{"emptyLinePlaceholder":3338},[2166,29686,29687],{"class":3301,"line":3396},[2166,29688,29689],{},"| 메타 | 값 |\n",[2166,29691,29692],{"class":3301,"line":3426},[2166,29693,29694],{},"| --- | --- |\n",[2166,29696,29697],{"class":3301,"line":3463},[2166,29698,29699],{},"| Post ID | **{{POST_ID}}** |\n",[2166,29701,29702],{"class":3301,"line":3504},[2166,29703,29704],{},"| Project | {project_id} · `{project_name}` ({성격 요약}) |\n",[2166,29706,29707],{"class":3301,"line":3538},[2166,29708,29709],{},"| 문의자 | {writer} (`{email_domain}` → 고객\u002F직원) |\n",[2166,29711,29712],{"class":3301,"line":3550},[2166,29713,29714],{},"| 응대자 | {comment_writer} (`{email_domain}` → 고객\u002F직원) |\n",[2166,29716,29717],{"class":3301,"line":3556},[2166,29718,29719],{},"| 일시 | 문의 {YYYY-MM-DD HH:MM} · 응답 {YYYY-MM-DD HH:MM} |\n",[2166,29721,29722],{"class":3301,"line":5367},[2166,29723,29724],{},"| FRT | **{N분\u002F시}** |\n",[2166,29726,29727],{"class":3301,"line":5375},[2166,29728,29729],{},"| 가시성 | 공개 \u002F **비공개** |\n",[2166,29731,29732],{"class":3301,"line":5392},[2166,29733,29734],{},"| 분류 규칙 | `@malgnsoft.com` = 직원 · 그 외 = 고객\u002F협력사 |\n",[2166,29736,29737],{"class":3301,"line":5404},[2166,29738,3339],{"emptyLinePlaceholder":3338},[2166,29740,29741],{"class":3301,"line":5415},[2166,29742,29743],{},"---\n",[2166,29745,29746],{"class":3301,"line":5421},[2166,29747,3339],{"emptyLinePlaceholder":3338},[2166,29749,29750],{"class":3301,"line":5432},[2166,29751,29752],{},"## 1. 문의 본문\n",[2166,29754,29755],{"class":3301,"line":5453},[2166,29756,3339],{"emptyLinePlaceholder":3338},[2166,29758,29759],{"class":3301,"line":5459},[2166,29760,29761],{},"> {정제된 본문 — HTML 제거}\n",[2166,29763,29764],{"class":3301,"line":8686},[2166,29765,3339],{"emptyLinePlaceholder":3338},[2166,29767,29768],{"class":3301,"line":8692},[2166,29769,29770],{},"## 2. 답변 본문 ({공개\u002F비공개})\n",[2166,29772,29773],{"class":3301,"line":8698},[2166,29774,3339],{"emptyLinePlaceholder":3338},[2166,29776,29777],{"class":3301,"line":8704},[2166,29778,29779],{},"> {정제된 답변 본문}\n",[2166,29781,29782],{"class":3301,"line":8710},[2166,29783,3339],{"emptyLinePlaceholder":3338},[2166,29785,29786],{"class":3301,"line":8716},[2166,29787,29788],{},"## 3. 한 줄 요약\n",[2166,29790,29791],{"class":3301,"line":8721},[2166,29792,3339],{"emptyLinePlaceholder":3338},[2166,29794,29795],{"class":3301,"line":8727},[2166,29796,29797],{},"> **{1~2 문장 요약 — 질의·답·결과}**\n",[2166,29799,29800],{"class":3301,"line":8733},[2166,29801,3339],{"emptyLinePlaceholder":3338},[2166,29803,29804],{"class":3301,"line":8739},[2166,29805,29743],{},[2166,29807,29808],{"class":3301,"line":8745},[2166,29809,3339],{"emptyLinePlaceholder":3338},[2166,29811,29812],{"class":3301,"line":8751},[2166,29813,29814],{},"## 4. 평가 (5축)\n",[2166,29816,29817],{"class":3301,"line":8756},[2166,29818,3339],{"emptyLinePlaceholder":3338},[2166,29820,29821],{"class":3301,"line":8762},[2166,29822,29823],{},"(범례, 그리고 §4-A ~ §4-E 각 5축의 표 + 평)\n",[2166,29825,29826],{"class":3301,"line":8767},[2166,29827,3339],{"emptyLinePlaceholder":3338},[2166,29829,29830],{"class":3301,"line":8773},[2166,29831,29832],{},"## 5. 종합 점수표\n",[2166,29834,29835],{"class":3301,"line":8779},[2166,29836,3339],{"emptyLinePlaceholder":3338},[2166,29838,29839],{"class":3301,"line":8785},[2166,29840,29841],{},"(★ × 5축 + 전체 평균)\n",[2166,29843,29844],{"class":3301,"line":8791},[2166,29845,3339],{"emptyLinePlaceholder":3338},[2166,29847,29848],{"class":3301,"line":8797},[2166,29849,29850],{},"## 6. 후속 조치 권장\n",[2166,29852,29853],{"class":3301,"line":8803},[2166,29854,3339],{"emptyLinePlaceholder":3338},[2166,29856,29857],{"class":3301,"line":8809},[2166,29858,29859],{},"(번호 매긴 액션 3~5개)\n",[2166,29861,29862],{"class":3301,"line":8815},[2166,29863,3339],{"emptyLinePlaceholder":3338},[2166,29865,29866],{"class":3301,"line":8821},[2166,29867,29868],{},"## 7. 관찰 (선택)\n",[2166,29870,29871],{"class":3301,"line":8827},[2166,29872,3339],{"emptyLinePlaceholder":3338},[2166,29874,29875],{"class":3301,"line":8832},[2166,29876,29877],{},"(비공개 패턴·정책 거절 일관성 등 발견 사항)\n",[2166,29879,29880],{"class":3301,"line":8838},[2166,29881,3339],{"emptyLinePlaceholder":3338},[2166,29883,29884],{"class":3301,"line":8844},[2166,29885,29886],{},"## 8. 추출 쿼리 (재현용)\n",[2166,29888,29889],{"class":3301,"line":8849},[2166,29890,3339],{"emptyLinePlaceholder":3338},[2166,29892,29893],{"class":3301,"line":8855},[2166,29894,29895],{},"(위 Q1·Q2 SQL)\n",[2166,29897,29898],{"class":3301,"line":8860},[2166,29899,3339],{"emptyLinePlaceholder":3338},[2166,29901,29902],{"class":3301,"line":8866},[2166,29903,29743],{},[2166,29905,29906],{"class":3301,"line":8871},[2166,29907,3339],{"emptyLinePlaceholder":3338},[2166,29909,29910],{"class":3301,"line":8877},[2166,29911,29912],{},"## Cross-link\n",[2166,29914,29915],{"class":3301,"line":8883},[2166,29916,3339],{"emptyLinePlaceholder":3338},[2166,29918,29919],{"class":3301,"line":8888},[2166,29920,29921],{},"- 정책: [LEGACY-DB-INVENTORY.md](..\u002FLEGACY-DB-INVENTORY.md) §6 (해당 시)\n",[2166,29923,29924],{"class":3301,"line":8894},[2166,29925,29926],{},"- 평가 양식 (장문): [prompts\u002Fcs-evaluation.md](..\u002Fprompts\u002Fcs-evaluation.md)\n",[2166,29928,29929],{"class":3301,"line":8899},[2166,29930,29931],{},"- 브리핑 카드 양식: [prompts\u002Fcustomer-briefing.md](..\u002Fprompts\u002Fcustomer-briefing.md)\n",[36,29933,29934],{"id":28751},[2166,29935,28754],{},[54,29937,29938,29943,29948,29953,29959,29969,29981,29992,29998],{},[57,29939,29940,29942],{},[28,29941,27964],{},": 한국어. 격식체.",[57,29944,29945,29947],{},[28,29946,27975],{},": ★ 1~5 (5가 최고).",[57,29949,29950,29952],{},[28,29951,27981],{},": ✓ 양호 · ⚠ 주의 · ✕ 문제 · ㅡ 정보 부족.",[57,29954,29955,27988,29957,27991],{},[28,29956,27987],{},[16,29958,6471],{},[57,29960,29961,29964,29965,29968],{},[28,29962,29963],{},"이메일 도메인 분류",": 메타 표에 항상 ",[16,29966,29967],{},"@xxx.com → 고객\u002F직원"," 형태로 명시.",[57,29970,29971,4664,29974,10758,29977,29980],{},[28,29972,29973],{},"본문 인용 시 HTML 정제",[16,29975,29976],{},"\u003C[^>]+>",[16,29978,29979],{},"&nbsp;"," → 공백 + 줄바꿈 보존.",[57,29982,29983,29985,29986,105,29989,29991],{},[28,29984,21560],{},": 메타에 이메일 표시 시 도메인만 노출 (",[16,29987,29988],{},"@nate.com",[16,29990,128],{},"). 전체 이메일 노출 금지.",[57,29993,29994,29997],{},[28,29995,29996],{},"표준답변 템플릿"," (§4-D): 1~3 단락의 공개판 초안. 비공개 답변일수록 필수.",[57,29999,30000,4664,30002,30005],{},[28,30001,28023],{},[16,30003,30004],{},"doc\u002Fexamples\u002Fqa-{{POST_ID}}-{한국어슬러그}.md",". 슬러그는 게시글 제목의 핵심 키워드 (예: \"사용자매뉴얼\", \"회원탈퇴\").",[36,30007,30009],{"id":30008},"품질-체크리스트",[2166,30010,28045],{},[54,30012,30014,30019,30025,30031,30037,30043,30049],{"className":30013},[10401],[57,30015,30017,28055],{"className":30016},[10405],[10407,30018],{"disabled":3338,"type":10409},[57,30020,30022,30024],{"className":30021},[10405],[10407,30023],{"disabled":3338,"type":10409}," 문의·답변 본문이 정제된 텍스트 인용 (HTML 태그 제거)",[57,30026,30028,30030],{"className":30027},[10405],[10407,30029],{"disabled":3338,"type":10409}," 5축 모두 점수 + 측정 근거 표 포함",[57,30032,30034,30036],{"className":30033},[10405],[10407,30035],{"disabled":3338,"type":10409}," 종합 점수표 + 전체 평균",[57,30038,30040,30042],{"className":30039},[10405],[10407,30041],{"disabled":3338,"type":10409}," 비공개 답변일 경우 §4-E에서 명시 + §4-D에 공개판 템플릿",[57,30044,30046,30048],{"className":30045},[10405],[10407,30047],{"disabled":3338,"type":10409}," 후속 조치 3~5건 (구체적 액션)",[57,30050,30052,30054,30055,30057],{"className":30051},[10405],[10407,30053],{"disabled":3338,"type":10409}," 측정 안 된 항목은 ",[16,30056,6471],{},"로 표시",[33,30059],{},[11,30061,28098],{"id":2393},[54,30063,30064,30070,30076,30095],{},[57,30065,28103,30066],{},[3257,30067,30068],{"href":11318},[16,30069,11319],{},[57,30071,28111,30072],{},[3257,30073,30074],{"href":6359},[16,30075,26996],{},[57,30077,30078,30079],{},"다른 평가 프롬프트:\n",[54,30080,30081,30088],{},[57,30082,30083,30087],{},[3257,30084,30085],{"href":28993},[16,30086,10889],{}," — 1페이지 브리핑 카드 (프로젝트 단위)",[57,30089,30090,30094],{},[3257,30091,30092],{"href":28178},[16,30093,11383],{}," — 풀 평가 보고서 (프로젝트 단위)",[57,30096,28125,30097,9264],{},[16,30098,128],{},[4258,30100,8979],{},{"title":423,"searchDepth":3342,"depth":3342,"links":30102},[30103,30104,30105,30106,30108,30115,30117,30118],{"id":26836,"depth":3335,"text":26836},{"id":26884,"depth":3335,"text":26884},{"id":26935,"depth":3335,"text":28135},{"id":29107,"depth":3335,"text":30107},"데이터 수집 쿼리 — {{POST_ID}}만 치환",{"id":29359,"depth":3335,"text":29362,"children":30109},[30110,30111,30112,30113,30114],{"id":29368,"depth":3342,"text":29369},{"id":29425,"depth":3342,"text":29426},{"id":29486,"depth":3342,"text":29487},{"id":29540,"depth":3342,"text":29541},{"id":29597,"depth":3342,"text":29598},{"id":29656,"depth":3335,"text":30116},"출력 양식 — 정확히 이 구조",{"id":28751,"depth":3335,"text":28754},{"id":30008,"depth":3335,"text":28045},{},"\u002Fprompts\u002Fqa-evaluation",{"title":28969,"description":423},"prompts\u002Fqa-evaluation","Zlsr8OBGAd5pkif0W0qCX5ERrPM4w_4g-lf7-5TcTSg",{"id":30125,"title":47,"body":30126,"description":30340,"extension":4340,"meta":30341,"navigation":3338,"path":30342,"seo":30343,"stem":30344,"__hash__":30345},"docs\u002FREADME.md",{"type":8,"value":30127,"toc":30335},[30128,30130,30135,30138,30196,30200,30250,30252,30255,30259,30302,30305,30323,30332],[11,30129,47],{"id":47},[24,30131,30132,30133,407],{},"NotebookLM 수준의 사내 솔루션 전문 고객상담 AI 챗봇 — ",[28,30134,4373],{},[24,30136,30137],{},"워크스페이스 진입점. 전체 시스템은 4개 저장소로 구성된다.",[135,30139,30140,30149],{},[138,30141,30142],{},[141,30143,30144,30147],{},[144,30145,30146],{},"저장소",[144,30148,146],{},[157,30150,30151,30163,30174,30185],{},[141,30152,30153,30160],{},[162,30154,30155,30159],{},[3257,30156,47],{"href":30157,"rel":30158},"https:\u002F\u002Fgithub.com\u002Fmalgnsoft\u002Fmalgn-helper",[5049]," (이 저장소)",[162,30161,30162],{},"사용자 챗봇 프론트엔드 — Nuxt 3 \u002F Cloudflare Pages",[141,30164,30165,30171],{},[162,30166,30167],{},[3257,30168,18],{"href":30169,"rel":30170},"https:\u002F\u002Fgithub.com\u002Fmalgnsoft\u002Fmalgn-helper-admin",[5049],[162,30172,30173],{},"관리자 프론트엔드 (자료·표준답변·상담 로그)",[141,30175,30176,30182],{},[162,30177,30178],{},[3257,30179,4404],{"href":30180,"rel":30181},"https:\u002F\u002Fgithub.com\u002Fmalgnsoft\u002Fmalgn-helper-api",[5049],[162,30183,30184],{},"API 서버 — Hono on Cloudflare Workers",[141,30186,30187,30193],{},[162,30188,30189],{},[3257,30190,4588],{"href":30191,"rel":30192},"https:\u002F\u002Fgithub.com\u002Fmalgnsoft\u002Fmalgn-helper-pms",[5049],[162,30194,30195],{},"PMS 애드온 — 상담사용 추천 답변·문의 분석 도우미",[36,30197,30199],{"id":30198},"핵심-문서","핵심 문서",[54,30201,30202,30207,30214,30220,30227,30233,30239,30244],{},[57,30203,30204,30206],{},[3257,30205,9949],{"href":4907}," — 시스템 개요·인프라·작업 규칙",[57,30208,30209,30213],{},[3257,30210,30212],{"href":30211},"doc\u002FTECH-STACK","doc\u002FTECH-STACK.md"," — 기술 스택 정의",[57,30215,30216,30219],{},[3257,30217,10472],{"href":30218},"doc\u002FROADMAP"," — Phase 1·Phase 2 로드맵",[57,30221,30222,30226],{},[3257,30223,30225],{"href":30224},"doc\u002FWBS","doc\u002FWBS.md"," — 작업 분해 (WBS)",[57,30228,30229,30232],{},[3257,30230,26996],{"href":30231},"doc\u002FLEGACY-DB-INVENTORY"," — 레거시 PMS DB 인벤토리",[57,30234,30235,30238],{},[3257,30236,9184],{"href":30237},"doc\u002FPROJECT-INQUIRY-ANALYSIS"," — 업체별 문의 분석",[57,30240,30241,30243],{},[3257,30242,5788],{"href":5788}," — 업체별 케이스 스터디",[57,30245,30246,30249],{},[3257,30247,30248],{"href":30248},"doc\u002Fprompts\u002F"," — 재사용 평가·브리핑 프롬프트",[36,30251,23572],{"id":23572},[24,30253,30254],{},"Cloudflare (Pages + Workers + R2 + Hyperdrive + AI Gateway) · Aurora MySQL · AWS OpenSearch · Anthropic Claude.",[36,30256,30258],{"id":30257},"개발배포-사용자-챗봇-프론트엔드","개발·배포 (사용자 챗봇 프론트엔드)",[415,30260,30262],{"className":4632,"code":30261,"language":4634,"meta":423,"style":423},"pnpm install              # 의존성 설치\npnpm dev                  # 로컬 개발 (nuxt dev)\npnpm build                # 프로덕션 빌드\npnpm deploy               # Cloudflare Pages 배포 (.output\u002Fpublic)\n",[16,30263,30264,30274,30284,30293],{"__ignoreMap":423},[2166,30265,30266,30268,30271],{"class":3301,"line":3302},[2166,30267,4778],{"class":3309},[2166,30269,30270],{"class":3316}," install",[2166,30272,30273],{"class":3422},"              # 의존성 설치\n",[2166,30275,30276,30278,30281],{"class":3301,"line":3335},[2166,30277,4778],{"class":3309},[2166,30279,30280],{"class":3316}," dev",[2166,30282,30283],{"class":3422},"                  # 로컬 개발 (nuxt dev)\n",[2166,30285,30286,30288,30290],{"class":3301,"line":3342},[2166,30287,4778],{"class":3309},[2166,30289,26528],{"class":3316},[2166,30291,30292],{"class":3422},"                # 프로덕션 빌드\n",[2166,30294,30295,30297,30299],{"class":3301,"line":3368},[2166,30296,4778],{"class":3309},[2166,30298,26561],{"class":3316},[2166,30300,30301],{"class":3422},"               # Cloudflare Pages 배포 (.output\u002Fpublic)\n",[24,30303,30304],{},"최초 배포 전 Pages 프로젝트 생성 필요:",[415,30306,30308],{"className":4632,"code":30307,"language":4634,"meta":423,"style":423},"wrangler pages project create malgn-helper\n",[16,30309,30310],{"__ignoreMap":423},[2166,30311,30312,30314,30316,30318,30320],{"class":3301,"line":3302},[2166,30313,26207],{"class":3309},[2166,30315,26538],{"class":3316},[2166,30317,26541],{"class":3316},[2166,30319,26212],{"class":3316},[2166,30321,30322],{"class":3316}," malgn-helper\n",[24,30324,30325,394,30328,30331],{},[16,30326,30327],{},"wrangler login",[16,30329,30330],{},"CLOUDFLARE_API_TOKEN"," 환경변수 필요.",[4258,30333,30334],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":423,"searchDepth":3342,"depth":3342,"links":30336},[30337,30338,30339],{"id":30198,"depth":3335,"text":30199},{"id":23572,"depth":3335,"text":23572},{"id":30257,"depth":3335,"text":30258},"NotebookLM 수준의 사내 솔루션 전문 고객상담 AI 챗봇 — 사용자 프론트엔드.",{},"\u002Freadme",{"title":47,"description":30340},"README","cVw8m110qID8JAJnDCNTFem5BUSNx95BivR7jB1f_W4",{"id":30347,"title":30348,"body":30349,"description":423,"extension":4340,"meta":31981,"navigation":3338,"path":31982,"seo":31983,"stem":22076,"__hash__":31984},"docs\u002FROADMAP.md","단계별 로드맵",{"type":8,"value":30350,"toc":31937},[30351,30354,30375,30377,30381,30384,30392,30395,30440,30444,30455,30457,30461,30522,30527,30529,30533,30538,30544,30637,30646,30648,30652,30760,30762,30766,30772,30849,30851,30855,30860,30864,30919,30923,30994,30998,31019,31023,31050,31054,31081,31085,31124,31128,31161,31165,31207,31210,31231,31235,31256,31262,31264,31268,31276,31282,31309,31313,31340,31344,31380,31384,31411,31415,31442,31446,31473,31477,31498,31502,31523,31529,31531,31535,31538,31619,31622,31701,31703,31707,31709,31762,31765,31845,31847,31851,31878,31880,31884],[11,30352,30348],{"id":30353},"단계별-로드맵",[21,30355,30356,30359,30372],{},[24,30357,30358],{},"두 단계로 나누어 진행한다.",[54,30360,30361,30367],{},[57,30362,30363,30366],{},[28,30364,30365],{},"Phase 1",": CS 관리자 사이트 — 자료\u002F답변 수집 + AI 추천 답변 (상담사 보조)",[57,30368,30369,30371],{},[28,30370,3088],{},": CS 상담 챗봇 — 고객이 직접 챗봇과 대화 (완전 자동화 + 에스컬레이션)",[24,30373,30374],{},"Phase 1에서 쌓인 자료·표준 답변·피드백이 Phase 2의 품질을 결정한다.",[33,30376],{},[36,30378,30380],{"id":30379},"_1-비전과-목표","1. 비전과 목표",[215,30382,30383],{"id":30383},"비전",[21,30385,30386],{},[24,30387,30388,30391],{},[28,30389,30390],{},"NotebookLM 수준의 답변 품질을 가진, 자사 솔루션 전문 고객상담 AI.","\n상담사를 대체하기 전에 먼저 상담사를 강화하고, 검증된 자산이 충분히 쌓인 뒤 고객에게 직접 노출한다.",[215,30393,30394],{"id":30394},"목표",[135,30396,30397,30406],{},[138,30398,30399],{},[141,30400,30401,30404],{},[144,30402,30403],{},"구분",[144,30405,30394],{},[157,30407,30408,30416,30424,30432],{},[141,30409,30410,30413],{},[162,30411,30412],{},"사업",[162,30414,30415],{},"반복 문의 자동화로 상담 비용 절감, 24\u002F7 응답 채널 확보",[141,30417,30418,30421],{},[162,30419,30420],{},"품질",[162,30422,30423],{},"출처 인용이 포함된 정확·일관된 답변, 잘못된 안내 제로 지향",[141,30425,30426,30429],{},[162,30427,30428],{},"안전",[162,30430,30431],{},"추측 금지 — 모호하면 \"모름\" 후 상담사 에스컬레이션",[141,30433,30434,30437],{},[162,30435,30436],{},"자산화",[162,30438,30439],{},"상담사 채택\u002F수정 피드백을 표준 답변으로 환류하는 선순환",[215,30441,30443],{"id":30442},"비목표-non-goals","비목표 (Non-goals)",[54,30445,30446,30449,30452],{},[57,30447,30448],{},"Phase 1에서 고객 직접 노출 안 함 (상담사 보조에 한정)",[57,30450,30451],{},"일반 잡담\u002F범용 어시스턴트 아님 (자사 솔루션 도메인 한정)",[57,30453,30454],{},"MVP에서 동영상·대용량 비동기 인덱싱 미포함 (Phase 2 조건부)",[33,30456],{},[36,30458,30460],{"id":30459},"_2-현재-상태","2. 현재 상태",[135,30462,30463,30471],{},[138,30464,30465],{},[141,30466,30467,30469],{},[144,30468,4143],{},[144,30470,7333],{},[157,30472,30473,30483,30500,30514],{},[141,30474,30475,30477],{},[162,30476,2976],{},[162,30478,30479,30482],{},[28,30480,30481],{},"기획·설계 문서 작성"," (개발 착수 전)",[141,30484,30485,30488],{},[162,30486,30487],{},"산출물",[162,30489,30490,105,30493,105,30497,30499],{},[3257,30491,9949],{"href":30492},"..\u002FCLAUDE",[3257,30494,30496],{"href":30495},"TECH-STACK","TECH-STACK.md",[3257,30498,10422],{"href":24024},", 본 로드맵",[141,30501,30502,30505],{},[162,30503,30504],{},"코드",[162,30506,30507,1365,30509,1365,30511,30513],{},[16,30508,47],{},[16,30510,4608],{},[16,30512,4611],{}," 디렉토리 비어 있음",[141,30515,30516,30519],{},[162,30517,30518],{},"다음 액션",[162,30520,30521],{},"미결 결정(§9) 확정 → Phase 1 인프라(1.1) 착수",[21,30523,30524],{},[24,30525,30526],{},"기준일: 2026-05-18. 진행 시 본 표를 갱신한다.",[33,30528],{},[36,30530,30532],{"id":30531},"_3-타임라인","3. 타임라인",[21,30534,30535],{},[24,30536,30537],{},"실제 일정은 인원·미결 결정 확정 후 산정. 아래는 상대적 마일스톤 스캐폴드.",[415,30539,30542],{"className":30540,"code":30541,"language":420},[418],"Phase 1  ─────────────────────────────────────────────▶\n  M1 인프라 Ready ─ M2 자료\u002F표준답변 수집 ─ M3 검색 동작 ─ M4 AI 추천 GA\n                                                          │\n                                          (운영하며 자산 축적·미커버 분석)\n                                                          ▼\nPhase 2                                  ───────────────────────────────▶\n        M5 챗봇 Alpha(내부) ─ M6 챗봇 Beta(제한 고객) ─ M7 챗봇 GA\n",[16,30543,30541],{"__ignoreMap":423},[135,30545,30546,30559],{},[138,30547,30548],{},[141,30549,30550,30553,30556],{},[144,30551,30552],{},"마일스톤",[144,30554,30555],{},"정의",[144,30557,30558],{},"선행",[157,30560,30561,30571,30582,30593,30604,30615,30626],{},[141,30562,30563,30566,30569],{},[162,30564,30565],{},"M1 인프라 Ready",[162,30567,30568],{},"1.1~1.3 완료 (인프라·데이터모델·인증)",[162,30570,538],{},[141,30572,30573,30576,30579],{},[162,30574,30575],{},"M2 자료\u002F표준답변 수집",[162,30577,30578],{},"1.4~1.5 완료",[162,30580,30581],{},"M1",[141,30583,30584,30587,30590],{},[162,30585,30586],{},"M3 검색 동작",[162,30588,30589],{},"1.6~1.7 완료 (인덱싱·하이브리드 검색)",[162,30591,30592],{},"M2",[141,30594,30595,30598,30601],{},[162,30596,30597],{},"M4 AI 추천 GA",[162,30599,30600],{},"1.8~1.10 완료, Phase 1 완료 기준 충족",[162,30602,30603],{},"M3",[141,30605,30606,30609,30612],{},[162,30607,30608],{},"M5 챗봇 Alpha",[162,30610,30611],{},"2.1~2.3 완료 (내부 테스트)",[162,30613,30614],{},"M4 + 자산 축적",[141,30616,30617,30620,30623],{},[162,30618,30619],{},"M6 챗봇 Beta",[162,30621,30622],{},"2.4~2.6 완료 (제한 고객)",[162,30624,30625],{},"M5",[141,30627,30628,30631,30634],{},[162,30629,30630],{},"M7 챗봇 GA",[162,30632,30633],{},"2.8 완료, 필요 시 2.7 포함",[162,30635,30636],{},"M6",[21,30638,30639],{},[24,30640,30641,30642,30645],{},"M4 → M5 사이에 Phase 1을 ",[28,30643,30644],{},"실제 운영하며 자산을 쌓는 기간","을 반드시 둔다. 자산 부족 상태로 챗봇을 노출하지 않는다.",[33,30647],{},[36,30649,30651],{"id":30650},"_4-주요-에픽","4. 주요 에픽",[135,30653,30654,30665],{},[138,30655,30656],{},[141,30657,30658,30661,30663],{},[144,30659,30660],{},"에픽",[144,30662,1292],{},[144,30664,21165],{},[157,30666,30667,30678,30688,30698,30708,30719,30730,30740,30750],{},[141,30668,30669,30672,30675],{},[162,30670,30671],{},"E1. 기반 인프라",[162,30673,30674],{},"Cloudflare\u002FAurora\u002FOpenSearch\u002FAI Gateway 셋업 + 데이터 모델 + 인증",[162,30676,30677],{},"P1",[141,30679,30680,30683,30686],{},[162,30681,30682],{},"E2. 지식 수집",[162,30684,30685],{},"자료 업로드·Q&A 임포트·표준 답변 관리",[162,30687,30677],{},[141,30689,30690,30693,30696],{},[162,30691,30692],{},"E3. 검색·인덱싱",[162,30694,30695],{},"동기 인덱싱 + BM25·k-NN 하이브리드 + 표준답변 우선 매칭",[162,30697,30677],{},[141,30699,30700,30703,30706],{},[162,30701,30702],{},"E4. AI 추천 답변",[162,30704,30705],{},"추천 파이프라인 + 출처 인용 + 상담사 채택\u002F수정\u002F거절",[162,30707,30677],{},[141,30709,30710,30713,30716],{},[162,30711,30712],{},"E5. 피드백 선순환",[162,30714,30715],{},"채택 → 표준답변 후보화, 미커버 질문 분석",[162,30717,30718],{},"P1→P2",[141,30720,30721,30724,30727],{},[162,30722,30723],{},"E6. 사용자 챗봇",[162,30725,30726],{},"챗 UI·세션·스트리밍·신뢰도 가드",[162,30728,30729],{},"P2",[141,30731,30732,30735,30738],{},[162,30733,30734],{},"E7. 에스컬레이션",[162,30736,30737],{},"\"모름\" 분기 → 티켓 → 관리자 큐 → 채널 연동",[162,30739,30729],{},[141,30741,30742,30745,30748],{},[162,30743,30744],{},"E8. 안전·품질",[162,30746,30747],{},"PII\u002F금칙어\u002F환각 가드, 응답 평가, A\u002FB",[162,30749,30729],{},[141,30751,30752,30755,30758],{},[162,30753,30754],{},"E9. 운영·관측",[162,30756,30757],{},"비용·지표·알람, 인덱싱 확장(Queue)",[162,30759,30718],{},[33,30761],{},[36,30763,30765],{"id":30764},"_5-우선순위","5. 우선순위",[24,30767,30768,30769],{},"원칙: ",[28,30770,30771],{},"정확성·안전 > 자산 축적 > 자동화 범위 확대.",[135,30773,30774,30785],{},[138,30775,30776],{},[141,30777,30778,30781,30783],{},[144,30779,30780],{},"순위",[144,30782,4143],{},[144,30784,3932],{},[157,30786,30787,30798,30808,30818,30828,30838],{},[141,30788,30789,30792,30795],{},[162,30790,30791],{},"P0",[162,30793,30794],{},"E1 인프라, E3 검색, E4 AI 추천",[162,30796,30797],{},"Phase 1 핵심 가치. 없으면 제품 성립 안 됨",[141,30799,30800,30802,30805],{},[162,30801,30791],{},[162,30803,30804],{},"출처 인용 \u002F \"모름\" 정책",[162,30806,30807],{},"잘못된 안내 방지 — 타협 불가 요구사항",[141,30809,30810,30812,30815],{},[162,30811,30677],{},[162,30813,30814],{},"E2 지식 수집, E5 피드백 루프",[162,30816,30817],{},"답변 품질과 자산 축적의 토대",[141,30819,30820,30822,30825],{},[162,30821,30677],{},[162,30823,30824],{},"E7 에스컬레이션",[162,30826,30827],{},"챗봇 안전판. Phase 2 필수",[141,30829,30830,30832,30835],{},[162,30831,30729],{},[162,30833,30834],{},"E8 안전·품질 고도화, E9 관측",[162,30836,30837],{},"운영 성숙도. 점진 강화",[141,30839,30840,30843,30846],{},[162,30841,30842],{},"P3",[162,30844,30845],{},"2.7 인덱싱 확장(Queue)",[162,30847,30848],{},"동영상\u002F대용량 도입 시에만",[33,30850],{},[36,30852,30854],{"id":30853},"phase-1-cs-관리자-사이트-ai-추천-답변","Phase 1 — CS 관리자 사이트 + AI 추천 답변",[24,30856,30857,30859],{},[28,30858,30394],{},": 상담사가 들어온 문의에 답변할 때, AI가 출처가 명확한 추천 답변을 제시한다.\n상담사는 추천을 채택\u002F수정\u002F거절하고, 그 결과가 다시 학습 자산으로 쌓인다.",[215,30861,30863],{"id":30862},"_11-인프라기반-작업","1.1 인프라·기반 작업",[54,30865,30867,30873,30881,30889,30895,30901,30907,30913],{"className":30866},[10401],[57,30868,30870,30872],{"className":30869},[10405],[10407,30871],{"disabled":3338,"type":10409}," Cloudflare 계정 환경 분리 (dev \u002F staging \u002F prod)",[57,30874,30876,2367,30878,30880],{"className":30875},[10405],[10407,30877],{"disabled":3338,"type":10409},[16,30879,4404],{}," 초기화 (Hono on Workers)",[57,30882,30884,2367,30886,30888],{"className":30883},[10405],[10407,30885],{"disabled":3338,"type":10409},[16,30887,18],{}," 초기화 (Nuxt 3 on Pages)",[57,30890,30892,30894],{"className":30891},[10405],[10407,30893],{"disabled":3338,"type":10409}," Hyperdrive 바인딩 → Aurora MySQL 연결",[57,30896,30898,30900],{"className":30897},[10405],[10407,30899],{"disabled":3338,"type":10409}," R2 버킷 생성 (원본 파일용)",[57,30902,30904,30906],{"className":30903},[10405],[10407,30905],{"disabled":3338,"type":10409}," OpenSearch 도메인 프로비저닝 + 접근 정책",[57,30908,30910,30912],{"className":30909},[10405],[10407,30911],{"disabled":3338,"type":10409}," AI Gateway 설정 + Anthropic API 키 연결",[57,30914,30916,30918],{"className":30915},[10405],[10407,30917],{"disabled":3338,"type":10409}," 시크릿\u002F환경변수 정리 (Workers Secrets, Pages env)",[215,30920,30922],{"id":30921},"_12-데이터-모델-aurora","1.2 데이터 모델 (Aurora)",[54,30924,30926,30935,30944,30952,30961,30970,30979,30988],{"className":30925},[10401],[57,30927,30929,2367,30931,30934],{"className":30928},[10405],[10407,30930],{"disabled":3338,"type":10409},[16,30932,30933],{},"users"," (관리자\u002F상담사)",[57,30936,30938,2367,30940,30943],{"className":30937},[10405],[10407,30939],{"disabled":3338,"type":10409},[16,30941,30942],{},"documents"," (원본 자료 메타데이터, R2 키 참조)",[57,30945,30947,2367,30949,30951],{"className":30946},[10405],[10407,30948],{"disabled":3338,"type":10409},[16,30950,21683],{}," (청크 본문 + OpenSearch 도큐먼트 id)",[57,30953,30955,2367,30957,30960],{"className":30954},[10405],[10407,30956],{"disabled":3338,"type":10409},[16,30958,30959],{},"standard_answers"," (표준 답변 본문, 분류, 상태)",[57,30962,30964,2367,30966,30969],{"className":30963},[10405],[10407,30965],{"disabled":3338,"type":10409},[16,30967,30968],{},"inquiries"," (들어온 문의)",[57,30971,30973,2367,30975,30978],{"className":30972},[10405],[10407,30974],{"disabled":3338,"type":10409},[16,30976,30977],{},"ai_suggestions"," (문의별 AI 추천 답변, 출처, 신뢰도)",[57,30980,30982,2367,30984,30987],{"className":30981},[10405],[10407,30983],{"disabled":3338,"type":10409},[16,30985,30986],{},"agent_responses"," (상담사 최종 답변, 채택\u002F수정 여부, 피드백)",[57,30989,30991,30993],{"className":30990},[10405],[10407,30992],{"disabled":3338,"type":10409}," 마이그레이션 도구 선정·도입",[215,30995,30997],{"id":30996},"_13-인증권한","1.3 인증·권한",[54,30999,31001,31007,31013],{"className":31000},[10401],[57,31002,31004,31006],{"className":31003},[10405],[10407,31005],{"disabled":3338,"type":10409}," 관리자 로그인 (사내 SSO \u002F 자체 계정 중 결정)",[57,31008,31010,31012],{"className":31009},[10405],[10407,31011],{"disabled":3338,"type":10409}," 역할 분리: admin(자료\u002F표준답변 관리), agent(상담)",[57,31014,31016,31018],{"className":31015},[10405],[10407,31017],{"disabled":3338,"type":10409}," API 토큰\u002F세션 처리",[215,31020,31022],{"id":31021},"_14-자료-수집-기능-관리자","1.4 자료 수집 기능 (관리자)",[54,31024,31026,31032,31038,31044],{"className":31025},[10401],[57,31027,31029,31031],{"className":31028},[10405],[10407,31030],{"disabled":3338,"type":10409}," 매뉴얼\u002F문서 업로드 UI (PDF, DOCX, 텍스트 등)",[57,31033,31035,31037],{"className":31034},[10405],[10407,31036],{"disabled":3338,"type":10409}," 기존 Q&A 일괄 가져오기 (CSV\u002F엑셀)",[57,31039,31041,31043],{"className":31040},[10405],[10407,31042],{"disabled":3338,"type":10409}," 자료 목록·검색·태그",[57,31045,31047,31049],{"className":31046},[10405],[10407,31048],{"disabled":3338,"type":10409}," 자료 삭제·버전 관리(최소한 갱신 시 재인덱싱)",[215,31051,31053],{"id":31052},"_15-표준-답변-관리","1.5 표준 답변 관리",[54,31055,31057,31063,31069,31075],{"className":31056},[10401],[57,31058,31060,31062],{"className":31059},[10405],[10407,31061],{"disabled":3338,"type":10409}," 표준 답변 작성 화면 (질문 패턴 + 답변 본문 + 출처 링크)",[57,31064,31066,31068],{"className":31065},[10405],[10407,31067],{"disabled":3338,"type":10409}," 검토·승인 워크플로 (draft → review → published)",[57,31070,31072,31074],{"className":31071},[10405],[10407,31073],{"disabled":3338,"type":10409}," 분류·태그",[57,31076,31078,31080],{"className":31077},[10405],[10407,31079],{"disabled":3338,"type":10409}," 비활성화\u002F만료 처리",[215,31082,31084],{"id":31083},"_16-인덱싱-파이프라인-동기-mvp","1.6 인덱싱 파이프라인 (동기 \u002F MVP)",[54,31086,31088,31094,31100,31106,31112,31118],{"className":31087},[10401],[57,31089,31091,31093],{"className":31090},[10405],[10407,31092],{"disabled":3338,"type":10409}," 텍스트 추출기 (PDF → 텍스트)",[57,31095,31097,31099],{"className":31096},[10405],[10407,31098],{"disabled":3338,"type":10409}," 청킹 로직 (크기\u002F오버랩 파라미터화)",[57,31101,31103,31105],{"className":31102},[10405],[10407,31104],{"disabled":3338,"type":10409}," 임베딩 생성 (모델 선정 필요)",[57,31107,31109,31111],{"className":31108},[10405],[10407,31110],{"disabled":3338,"type":10409}," OpenSearch upsert (BM25 필드 + 벡터 필드)",[57,31113,31115,31117],{"className":31114},[10405],[10407,31116],{"disabled":3338,"type":10409}," 재인덱싱 트리거 (자료\u002F표준 답변 갱신 시)",[57,31119,31121,31123],{"className":31120},[10405],[10407,31122],{"disabled":3338,"type":10409}," 인덱싱 상태 표시 (관리자 화면)",[215,31125,31127],{"id":31126},"_17-검색","1.7 검색",[54,31129,31131,31137,31143,31149,31155],{"className":31130},[10401],[57,31132,31134,31136],{"className":31133},[10405],[10407,31135],{"disabled":3338,"type":10409}," BM25 쿼리 빌더",[57,31138,31140,31142],{"className":31139},[10405],[10407,31141],{"disabled":3338,"type":10409}," k-NN 벡터 검색",[57,31144,31146,31148],{"className":31145},[10405],[10407,31147],{"disabled":3338,"type":10409}," 하이브리드 결합 (RRF 또는 가중치 합산)",[57,31150,31152,31154],{"className":31151},[10405],[10407,31153],{"disabled":3338,"type":10409}," 표준 답변 우선 매칭 로직",[57,31156,31158,31160],{"className":31157},[10405],[10407,31159],{"disabled":3338,"type":10409}," 결과 디버깅 뷰 (관리자가 검색 결과\u002F스코어 확인)",[215,31162,31164],{"id":31163},"_18-ai-추천-답변-핵심-기능","1.8 AI 추천 답변 (핵심 기능)",[54,31166,31168,31174,31180,31186,31192,31201],{"className":31167},[10401],[57,31169,31171,31173],{"className":31170},[10405],[10407,31172],{"disabled":3338,"type":10409}," 문의 입력 화면 (상담사가 받은 질문을 붙여 넣음)",[57,31175,31177,31179],{"className":31176},[10405],[10407,31178],{"disabled":3338,"type":10409}," 파이프라인: 표준 답변 매칭 → 하이브리드 검색 → Claude 호출",[57,31181,31183,31185],{"className":31182},[10405],[10407,31184],{"disabled":3338,"type":10409}," 출처 인용을 응답에 포함 (필수)",[57,31187,31189,31191],{"className":31188},[10405],[10407,31190],{"disabled":3338,"type":10409}," 신뢰도\u002F근거 수준 표시",[57,31193,31195,31197,31198],{"className":31194},[10405],[10407,31196],{"disabled":3338,"type":10409}," 상담사 액션: ",[28,31199,31200],{},"채택 \u002F 수정 후 사용 \u002F 거절(이유)",[57,31202,31204,31206],{"className":31203},[10405],[10407,31205],{"disabled":3338,"type":10409}," 채택\u002F수정 결과 저장 → 학습 자산화",[215,31208,6984],{"id":31209},"_19-피드백-루프",[54,31211,31213,31219,31225],{"className":31212},[10401],[57,31214,31216,31218],{"className":31215},[10405],[10407,31217],{"disabled":3338,"type":10409}," 자주 채택된 답변 → 표준 답변 후보로 자동 추천",[57,31220,31222,31224],{"className":31221},[10405],[10407,31223],{"disabled":3338,"type":10409}," 거절 사유 통계 (자료 부족? 답변 부정확? 정책 위반?)",[57,31226,31228,31230],{"className":31227},[10405],[10407,31229],{"disabled":3338,"type":10409}," 미커버 질문 목록 (검색 hit 낮음 \u002F 신뢰도 낮음)",[215,31232,31234],{"id":31233},"_110-운영","1.10 운영",[54,31236,31238,31244,31250],{"className":31237},[10401],[57,31239,31241,31243],{"className":31240},[10405],[10407,31242],{"disabled":3338,"type":10409}," AI Gateway 사용량\u002F비용 대시보드",[57,31245,31247,31249],{"className":31246},[10405],[10407,31248],{"disabled":3338,"type":10409}," LLM 호출 로깅 (요청·응답·토큰)",[57,31251,31253,31255],{"className":31252},[10405],[10407,31254],{"disabled":3338,"type":10409}," 에러 알림 (인덱싱 실패, LLM 실패)",[24,31257,31258,31261],{},[28,31259,31260],{},"Phase 1 완료 기준",": 상담사가 관리자 사이트에서 문의를 받아 AI 추천 답변을 보고 채택\u002F수정해 응답을 보낼 수 있다. 자료·표준 답변·피드백이 DB에 쌓이고 있다.",[33,31263],{},[36,31265,31267],{"id":31266},"phase-2-cs-상담-챗봇-고객-직접-대화","Phase 2 — CS 상담 챗봇 (고객 직접 대화)",[24,31269,31270,31272,31273,31275],{},[28,31271,30394],{},": 고객이 ",[16,31274,47],{}," 챗봇과 직접 대화한다.\nPhase 1에서 검증된 자료·표준 답변·답변 정책을 그대로 활용하되, \"모르면 모른다\" 원칙으로 상담사에게 안전하게 넘긴다.",[215,31277,31279,31280,78],{"id":31278},"_21-사용자-프론트엔드-malgn-helper","2.1 사용자 프론트엔드 (",[16,31281,47],{},[54,31283,31285,31291,31297,31303],{"className":31284},[10401],[57,31286,31288,31290],{"className":31287},[10405],[10407,31289],{"disabled":3338,"type":10409}," Nuxt 3 초기화 및 Cloudflare Pages 배포",[57,31292,31294,31296],{"className":31293},[10405],[10407,31295],{"disabled":3338,"type":10409}," 챗 UI (스트리밍, 마크다운, 출처 카드)",[57,31298,31300,31302],{"className":31299},[10405],[10407,31301],{"disabled":3338,"type":10409}," 세션 유지 \u002F 익명 여부 정책",[57,31304,31306,31308],{"className":31305},[10405],[10407,31307],{"disabled":3338,"type":10409}," 모바일 반응형",[215,31310,31312],{"id":31311},"_22-챗-세션메시지","2.2 챗 세션·메시지",[54,31314,31316,31328,31334],{"className":31315},[10401],[57,31317,31319,2367,31321,105,31324,31327],{"className":31318},[10405],[10407,31320],{"disabled":3338,"type":10409},[16,31322,31323],{},"chat_sessions",[16,31325,31326],{},"chat_messages"," 테이블",[57,31329,31331,31333],{"className":31330},[10405],[10407,31332],{"disabled":3338,"type":10409}," 세션 컨텍스트 관리 (최근 N턴)",[57,31335,31337,31339],{"className":31336},[10405],[10407,31338],{"disabled":3338,"type":10409}," 사용자 메타데이터(있다면) 연동",[215,31341,31343],{"id":31342},"_23-챗봇-답변-파이프라인","2.3 챗봇 답변 파이프라인",[54,31345,31347,31353,31359,31365,31371],{"className":31346},[10401],[57,31348,31350,31352],{"className":31349},[10405],[10407,31351],{"disabled":3338,"type":10409}," 표준 답변 매칭 → hit 시 즉시 반환 (Phase 1 자산 재사용)",[57,31354,31356,31358],{"className":31355},[10405],[10407,31357],{"disabled":3338,"type":10409}," 하이브리드 검색 → 컨텍스트 구성",[57,31360,31362,31364],{"className":31361},[10405],[10407,31363],{"disabled":3338,"type":10409}," Claude 스트리밍 응답 + 출처 인용",[57,31366,31368,31370],{"className":31367},[10405],[10407,31369],{"disabled":3338,"type":10409}," 프롬프트 캐싱(시스템 프롬프트, 표준 답변 카탈로그)",[57,31372,31374,2367,31376,31379],{"className":31373},[10405],[10407,31375],{"disabled":3338,"type":10409},[28,31377,31378],{},"신뢰도 가드",": 근거 부족 \u002F 모호 → \"모름\" 응답으로 분기",[215,31381,31383],{"id":31382},"_24-에스컬레이션","2.4 에스컬레이션",[54,31385,31387,31393,31399,31405],{"className":31386},[10401],[57,31388,31390,31392],{"className":31389},[10405],[10407,31391],{"disabled":3338,"type":10409}," \"상담사 연결\" 버튼\u002F플로우",[57,31394,31396,31398],{"className":31395},[10405],[10407,31397],{"disabled":3338,"type":10409}," 에스컬레이션 티켓 생성 → 관리자 큐",[57,31400,31402,31404],{"className":31401},[10405],[10407,31403],{"disabled":3338,"type":10409}," 채널 결정 (인앱 \u002F 이메일 \u002F Slack)",[57,31406,31408,31410],{"className":31407},[10405],[10407,31409],{"disabled":3338,"type":10409}," SLA·우선순위 정책",[215,31412,31414],{"id":31413},"_25-관리자-측-확장","2.5 관리자 측 확장",[54,31416,31418,31424,31430,31436],{"className":31417},[10401],[57,31419,31421,31423],{"className":31420},[10405],[10407,31422],{"disabled":3338,"type":10409}," 챗 로그 열람·검색",[57,31425,31427,31429],{"className":31426},[10405],[10407,31428],{"disabled":3338,"type":10409}," 에스컬레이션 큐 처리 화면",[57,31431,31433,31435],{"className":31432},[10405],[10407,31434],{"disabled":3338,"type":10409}," 챗봇 미커버 질문 자동 수집 → 표준 답변 후보화 (Phase 1 루프 확장)",[57,31437,31439,31441],{"className":31438},[10405],[10407,31440],{"disabled":3338,"type":10409}," 챗봇 응답 품질 리뷰 (샘플링)",[215,31443,31445],{"id":31444},"_26-안전품질","2.6 안전·품질",[54,31447,31449,31455,31461,31467],{"className":31448},[10401],[57,31450,31452,31454],{"className":31451},[10405],[10407,31453],{"disabled":3338,"type":10409}," 금칙어\u002FPII 필터",[57,31456,31458,31460],{"className":31457},[10405],[10407,31459],{"disabled":3338,"type":10409}," 환각 가드 (출처 없는 응답 차단 정책)",[57,31462,31464,31466],{"className":31463},[10405],[10407,31465],{"disabled":3338,"type":10409}," 응답 평가(좋아요\u002F싫어요) 수집",[57,31468,31470,31472],{"className":31469},[10405],[10407,31471],{"disabled":3338,"type":10409}," A\u002FB (프롬프트\u002F검색 파라미터)",[215,31474,31476],{"id":31475},"_27-인덱싱-확장-필요-시","2.7 인덱싱 확장 (필요 시)",[54,31478,31480,31486,31492],{"className":31479},[10401],[57,31481,31483,31485],{"className":31482},[10405],[10407,31484],{"disabled":3338,"type":10409}," 동영상 자료 도입 → Queue + Indexer Worker 비동기 파이프라인 추가",[57,31487,31489,31491],{"className":31488},[10405],[10407,31490],{"disabled":3338,"type":10409}," 대용량 PDF 분할 처리",[57,31493,31495,31497],{"className":31494},[10405],[10407,31496],{"disabled":3338,"type":10409}," 인덱싱 진행률·재시도 UI",[215,31499,31501],{"id":31500},"_28-운영관측","2.8 운영·관측",[54,31503,31505,31511,31517],{"className":31504},[10401],[57,31506,31508,31510],{"className":31507},[10405],[10407,31509],{"disabled":3338,"type":10409}," 챗 응답 시간\u002F실패율 지표",[57,31512,31514,31516],{"className":31513},[10405],[10407,31515],{"disabled":3338,"type":10409}," 비용 모니터링 (토큰·임베딩·OpenSearch)",[57,31518,31520,31522],{"className":31519},[10405],[10407,31521],{"disabled":3338,"type":10409}," 알람 (응답 실패, 에스컬레이션 적체)",[24,31524,31525,31528],{},[28,31526,31527],{},"Phase 2 완료 기준",": 고객이 챗봇과 대화해 답변을 받거나, 모호한 경우 상담사 에스컬레이션으로 안전하게 빠진다. Phase 1의 피드백 루프가 챗봇 데이터까지 자연스럽게 확장되어 있다.",[33,31530],{},[36,31532,31534],{"id":31533},"_6-성공지표-kpi","6. 성공지표 (KPI)",[215,31536,30365],{"id":31537},"phase-1",[135,31539,31540,31551],{},[138,31541,31542],{},[141,31543,31544,31546,31548],{},[144,31545,22711],{},[144,31547,30555],{},[144,31549,31550],{},"목표(초기)",[157,31552,31553,31564,31575,31586,31597,31608],{},[141,31554,31555,31558,31561],{},[162,31556,31557],{},"추천 채택률",[162,31559,31560],{},"상담사가 AI 추천을 (수정 포함) 사용한 비율",[162,31562,31563],{},"≥ 60%",[141,31565,31566,31569,31572],{},[162,31567,31568],{},"무수정 채택률",[162,31570,31571],{},"수정 없이 그대로 채택한 비율",[162,31573,31574],{},"≥ 30%",[141,31576,31577,31580,31583],{},[162,31578,31579],{},"인용 정확도",[162,31581,31582],{},"추천 답변의 출처가 실제 근거와 일치하는 비율",[162,31584,31585],{},"≥ 95%",[141,31587,31588,31591,31594],{},[162,31589,31590],{},"잘못된 안내",[162,31592,31593],{},"사실과 다른 답변 발생 건수",[162,31595,31596],{},"0건 지향",[141,31598,31599,31602,31605],{},[162,31600,31601],{},"응답 생성 시간",[162,31603,31604],{},"문의 입력 → 추천 표시 (p95)",[162,31606,31607],{},"≤ 8초",[141,31609,31610,31613,31616],{},[162,31611,31612],{},"자산 축적",[162,31614,31615],{},"표준 답변 수 \u002F 커버된 질문 유형",[162,31617,31618],{},"지속 증가",[215,31620,3088],{"id":31621},"phase-2",[135,31623,31624,31634],{},[138,31625,31626],{},[141,31627,31628,31630,31632],{},[144,31629,22711],{},[144,31631,30555],{},[144,31633,31550],{},[157,31635,31636,31647,31658,31669,31679,31690],{},[141,31637,31638,31641,31644],{},[162,31639,31640],{},"자동 응답 해결률",[162,31642,31643],{},"에스컬레이션 없이 종료된 대화 비율",[162,31645,31646],{},"≥ 50%",[141,31648,31649,31652,31655],{},[162,31650,31651],{},"에스컬레이션 정확도",[162,31653,31654],{},"\"모름\" 분기가 실제로 답할 수 없던 경우 비율",[162,31656,31657],{},"≥ 90%",[141,31659,31660,31663,31666],{},[162,31661,31662],{},"사용자 만족",[162,31664,31665],{},"응답 좋아요 비율",[162,31667,31668],{},"≥ 80%",[141,31670,31671,31674,31677],{},[162,31672,31673],{},"환각 발생",[162,31675,31676],{},"출처 없는 단정적 답변 건수",[162,31678,31596],{},[141,31680,31681,31684,31687],{},[162,31682,31683],{},"챗 응답 지연",[162,31685,31686],{},"첫 토큰까지 시간 (p95)",[162,31688,31689],{},"≤ 3초",[141,31691,31692,31695,31698],{},[162,31693,31694],{},"비용\u002F대화",[162,31696,31697],{},"대화당 LLM+검색 비용",[162,31699,31700],{},"예산 내 유지",[33,31702],{},[36,31704,31706],{"id":31705},"_7-의존성과-리스크","7. 의존성과 리스크",[215,31708,16835],{"id":16835},[135,31710,31711,31720],{},[138,31712,31713],{},[141,31714,31715,31717],{},[144,31716,1497],{},[144,31718,31719],{},"영향",[157,31721,31722,31730,31738,31746,31754],{},[141,31723,31724,31727],{},[162,31725,31726],{},"외부 AWS (Aurora, OpenSearch) ↔ Cloudflare 네트워크",[162,31728,31729],{},"지연·연결 안정성. Hyperdrive·접근정책 선검증 필요",[141,31731,31732,31735],{},[162,31733,31734],{},"미결 결정(§9)",[162,31736,31737],{},"임베딩\u002FORM\u002F인증 미확정 시 1.2·1.6·1.3 착수 불가",[141,31739,31740,31743],{},[162,31741,31742],{},"초기 자료 품질·분량",[162,31744,31745],{},"빈약하면 추천 품질 미달 → Phase 2 진입 지연",[141,31747,31748,31751],{},[162,31749,31750],{},"AI Gateway \u002F Anthropic 가용성·쿼터",[162,31752,31753],{},"추천·챗 전 기능의 단일 의존점",[141,31755,31756,31759],{},[162,31757,31758],{},"Phase 1 운영 자산",[162,31760,31761],{},"Phase 2 챗봇 품질의 전제 (M4→M5 게이트)",[215,31763,31764],{"id":31764},"리스크",[135,31766,31767,31778],{},[138,31768,31769],{},[141,31770,31771,31773,31775],{},[144,31772,31764],{},[144,31774,31719],{},[144,31776,31777],{},"완화",[157,31779,31780,31791,31802,31813,31824,31835],{},[141,31781,31782,31785,31788],{},[162,31783,31784],{},"한국어 검색 품질 미달",[162,31786,31787],{},"추천 정확도 저하",[162,31789,31790],{},"임베딩 모델 비교 PoC, BM25 가중·형태소 분석 검토",[141,31792,31793,31796,31799],{},[162,31794,31795],{},"환각\u002F잘못된 안내",[162,31797,31798],{},"신뢰 훼손, 사업 리스크",[162,31800,31801],{},"출처 없는 답변 차단, \"모름\" 분기, 상담사 검토 게이트",[141,31803,31804,31807,31810],{},[162,31805,31806],{},"동기 인덱싱 한계",[162,31808,31809],{},"대용량\u002F동영상에서 Worker 타임아웃",[162,31811,31812],{},"텍스트 한정 운영, 한도 초과 시 Queue 도입(2.7)",[141,31814,31815,31818,31821],{},[162,31816,31817],{},"자산 부족 상태 챗봇 노출",[162,31819,31820],{},"낮은 해결률·불만",[162,31822,31823],{},"M4→M5 자산 축적 게이트 강제",[141,31825,31826,31829,31832],{},[162,31827,31828],{},"비용 초과",[162,31830,31831],{},"운영비 부담",[162,31833,31834],{},"AI Gateway 캐싱·rate limit, 비용 대시보드·알람",[141,31836,31837,31840,31842],{},[162,31838,31839],{},"표준답변 노후화",[162,31841,31590],{},[162,31843,31844],{},"만료·검토 워크플로(1.5), 주기적 리뷰",[33,31846],{},[36,31848,31850],{"id":31849},"_8-거버넌스-운영","8. 거버넌스 \u002F 운영",[54,31852,31853,31859,31865],{},[57,31854,31855,31858],{},[28,31856,31857],{},"단계 게이트",": 각 마일스톤은 완료 기준 충족 시에만 다음 단계로. 특히 M4→M5는 자산 축적 검증 필수.",[57,31860,31861,31864],{},[28,31862,31863],{},"품질 리뷰",": 주기적 답변 샘플링 리뷰(인용 정확도·잘못된 안내)로 KPI 추적.",[57,31866,31867,31870,31871,2855,31873,2855,31875,31877],{},[28,31868,31869],{},"문서 동기화",": 범위\u002F아키텍처 변경 시 ",[3257,31872,9949],{"href":30492},[3257,31874,30496],{"href":30495},[3257,31876,10422],{"href":24024},"와 본 문서 동시 갱신.",[33,31879],{},[36,31881,31883],{"id":31882},"_9-미결-결정-양-단계-공통","9. 미결 결정 (양 단계 공통)",[135,31885,31886,31895],{},[138,31887,31888],{},[141,31889,31890,31892],{},[144,31891,4143],{},[144,31893,31894],{},"필요 시점",[157,31896,31897,31905,31913,31921,31929],{},[141,31898,31899,31902],{},[162,31900,31901],{},"임베딩 모델 (Anthropic \u002F OpenAI \u002F 한국어 특화 오픈모델)",[162,31903,31904],{},"1.6 인덱싱 전",[141,31906,31907,31910],{},[162,31908,31909],{},"ORM\u002F마이그레이션 도구",[162,31911,31912],{},"1.2 데이터 모델 전",[141,31914,31915,31918],{},[162,31916,31917],{},"인증 방식 (관리자, 사용자 각각)",[162,31919,31920],{},"1.3 인증 전",[141,31922,31923,31926],{},[162,31924,31925],{},"에스컬레이션 채널 표준 (인앱\u002F이메일\u002FSlack\u002F티켓)",[162,31927,31928],{},"2.4 에스컬레이션 전",[141,31930,31931,31934],{},[162,31932,31933],{},"관측 스택 (로그·메트릭·알람)",[162,31935,31936],{},"1.10 운영 전",{"title":423,"searchDepth":3342,"depth":3342,"links":31938},[31939,31944,31945,31946,31947,31948,31960,31971,31975,31979,31980],{"id":30379,"depth":3335,"text":30380,"children":31940},[31941,31942,31943],{"id":30383,"depth":3342,"text":30383},{"id":30394,"depth":3342,"text":30394},{"id":30442,"depth":3342,"text":30443},{"id":30459,"depth":3335,"text":30460},{"id":30531,"depth":3335,"text":30532},{"id":30650,"depth":3335,"text":30651},{"id":30764,"depth":3335,"text":30765},{"id":30853,"depth":3335,"text":30854,"children":31949},[31950,31951,31952,31953,31954,31955,31956,31957,31958,31959],{"id":30862,"depth":3342,"text":30863},{"id":30921,"depth":3342,"text":30922},{"id":30996,"depth":3342,"text":30997},{"id":31021,"depth":3342,"text":31022},{"id":31052,"depth":3342,"text":31053},{"id":31083,"depth":3342,"text":31084},{"id":31126,"depth":3342,"text":31127},{"id":31163,"depth":3342,"text":31164},{"id":31209,"depth":3342,"text":6984},{"id":31233,"depth":3342,"text":31234},{"id":31266,"depth":3335,"text":31267,"children":31961},[31962,31964,31965,31966,31967,31968,31969,31970],{"id":31278,"depth":3342,"text":31963},"2.1 사용자 프론트엔드 (malgn-helper)",{"id":31311,"depth":3342,"text":31312},{"id":31342,"depth":3342,"text":31343},{"id":31382,"depth":3342,"text":31383},{"id":31413,"depth":3342,"text":31414},{"id":31444,"depth":3342,"text":31445},{"id":31475,"depth":3342,"text":31476},{"id":31500,"depth":3342,"text":31501},{"id":31533,"depth":3335,"text":31534,"children":31972},[31973,31974],{"id":31537,"depth":3342,"text":30365},{"id":31621,"depth":3342,"text":3088},{"id":31705,"depth":3335,"text":31706,"children":31976},[31977,31978],{"id":16835,"depth":3342,"text":16835},{"id":31764,"depth":3342,"text":31764},{"id":31849,"depth":3335,"text":31850},{"id":31882,"depth":3335,"text":31883},{},"\u002Froadmap",{"title":30348,"description":423},"8JNtBQsCoNdJEXvaZhegrG1ZOXmWqXmc0F2Pn0QLuoo",{"id":31986,"title":31987,"body":31988,"description":423,"extension":4340,"meta":32513,"navigation":3338,"path":32514,"seo":32515,"stem":30495,"__hash__":32516},"docs\u002FTECH-STACK.md","기술 스택",{"type":8,"value":31989,"toc":32488},[31990,31993,32001,32003,32007,32101,32103,32107,32113,32137,32143,32172,32174,32180,32223,32225,32229,32233,32253,32257,32270,32274,32317,32319,32323,32368,32372,32378,32380,32384,32388,32396,32400,32423,32425,32429,32465,32467,32471],[11,31991,31987],{"id":31992},"기술-스택",[21,31994,31995],{},[24,31996,31997,31998,32000],{},"고객상담 AI 챗봇 (Malgn Helper) 기술 스택 정의 문서.\n변경 시 본 문서와 ",[3257,31999,9949],{"href":30492},"를 함께 갱신한다.",[33,32002],{},[36,32004,32006],{"id":32005},"_1-전체-개요","1. 전체 개요",[135,32008,32009,32021],{},[138,32010,32011],{},[141,32012,32013,32016,32019],{},[144,32014,32015],{},"레이어",[144,32017,32018],{},"기술",[144,32020,2979],{},[157,32022,32023,32033,32041,32051,32061,32070,32080,32091],{},[141,32024,32025,32027,32030],{},[162,32026,4373],{},[162,32028,32029],{},"Nuxt 3",[162,32031,32032],{},"Cloudflare Pages",[141,32034,32035,32037,32039],{},[162,32036,4382],{},[162,32038,32029],{},[162,32040,32032],{},[141,32042,32043,32045,32048],{},[162,32044,4391],{},[162,32046,32047],{},"Hono",[162,32049,32050],{},"Cloudflare Workers",[141,32052,32053,32056,32058],{},[162,32054,32055],{},"RDB",[162,32057,4481],{},[162,32059,32060],{},"Hyperdrive 경유",[141,32062,32063,32065,32067],{},[162,32064,1182],{},[162,32066,4491],{},[162,32068,32069],{},"k-NN(벡터) + BM25 하이브리드",[141,32071,32072,32075,32077],{},[162,32073,32074],{},"객체 스토리지",[162,32076,4498],{},[162,32078,32079],{},"원본 파일(매뉴얼·동영상 등)",[141,32081,32082,32085,32088],{},[162,32083,32084],{},"LLM",[162,32086,32087],{},"Claude",[162,32089,32090],{},"Cloudflare AI Gateway 경유",[141,32092,32093,32095,32098],{},[162,32094,1295],{},[162,32096,32097],{},"동기 처리(MVP) → Cloudflare Queues(추후)",[162,32099,32100],{},"2단계 도입",[33,32102],{},[36,32104,32106],{"id":32105},"_2-프론트엔드","2. 프론트엔드",[215,32108,32110,32111,78],{"id":32109},"_21-사용자-malgn-helper","2.1 사용자 (",[16,32112,47],{},[54,32114,32115,32120,32125,32131],{},[57,32116,32117,32119],{},[28,32118,24234],{},": Nuxt 3",[57,32121,32122,32124],{},[28,32123,11529],{},": Cloudflare Pages",[57,32126,32127,32130],{},[28,32128,32129],{},"주요 화면",": 챗봇 대화 UI, 출처 인용 표시, 에스컬레이션 요청",[57,32132,32133,32136],{},[28,32134,32135],{},"인증",": 필요 시 추가 (게스트 허용 여부는 운영 정책으로 결정)",[215,32138,32140,32141,78],{"id":32139},"_22-관리자-malgn-helper-admin","2.2 관리자 (",[16,32142,18],{},[54,32144,32145,32149,32153],{},[57,32146,32147,32119],{},[28,32148,24234],{},[57,32150,32151,32124],{},[28,32152,11529],{},[57,32154,32155,4813,32158],{},[28,32156,32157],{},"주요 기능",[54,32159,32160,32163,32166,32169],{},[57,32161,32162],{},"자료(매뉴얼·동영상·Q&A) 업로드 및 메타데이터 관리",[57,32164,32165],{},"표준 답변 등록·검토",[57,32167,32168],{},"상담 로그 열람 \u002F 에스컬레이션 큐 처리",[57,32170,32171],{},"인덱싱 상태 모니터링",[33,32173],{},[36,32175,32177,32178,78],{"id":32176},"_3-api-서버-malgn-helper-api","3. API 서버 (",[16,32179,4404],{},[54,32181,32182,32187,32193,32211,32217],{},[57,32183,32184,32186],{},[28,32185,24234],{},": Hono",[57,32188,32189,32192],{},[28,32190,32191],{},"런타임",": Cloudflare Workers",[57,32194,32195,4813,32197],{},[28,32196,152],{},[54,32198,32199,32202,32205,32208],{},[57,32200,32201],{},"챗 요청 처리 (검색 → 컨텍스트 구성 → LLM 호출 → 응답)",[57,32203,32204],{},"표준 답변 우선 매칭 로직",[57,32206,32207],{},"자료 업로드 → R2 저장 → 인덱싱 트리거",[57,32209,32210],{},"관리자 CRUD 엔드포인트",[57,32212,32213,32216],{},[28,32214,32215],{},"DB 접근",": Hyperdrive 바인딩만 사용. 직접 커넥션 금지.",[57,32218,32219,32222],{},[28,32220,32221],{},"외부 호출",": AI Gateway, OpenSearch는 fetch 기반 클라이언트.",[33,32224],{},[36,32226,32228],{"id":32227},"_4-데이터-저장소","4. 데이터 저장소",[215,32230,32232],{"id":32231},"_41-aurora-mysql-via-hyperdrive","4.1 Aurora MySQL (via Hyperdrive)",[54,32234,32235,32241,32247],{},[57,32236,32237,32240],{},[28,32238,32239],{},"용도",": 사용자, 대화 세션, 메시지, 표준 답변, 자료 메타데이터, 에스컬레이션 티켓.",[57,32242,32243,32246],{},[28,32244,32245],{},"접근 방식",": Cloudflare Hyperdrive 바인딩으로 Worker에서 풀링 + 캐싱.",[57,32248,32249,32252],{},[28,32250,32251],{},"마이그레이션",": 도구 미정 (Drizzle \u002F Prisma \u002F 직접 SQL 중 결정 필요).",[215,32254,32256],{"id":32255},"_42-cloudflare-r2","4.2 Cloudflare R2",[54,32258,32259,32264],{},[57,32260,32261,32263],{},[28,32262,32239],{},": 업로드된 원본 파일(PDF, 동영상, 첨부 이미지).",[57,32265,32266,32269],{},[28,32267,32268],{},"참조",": DB에는 R2 키만 저장. 다운로드는 서명 URL로 발급.",[215,32271,32273],{"id":32272},"_43-aws-opensearch-service","4.3 AWS OpenSearch Service",[54,32275,32276,32281,32303],{},[57,32277,32278,32280],{},[28,32279,32239],{},": 청크 단위 본문\u002F임베딩 인덱싱, 하이브리드 검색.",[57,32282,32283,4813,32286],{},[28,32284,32285],{},"검색 전략",[54,32287,32288,32294,32300],{},[57,32289,32290,32293],{},[28,32291,32292],{},"BM25",": 키워드 기반 정확 매칭",[57,32295,32296,32299],{},[28,32297,32298],{},"k-NN (벡터)",": 의미 기반 유사도",[57,32301,32302],{},"두 결과를 가중치로 결합(RRF 또는 직접 스코어 합산) — 구체 가중치는 운영 중 튜닝.",[57,32304,32305,4664,32308,32310,32311,32313,32314,32316],{},[28,32306,32307],{},"인덱스 설계",[16,32309,30942],{},"(원본), ",[16,32312,21683],{},"(청크+벡터), ",[16,32315,30959],{},"(표준 답변).",[33,32318],{},[36,32320,32322],{"id":32321},"_5-ai-llm","5. AI \u002F LLM",[54,32324,32325,32337,32343,32362],{},[57,32326,32327,32330,32331,32334,32335,133],{},[28,32328,32329],{},"모델",": Claude (기본 ",[16,32332,32333],{},"claude-opus-4-7"," 또는 비용 균형이 필요할 때 ",[16,32336,17870],{},[57,32338,32339,32342],{},[28,32340,32341],{},"호출 경로",": Cloudflare AI Gateway → Anthropic API.",[57,32344,32345,4813,32348],{},[28,32346,32347],{},"AI Gateway 사용 이유",[54,32349,32350,32353,32356,32359],{},[57,32351,32352],{},"캐싱(동일 프롬프트 응답 재사용)",[57,32354,32355],{},"로깅·분석",[57,32357,32358],{},"rate limit \u002F 비용 제어",[57,32360,32361],{},"실패 시 폴백 전략 적용",[57,32363,32364,32367],{},[28,32365,32366],{},"프롬프트 캐싱",": 시스템 프롬프트 + 표준 답변 카탈로그 등 고정 컨텍스트에 적극 적용.",[215,32369,32371],{"id":32370},"_51-답변-파이프라인","5.1 답변 파이프라인",[415,32373,32376],{"className":32374,"code":32375,"language":420},[418],"질의\n ├─ (1) 표준 답변 매칭 → hit 시 즉시 반환\n ├─ (2) 하이브리드 검색 (BM25 + k-NN) → top-k 청크 추출\n ├─ (3) Claude에 컨텍스트 + 인용 지시와 함께 전달\n └─ (4) 응답 신뢰도 부족 시 \"모름 + 상담사 연결\" 반환\n",[16,32377,32375],{"__ignoreMap":423},[33,32379],{},[36,32381,32383],{"id":32382},"_6-인덱싱-파이프라인","6. 인덱싱 파이프라인",[215,32385,32387],{"id":32386},"mvp-현재-단계","MVP (현재 단계)",[54,32389,32390,32393],{},[57,32391,32392],{},"관리자 업로드 → API가 동기로 텍스트 추출 → 청킹 → 임베딩 → OpenSearch upsert.",[57,32394,32395],{},"텍스트 위주 자료 전제. Worker CPU 제한 내 처리 가능한 크기만 허용.",[215,32397,32399],{"id":32398},"_2단계-동영상대용량-도입-시","2단계 (동영상\u002F대용량 도입 시)",[54,32401,32402,32405,32420],{},[57,32403,32404],{},"업로드 후 Cloudflare Queue에 인덱싱 작업 enqueue.",[57,32406,32407,32408,32411,32412],{},"별도 ",[28,32409,32410],{},"Indexer Worker","가 consumer로 동작:\n",[54,32413,32414,32417],{},[57,32415,32416],{},"동영상 → 트랜스크립트 추출",[57,32418,32419],{},"대용량 PDF → 분할 처리, 재시도, 진행률 기록",[57,32421,32422],{},"관리자 화면에서 인덱싱 상태(pending\u002Fprocessing\u002Fdone\u002Ffailed) 표시.",[33,32424],{},[36,32426,32428],{"id":32427},"_7-인프라-배포","7. 인프라 \u002F 배포",[54,32430,32431,32437,32453,32459],{},[57,32432,32433,32436],{},[28,32434,32435],{},"호스팅",": Cloudflare (Pages + Workers + R2 + Hyperdrive + AI Gateway)",[57,32438,32439,4813,32442],{},[28,32440,32441],{},"외부 서비스",[54,32443,32444,32447,32450],{},[57,32445,32446],{},"Aurora MySQL (AWS)",[57,32448,32449],{},"OpenSearch Service (AWS)",[57,32451,32452],{},"Anthropic API (AI Gateway 경유)",[57,32454,32455,32458],{},[28,32456,32457],{},"환경 분리",": dev \u002F staging \u002F prod — Cloudflare 환경별 바인딩과 시크릿으로 분리.",[57,32460,32461,32464],{},[28,32462,32463],{},"시크릿 관리",": Cloudflare Workers 시크릿 \u002F Pages 환경변수.",[33,32466],{},[36,32468,32470],{"id":32469},"_8-미결-사항-tbd","8. 미결 사항 (TBD)",[54,32472,32473,32476,32479,32482,32485],{},[57,32474,32475],{},"ORM\u002F마이그레이션 도구 선정",[57,32477,32478],{},"임베딩 모델 (Anthropic 자체 \u002F OpenAI \u002F 한국어 특화 오픈모델) 결정",[57,32480,32481],{},"인증 방식 (사용자\u002F관리자 각각)",[57,32483,32484],{},"관측: 로깅·메트릭·알람 스택 (Cloudflare Logs \u002F 외부 APM)",[57,32486,32487],{},"에스컬레이션 채널 (이메일 \u002F Slack \u002F 자체 티켓 시스템)",{"title":423,"searchDepth":3342,"depth":3342,"links":32489},[32490,32491,32497,32499,32504,32507,32511,32512],{"id":32005,"depth":3335,"text":32006},{"id":32105,"depth":3335,"text":32106,"children":32492},[32493,32495],{"id":32109,"depth":3342,"text":32494},"2.1 사용자 (malgn-helper)",{"id":32139,"depth":3342,"text":32496},"2.2 관리자 (malgn-helper-admin)",{"id":32176,"depth":3335,"text":32498},"3. API 서버 (malgn-helper-api)",{"id":32227,"depth":3335,"text":32228,"children":32500},[32501,32502,32503],{"id":32231,"depth":3342,"text":32232},{"id":32255,"depth":3342,"text":32256},{"id":32272,"depth":3342,"text":32273},{"id":32321,"depth":3335,"text":32322,"children":32505},[32506],{"id":32370,"depth":3342,"text":32371},{"id":32382,"depth":3335,"text":32383,"children":32508},[32509,32510],{"id":32386,"depth":3342,"text":32387},{"id":32398,"depth":3342,"text":32399},{"id":32427,"depth":3335,"text":32428},{"id":32469,"depth":3335,"text":32470},{},"\u002Ftech-stack",{"title":31987,"description":423},"40pPM5aiKaugqPGvve22xmZ1-fLbMhhYoCgnpu7brkk",{"id":32518,"title":32519,"body":32520,"description":423,"extension":4340,"meta":35250,"navigation":3338,"path":12910,"seo":35251,"stem":24024,"__hash__":35252},"docs\u002FWBS.md","WBS (Work Breakdown Structure)",{"type":8,"value":32521,"toc":35201},[32522,32525,32557,32559,32563,32677,32681,32683,32776,32780,32850,32856,32951,32957,33023,33028,33036,33042,33049,33053,33099,33103,33136,33138,33142,33197,33202,33207,33209,33213,33217,33316,33320,33495,33499,33502,33564,33568,33662,33668,33785,33791,33844,33849,34111,34115,34188,34192,34298,34302,34363,34365,34369,34374,34377,34381,34441,34445,34527,34531,34534,34561,34564,34616,34620,34658,34663,34701,34707,34735,34739,34788,34792,34863,34867,34905,34907,34911,34989,34991,34995,34998,35094,35096,35100,35112,35190],[11,32523,32519],{"id":32524},"wbs-work-breakdown-structure",[21,32526,32527,32533,32545,32548],{},[24,32528,32529,32530,407],{},"SI 표준 단계(착수\u002F분석 → 설계 → 구현 → 교육·연동 → 테스트 → 이행)를 ",[28,32531,32532],{},"Phase별로 독립 적용",[54,32534,32535,32540],{},[57,32536,32537,32539],{},[28,32538,30365],{},": CS 관리자 + AI 추천 답변 (선행 — 자료\u002F답변 자산을 쌓고 상담사 보조)",[57,32541,32542,32544],{},[28,32543,3088],{},": CS 상담 챗봇 (Phase 1 자산을 활용한 고객 직접 응대)",[24,32546,32547],{},"각 Phase는 자체 착수→이행 사이클을 가진다. Phase 2는 Phase 1의 인프라·자료·표준답변을 재사용하므로 분석·설계 비중이 축소된다.",[24,32549,32550,32552,32553,32556],{},[28,32551,15425],{},": 2026-06-05 · 일별 변경은 ",[3257,32554,17380],{"href":32555},"history\u002F","에 누적 기록.",[33,32558],{},[36,32560,32562],{"id":32561},"진행률-스냅샷-2026-06-05-기준","진행률 스냅샷 (2026-06-05 기준)",[135,32564,32565,32577],{},[138,32566,32567],{},[141,32568,32569,32572,32574],{},[144,32570,32571],{},"Phase \u002F 단계",[144,32573,12848],{},[144,32575,32576],{},"핵심 진행 사항",[157,32578,32579,32593,32615,32634,32648,32663],{},[141,32580,32581,32586,32590],{},[162,32582,32583],{},[28,32584,32585],{},"Phase 1 · 착수\u002F분석",[162,32587,32588],{},[28,32589,15357],{},[162,32591,32592],{},"환경 검토·인프라 활성화·자료 인벤토리·요구사항 정의 모두 완료. 정식 요구사항 정의서만 잔여",[141,32594,32595,32600,32605],{},[162,32596,32597],{},[28,32598,32599],{},"Phase 1 · 설계",[162,32601,32602],{},[28,32603,32604],{},"85%",[162,32606,32607,32608,32611,32612,32614],{},"hp_* ",[28,32609,32610],{},"5테이블"," ERD·DDL(+",[16,32613,77],{}," 신설), OpenAPI 3.1 명세, Q&A 5축+templates 6종 스펙. 검색 인덱스 매핑 미진",[141,32616,32617,32622,32627],{},[162,32618,32619],{},[28,32620,32621],{},"Phase 1 · 구현",[162,32623,32624],{},[28,32625,32626],{},"72%",[162,32628,32629,32630,32633],{},"API 24+ 엔드포인트 (announce-eval·migrate 포함), PMS 5페이지 + UX\u002FLLM\u002FVision 폴리시 다회, LLM 안정화(gpt-4.1-mini via AI Gateway malgn-helper2), ",[28,32631,32632],{},"이미지 자산 자동 캡션·저장","(hp_image_asset). 자료 인덱싱·하이브리드 검색·관리자 UI 미진",[141,32635,32636,32641,32645],{},[162,32637,32638],{},[28,32639,32640],{},"Phase 1 · 교육·연동",[162,32642,32643],{},[28,32644,15396],{},[162,32646,32647],{},"OpenAPI(Scalar) + 배포·이력·분류·MySQL 인덱스·Cloudflare Access 가이드. 정식 상담사 교육·기존 시스템 연동 미진",[141,32649,32650,32655,32660],{},[162,32651,32652],{},[28,32653,32654],{},"Phase 1 · 테스트",[162,32656,32657],{},[28,32658,32659],{},"15%",[162,32661,32662],{},"UI 호환성·캐시·CORS·HTML escape·Vision URL 절대화·region 차단 우회 등 다회차 오류 처리. 정식 단위·통합·UAT 미진",[141,32664,32665,32670,32674],{},[162,32666,32667],{},[28,32668,32669],{},"Phase 1 · 이행",[162,32671,32672],{},[28,32673,15365],{},[162,32675,32676],{},"API + PMS 운영 단계 (60+회 deploy.sh 이력). 관리자·사용자 챗봇 본 기능 미배포",[36,32678,32680],{"id":32679},"누적-완료-자산-2026-06-05","누적 완료 자산 (2026-06-05)",[215,32682,23572],{"id":23572},[54,32684,32685,32696,32699,32707,32716,32724,32735,32742,32752,32758,32764,32773],{},[57,32686,32687,32688,105,32690,105,32692,105,32694],{},"✅ 4개 GitHub repo 연결·첫 푸시 — ",[16,32689,47],{},[16,32691,4608],{},[16,32693,4611],{},[16,32695,4614],{},[57,32697,32698],{},"✅ Cloudflare 환경 — Pages 3 (helper·admin·pms) + Workers 1 (api) 모두 운영",[57,32700,32701,32702,1365,32704,32706],{},"✅ wrangler 설정 (",[16,32703,4821],{},[16,32705,4701],{},") + account_id 명시",[57,32708,32709,32710,32715],{},"✅ 일괄 배포 스크립트 ",[3257,32711,32713],{"href":32712},"..\u002Fscripts\u002Fdeploy.sh",[16,32714,4840],{}," — commit + push + deploy + 이력 자동 기록 (40+회 실행)",[57,32717,32718,32719,32723],{},"✅ 일단위 작업 이력 ",[3257,32720,32721],{"href":32555},[16,32722,17380],{}," 운영 — 일별 누적 (28일·29일 완료)",[57,32725,32726,32727,2367,32730,12086,32732,32734],{},"✅ ",[28,32728,32729],{},"Cloudflare Hyperdrive",[16,32731,12085],{},[16,32733,12089],{},") — PMS MySQL(5.6.51) 연결 + read cache (1분)",[57,32736,32726,32737,2367,32739,32741],{},[28,32738,4498],{},[16,32740,12096],{}," — WBS 영속화 + 원본 파일 저장소 준비",[57,32743,32726,32744,2367,32746,32748,32749,32751],{},[28,32745,4515],{},[16,32747,15599],{}," (compat endpoint, Provider OpenAI 키 등록) — OpenAI 호출 캐싱·로깅·rate 일원화. (이전 ",[16,32750,47],{}," 게이트웨이는 결제 정책 변경으로 폐기)",[57,32753,32726,32754,32757],{},[28,32755,32756],{},"Cloudflare Workers AI binding"," — Workers AI catalog 모델 fallback 가능 (Llama 3.3 70B 등 region 우회용)",[57,32759,32726,32760,32763],{},[28,32761,32762],{},"Smart Placement"," 활성 — backend 가까운 colo 자동 라우팅",[57,32765,32726,32766,4664,32769,105,32771],{},[28,32767,32768],{},"시크릿",[16,32770,4544],{},[16,32772,12111],{},[57,32774,32775],{},"⚪ Aurora MySQL (별도 — 현재는 PMS DB 직접 연결로 대체), OpenSearch (미설치)",[215,32777,32779],{"id":32778},"문서자산","문서·자산",[54,32781,32782,32799,32819,32833,32839,32847],{},[57,32783,32784,32785,2212,32787,2212,32790,2212,32792,32794,32795,2212,32797],{},"✅ 워크스페이스 문서: ",[3257,32786,9949],{"href":30492},[3257,32788,10619],{"href":32789},"..\u002FREADME",[3257,32791,30496],{"href":30495},[3257,32793,6981],{"href":22076}," · 본 WBS · ",[3257,32796,6360],{"href":22255},[3257,32798,5780],{"href":24053},[57,32800,32726,32801,4664,32803,32805,32806,32809,32810,1305,32812,32814,32815,32818],{},[28,32802,16936],{},[3257,32804,12455],{"href":19550}," (hp_* 4테이블 ERD\u002FDDL) · ",[3257,32807,12452],{"href":32808},"WBS-TRACKER"," (WBS Live Tracker 사양) · ",[3257,32811,3260],{"href":3259},[16,32813,3973],{}," 보호 가이드) · ",[3257,32816,32817],{"href":22792},"MYSQL-INDEXES.md"," (4단계 폴백)",[57,32820,32821,32822,32825,32826,2212,32828,2212,32830],{},"✅ 재사용 프롬프트 3종 (",[3257,32823,32824],{"href":32824},"prompts\u002F","): ",[16,32827,28178],{},[16,32829,28993],{},[16,32831,32832],{},"qa-evaluation",[57,32834,32835,32836,78],{},"✅ 케이스 스터디·예시 3종 (",[3257,32837,32838],{"href":32838},"examples\u002F",[57,32840,32726,32841,32844,32845,78],{},[28,32842,32843],{},"OpenAPI 3.1 명세"," (수동 작성, 22개 엔드포인트) + Scalar API Reference UI (",[16,32846,3239],{},[57,32848,32849],{},"✅ 일별 이력: 5\u002F28·29 · 6\u002F1·2·4·5 (운영 단계 진입 후 일별 누적)",[215,32851,32853,32855],{"id":32852},"malgn-helper-api-hono-on-workers",[16,32854,4404],{}," (Hono on Workers)",[54,32857,32858,32898,32901,32910,32918,32928,32931,32934,32942],{},[57,32859,32726,32860,4664,32863,2212,32866,2212,32869,2212,32872,2212,32875,32877,32878,2212,32881,32883,32884,2212,32887,2212,32889,2212,32891,2212,32893,2212,32896],{},[28,32861,32862],{},"24+ 엔드포인트",[16,32864,32865],{},"\u002Fpms\u002Fprojects",[16,32867,32868],{},"\u002Fpms\u002Fposts\u002F:id",[16,32870,32871],{},"\u002Fpms\u002Fprojects\u002F:id\u002Fbriefing(\u002Fgenerate)",[16,32873,32874],{},"\u002Fpms\u002Fposts\u002F:id\u002Feval(\u002Fgenerate)",[16,32876,16144],{}," (직원 안내글 평가, 코드만) · ",[16,32879,32880],{},"\u002Fpms\u002Fevals\u002F:id",[16,32882,700],{}," (CRUD) · ",[16,32885,32886],{},"\u002Fpms\u002Fprojects\u002F:id\u002Fstandard-answer-suggestions",[16,32888,104],{},[16,32890,108],{},[16,32892,16454],{},[16,32894,32895],{},"\u002Fhealthz",[16,32897,3239],{},[57,32899,32900],{},"✅ Hyperdrive 경유 PMS DB 연결 + 직원\u002F고객\u002F협력사 분류 + 비공개 댓글 본문 마스킹",[57,32902,32903,32904,32906,32907,32909],{},"✅ LLM 실연동: OpenAI ",[16,32905,2772],{}," via AI Gateway ",[16,32908,15599],{}," (compat + BYOK)",[57,32911,32726,32912,32914,32915,32917],{},[16,32913,2800],{}," 기반 24h 캐시 + ",[16,32916,12177],{}," 비용·지연·실패 감사",[57,32919,32726,32920,32923,32924,32927],{},[28,32921,32922],{},"GPT-4.1-mini Vision"," — 원본 응답의 이미지 절대URL을 직접 첨부, LLM이 화면 인지 후 캡션 작성. 상대경로(",[16,32925,32926],{},"\u002Fdata\u002F·..\u002Fdata\u002F·.\u002Fdata\u002F",") 모두 절대화",[57,32929,32930],{},"✅ 표준답변 컨텍스트 보강 — 같은 프로젝트 최근 5건을 LLM에 전달 (톤·구조 참고)",[57,32932,32933],{},"✅ Q&A 평가 prompt: 5축 + D축 templates 6종(짧은\u002F긴\u002F친절\u002F비즈니스\u002FFAQ\u002F단계별), 4파트 구성 강제",[57,32935,32726,32936,32939,32940,78],{},[28,32937,32938],{},"inquiry-only 모드",": 답변 없는 문의는 5축 평가 생략하고 추천 답변 6개만 D축 wrap (",[16,32941,16319],{},[57,32943,32726,32944,32947,32948,32950],{},[28,32945,32946],{},"hp_image_asset 자동 캡션",": eval\u002Fgenerate에서 본문·응답 양쪽 ",[16,32949,16398],{}," 이미지 추출 → Vision 자동 분석·저장 (src_path UNIQUE 캐시)",[215,32952,32954,32956],{"id":32953},"malgn-helper-pms-nuxt-3-pages",[16,32955,4588],{}," (Nuxt 3 \u002F Pages)",[54,32958,32959,32962,32969,32982,32991,33014],{},[57,32960,32961],{},"✅ 브리핑 카드 컴포넌트 + 모달 워크플로 (실 API 연동, mock 제거)",[57,32963,32964,32965,32968],{},"✅ Q&A 평가 카드 컴포넌트 + ",[28,32966,32967],{},"인-모달 상태 전환"," (loading\u002Ferror\u002Fresult 같은 모달 안에서 분기)",[57,32970,32971,32972,32974,32975,32977,32978,32981],{},"✅ 임베드 인터페이스 — ",[16,32973,16034],{},"(내부 nav 숨김) \u002F ",[16,32976,16038],{}," (모달 자동 오픈), ",[16,32979,32980],{},"postMessage"," 닫기 신호. 두 시그널 모두 임베드로 인식",[57,32983,32984,32985,32988,32989],{},"✅ 표준답변 다중 템플릿 (6종) + ",[28,32986,32987],{},"추천 문의 답변 별도 섹션 분리"," + \"표준답변으로 저장\" → ",[16,32990,3610],{},[57,32992,32993,32994,2212,32996,2212,32998,2212,33001,2212,33004,33006,33007,2212,33009,2212,33011,33013],{},"✅ 페이지 7종: ",[16,32995,12267],{},[16,32997,16026],{},[16,32999,33000],{},"\u002Fprojects\u002F[id]\u002Fposts",[16,33002,33003],{},"\u002Fposts\u002F[id]",[16,33005,16083],{}," (임베드 전용) · ",[16,33008,108],{},[16,33010,104],{},[16,33012,12910],{}," (WBS Live Tracker)",[57,33015,33016,33017,33019,33020],{},"✅ UX 폴리시: 분석 모달은 valid 결과 도착 후 열기 \u002F Q&A 본문 초기 접힘 \u002F 빈 결과 \"다시 시도\" \u002F 모달 안 삭제 → 서버+메모리 동기화 \u002F PersonBlock UTooltip 제거 fix \u002F 메타 일시 ",[16,33018,16347],{}," 한 줄 \u002F 추천 답변 가독성(my-3·line-height 1.8) \u002F ",[28,33021,33022],{},"다크모드 비활성(CSS body bg)",[215,33024,33026,32956],{"id":33025},"malgn-helper-admin-nuxt-3-pages",[16,33027,18],{},[54,33029,33030,33033],{},[57,33031,33032],{},"✅ 보일러플레이트 + 첫 배포",[57,33034,33035],{},"⚪ 본 기능 미착수 (자료 업로드·표준답변 관리·에스컬레이션 검토)",[215,33037,33039,33041],{"id":33038},"malgn-helper-사용자-챗봇-pages",[16,33040,47],{}," (사용자 챗봇 \u002F Pages)",[54,33043,33044,33046],{},[57,33045,33032],{},[57,33047,33048],{},"⚪ 본 기능 미착수 (챗 UI · RAG 응답)",[215,33050,33052],{"id":33051},"db-인덱스","DB · 인덱스",[54,33054,33055,33076,33086,33091],{},[57,33056,32726,33057,33062,33063,2212,33065,2212,33067,2212,33069,2212,33071,33075],{},[2369,33058,33059,33061],{},[2369,33060,17663],{}," 5테이블","* — ",[16,33064,2854],{},[16,33066,2858],{},[16,33068,2125],{},[16,33070,12177],{},[28,33072,33073],{},[16,33074,77],{},"(신규, Vision 자동 캡션·src_path UNIQUE prefix 191)",[57,33077,33078,33079,1524,33082,33085],{},"✅ MySQL 부하 대책: ",[16,33080,33081],{},"tb_post (project_id, status, reg_date)",[16,33083,33084],{},"tb_post_comment (post_id, status, reg_date)"," 인덱스 추가 → 91초→244ms",[57,33087,32726,33088,33090],{},[16,33089,12606],{}," VARCHAR(20) → VARCHAR(100) 마이그레이션 (긴 평 저장)",[57,33092,32726,33093,33095,33096,33098],{},[16,33094,77],{}," 마이그레이션 (일회용 ",[16,33097,16407],{}," 엔드포인트)",[215,33100,33102],{"id":33101},"운영-정책","운영 정책",[54,33104,33105,33118,33121,33124,33127,33130,33133],{},[57,33106,33107,33108,17678,33110,17091,33112,1365,33114,33117],{},"✅ 분류 규칙: ",[28,33109,29454],{},[16,33111,128],{},[16,33113,132],{},[28,33115,33116],{},"협력사"," = 화이트리스트(플로즈·옐로우윈·온케어·송한나) \u002F 그 외 = 고객 (이름·게시판 패턴 추정 금지 — 메모리 저장)",[57,33119,33120],{},"✅ 영업시간 FRT: KST 평일 09–17 + 한국 공휴일 Set 제외",[57,33122,33123],{},"✅ 브리핑 statusLabel 5단계(휴면\u002F원활\u002F주의\u002F경고\u002F긴급) + 미응답 임계값·LLM urgent 격상 룰 (LLM이 라벨 직접 결정 금지)",[57,33125,33126],{},"✅ 비공개 답변 처리 전략 — Phase 2 챗봇 응답에 직접 인용·출처 노출 금지 (메모리 저장)",[57,33128,33129],{},"✅ 첨부파일 처리 전략 (텍스트·이미지·동영상 단계별)",[57,33131,33132],{},"✅ 스레드 처리 전략 (단일 도큐먼트 압축 + 화자 라벨)",[57,33134,33135],{},"✅ Closing 패턴 가이드 (감사합니다 vs 행동 안내 분기)",[33,33137],{},[36,33139,33141],{"id":33140},"단계별-가중치","단계별 가중치",[135,33143,33144,33152],{},[138,33145,33146],{},[141,33147,33148,33150],{},[144,33149,2976],{},[144,33151,23448],{},[157,33153,33154,33161,33168,33175,33183,33190],{},[141,33155,33156,33159],{},[162,33157,33158],{},"1. 착수\u002F분석",[162,33160,15391],{},[141,33162,33163,33166],{},[162,33164,33165],{},"2. 설계",[162,33167,15378],{},[141,33169,33170,33173],{},[162,33171,33172],{},"3. 구현",[162,33174,15365],{},[141,33176,33177,33180],{},[162,33178,33179],{},"4. 교육 및 연동",[162,33181,33182],{},"20%",[141,33184,33185,33188],{},[162,33186,33187],{},"5. 테스트",[162,33189,33182],{},[141,33191,33192,33195],{},[162,33193,33194],{},"6. 이행",[162,33196,15415],{},[21,33198,33199],{},[24,33200,33201],{},"참고 가중치이며 일정 수립 시 Phase별 재산정.",[24,33203,33204,33206],{},[28,33205,12730],{},": ✅ 완료 · 🟢 진행 중 · ⚪ 대기 · ⛔ 보류",[33,33208],{},[11,33210,33212],{"id":33211},"phase-1-cs-관리자-ai-추천-답변-pms-애드온","Phase 1 — CS 관리자 + AI 추천 답변 (+ PMS 애드온)",[36,33214,33216],{"id":33215},"p1-1-착수분석-10","P1-1. 착수\u002F분석 (10%)",[135,33218,33219,33233],{},[138,33220,33221],{},[141,33222,33223,33225,33227,33229,33231],{},[144,33224,13179],{},[144,33226,13182],{},[144,33228,7333],{},[144,33230,30487],{},[144,33232,2979],{},[157,33234,33235,33252,33275,33291],{},[141,33236,33237,33240,33243,33246,33249],{},[162,33238,33239],{},"1-1",[162,33241,33242],{},"요구사항 도출",[162,33244,33245],{},"🟢",[162,33247,33248],{},"답변 품질·출처 인용·\"모름\" 정책·표준답변 우선·상담사 채택 플로우 — CLAUDE.md\u002FROADMAP\u002FHP-SCHEMA에 정의. 실 운영 검증으로 요구사항 추가 발굴 (영업시간 FRT, 직원\u002F협력사\u002F고객 분류, 5단계 statusLabel 등)",[162,33250,33251],{},"정식 요구사항 정의서 별도 작성 필요",[141,33253,33254,33257,33260,33262,33273],{},[162,33255,33256],{},"1-2",[162,33258,33259],{},"수행범위 정의 및 확인",[162,33261,245],{},[162,33263,33264,33265,33268,33269,33272],{},"Phase 1·2 분리, ",[28,33266,33267],{},"4개 repo 정의"," (helper \u002F admin \u002F api \u002F ",[28,33270,33271],{},"pms 신규","), PMS 애드온 범위 포함",[162,33274],{},[141,33276,33277,33280,33283,33285,33288],{},[162,33278,33279],{},"1-3",[162,33281,33282],{},"개발환경 검토",[162,33284,245],{},[162,33286,33287],{},"Cloudflare(Pages·Workers·R2·AI Gateway·Hyperdrive) 활성화 완료. PMS MySQL은 Hyperdrive 경유 연결 검증 완료. OpenSearch는 별도 진행",[162,33289,33290],{},"wrangler·account_id 표준화",[141,33292,33293,33296,33299,33301,33310],{},[162,33294,33295],{},"1-4",[162,33297,33298],{},"기본자료 검토",[162,33300,245],{},[162,33302,33303,33304,5824],{},"레거시 PMS DB 인벤토리(1,358 Q&A 후보), 200+ 프로젝트 분포 분석, 비공개·첨부·스레드 처리 전략 수립. ",[2369,33305,33306,33309],{},[2369,33307,33308],{},"27개 tb_"," 테이블 구조 파악 완료",[162,33311,33312,105,33314],{},[3257,33313,6360],{"href":22255},[3257,33315,5780],{"href":24053},[36,33317,33319],{"id":33318},"p1-2-설계-25","P1-2. 설계 (25%)",[135,33321,33322,33336],{},[138,33323,33324],{},[141,33325,33326,33328,33330,33332,33334],{},[144,33327,13179],{},[144,33329,13182],{},[144,33331,7333],{},[144,33333,30487],{},[144,33335,2979],{},[157,33337,33338,33362,33387,33417,33454,33470],{},[141,33339,33340,33343,33346,33348,33353],{},[162,33341,33342],{},"2-1",[162,33344,33345],{},"전체 진행 일정 (WBS)",[162,33347,245],{},[162,33349,33350,33351,78],{},"본 문서 + 진행률 스냅샷 + WBS Live Tracker (",[16,33352,12910],{},[162,33354,33355,33356,33358,33359,33361],{},"일별 ",[3257,33357,32555],{"href":32555}," 누적, ",[16,33360,12910],{}," 인라인 편집 + R2 자동 저장",[141,33363,33364,33367,33370,33372,33384],{},[162,33365,33366],{},"2-2",[162,33368,33369],{},"시스템 아키텍처 설계",[162,33371,245],{},[162,33373,33374,33375,33377,33378,33380,33381,33383],{},"CLAUDE.md 데이터 흐름, ",[3257,33376,30496],{"href":30495},", 4 repo 책임 분리, ",[3257,33379,12455],{"href":19550}," hp_* ERD, ",[3257,33382,3260],{"href":3259}," 권한 모델",[162,33385,33386],{},"상세 시퀀스 다이어그램은 P2 진입 시 보강",[141,33388,33389,33392,33395,33397,33412],{},[162,33390,33391],{},"2-3",[162,33393,33394],{},"화면명세서 작성",[162,33396,33245],{},[162,33398,33399,33400,2367,33402,2367,33405,2367,33407,2367,33409,33411],{},"PMS 카드 2종 (브리핑·Q&A 평가) + 페이지 7종 (",[16,33401,12267],{},[16,33403,33404],{},"\u002Fposts",[16,33406,108],{},[16,33408,104],{},[16,33410,12910],{}," 등) 실구현 명세",[162,33413,14,33414,33416],{},[16,33415,18],{},") 본격 화면 명세 미진",[141,33418,33419,33422,33425,33427,33451],{},[162,33420,33421],{},"2-4",[162,33423,33424],{},"데이터 설계",[162,33426,245],{},[162,33428,33429,33434,33435,33437,33438,2212,33440,2212,33442,2212,33444,2212,33446,33450],{},[2369,33430,33431,33433],{},[2369,33432,17663],{}," 5테이블 ERD\u002FDDL","* (",[3257,33436,12455],{"href":19550},") — ",[16,33439,2854],{},[16,33441,2858],{},[16,33443,2125],{},[16,33445,12177],{},[28,33447,33448],{},[16,33449,77],{},"(신규, Vision 자동 캡션). 인덱스·캐시 키·llm_input_hash·src_path UNIQUE 전략 포함",[162,33452,33453],{},"OpenSearch 인덱스 매핑·R2 키 규칙은 Phase 1 후반·Phase 2 진입 시",[141,33455,33456,33459,33462,33464,33467],{},[162,33457,33458],{},"2-5",[162,33460,33461],{},"디자인 시안",[162,33463,33245],{},[162,33465,33466],{},"브리핑·Q&A 평가 카드(Notion-clean) + PMS 페이지 디자인(Tailwind v4 + Soft SaaS 톤)",[162,33468,33469],{},"관리자·사용자 챗봇 화면 시안 미진",[141,33471,33472,33475,33478,33480,33492],{},[162,33473,33474],{},"2-6",[162,33476,33477],{},"AI 프로토타입 서비스 구현",[162,33479,245],{},[162,33481,33482,2448,33485,2212,33488,33491],{},[28,33483,33484],{},"실 LLM 호출 운영 중",[16,33486,33487],{},"\u002Fpms\u002Fprojects\u002F:id\u002Fbriefing\u002Fgenerate",[16,33489,33490],{},"\u002Fpms\u002Fposts\u002F:id\u002Feval\u002Fgenerate"," 24h 캐시 + Vision + 표준답변 컨텍스트",[162,33493,33494],{},"챗봇용 RAG(검색→인용→\"모름\" 가드)는 Phase 1 후반 신설 예정",[36,33496,33498],{"id":33497},"p1-3-구현-40","P1-3. 구현 (40%)",[215,33500,25683],{"id":33501},"db",[135,33503,33504,33518],{},[138,33505,33506],{},[141,33507,33508,33510,33512,33514,33516],{},[144,33509,13179],{},[144,33511,13182],{},[144,33513,7333],{},[144,33515,30487],{},[144,33517,2979],{},[157,33519,33520],{},[141,33521,33522,33525,33528,33530,33561],{},[162,33523,33524],{},"3-1",[162,33526,33527],{},"DB 구축",[162,33529,33245],{},[162,33531,33532,1524,33537,33434,33542,2212,33544,2212,33546,2212,33548,2212,33550,33554,33555,33557,33558,33560],{},[28,33533,12082,33534,33536],{},[16,33535,12085],{}," 바인딩",[2369,33538,33539,33541],{},[2369,33540,17663],{}," 5테이블 적용",[16,33543,2854],{},[16,33545,2858],{},[16,33547,2125],{},[16,33549,12177],{},[28,33551,33552],{},[16,33553,77],{},"). ",[16,33556,15640],{}," VARCHAR(100) 마이그레이션, MySQL 인덱스 추가, ",[16,33559,77],{}," UNIQUE prefix(191) 적용",[162,33562,33563],{},"Aurora 별도 인스턴스는 미진(현재는 PMS DB 공존 운영)",[215,33565,33567],{"id":33566},"디자인-퍼블리싱","디자인 \u002F 퍼블리싱",[135,33569,33570,33584],{},[138,33571,33572],{},[141,33573,33574,33576,33578,33580,33582],{},[144,33575,13179],{},[144,33577,13182],{},[144,33579,7333],{},[144,33581,30487],{},[144,33583,2979],{},[157,33585,33586,33613,33640],{},[141,33587,33588,33591,33594,33596,33608],{},[162,33589,33590],{},"3-2",[162,33592,33593],{},"Front 디자인",[162,33595,33245],{},[162,33597,33598,33599,2367,33601,2367,33603,2367,33605,33607],{},"PMS 카드 2종 + 페이지 7종(",[16,33600,12267],{},[16,33602,33404],{},[16,33604,3973],{},[16,33606,12910],{},") 디자인 통합",[162,33609,14,33610,33612],{},[16,33611,18],{},")·사용자 챗봇 본격 화면 미진",[141,33614,33615,33618,33621,33623,33638],{},[162,33616,33617],{},"3-3",[162,33619,33620],{},"Front 퍼블리싱",[162,33622,33245],{},[162,33624,33625,33626,2212,33629,2212,33631,2212,33634,33637],{},"Nuxt 3 컴포넌트: ",[16,33627,33628],{},"BriefingCard.vue",[16,33630,11454],{},[16,33632,33633],{},"QaAxisCard.vue",[16,33635,33636],{},"QaScoreSummary.vue"," 외 보조 컴포넌트 + 7개 페이지 라우트",[162,33639],{},[141,33641,33642,33645,33648,33650,33659],{},[162,33643,33644],{},"3-4",[162,33646,33647],{},"디자인\u002F퍼블리싱 검수",[162,33649,33245],{},[162,33651,33652,33653,24613,33655,33658],{},"Tailwind v4 + Nuxt UI v3 호환성 이슈 다회차 수정, ",[16,33654,16105],{},[16,33656,33657],{},"\u002Fdata\u002F"," 자산 도메인 prefix 처리, prose dark\u002Flight 정합",[162,33660,33661],{},"추가 회귀 검증 필요",[215,33663,33665,33666,78],{"id":33664},"api-malgn-helper-api","API (",[16,33667,4404],{},[135,33669,33670,33684],{},[138,33671,33672],{},[141,33673,33674,33676,33678,33680,33682],{},[144,33675,13179],{},[144,33677,13182],{},[144,33679,7333],{},[144,33681,30487],{},[144,33683,2979],{},[157,33685,33686,33705,33741,33761],{},[141,33687,33688,33691,33694,33696,33703],{},[162,33689,33690],{},"3-5",[162,33692,33693],{},"워커 및 프레임워크 설치",[162,33695,245],{},[162,33697,33698,33699,33702],{},"Hono on Workers + 운영 (",[3257,33700,10806],{"href":10806,"rel":33701},[5049],") + Hyperdrive·R2·AI Gateway·Workers AI binding·Smart Placement 활성",[162,33704],{},[141,33706,33707,33710,33713,33715,33738],{},[162,33708,33709],{},"3-6",[162,33711,33712],{},"API 개발",[162,33714,33245],{},[162,33716,33717,2448,33719,33721,33722,33724,33725,2855,33727,2855,33729,33731,33732,33734,33735,33737],{},[28,33718,32862],{},[16,33720,32865],{}," 목록·상세·브리핑(generate)·게시글·Q&A 평가(generate, inquiry-only 자동 분기)·announce-eval(직원 안내글, 코드만)·평가 CRUD\u002F삭제·",[16,33723,700],{}," CRUD·표준답변 추천·",[16,33726,104],{},[16,33728,108],{},[16,33730,16454],{}," · OpenAPI(",[16,33733,3239],{},"). 캐시·감사·Vision·표준답변 컨텍스트·",[28,33736,32946],{}," 모두 연동",[162,33739,33740],{},"자료 인덱싱·하이브리드 검색·챗봇 응답 파이프라인 미진",[141,33742,33743,33746,33749,33751,33759],{},[162,33744,33745],{},"3-6-1",[162,33747,33748],{},"LLM·게이트웨이 안정화",[162,33750,245],{},[162,33752,12100,33753,33755,33756,33758],{},[16,33754,15599],{},"(BYOK) + ",[16,33757,15606],{}," + Authorization+cf-aig-authorization 헤더. 6가지 경로 검증 후 최종 안착 (region 차단·결제 정책 우회 트러블슈팅 기록)",[162,33760],{},[141,33762,33763,33766,33769,33771,33782],{},[162,33764,33765],{},"3-6-2",[162,33767,33768],{},"이미지 자산 자동 캡션",[162,33770,245],{},[162,33772,33773,33775,33776,33778,33779,33781],{},[16,33774,16378],{}," 함수 + ",[16,33777,77],{}," UNIQUE 캐시. eval\u002Fgenerate에서 본문(inquiry)·응답(reply) ",[16,33780,16398],{}," 이미지 추출 → Vision 자동 분석 → title·description 저장",[162,33783,33784],{},"검증: post 149694 9장 정확한 한국어 캡션",[215,33786,33788,33789,78],{"id":33787},"admin-malgn-helper-admin","Admin (",[16,33790,18],{},[135,33792,33793,33807],{},[138,33794,33795],{},[141,33796,33797,33799,33801,33803,33805],{},[144,33798,13179],{},[144,33800,13182],{},[144,33802,7333],{},[144,33804,30487],{},[144,33806,2979],{},[157,33808,33809,33829],{},[141,33810,33811,33814,33817,33820,33826],{},[162,33812,33813],{},"3-7",[162,33815,33816],{},"AI 설정 페이지",[162,33818,33819],{},"⚪",[162,33821,33822,33823,78],{},"Nuxt 3 보일러플레이트만, 첫 배포 (",[3257,33824,10202],{"href":10202,"rel":33825},[5049],[162,33827,33828],{},"자료\u002F표준답변\u002F모델 설정 화면 미진",[141,33830,33831,33834,33837,33839,33841],{},[162,33832,33833],{},"3-8",[162,33835,33836],{},"AI 시연 페이지 개발",[162,33838,33819],{},[162,33840,538],{},[162,33842,33843],{},"문의→추천답변→채택 플로우 미진. 현재는 PMS 측 분석 모달이 유사 역할 수행",[215,33845,12768,33847,78],{"id":33846},"pms-애드온-malgn-helper-pms",[16,33848,4588],{},[135,33850,33851,33865],{},[138,33852,33853],{},[141,33854,33855,33857,33859,33861,33863],{},[144,33856,13179],{},[144,33858,13182],{},[144,33860,7333],{},[144,33862,30487],{},[144,33864,2979],{},[157,33866,33867,33884,33905,33922,33948,33966,33984,34011,34032,34055,34072,34090],{},[141,33868,33869,33872,33875,33877,33882],{},[162,33870,33871],{},"3-9",[162,33873,33874],{},"브리핑 카드 컴포넌트 통합",[162,33876,245],{},[162,33878,33879,33881],{},[16,33880,33628],{}," + types\u002Fdata\u002Fcomposables + 모달 워크플로",[162,33883],{},[141,33885,33886,33889,33892,33894,33903],{},[162,33887,33888],{},"3-10",[162,33890,33891],{},"Q&A 평가 카드 컴포넌트 통합",[162,33893,245],{},[162,33895,33896,1524,33898,1524,33900,33902],{},[16,33897,11454],{},[16,33899,33633],{},[16,33901,33636],{}," + 표준답변 6종 (짧은\u002F긴\u002F친절\u002F비즈니스\u002FFAQ\u002F단계별)",[162,33904],{},[141,33906,33907,33910,33913,33915,33920],{},[162,33908,33909],{},"3-11",[162,33911,33912],{},"워크플로 페이지",[162,33914,245],{},[162,33916,33917,33919],{},[16,33918,16026],{}," 빈 상태 → AI 생성 → 모달. 서버 히스토리 fetch (localStorage v1 자동 정리)",[162,33921],{},[141,33923,33924,33927,33930,33932,33946],{},[162,33925,33926],{},"3-12",[162,33928,33929],{},"임베드 인터페이스",[162,33931,245],{},[162,33933,33934,32974,33936,33938,33939,33942,33943,33945],{},[16,33935,16034],{},[16,33937,16038],{},"(모달 자동 오픈, 임베드로 인식) · ",[16,33940,33941],{},"window.open","·iframe 호환 · ",[16,33944,32980],{}," 닫기 신호",[162,33947],{},[141,33949,33950,33953,33956,33958,33964],{},[162,33951,33952],{},"3-13",[162,33954,33955],{},"표준답변 다중 템플릿 + 저장",[162,33957,245],{},[162,33959,33960,33961,33963],{},"D축 templates 6개 LLM 자동 생성 → \"표준답변으로 저장\" → ",[16,33962,3610],{}," 영속화",[162,33965],{},[141,33967,33968,33971,33974,33976,33982],{},[162,33969,33970],{},"3-14",[162,33972,33973],{},"실제 API 연동",[162,33975,245],{},[162,33977,33978,33979,33981],{},"브리핑·Q&A 평가·표준답변·삭제·검색 모두 ",[16,33980,4404],{}," 호출로 전환. mock 제거",[162,33983],{},[141,33985,33986,33989,33992,33994,34008],{},[162,33987,33988],{},"3-15",[162,33990,33991],{},"Q&A 평가 카드 워크플로 페이지",[162,33993,245],{},[162,33995,33996,33998,33999,34001,34002,17484,34004,34007],{},[16,33997,108],{}," 목록(정렬·필터·점수 색 분기) + 행 클릭 → ",[16,34000,2739],{}," 모달. 빈 결과 행은 기본 숨김(",[16,34003,12362],{},[16,34005,34006],{},"\u002Fposts\u002F:id"," 상세 안 \"AI 문의 답변 분석\" 모달",[162,34009,34010],{},"LLM 행만 모달 즉시 열기 폴리시 추가 검토 중",[141,34012,34013,34016,34019,34021,34030],{},[162,34014,34015],{},"3-16",[162,34017,34018],{},"UX 폴리시 라운드",[162,34020,245],{},[162,34022,34023,34024,34026,34027,34029],{},"분석 모달 valid 결과 후 표시 → ",[28,34025,32967],{},"(loading\u002Ferror\u002Fresult 같은 모달 안 분기) · Q&A 본문 초기 접힘 · \"다시 시도\" 모달 · 모달 안 삭제 → 서버+메모리 동기화 · followups 빈 섹션 제거 · PersonBlock UTooltip 제거 fix · 메타 일시 ",[16,34028,16347],{}," 한 줄 · 추천 답변 가독성(my-3·1.8) · 다크모드 비활성(CSS body bg)",[162,34031],{},[141,34033,34034,34037,34040,34042,34053],{},[162,34035,34036],{},"3-17",[162,34038,34039],{},"LLM 품질 라운드",[162,34041,245],{},[162,34043,34044,34047,34048,467,34050,34052],{},[28,34045,34046],{},"GPT-4o Vision"," 이미지 분석 + 캡션 · 표준답변 컨텍스트(최근 5건) · 4파트 답변 강제(인사\u002F공감\u002F핵심\u002F보조\u002F마무리) · maxTokens 8000 · 이미지 URL 절대화(",[16,34049,32926],{},[28,34051,32987],{},"(D축 안에서 빼냄)",[162,34054],{},[141,34056,34057,34060,34063,34065,34070],{},[162,34058,34059],{},"3-18",[162,34061,34062],{},"inquiry-only 모드 (답변 없는 문의)",[162,34064,245],{},[162,34066,34067,34069],{},[16,34068,16319],{}," 신설 — resp 없으면 5축 평가 생략하고 추천 답변 6개만 D축 wrap. 모호 시 commentary에 \"추가 확인 필요 정보\" 명시",[162,34071],{},[141,34073,34074,34077,34080,34082,34087],{},[162,34075,34076],{},"3-19",[162,34078,34079],{},"안내글 평가 엔드포인트",[162,34081,33245],{},[162,34083,34084,34086],{},[16,34085,16144],{}," — 직원 작성 안내글 3축(톤\u002F명확성\u002F완전성) + 3개 추천(짧은\u002F명료한\u002F자세한). 캐싱·hp_qa_eval 저장·hp_llm_log 감사 재활용",[162,34088,34089],{},"PMS UI 통합 미진 (코드만 들어가 있음)",[141,34091,34092,34095,34097,34099,34108],{},[162,34093,34094],{},"3-20",[162,34096,32946],{},[162,34098,245],{},[162,34100,34101,34102,34104,34105,34107],{},"5번째 hp_* 테이블 + ",[16,34103,16378],{}," + eval\u002Fgenerate에서 본문·응답 양쪽 ",[16,34106,16398],{}," 이미지 추출 → Vision 자동 분석 → title·description 저장 (src_path UNIQUE 캐시)",[162,34109,34110],{},"검증: post 149694 9장 한국어 캡션 정확",[36,34112,34114],{"id":34113},"p1-4-교육-및-연동-20","P1-4. 교육 및 연동 (20%)",[135,34116,34117,34131],{},[138,34118,34119],{},[141,34120,34121,34123,34125,34127,34129],{},[144,34122,13179],{},[144,34124,13182],{},[144,34126,7333],{},[144,34128,30487],{},[144,34130,2979],{},[157,34132,34133,34158,34173],{},[141,34134,34135,34138,34141,34143,34155],{},[162,34136,34137],{},"4-1",[162,34139,34140],{},"개발자 가이드 작성",[162,34142,33245],{},[162,34144,34145,34146,34149,34150,34152,34153],{},"CLAUDE.md 배포 절차·LLM 모델·secret 규칙, deploy.sh 사용법, history 시스템 메모리, 분류·표준답변·캐싱 메모리, ",[28,34147,34148],{},"OpenAPI(Scalar)"," 22 엔드포인트, ",[3257,34151,32817],{"href":22792}," 4단계 폴백, ",[3257,34154,3260],{"href":3259},[162,34156,34157],{},"자료 인덱싱·표준답변 큐레이션 가이드 미진",[141,34159,34160,34163,34166,34168,34170],{},[162,34161,34162],{},"4-2",[162,34164,34165],{},"개발자 교육",[162,34167,33819],{},[162,34169,538],{},[162,34171,34172],{},"상담사 사용 교육 미진",[141,34174,34175,34178,34181,34183,34185],{},[162,34176,34177],{},"4-3",[162,34179,34180],{},"서비스 연동",[162,34182,33819],{},[162,34184,538],{},[162,34186,34187],{},"기존 CS 시스템\u002FSSO 연동 미진. PMS DB는 Hyperdrive 경유 직접 연결로 확보",[36,34189,34191],{"id":34190},"p1-5-테스트-20","P1-5. 테스트 (20%)",[135,34193,34194,34208],{},[138,34195,34196],{},[141,34197,34198,34200,34202,34204,34206],{},[144,34199,13179],{},[144,34201,13182],{},[144,34203,7333],{},[144,34205,30487],{},[144,34207,2979],{},[157,34209,34210,34226,34241,34256,34283],{},[141,34211,34212,34215,34218,34220,34223],{},[162,34213,34214],{},"5-1",[162,34216,34217],{},"베타 오픈(테스트 서버)",[162,34219,33245],{},[162,34221,34222],{},"PMS·API 운영 단계 진입 — 사용자가 실 게시물(149694 등)로 일별 검증 중",[162,34224,34225],{},"정식 베타 사용자 범위·SLA 미진",[141,34227,34228,34231,34234,34236,34238],{},[162,34229,34230],{},"5-2",[162,34232,34233],{},"단위 테스트",[162,34235,33819],{},[162,34237,538],{},[162,34239,34240],{},"API·LLM·캐시 키 단위 테스트",[141,34242,34243,34246,34249,34251,34253],{},[162,34244,34245],{},"5-3",[162,34247,34248],{},"통합 테스트",[162,34250,33819],{},[162,34252,538],{},[162,34254,34255],{},"자료 업로드→인덱싱→검색→추천→채택 E2E",[141,34257,34258,34261,34264,34266,34280],{},[162,34259,34260],{},"5-4",[162,34262,34263],{},"오류 수정작업",[162,34265,33245],{},[162,34267,34268,34269,34272,34273,34276,34277,34279],{},"UI 호환성·CORS DELETE\u002FPATCH·Hyperdrive stale read·members 쿼리 91s→244ms·잘못된 빈 캐시·LOCK=NONE 미지원·HTML escape·이미지 상대경로(",[16,34270,34271],{},"..\u002Fdata\u002F",") 절대화·",[28,34274,34275],{},"OpenAI region 차단 우회","(BYOK→AI Gateway ",[16,34278,15599],{}," Provider+Authorization)·utf8mb4 UNIQUE prefix 191 조정 등 다회차",[162,34281,34282],{},"본 기능 결함 처리 진행 중",[141,34284,34285,34288,34291,34293,34295],{},[162,34286,34287],{},"5-5",[162,34289,34290],{},"최종 테스트",[162,34292,33819],{},[162,34294,538],{},[162,34296,34297],{},"UAT + 답변 품질 평가",[36,34299,34301],{"id":34300},"p1-6-이행-5","P1-6. 이행 (5%)",[135,34303,34304,34318],{},[138,34305,34306],{},[141,34307,34308,34310,34312,34314,34316],{},[144,34309,13179],{},[144,34311,13182],{},[144,34313,7333],{},[144,34315,30487],{},[144,34317,2979],{},[157,34319,34320,34348],{},[141,34321,34322,34325,34327,34329,34345],{},[162,34323,34324],{},"6-1",[162,34326,11529],{},[162,34328,33245],{},[162,34330,34331,34332,1365,34335,34340,34341,34344],{},"4개 repo 운영 (",[3257,34333,10806],{"href":10806,"rel":34334},[5049],[3257,34336,34339],{"href":34337,"rel":34338},"https:\u002F\u002Fmalgn-helper-%7Bpms,admin,_%7D.pages.dev",[5049],"https:\u002F\u002Fmalgn-helper-{pms,admin,_}.pages.dev","). API·PMS는 ",[28,34342,34343],{},"60+회 deploy.sh"," 이력으로 사실상 일일 배포",[162,34346,34347],{},"관리자·사용자 챗봇 본 기능 배포는 본격 진행 후",[141,34349,34350,34353,34356,34358,34360],{},[162,34351,34352],{},"6-2",[162,34354,34355],{},"완료 보고 및 공유",[162,34357,33819],{},[162,34359,538],{},[162,34361,34362],{},"Phase 2 입력자료 정리 포함",[33,34364],{},[11,34366,34368],{"id":34367},"phase-2-cs-상담-챗봇","Phase 2 — CS 상담 챗봇",[21,34370,34371],{},[24,34372,34373],{},"Phase 1의 인프라·자료·표준답변을 그대로 재사용하므로 새 인프라 셋업은 없다.\n신규 작업은 사용자 챗 UX, 챗 세션, 스트리밍·신뢰도 가드, 에스컬레이션, 운영 확장에 집중된다.",[24,34375,34376],{},"(Phase 1 완료 후 본격 진행. 현재는 모두 ⚪ 대기.)",[36,34378,34380],{"id":34379},"p2-1-착수분석-10","P2-1. 착수\u002F분석 (10%)",[135,34382,34383,34395],{},[138,34384,34385],{},[141,34386,34387,34389,34391,34393],{},[144,34388,13179],{},[144,34390,13182],{},[144,34392,7333],{},[144,34394,30487],{},[157,34396,34397,34408,34419,34430],{},[141,34398,34399,34401,34403,34405],{},[162,34400,33239],{},[162,34402,33242],{},[162,34404,33819],{},[162,34406,34407],{},"사용자 챗 UX, 익명\u002F세션 정책, 에스컬레이션 SLA, 안전 가드(PII·금칙어·환각)",[141,34409,34410,34412,34414,34416],{},[162,34411,33256],{},[162,34413,33259],{},[162,34415,33819],{},[162,34417,34418],{},"Phase 2 범위 합의서 (P1 자산 재사용 명시, 동영상\u002FQueue 도입 여부 결정)",[141,34420,34421,34423,34425,34427],{},[162,34422,33279],{},[162,34424,33282],{},[162,34426,33819],{},[162,34428,34429],{},"P1 환경의 챗봇 트래픽 대응 점검, AI Gateway 캐싱·rate 정책 재점검",[141,34431,34432,34434,34436,34438],{},[162,34433,33295],{},[162,34435,33298],{},[162,34437,33819],{},[162,34439,34440],{},"P1 운영 중 쌓인 자료·표준답변·미커버 질문 분석. 추가 도입 자료(동영상 등) 식별",[36,34442,34444],{"id":34443},"p2-2-설계-25","P2-2. 설계 (25%)",[135,34446,34447,34459],{},[138,34448,34449],{},[141,34450,34451,34453,34455,34457],{},[144,34452,13179],{},[144,34454,13182],{},[144,34456,7333],{},[144,34458,30487],{},[157,34460,34461,34472,34483,34494,34505,34516],{},[141,34462,34463,34465,34467,34469],{},[162,34464,33342],{},[162,34466,33345],{},[162,34468,33819],{},[162,34470,34471],{},"Phase 2 일정표",[141,34473,34474,34476,34478,34480],{},[162,34475,33366],{},[162,34477,33369],{},[162,34479,33819],{},[162,34481,34482],{},"확장 아키텍처(챗 세션·스트리밍·에스컬레이션, Queue\u002FIndexer Worker 도입 여부 결정)",[141,34484,34485,34487,34489,34491],{},[162,34486,33391],{},[162,34488,33394],{},[162,34490,33819],{},[162,34492,34493],{},"사용자 챗봇 화면 명세 + 관리자 추가 화면(챗 로그·에스컬레이션 큐·미커버 질문)",[141,34495,34496,34498,34500,34502],{},[162,34497,33421],{},[162,34499,33424],{},[162,34501,33819],{},[162,34503,34504],{},"chat_sessions·chat_messages·escalation_tickets·feedback 스키마 추가, 챗 로그 인덱스",[141,34506,34507,34509,34511,34513],{},[162,34508,33458],{},[162,34510,33461],{},[162,34512,33819],{},[162,34514,34515],{},"사용자 챗봇 시안(모바일 포함), 관리자 추가 화면 시안",[141,34517,34518,34520,34522,34524],{},[162,34519,33474],{},[162,34521,33477],{},[162,34523,33819],{},[162,34525,34526],{},"챗 PoC: 스트리밍 응답 + 출처 카드 + \"모름\" 분기 + 에스컬레이션 흐름 검증",[36,34528,34530],{"id":34529},"p2-3-구현-40","P2-3. 구현 (40%)",[215,34532,25683],{"id":34533},"db-1",[135,34535,34536,34548],{},[138,34537,34538],{},[141,34539,34540,34542,34544,34546],{},[144,34541,13179],{},[144,34543,13182],{},[144,34545,7333],{},[144,34547,30487],{},[157,34549,34550],{},[141,34551,34552,34554,34556,34558],{},[162,34553,33524],{},[162,34555,33527],{},[162,34557,33819],{},[162,34559,34560],{},"Phase 2 추가 스키마 마이그레이션(챗 세션\u002F메시지\u002F에스컬레이션\u002F피드백)",[215,34562,33567],{"id":34563},"디자인-퍼블리싱-1",[135,34565,34566,34578],{},[138,34567,34568],{},[141,34569,34570,34572,34574,34576],{},[144,34571,13179],{},[144,34573,13182],{},[144,34575,7333],{},[144,34577,30487],{},[157,34579,34580,34591,34605],{},[141,34581,34582,34584,34586,34588],{},[162,34583,33590],{},[162,34585,33593],{},[162,34587,33819],{},[162,34589,34590],{},"사용자 챗봇 디자인 + 관리자 추가 화면 디자인",[141,34592,34593,34595,34597,34599],{},[162,34594,33617],{},[162,34596,33620],{},[162,34598,33819],{},[162,34600,34601,34602,34604],{},"Nuxt 컴포넌트\u002F페이지(",[16,34603,47],{}," + admin 추가)",[141,34606,34607,34609,34611,34613],{},[162,34608,33644],{},[162,34610,33647],{},[162,34612,33819],{},[162,34614,34615],{},"검수 보고",[215,34617,34619],{"id":34618},"api","API",[135,34621,34622,34634],{},[138,34623,34624],{},[141,34625,34626,34628,34630,34632],{},[144,34627,13179],{},[144,34629,13182],{},[144,34631,7333],{},[144,34633,30487],{},[157,34635,34636,34647],{},[141,34637,34638,34640,34642,34644],{},[162,34639,33690],{},[162,34641,33693],{},[162,34643,33819],{},[162,34645,34646],{},"P1 워커 재사용 + 스트리밍 응답 인프라, 필요 시 Queue\u002FIndexer Worker 추가",[141,34648,34649,34651,34653,34655],{},[162,34650,33709],{},[162,34652,33712],{},[162,34654,33819],{},[162,34656,34657],{},"챗 세션\u002F메시지 API, 스트리밍 답변, 신뢰도 가드, 에스컬레이션 API, 피드백, 챗 로그 검색",[215,34659,33788,34661,78],{"id":34660},"admin-malgn-helper-admin-1",[16,34662,18],{},[135,34664,34665,34677],{},[138,34666,34667],{},[141,34668,34669,34671,34673,34675],{},[144,34670,13179],{},[144,34672,13182],{},[144,34674,7333],{},[144,34676,30487],{},[157,34678,34679,34690],{},[141,34680,34681,34683,34685,34687],{},[162,34682,33813],{},[162,34684,33816],{},[162,34686,33819],{},[162,34688,34689],{},"챗봇 운영 설정(시스템 프롬프트·캐싱·안전 가드), 미커버 질문 → 표준답변 후보 자동 추천",[141,34691,34692,34694,34696,34698],{},[162,34693,33833],{},[162,34695,33836],{},[162,34697,33819],{},[162,34699,34700],{},"챗 로그 열람·검색, 에스컬레이션 큐 처리, 응답 품질 샘플링 리뷰",[215,34702,34704,34705,78],{"id":34703},"front-malgn-helper","Front (",[16,34706,47],{},[135,34708,34709,34721],{},[138,34710,34711],{},[141,34712,34713,34715,34717,34719],{},[144,34714,13179],{},[144,34716,13182],{},[144,34718,7333],{},[144,34720,30487],{},[157,34722,34723],{},[141,34724,34725,34727,34730,34732],{},[162,34726,33871],{},[162,34728,34729],{},"사용자단 AI 챗봇 연동",[162,34731,33819],{},[162,34733,34734],{},"챗 UI(스트리밍·마크다운·출처 카드) + 세션 유지 + 에스컬레이션 버튼 + 모바일 반응형",[36,34736,34738],{"id":34737},"p2-4-교육-및-연동-20","P2-4. 교육 및 연동 (20%)",[135,34740,34741,34753],{},[138,34742,34743],{},[141,34744,34745,34747,34749,34751],{},[144,34746,13179],{},[144,34748,13182],{},[144,34750,7333],{},[144,34752,30487],{},[157,34754,34755,34766,34777],{},[141,34756,34757,34759,34761,34763],{},[162,34758,34137],{},[162,34760,34140],{},[162,34762,33819],{},[162,34764,34765],{},"챗봇 운영 가이드(프롬프트·캐싱·안전 가드·에스컬레이션) 추가",[141,34767,34768,34770,34772,34774],{},[162,34769,34162],{},[162,34771,34165],{},[162,34773,33819],{},[162,34775,34776],{},"상담사 교육(에스컬레이션 처리, 챗 로그 리뷰)",[141,34778,34779,34781,34783,34785],{},[162,34780,34177],{},[162,34782,34180],{},[162,34784,33819],{},[162,34786,34787],{},"에스컬레이션 채널 연동(Slack\u002F이메일\u002F티켓 시스템), 사이트 임베드(필요 시)",[36,34789,34791],{"id":34790},"p2-5-테스트-20","P2-5. 테스트 (20%)",[135,34793,34794,34806],{},[138,34795,34796],{},[141,34797,34798,34800,34802,34804],{},[144,34799,13179],{},[144,34801,13182],{},[144,34803,7333],{},[144,34805,30487],{},[157,34807,34808,34819,34830,34841,34852],{},[141,34809,34810,34812,34814,34816],{},[162,34811,34214],{},[162,34813,34217],{},[162,34815,33819],{},[162,34817,34818],{},"스테이징 챗봇 오픈, 제한 고객 베타",[141,34820,34821,34823,34825,34827],{},[162,34822,34230],{},[162,34824,34233],{},[162,34826,33819],{},[162,34828,34829],{},"챗 API\u002F스트리밍\u002F가드 단위 테스트",[141,34831,34832,34834,34836,34838],{},[162,34833,34245],{},[162,34835,34248],{},[162,34837,33819],{},[162,34839,34840],{},"챗 E2E(질문→검색→답변→인용→평가→에스컬레이션)",[141,34842,34843,34845,34847,34849],{},[162,34844,34260],{},[162,34846,34263],{},[162,34848,33819],{},[162,34850,34851],{},"결함 처리 이력",[141,34853,34854,34856,34858,34860],{},[162,34855,34287],{},[162,34857,34290],{},[162,34859,33819],{},[162,34861,34862],{},"UAT + 환각 가드 검증, \"모름\" 분기 검증, PII\u002F금칙어 검증, 부하 테스트",[36,34864,34866],{"id":34865},"p2-6-이행-5","P2-6. 이행 (5%)",[135,34868,34869,34881],{},[138,34870,34871],{},[141,34872,34873,34875,34877,34879],{},[144,34874,13179],{},[144,34876,13182],{},[144,34878,7333],{},[144,34880,30487],{},[157,34882,34883,34894],{},[141,34884,34885,34887,34889,34891],{},[162,34886,34324],{},[162,34888,11529],{},[162,34890,33819],{},[162,34892,34893],{},"프로덕션 배포(사용자 챗봇), 트래픽·비용 모니터링 강화",[141,34895,34896,34898,34900,34902],{},[162,34897,34352],{},[162,34899,34355],{},[162,34901,33819],{},[162,34903,34904],{},"Phase 2 완료 보고서, 운영 인수인계, 운영 KPI(응답 시간·정답률·에스컬레이션율) 정의",[33,34906],{},[36,34908,34910],{"id":34909},"phase-간-의존-관계-재사용","Phase 간 의존 관계 \u002F 재사용",[135,34912,34913,34923],{},[138,34914,34915],{},[141,34916,34917,34920],{},[144,34918,34919],{},"Phase 2 항목",[144,34921,34922],{},"재사용\u002F의존하는 Phase 1 산출물",[157,34924,34925,34933,34941,34949,34957,34965,34973,34981],{},[141,34926,34927,34930],{},[162,34928,34929],{},"P2-1-4 기본자료 검토",[162,34931,34932],{},"P1 운영 중 쌓인 자료·표준답변·미커버 질문",[141,34934,34935,34938],{},[162,34936,34937],{},"P2-2-2 아키텍처",[162,34939,34940],{},"P1 아키텍처(인프라·검색·추천 파이프라인)",[141,34942,34943,34946],{},[162,34944,34945],{},"P2-2-4 데이터 설계",[162,34947,34948],{},"P1 ERD에 챗\u002F에스컬레이션만 추가",[141,34950,34951,34954],{},[162,34952,34953],{},"P2-3-1 DB",[162,34955,34956],{},"P1 Aurora·Hyperdrive 그대로 사용",[141,34958,34959,34962],{},[162,34960,34961],{},"P2-3-5 워커",[162,34963,34964],{},"P1 Hono 워커·바인딩 재사용",[141,34966,34967,34970],{},[162,34968,34969],{},"P2-3-6 API",[162,34971,34972],{},"P1 추천답변 파이프라인을 챗봇용으로 확장",[141,34974,34975,34978],{},[162,34976,34977],{},"P2-3-9 챗봇",[162,34979,34980],{},"P1 표준답변·하이브리드 검색·AI Gateway 그대로 호출",[141,34982,34983,34986],{},[162,34984,34985],{},"P2-5-5 최종 테스트",[162,34987,34988],{},"P1 답변 품질 평가 방법론 재사용",[33,34990],{},[36,34992,34994],{"id":34993},"횡단cross-cutting-운영-도구-이번-사이클에서-추가","횡단(Cross-cutting) 운영 도구 — 이번 사이클에서 추가",[24,34996,34997],{},"Phase별 작업과 별도로 진행되는 운영 도구. 모두 ✅ 완료.",[135,34999,35000,35011],{},[138,35001,35002],{},[141,35003,35004,35006,35008],{},[144,35005,4143],{},[144,35007,30487],{},[144,35009,35010],{},"위치",[157,35012,35013,35028,35043,35060,35081],{},[141,35014,35015,35018,35024],{},[162,35016,35017],{},"일괄 배포 스크립트",[162,35019,35020,35023],{},[16,35021,35022],{},"commit + push + deploy + history append"," 4단계 일괄 처리",[162,35025,35026],{},[3257,35027,4840],{"href":32712},[141,35029,35030,35033,35039],{},[162,35031,35032],{},"일단위 작업 이력",[162,35034,35035,35038],{},[16,35036,35037],{},"history.yyyyMMdd.md"," 누적 기록 (덮어쓰기 X)",[162,35040,35041],{},[3257,35042,17380],{"href":32555},[141,35044,35045,35048,35053],{},[162,35046,35047],{},"다중 계정 Cloudflare",[162,35049,35050,35052],{},[16,35051,4825],{},"를 wrangler 설정에 명시 — env 변수 불필요",[162,35054,35055,35056,1365,35058],{},"각 repo의 ",[16,35057,4821],{},[16,35059,4701],{},[141,35061,35062,35065,35076],{},[162,35063,35064],{},"Pages 배포 표준",[162,35066,35067,35068,35070,35071,35073,35074],{},"Nuxt 3 ",[16,35069,24329],{}," preset, 출력 디렉토리 ",[16,35072,4878],{},", deploy 스크립트 ",[16,35075,4862],{},[162,35077,35078,35080],{},[3257,35079,9949],{"href":30492}," 배포 절차",[141,35082,35083,35086,35091],{},[162,35084,35085],{},"작성자 분류 규칙",[162,35087,35088,35090],{},[16,35089,128],{}," = 직원 \u002F 그 외 = 고객·협력사 (이름·패턴 추정 금지)",[162,35092,35093],{},"메모리 + 모든 분석 문서에 적용",[33,35095],{},[36,35097,35099],{"id":35098},"다음-단계-우선순위-제안","다음 단계 우선순위 (제안)",[21,35101,35102],{},[24,35103,35104,35105,35108,35109,407],{},"M1(인프라 Ready) ",[28,35106,35107],{},"통과",". 현재 M2(자료 수집 + 검색) 진입 직전 — ",[28,35110,35111],{},"이미지 자산은 hp_image_asset로 자동 캡션·축적 시작됨",[1925,35113,35114,35130,35138,35150,35157,35168,35176,35182],{},[57,35115,35116,35119,35120,35123,35124,35129],{},[28,35117,35118],{},"OpenSearch 도메인 셋업 + 인덱스 매핑"," — k-NN(",[16,35121,35122],{},"text-embedding-3-small"," 1536d) + BM25 하이브리드. 청크 단위 doc 구조 + ",[28,35125,35126,35128],{},[16,35127,77],{}," description","도 인덱싱(이미지가 텍스트로 검색됨)",[57,35131,35132,35137],{},[28,35133,35134,35136],{},[16,35135,18],{}," 자료 업로드 MVP"," — R2 업로드 → 텍스트 추출(PDF·MD·HTML) → 청크 → 임베딩 → OpenSearch 색인. 동기 처리(MVP), Queue는 동영상 도입 시",[57,35139,35140,35145,35146,35149],{},[28,35141,35142,35143,78],{},"챗봇 응답 파이프라인 (",[16,35144,15454],{}," — 표준답변 매칭 우선 → 하이브리드 검색 → LLM 답변 + 출처 인용 + 신뢰도 가드(\"모름\" 분기 → 에스컬레이션). PMS 측 Q&A 분석에서 검증된 prompt·캐시·감사 인프라 재사용. 답변에 관련 이미지 첨부 시 ",[16,35147,35148],{},"hp_image_asset.title\u002Fdescription","을 alt·캡션으로 활용",[57,35151,35152,35156],{},[28,35153,35154,15460],{},[16,35155,47],{}," — NotebookLM 스타일 본문+출처 패널, 스트리밍 응답, 모바일 반응형",[57,35158,35159,35162,35163,3351,35165,35167],{},[28,35160,35161],{},"관리자 추가 화면"," — 표준답변 관리(승인 워크플로) · 상담 로그 검토 · 에스컬레이션 큐 · ",[28,35164,749],{},[16,35166,77],{}," 검색·태그 큐레이션)",[57,35169,35170,2448,35173,35175],{},[28,35171,35172],{},"안내글 평가 PMS UI 통합",[16,35174,16144],{}," 엔드포인트는 있고 UI만 미통합 (작성자 staff 분기 + 모달 재활용)",[57,35177,35178,35181],{},[28,35179,35180],{},"inquiry-only 응답 UI 분기"," — D축만 있는 axes일 때 5축 평가 섹션 숨김 처리",[57,35183,35184,2448,35187,35189],{},[28,35185,35186],{},"(병행) PMS UX 잔여 폴리시",[16,35188,108],{}," LLM 행 모달 즉시 열기 · 정렬·필터 추가",[24,35191,35192,35193,35200],{},"위 1",[12602,35194,35195,35196,35199],{},"4가 완료되면 ",[28,35197,35198],{},"Phase 1 본 기능 베타"," 가능. 5는 Phase 1·2 공통 자산. 6","8은 단기 폴리시.",{"title":423,"searchDepth":3342,"depth":3342,"links":35202},[35203,35204,35218,35219,35220,35221,35231,35232,35233,35234,35235,35236,35244,35245,35246,35247,35248,35249],{"id":32561,"depth":3335,"text":32562},{"id":32679,"depth":3335,"text":32680,"children":35205},[35206,35207,35208,35210,35212,35214,35216,35217],{"id":23572,"depth":3342,"text":23572},{"id":32778,"depth":3342,"text":32779},{"id":32852,"depth":3342,"text":35209},"malgn-helper-api (Hono on Workers)",{"id":32953,"depth":3342,"text":35211},"malgn-helper-pms (Nuxt 3 \u002F Pages)",{"id":33025,"depth":3342,"text":35213},"malgn-helper-admin (Nuxt 3 \u002F Pages)",{"id":33038,"depth":3342,"text":35215},"malgn-helper (사용자 챗봇 \u002F Pages)",{"id":33051,"depth":3342,"text":33052},{"id":33101,"depth":3342,"text":33102},{"id":33140,"depth":3335,"text":33141},{"id":33215,"depth":3335,"text":33216},{"id":33318,"depth":3335,"text":33319},{"id":33497,"depth":3335,"text":33498,"children":35222},[35223,35224,35225,35227,35229],{"id":33501,"depth":3342,"text":25683},{"id":33566,"depth":3342,"text":33567},{"id":33664,"depth":3342,"text":35226},"API (malgn-helper-api)",{"id":33787,"depth":3342,"text":35228},"Admin (malgn-helper-admin)",{"id":33846,"depth":3342,"text":35230},"PMS 애드온 (malgn-helper-pms)",{"id":34113,"depth":3335,"text":34114},{"id":34190,"depth":3335,"text":34191},{"id":34300,"depth":3335,"text":34301},{"id":34379,"depth":3335,"text":34380},{"id":34443,"depth":3335,"text":34444},{"id":34529,"depth":3335,"text":34530,"children":35237},[35238,35239,35240,35241,35242],{"id":34533,"depth":3342,"text":25683},{"id":34563,"depth":3342,"text":33567},{"id":34618,"depth":3342,"text":34619},{"id":34660,"depth":3342,"text":35228},{"id":34703,"depth":3342,"text":35243},"Front (malgn-helper)",{"id":34737,"depth":3335,"text":34738},{"id":34790,"depth":3335,"text":34791},{"id":34865,"depth":3335,"text":34866},{"id":34909,"depth":3335,"text":34910},{"id":34993,"depth":3335,"text":34994},{"id":35098,"depth":3335,"text":35099},{},{"title":32519,"description":423},"4iFcyvZuLI7qQpYDzruFZ9ff1zTIJDfarjqF-pmDi9k",{"id":35254,"title":35255,"body":35256,"description":43902,"extension":4340,"meta":43903,"navigation":3338,"path":43904,"seo":43905,"stem":32808,"__hash__":43906},"docs\u002FWBS-TRACKER.md","WBS Live Tracker — 자체 완결 빌드 가이드",{"type":8,"value":35257,"toc":43869},[35258,35261,35268,35289,35291,35295,35298,35336,35339,35341,35345,35430,35435,35498,35508,35513,35530,35532,35536,35542,35918,35925,35928,36205,36209,36227,36229,36233,36239,36244,36283,36285,36289,36295,36362,36369,37211,37218,37275,37279,37343,37347,37443,37445,37449,37453,37477,37484,37492,43405,43409,43415,43444,43446,43450,43554,43569,43571,43575,43655,43657,43661,43664,43735,43738,43740,43744,43777,43779,43783,43866],[11,35259,35255],{"id":35260},"wbs-live-tracker-자체-완결-빌드-가이드",[24,35262,35263,35264,35267],{},"이 문서 하나만 있으면 어떤 프로젝트에서도 ",[28,35265,35266],{},"동일한 WBS Live Tracker 페이지","를 처음부터 만들 수 있다.\n프론트엔드(Nuxt) + 백엔드(Hono on Workers) + 영속화(R2) + 자동 저장 흐름을 전부 포함한다.",[21,35269,35270],{},[24,35271,35272,35273,1524,35275,35277,35278,35280,35281,35284,35285,35288],{},"본 프로젝트(",[16,35274,4588],{},[16,35276,4404],{},")에서 운영 중인 ",[16,35279,12910],{}," 페이지의 사양·코드·셋업 절차를 그대로 정리한 자체 완결 사양서.\n작업 항목 목록(=콘텐츠)은 ",[3257,35282,10422],{"href":35283},".\u002FWBS","에 있고, 본 문서는 ",[28,35286,35287],{},"그것을 보여주고 편집하는 시스템(=툴)"," 을 다룬다.",[33,35290],{},[36,35292,35294],{"id":35293},"_1-무엇을-만드는가","1. 무엇을 만드는가",[24,35296,35297],{},"웹 페이지 한 화면에 프로젝트 WBS(Work Breakdown Structure)를 표시·편집한다.",[54,35299,35300,35306,35312,35322,35328],{},[57,35301,35302,35305],{},[28,35303,35304],{},"읽기",": 단계별 진행률, 가중평균, 완료\u002F진행 카운트, 단계별 작업 표",[57,35307,35308,35311],{},[28,35309,35310],{},"편집(인라인)",": 산출물 URL · 목표일 · 완료일 · 상태 — 모두 표 안에서 즉시 수정",[57,35313,35314,35317,35318,35321],{},[28,35315,35316],{},"저장",": 모든 수정은 ",[28,35319,35320],{},"800ms 디바운스 후 R2에 자동 저장",". \"저장\" 버튼 없음",[57,35323,35324,35327],{},[28,35325,35326],{},"공유",": 같은 URL을 열면 다른 사용자도 최신 상태를 즉시 봄",[57,35329,35330,35332,35333,35335],{},[28,35331,19515],{},": 언제든 현재 상태를 ",[16,35334,15644],{},"으로 다운로드",[24,35337,35338],{},"전형적인 \"Notion 데이터베이스 + 자동 동기화\" 경험을 단일 JSON으로 단순화한 형태.",[33,35340],{},[36,35342,35344],{"id":35343},"_2-디자인-컨셉-soft-saas-notion-linear-height-풍","2. 디자인 컨셉 — Soft SaaS (Notion \u002F Linear \u002F Height 풍)",[135,35346,35347,35356],{},[138,35348,35349],{},[141,35350,35351,35354],{},[144,35352,35353],{},"토큰",[144,35355,1540],{},[157,35357,35358,35366,35374,35385,35400,35411,35419],{},[141,35359,35360,35363],{},[162,35361,35362],{},"톤",[162,35364,35365],{},"라이트, 부드러운 모서리, 옅은 회색 라인",[141,35367,35368,35371],{},[162,35369,35370],{},"폰트",[162,35372,35373],{},"Pretendard Variable (한국어 가독성)",[141,35375,35376,35379],{},[162,35377,35378],{},"색상",[162,35380,35381,35384],{},[16,35382,35383],{},"neutral"," 기반 + 의미색 5가지",[141,35386,35387,35390],{},[162,35388,35389],{},"모서리",[162,35391,35392,35395,35396,35399],{},[16,35393,35394],{},"rounded-xl"," (카드) \u002F ",[16,35397,35398],{},"rounded-md"," (인풋·칩)",[141,35401,35402,35405],{},[162,35403,35404],{},"그림자",[162,35406,35407,35408],{},"거의 없음. 플로팅 바만 ",[16,35409,35410],{},"shadow-lg shadow-neutral-900\u002F10",[141,35412,35413,35416],{},[162,35414,35415],{},"본문 폰트",[162,35417,35418],{},"14px 기본, 12~13px 보조",[141,35420,35421,35424],{},[162,35422,35423],{},"폭",[162,35425,35426,35429],{},[16,35427,35428],{},"max-w-5xl"," 중앙 정렬",[24,35431,35432],{},[28,35433,35434],{},"의미색 (상태 \u002F 진행률 \u002F 마감)",[135,35436,35437,35446],{},[138,35438,35439],{},[141,35440,35441,35443],{},[144,35442,1543],{},[144,35444,35445],{},"Tailwind",[157,35447,35448,35458,35468,35478,35488],{},[141,35449,35450,35453],{},[162,35451,35452],{},"완료 \u002F 70%+ 진행",[162,35454,35455],{},[16,35456,35457],{},"emerald-500 \u002F 50 \u002F 200 \u002F 700",[141,35459,35460,35463],{},[162,35461,35462],{},"진행 중 \u002F 30~69% \u002F 수정 감지",[162,35464,35465],{},[16,35466,35467],{},"amber-500 \u002F 50 \u002F 200 \u002F 700",[141,35469,35470,35473],{},[162,35471,35472],{},"대기 \u002F 0%",[162,35474,35475],{},[16,35476,35477],{},"neutral-300 \u002F 50 \u002F 200 \u002F 600",[141,35479,35480,35483],{},[162,35481,35482],{},"보류 \u002F 마감 초과",[162,35484,35485],{},[16,35486,35487],{},"rose-500 \u002F 50 \u002F 200 \u002F 700",[141,35489,35490,35493],{},[162,35491,35492],{},"저장 중",[162,35494,35495],{},[16,35496,35497],{},"sky-500",[24,35499,35500,35503,35504,35507],{},[28,35501,35502],{},"비주얼 앵커",": 6단계 이모지 ",[16,35505,35506],{},"🎯 📐 🛠️ 📚 🧪 🚀"," — 화면 상단·각 단계 헤더에 동일 위치로 반복해 시선 동선을 만든다.",[24,35509,35510],{},[28,35511,35512],{},"레이아웃 원칙",[1925,35514,35515,35518,35521,35524],{},[57,35516,35517],{},"상단 히어로 4칸(전체 진행률·완료·진행중 + 여유칸)으로 즉시 요약",[57,35519,35520],{},"단계별 한 줄 리스트(이름·요약·진행률 게이지·건수) → 클릭 시 해당 섹션으로 스크롤",[57,35522,35523],{},"단계별 표는 Notion 데이터베이스 스타일 — 헤더 얇은 회색, 행 호버, 셀이 곧 인풋",[57,35525,35526,35527,78],{},"우하단 플로팅 바로 자동 저장 상태 노출 (",[16,35528,35529],{},"수정 감지 → 저장 중 → 저장됨 · n초 전",[33,35531],{},[36,35533,35535],{"id":35534},"_3-데이터-모델","3. 데이터 모델",[215,35537,17775,35539,35541],{"id":35538},"_3-1-wbsjson-스키마",[16,35540,15644],{}," 스키마",[415,35543,35545],{"className":3294,"code":35544,"language":3296,"meta":423,"style":423},"type Status = \"done\" | \"in_progress\" | \"pending\" | \"blocked\";\n\ntype Task = {\n  id: string;              \u002F\u002F 전역 유니크 (예: \"P1-3-9\")\n  taskNo: string;          \u002F\u002F 단계 내 표시용 번호 (예: \"3-9\")\n  title: string;\n  status: Status;\n  note: string | null;\n  targetDate: string | null;      \u002F\u002F \"YYYY-MM-DD\"\n  completionDate: string | null;  \u002F\u002F \"YYYY-MM-DD\"\n  deliverableUrl: string | null;\n};\n\ntype Stage = {\n  id: string;       \u002F\u002F \"P1-1\" 등\n  name: string;\n  weight: number;   \u002F\u002F 합계 100\n  progress: number; \u002F\u002F 0~100\n  summary: string;\n  tasks: Task[];\n};\n\ntype WbsDoc = {\n  _meta: {\n    lastUpdated: string;  \u002F\u002F \"YYYY-MM-DD\" — 저장 시 자동 갱신\n    project: string;\n    source: string;       \u002F\u002F 외부 참조 문서 경로 (예: \"doc\u002FWBS.md\")\n    editGuide: string;    \u002F\u002F 편집 가이드 한 줄\n  };\n  phase1: { stages: Stage[] };\n};\n",[16,35546,35547,35576,35580,35591,35607,35622,35633,35644,35659,35678,35696,35711,35716,35720,35731,35745,35756,35772,35786,35797,35809,35813,35817,35828,35837,35851,35862,35876,35891,35895,35914],{"__ignoreMap":423},[2166,35548,35549,35551,35554,35556,35559,35561,35564,35566,35569,35571,35574],{"class":3301,"line":3302},[2166,35550,3306],{"class":3305},[2166,35552,35553],{"class":3309}," Status",[2166,35555,3313],{"class":3305},[2166,35557,35558],{"class":3316}," \"done\"",[2166,35560,3320],{"class":3305},[2166,35562,35563],{"class":3316}," \"in_progress\"",[2166,35565,3320],{"class":3305},[2166,35567,35568],{"class":3316}," \"pending\"",[2166,35570,3320],{"class":3305},[2166,35572,35573],{"class":3316}," \"blocked\"",[2166,35575,3332],{"class":3331},[2166,35577,35578],{"class":3301,"line":3335},[2166,35579,3339],{"emptyLinePlaceholder":3338},[2166,35581,35582,35584,35587,35589],{"class":3301,"line":3342},[2166,35583,3306],{"class":3305},[2166,35585,35586],{"class":3309}," Task",[2166,35588,3313],{"class":3305},[2166,35590,3393],{"class":3331},[2166,35592,35593,35596,35598,35601,35604],{"class":3301,"line":3368},[2166,35594,35595],{"class":3356},"  id",[2166,35597,3360],{"class":3305},[2166,35599,35600],{"class":3402}," string",[2166,35602,35603],{"class":3331},";              ",[2166,35605,35606],{"class":3422},"\u002F\u002F 전역 유니크 (예: \"P1-3-9\")\n",[2166,35608,35609,35612,35614,35616,35619],{"class":3301,"line":3396},[2166,35610,35611],{"class":3356},"  taskNo",[2166,35613,3360],{"class":3305},[2166,35615,35600],{"class":3402},[2166,35617,35618],{"class":3331},";          ",[2166,35620,35621],{"class":3422},"\u002F\u002F 단계 내 표시용 번호 (예: \"3-9\")\n",[2166,35623,35624,35627,35629,35631],{"class":3301,"line":3426},[2166,35625,35626],{"class":3356},"  title",[2166,35628,3360],{"class":3305},[2166,35630,35600],{"class":3402},[2166,35632,3332],{"class":3331},[2166,35634,35635,35638,35640,35642],{"class":3301,"line":3463},[2166,35636,35637],{"class":3356},"  status",[2166,35639,3360],{"class":3305},[2166,35641,35553],{"class":3309},[2166,35643,3332],{"class":3331},[2166,35645,35646,35649,35651,35653,35655,35657],{"class":3301,"line":3504},[2166,35647,35648],{"class":3356},"  note",[2166,35650,3360],{"class":3305},[2166,35652,35600],{"class":3402},[2166,35654,3320],{"class":3305},[2166,35656,25741],{"class":3402},[2166,35658,3332],{"class":3331},[2166,35660,35661,35664,35666,35668,35670,35672,35675],{"class":3301,"line":3538},[2166,35662,35663],{"class":3356},"  targetDate",[2166,35665,3360],{"class":3305},[2166,35667,35600],{"class":3402},[2166,35669,3320],{"class":3305},[2166,35671,25741],{"class":3402},[2166,35673,35674],{"class":3331},";      ",[2166,35676,35677],{"class":3422},"\u002F\u002F \"YYYY-MM-DD\"\n",[2166,35679,35680,35683,35685,35687,35689,35691,35694],{"class":3301,"line":3550},[2166,35681,35682],{"class":3356},"  completionDate",[2166,35684,3360],{"class":3305},[2166,35686,35600],{"class":3402},[2166,35688,3320],{"class":3305},[2166,35690,25741],{"class":3402},[2166,35692,35693],{"class":3331},";  ",[2166,35695,35677],{"class":3422},[2166,35697,35698,35701,35703,35705,35707,35709],{"class":3301,"line":3556},[2166,35699,35700],{"class":3356},"  deliverableUrl",[2166,35702,3360],{"class":3305},[2166,35704,35600],{"class":3402},[2166,35706,3320],{"class":3305},[2166,35708,25741],{"class":3402},[2166,35710,3332],{"class":3331},[2166,35712,35713],{"class":3301,"line":5367},[2166,35714,35715],{"class":3331},"};\n",[2166,35717,35718],{"class":3301,"line":5375},[2166,35719,3339],{"emptyLinePlaceholder":3338},[2166,35721,35722,35724,35727,35729],{"class":3301,"line":5392},[2166,35723,3306],{"class":3305},[2166,35725,35726],{"class":3309}," Stage",[2166,35728,3313],{"class":3305},[2166,35730,3393],{"class":3331},[2166,35732,35733,35735,35737,35739,35742],{"class":3301,"line":5404},[2166,35734,35595],{"class":3356},[2166,35736,3360],{"class":3305},[2166,35738,35600],{"class":3402},[2166,35740,35741],{"class":3331},";       ",[2166,35743,35744],{"class":3422},"\u002F\u002F \"P1-1\" 등\n",[2166,35746,35747,35750,35752,35754],{"class":3301,"line":5415},[2166,35748,35749],{"class":3356},"  name",[2166,35751,3360],{"class":3305},[2166,35753,35600],{"class":3402},[2166,35755,3332],{"class":3331},[2166,35757,35758,35761,35763,35766,35769],{"class":3301,"line":5421},[2166,35759,35760],{"class":3356},"  weight",[2166,35762,3360],{"class":3305},[2166,35764,35765],{"class":3402}," number",[2166,35767,35768],{"class":3331},";   ",[2166,35770,35771],{"class":3422},"\u002F\u002F 합계 100\n",[2166,35773,35774,35777,35779,35781,35783],{"class":3301,"line":5432},[2166,35775,35776],{"class":3356},"  progress",[2166,35778,3360],{"class":3305},[2166,35780,35765],{"class":3402},[2166,35782,5280],{"class":3331},[2166,35784,35785],{"class":3422},"\u002F\u002F 0~100\n",[2166,35787,35788,35791,35793,35795],{"class":3301,"line":5453},[2166,35789,35790],{"class":3356},"  summary",[2166,35792,3360],{"class":3305},[2166,35794,35600],{"class":3402},[2166,35796,3332],{"class":3331},[2166,35798,35799,35802,35804,35806],{"class":3301,"line":5459},[2166,35800,35801],{"class":3356},"  tasks",[2166,35803,3360],{"class":3305},[2166,35805,35586],{"class":3309},[2166,35807,35808],{"class":3331},"[];\n",[2166,35810,35811],{"class":3301,"line":8686},[2166,35812,35715],{"class":3331},[2166,35814,35815],{"class":3301,"line":8692},[2166,35816,3339],{"emptyLinePlaceholder":3338},[2166,35818,35819,35821,35824,35826],{"class":3301,"line":8698},[2166,35820,3306],{"class":3305},[2166,35822,35823],{"class":3309}," WbsDoc",[2166,35825,3313],{"class":3305},[2166,35827,3393],{"class":3331},[2166,35829,35830,35833,35835],{"class":3301,"line":8704},[2166,35831,35832],{"class":3356},"  _meta",[2166,35834,3360],{"class":3305},[2166,35836,3393],{"class":3331},[2166,35838,35839,35842,35844,35846,35848],{"class":3301,"line":8710},[2166,35840,35841],{"class":3356},"    lastUpdated",[2166,35843,3360],{"class":3305},[2166,35845,35600],{"class":3402},[2166,35847,35693],{"class":3331},[2166,35849,35850],{"class":3422},"\u002F\u002F \"YYYY-MM-DD\" — 저장 시 자동 갱신\n",[2166,35852,35853,35856,35858,35860],{"class":3301,"line":8716},[2166,35854,35855],{"class":3356},"    project",[2166,35857,3360],{"class":3305},[2166,35859,35600],{"class":3402},[2166,35861,3332],{"class":3331},[2166,35863,35864,35867,35869,35871,35873],{"class":3301,"line":8721},[2166,35865,35866],{"class":3356},"    source",[2166,35868,3360],{"class":3305},[2166,35870,35600],{"class":3402},[2166,35872,35741],{"class":3331},[2166,35874,35875],{"class":3422},"\u002F\u002F 외부 참조 문서 경로 (예: \"doc\u002FWBS.md\")\n",[2166,35877,35878,35881,35883,35885,35888],{"class":3301,"line":8727},[2166,35879,35880],{"class":3356},"    editGuide",[2166,35882,3360],{"class":3305},[2166,35884,35600],{"class":3402},[2166,35886,35887],{"class":3331},";    ",[2166,35889,35890],{"class":3422},"\u002F\u002F 편집 가이드 한 줄\n",[2166,35892,35893],{"class":3301,"line":8733},[2166,35894,3553],{"class":3331},[2166,35896,35897,35900,35902,35904,35907,35909,35911],{"class":3301,"line":8739},[2166,35898,35899],{"class":3356},"  phase1",[2166,35901,3360],{"class":3305},[2166,35903,25680],{"class":3331},[2166,35905,35906],{"class":3356},"stages",[2166,35908,3360],{"class":3305},[2166,35910,35726],{"class":3309},[2166,35912,35913],{"class":3331},"[] };\n",[2166,35915,35916],{"class":3301,"line":8745},[2166,35917,35715],{"class":3331},[215,35919,35921,35922,78],{"id":35920},"_3-2-초기-시드-예시-publicwbsjson","3-2. 초기 시드 예시 (",[16,35923,35924],{},"public\u002Fwbs.json",[24,35926,35927],{},"R2가 비었을 때 fallback으로 한 번 읽힌 뒤, 첫 저장 때 R2에 복사된다. 이후 시드 파일은 사용되지 않는다.",[415,35929,35932],{"className":35930,"code":35931,"language":3445,"meta":423,"style":423},"language-json shiki shiki-themes github-light github-dark","{\n  \"_meta\": {\n    \"lastUpdated\": \"2026-05-29\",\n    \"project\": \"Malgn Helper\",\n    \"source\": \"doc\u002FWBS.md\",\n    \"editGuide\": \"각 항목 수정 즉시 API(R2)에 자동 저장됨\"\n  },\n  \"phase1\": {\n    \"stages\": [\n      {\n        \"id\": \"P1-1\",\n        \"name\": \"착수 \u002F 분석\",\n        \"weight\": 10,\n        \"progress\": 70,\n        \"summary\": \"요구사항·범위·이해관계자 정리\",\n        \"tasks\": [\n          {\n            \"id\": \"P1-1-1\",\n            \"taskNo\": \"1-1\",\n            \"title\": \"이해관계자 인터뷰\",\n            \"status\": \"done\",\n            \"note\": null,\n            \"targetDate\": \"2026-05-20\",\n            \"completionDate\": \"2026-05-18\",\n            \"deliverableUrl\": null\n          }\n        ]\n      }\n    ]\n  }\n}\n",[16,35933,35934,35938,35946,35958,35970,35982,35992,35996,36003,36011,36015,36027,36039,36050,36062,36074,36081,36086,36098,36110,36122,36134,36146,36158,36170,36180,36185,36189,36193,36197,36201],{"__ignoreMap":423},[2166,35935,35936],{"class":3301,"line":3302},[2166,35937,13095],{"class":3331},[2166,35939,35940,35943],{"class":3301,"line":3335},[2166,35941,35942],{"class":3402},"  \"_meta\"",[2166,35944,35945],{"class":3331},": {\n",[2166,35947,35948,35951,35953,35956],{"class":3301,"line":3342},[2166,35949,35950],{"class":3402},"    \"lastUpdated\"",[2166,35952,4664],{"class":3331},[2166,35954,35955],{"class":3316},"\"2026-05-29\"",[2166,35957,5401],{"class":3331},[2166,35959,35960,35963,35965,35968],{"class":3301,"line":3368},[2166,35961,35962],{"class":3402},"    \"project\"",[2166,35964,4664],{"class":3331},[2166,35966,35967],{"class":3316},"\"Malgn Helper\"",[2166,35969,5401],{"class":3331},[2166,35971,35972,35975,35977,35980],{"class":3301,"line":3396},[2166,35973,35974],{"class":3402},"    \"source\"",[2166,35976,4664],{"class":3331},[2166,35978,35979],{"class":3316},"\"doc\u002FWBS.md\"",[2166,35981,5401],{"class":3331},[2166,35983,35984,35987,35989],{"class":3301,"line":3426},[2166,35985,35986],{"class":3402},"    \"editGuide\"",[2166,35988,4664],{"class":3331},[2166,35990,35991],{"class":3316},"\"각 항목 수정 즉시 API(R2)에 자동 저장됨\"\n",[2166,35993,35994],{"class":3301,"line":3463},[2166,35995,24379],{"class":3331},[2166,35997,35998,36001],{"class":3301,"line":3504},[2166,35999,36000],{"class":3402},"  \"phase1\"",[2166,36002,35945],{"class":3331},[2166,36004,36005,36008],{"class":3301,"line":3538},[2166,36006,36007],{"class":3402},"    \"stages\"",[2166,36009,36010],{"class":3331},": [\n",[2166,36012,36013],{"class":3301,"line":3550},[2166,36014,13115],{"class":3331},[2166,36016,36017,36020,36022,36025],{"class":3301,"line":3556},[2166,36018,36019],{"class":3402},"        \"id\"",[2166,36021,4664],{"class":3331},[2166,36023,36024],{"class":3316},"\"P1-1\"",[2166,36026,5401],{"class":3331},[2166,36028,36029,36032,36034,36037],{"class":3301,"line":5367},[2166,36030,36031],{"class":3402},"        \"name\"",[2166,36033,4664],{"class":3331},[2166,36035,36036],{"class":3316},"\"착수 \u002F 분석\"",[2166,36038,5401],{"class":3331},[2166,36040,36041,36044,36046,36048],{"class":3301,"line":5375},[2166,36042,36043],{"class":3402},"        \"weight\"",[2166,36045,4664],{"class":3331},[2166,36047,23196],{"class":3402},[2166,36049,5401],{"class":3331},[2166,36051,36052,36055,36057,36060],{"class":3301,"line":5392},[2166,36053,36054],{"class":3402},"        \"progress\"",[2166,36056,4664],{"class":3331},[2166,36058,36059],{"class":3402},"70",[2166,36061,5401],{"class":3331},[2166,36063,36064,36067,36069,36072],{"class":3301,"line":5404},[2166,36065,36066],{"class":3402},"        \"summary\"",[2166,36068,4664],{"class":3331},[2166,36070,36071],{"class":3316},"\"요구사항·범위·이해관계자 정리\"",[2166,36073,5401],{"class":3331},[2166,36075,36076,36079],{"class":3301,"line":5415},[2166,36077,36078],{"class":3402},"        \"tasks\"",[2166,36080,36010],{"class":3331},[2166,36082,36083],{"class":3301,"line":5421},[2166,36084,36085],{"class":3331},"          {\n",[2166,36087,36088,36091,36093,36096],{"class":3301,"line":5432},[2166,36089,36090],{"class":3402},"            \"id\"",[2166,36092,4664],{"class":3331},[2166,36094,36095],{"class":3316},"\"P1-1-1\"",[2166,36097,5401],{"class":3331},[2166,36099,36100,36103,36105,36108],{"class":3301,"line":5453},[2166,36101,36102],{"class":3402},"            \"taskNo\"",[2166,36104,4664],{"class":3331},[2166,36106,36107],{"class":3316},"\"1-1\"",[2166,36109,5401],{"class":3331},[2166,36111,36112,36115,36117,36120],{"class":3301,"line":5459},[2166,36113,36114],{"class":3402},"            \"title\"",[2166,36116,4664],{"class":3331},[2166,36118,36119],{"class":3316},"\"이해관계자 인터뷰\"",[2166,36121,5401],{"class":3331},[2166,36123,36124,36127,36129,36132],{"class":3301,"line":8686},[2166,36125,36126],{"class":3402},"            \"status\"",[2166,36128,4664],{"class":3331},[2166,36130,36131],{"class":3316},"\"done\"",[2166,36133,5401],{"class":3331},[2166,36135,36136,36139,36141,36144],{"class":3301,"line":8692},[2166,36137,36138],{"class":3402},"            \"note\"",[2166,36140,4664],{"class":3331},[2166,36142,36143],{"class":3402},"null",[2166,36145,5401],{"class":3331},[2166,36147,36148,36151,36153,36156],{"class":3301,"line":8698},[2166,36149,36150],{"class":3402},"            \"targetDate\"",[2166,36152,4664],{"class":3331},[2166,36154,36155],{"class":3316},"\"2026-05-20\"",[2166,36157,5401],{"class":3331},[2166,36159,36160,36163,36165,36168],{"class":3301,"line":8704},[2166,36161,36162],{"class":3402},"            \"completionDate\"",[2166,36164,4664],{"class":3331},[2166,36166,36167],{"class":3316},"\"2026-05-18\"",[2166,36169,5401],{"class":3331},[2166,36171,36172,36175,36177],{"class":3301,"line":8710},[2166,36173,36174],{"class":3402},"            \"deliverableUrl\"",[2166,36176,4664],{"class":3331},[2166,36178,36179],{"class":3402},"null\n",[2166,36181,36182],{"class":3301,"line":8716},[2166,36183,36184],{"class":3331},"          }\n",[2166,36186,36187],{"class":3301,"line":8721},[2166,36188,13145],{"class":3331},[2166,36190,36191],{"class":3301,"line":8727},[2166,36192,13150],{"class":3331},[2166,36194,36195],{"class":3301,"line":8733},[2166,36196,13155],{"class":3331},[2166,36198,36199],{"class":3301,"line":8739},[2166,36200,5456],{"class":3331},[2166,36202,36203],{"class":3301,"line":8745},[2166,36204,3559],{"class":3331},[215,36206,36208],{"id":36207},"_3-3-비즈니스-규칙","3-3. 비즈니스 규칙",[54,36210,36211,36216,36221],{},[57,36212,36213],{},[16,36214,36215],{},"weightedAverage = round(Σ(stage.progress × stage.weight) \u002F Σ(stage.weight), 0.1)",[57,36217,36218],{},[16,36219,36220],{},"isOverdue(task) = task.status !== \"done\" && task.targetDate && task.targetDate \u003C _meta.lastUpdated",[57,36222,36223,36224,36226],{},"빈 문자열은 모두 ",[16,36225,36143],{},"로 정규화 (입력값 ↔ JSON 직렬화 안정성)",[33,36228],{},[36,36230,36232],{"id":36231},"_4-아키텍처","4. 아키텍처",[415,36234,36237],{"className":36235,"code":36236,"language":420},[418],"브라우저 (Nuxt 페이지 \u002Fwbs)\n    │\n    │  GET  \u002Fwbs   ← 초기 로드\n    │  PUT  \u002Fwbs   ← 800ms 디바운스 후\n    ▼\n\u003Capi> Worker (Hono on Cloudflare Workers)\n    │\n    │  R2.get(\"wbs\u002Fwbs.json\")\n    │  R2.put(\"wbs\u002Fwbs.json\", body)\n    ▼\nCloudflare R2 bucket\n",[16,36238,36236],{"__ignoreMap":423},[24,36240,36241],{},[28,36242,36243],{},"핵심 결정",[54,36245,36246,36255,36261,36267,36277],{},[57,36247,36248,3351,36251,36254],{},[28,36249,36250],{},"R2 단일 객체",[16,36252,36253],{},"wbs\u002Fwbs.json",")에 전체 문서를 통째로 저장. 동시 편집은 가정하지 않음(team 내부 도구).",[57,36256,36257,36260],{},[28,36258,36259],{},"DB 미사용",". WBS 1건만 다루므로 D1\u002FMySQL은 과도. R2 + JSON으로 충분.",[57,36262,36263,36266],{},[28,36264,36265],{},"localStorage 미사용",". 자동 저장 + 공유가 목표이므로 클라이언트 로컬 상태는 두지 않음.",[57,36268,36269,36276],{},[28,36270,36271,36272,36275],{},"초기 시드는 ",[16,36273,36274],{},"public\u002F","에 정적 호스팅"," → R2 비었을 때 1회만 사용.",[57,36278,36279,36282],{},[28,36280,36281],{},"인증은 의도적으로 생략","(MVP). 사내 운영자만 URL을 알도록 운영. 필요 시 Cloudflare Access로 페이지 + API 동시 보호.",[33,36284],{},[36,36286,36288],{"id":36287},"_5-백엔드-구현-hono-on-workers","5. 백엔드 구현 (Hono on Workers)",[215,36290,36292,36293],{"id":36291},"_5-1-wranglerjsonc","5-1. ",[16,36294,4821],{},[415,36296,36298],{"className":13086,"code":36297,"language":13088,"meta":423,"style":423},"{\n  \"$schema\": \"https:\u002F\u002Fjson.schemastore.org\u002Fwrangler.json\",\n  \"name\": \"\u003Capi-worker-name>\",\n  \"account_id\": \"\u003Cyour-account-id>\",\n  \"main\": \"src\u002Findex.ts\",\n  \"compatibility_date\": \"2026-05-27\",\n  \"compatibility_flags\": [\"nodejs_compat\"],\n  \"observability\": { \"enabled\": true },\n\n  \"r2_buckets\": [\n    { \"binding\": \"R2\", \"bucket_name\": \"\u003Cyour-r2-bucket>\" }\n  ]\n}\n",[16,36299,36300,36304,36309,36314,36319,36324,36329,36334,36339,36343,36348,36353,36358],{"__ignoreMap":423},[2166,36301,36302],{"class":3301,"line":3302},[2166,36303,13095],{},[2166,36305,36306],{"class":3301,"line":3335},[2166,36307,36308],{},"  \"$schema\": \"https:\u002F\u002Fjson.schemastore.org\u002Fwrangler.json\",\n",[2166,36310,36311],{"class":3301,"line":3342},[2166,36312,36313],{},"  \"name\": \"\u003Capi-worker-name>\",\n",[2166,36315,36316],{"class":3301,"line":3368},[2166,36317,36318],{},"  \"account_id\": \"\u003Cyour-account-id>\",\n",[2166,36320,36321],{"class":3301,"line":3396},[2166,36322,36323],{},"  \"main\": \"src\u002Findex.ts\",\n",[2166,36325,36326],{"class":3301,"line":3426},[2166,36327,36328],{},"  \"compatibility_date\": \"2026-05-27\",\n",[2166,36330,36331],{"class":3301,"line":3463},[2166,36332,36333],{},"  \"compatibility_flags\": [\"nodejs_compat\"],\n",[2166,36335,36336],{"class":3301,"line":3504},[2166,36337,36338],{},"  \"observability\": { \"enabled\": true },\n",[2166,36340,36341],{"class":3301,"line":3538},[2166,36342,3339],{"emptyLinePlaceholder":3338},[2166,36344,36345],{"class":3301,"line":3550},[2166,36346,36347],{},"  \"r2_buckets\": [\n",[2166,36349,36350],{"class":3301,"line":3556},[2166,36351,36352],{},"    { \"binding\": \"R2\", \"bucket_name\": \"\u003Cyour-r2-bucket>\" }\n",[2166,36354,36355],{"class":3301,"line":5367},[2166,36356,36357],{},"  ]\n",[2166,36359,36360],{"class":3301,"line":5375},[2166,36361,3559],{},[215,36363,36365,36366,36368],{"id":36364},"_5-2-srcindexts-전체","5-2. ",[16,36367,10130],{}," (전체)",[415,36370,36372],{"className":3294,"code":36371,"language":3296,"meta":423,"style":423},"import { Hono } from \"hono\";\nimport { cors } from \"hono\u002Fcors\";\n\ntype Bindings = {\n  R2: R2Bucket;\n};\n\nconst app = new Hono\u003C{ Bindings: Bindings }>();\n\napp.use(\n  \"*\",\n  cors({\n    origin: (origin) => {\n      if (!origin) return \"*\";\n      if (\u002F\\.pages\\.dev$\u002F.test(origin)) return origin;\n      if (\u002F\\.malgnsoft\\.com$\u002F.test(origin)) return origin;   \u002F\u002F ← 자기 도메인 패턴으로 교체\n      if (\u002F^https?:\\\u002F\\\u002F(localhost|127\\.0\\.0\\.1)(:\\d+)?$\u002F.test(origin)) return origin;\n      return null;\n    },\n    allowMethods: [\"GET\", \"PUT\", \"POST\", \"OPTIONS\"],\n    allowHeaders: [\"Content-Type\"],\n    maxAge: 86400,\n  }),\n);\n\napp.get(\"\u002F\", (c) => c.json({ name: \"wbs-api\", status: \"ok\" }));\napp.get(\"\u002Fhealthz\", (c) => c.json({ ok: true }));\n\nconst WBS_KEY = \"wbs\u002Fwbs.json\";\n\napp.get(\"\u002Fwbs\", async (c) => {\n  const obj = await c.env.R2.get(WBS_KEY);\n  if (!obj) return c.json({ exists: false }, 404);\n  const body = await obj.text();\n  return new Response(body, {\n    headers: {\n      \"Content-Type\": \"application\u002Fjson; charset=utf-8\",\n      \"Cache-Control\": \"no-store\",\n      ETag: obj.httpEtag,\n    },\n  });\n});\n\napp.put(\"\u002Fwbs\", async (c) => {\n  const text = await c.req.text();\n  try {\n    JSON.parse(text);\n  } catch {\n    return c.json({ error: \"invalid json\" }, 400);\n  }\n  if (text.length > 1_000_000) {\n    return c.json({ error: \"payload too large\" }, 413);\n  }\n  await c.env.R2.put(WBS_KEY, text, {\n    httpMetadata: { contentType: \"application\u002Fjson; charset=utf-8\" },\n  });\n  return c.json({ ok: true, size: text.length, savedAt: new Date().toISOString() });\n});\n\nexport default app;\n",[16,36373,36374,36388,36402,36406,36417,36429,36433,36437,36465,36469,36477,36484,36491,36508,36527,36566,36602,36667,36676,36681,36706,36716,36726,36731,36735,36739,36778,36808,36812,36826,36830,36855,36883,36912,36930,36942,36947,36959,36971,36976,36980,36985,36989,36993,37018,37035,37041,37054,37062,37082,37086,37104,37124,37128,37147,37156,37160,37194,37198,37202],{"__ignoreMap":423},[2166,36375,36376,36378,36381,36383,36386],{"class":3301,"line":3302},[2166,36377,5214],{"class":3305},[2166,36379,36380],{"class":3331}," { Hono } ",[2166,36382,5220],{"class":3305},[2166,36384,36385],{"class":3316}," \"hono\"",[2166,36387,3332],{"class":3331},[2166,36389,36390,36392,36395,36397,36400],{"class":3301,"line":3335},[2166,36391,5214],{"class":3305},[2166,36393,36394],{"class":3331}," { cors } ",[2166,36396,5220],{"class":3305},[2166,36398,36399],{"class":3316}," \"hono\u002Fcors\"",[2166,36401,3332],{"class":3331},[2166,36403,36404],{"class":3301,"line":3342},[2166,36405,3339],{"emptyLinePlaceholder":3338},[2166,36407,36408,36410,36413,36415],{"class":3301,"line":3368},[2166,36409,3306],{"class":3305},[2166,36411,36412],{"class":3309}," Bindings",[2166,36414,3313],{"class":3305},[2166,36416,3393],{"class":3331},[2166,36418,36419,36422,36424,36427],{"class":3301,"line":3396},[2166,36420,36421],{"class":3356},"  R2",[2166,36423,3360],{"class":3305},[2166,36425,36426],{"class":3309}," R2Bucket",[2166,36428,3332],{"class":3331},[2166,36430,36431],{"class":3301,"line":3426},[2166,36432,35715],{"class":3331},[2166,36434,36435],{"class":3301,"line":3463},[2166,36436,3339],{"emptyLinePlaceholder":3338},[2166,36438,36439,36441,36444,36446,36449,36452,36455,36458,36460,36462],{"class":3301,"line":3504},[2166,36440,5234],{"class":3305},[2166,36442,36443],{"class":3402}," app",[2166,36445,3313],{"class":3305},[2166,36447,36448],{"class":3305}," new",[2166,36450,36451],{"class":3309}," Hono",[2166,36453,36454],{"class":3331},"\u003C{ ",[2166,36456,36457],{"class":3356},"Bindings",[2166,36459,3360],{"class":3305},[2166,36461,36412],{"class":3309},[2166,36463,36464],{"class":3331}," }>();\n",[2166,36466,36467],{"class":3301,"line":3538},[2166,36468,3339],{"emptyLinePlaceholder":3338},[2166,36470,36471,36473,36475],{"class":3301,"line":3550},[2166,36472,5474],{"class":3331},[2166,36474,5477],{"class":3309},[2166,36476,5245],{"class":3331},[2166,36478,36479,36482],{"class":3301,"line":3556},[2166,36480,36481],{"class":3316},"  \"*\"",[2166,36483,5401],{"class":3331},[2166,36485,36486,36489],{"class":3301,"line":5367},[2166,36487,36488],{"class":3309},"  cors",[2166,36490,26365],{"class":3331},[2166,36492,36493,36496,36499,36502,36504,36506],{"class":3301,"line":5375},[2166,36494,36495],{"class":3309},"    origin",[2166,36497,36498],{"class":3331},": (",[2166,36500,36501],{"class":3356},"origin",[2166,36503,3387],{"class":3331},[2166,36505,3390],{"class":3305},[2166,36507,3393],{"class":3331},[2166,36509,36510,36513,36515,36517,36520,36522,36525],{"class":3301,"line":5392},[2166,36511,36512],{"class":3305},"      if",[2166,36514,1305],{"class":3331},[2166,36516,3434],{"class":3305},[2166,36518,36519],{"class":3331},"origin) ",[2166,36521,3440],{"class":3305},[2166,36523,36524],{"class":3316}," \"*\"",[2166,36526,3332],{"class":3331},[2166,36528,36529,36531,36533,36535,36539,36543,36545,36548,36551,36553,36555,36558,36561,36563],{"class":3301,"line":5404},[2166,36530,36512],{"class":3305},[2166,36532,1305],{"class":3331},[2166,36534,530],{"class":3316},[2166,36536,36538],{"class":36537},"snhLl","\\.",[2166,36540,36542],{"class":36541},"sA_wV","pages",[2166,36544,36538],{"class":36537},[2166,36546,36547],{"class":36541},"dev",[2166,36549,36550],{"class":3305},"$",[2166,36552,530],{"class":3316},[2166,36554,407],{"class":3331},[2166,36556,36557],{"class":3309},"test",[2166,36559,36560],{"class":3331},"(origin)) ",[2166,36562,3440],{"class":3305},[2166,36564,36565],{"class":3331}," origin;\n",[2166,36567,36568,36570,36572,36574,36576,36579,36581,36584,36586,36588,36590,36592,36594,36596,36599],{"class":3301,"line":5415},[2166,36569,36512],{"class":3305},[2166,36571,1305],{"class":3331},[2166,36573,530],{"class":3316},[2166,36575,36538],{"class":36537},[2166,36577,36578],{"class":36541},"malgnsoft",[2166,36580,36538],{"class":36537},[2166,36582,36583],{"class":36541},"com",[2166,36585,36550],{"class":3305},[2166,36587,530],{"class":3316},[2166,36589,407],{"class":3331},[2166,36591,36557],{"class":3309},[2166,36593,36560],{"class":3331},[2166,36595,3440],{"class":3305},[2166,36597,36598],{"class":3331}," origin;   ",[2166,36600,36601],{"class":3422},"\u002F\u002F ← 자기 도메인 패턴으로 교체\n",[2166,36603,36604,36606,36608,36610,36613,36616,36618,36620,36623,36626,36628,36631,36633,36635,36637,36639,36641,36644,36647,36650,36652,36655,36657,36659,36661,36663,36665],{"class":3301,"line":5421},[2166,36605,36512],{"class":3305},[2166,36607,1305],{"class":3331},[2166,36609,530],{"class":3316},[2166,36611,36612],{"class":3305},"^",[2166,36614,36615],{"class":36541},"https",[2166,36617,25723],{"class":3305},[2166,36619,3360],{"class":36541},[2166,36621,36622],{"class":36537},"\\\u002F\\\u002F",[2166,36624,36625],{"class":36541},"(localhost",[2166,36627,25695],{"class":3305},[2166,36629,36630],{"class":36541},"127",[2166,36632,36538],{"class":36537},[2166,36634,20067],{"class":36541},[2166,36636,36538],{"class":36537},[2166,36638,20067],{"class":36541},[2166,36640,36538],{"class":36537},[2166,36642,36643],{"class":36541},"1)(:",[2166,36645,36646],{"class":3402},"\\d",[2166,36648,36649],{"class":3305},"+",[2166,36651,78],{"class":36541},[2166,36653,36654],{"class":3305},"?$",[2166,36656,530],{"class":3316},[2166,36658,407],{"class":3331},[2166,36660,36557],{"class":3309},[2166,36662,36560],{"class":3331},[2166,36664,3440],{"class":3305},[2166,36666,36565],{"class":3331},[2166,36668,36669,36672,36674],{"class":3301,"line":5432},[2166,36670,36671],{"class":3305},"      return",[2166,36673,25741],{"class":3402},[2166,36675,3332],{"class":3331},[2166,36677,36678],{"class":3301,"line":5453},[2166,36679,36680],{"class":3331},"    },\n",[2166,36682,36683,36686,36689,36691,36694,36696,36699,36701,36704],{"class":3301,"line":5459},[2166,36684,36685],{"class":3331},"    allowMethods: [",[2166,36687,36688],{"class":3316},"\"GET\"",[2166,36690,105],{"class":3331},[2166,36692,36693],{"class":3316},"\"PUT\"",[2166,36695,105],{"class":3331},[2166,36697,36698],{"class":3316},"\"POST\"",[2166,36700,105],{"class":3331},[2166,36702,36703],{"class":3316},"\"OPTIONS\"",[2166,36705,26401],{"class":3331},[2166,36707,36708,36711,36714],{"class":3301,"line":8686},[2166,36709,36710],{"class":3331},"    allowHeaders: [",[2166,36712,36713],{"class":3316},"\"Content-Type\"",[2166,36715,26401],{"class":3331},[2166,36717,36718,36721,36724],{"class":3301,"line":8692},[2166,36719,36720],{"class":3331},"    maxAge: ",[2166,36722,36723],{"class":3402},"86400",[2166,36725,5401],{"class":3331},[2166,36727,36728],{"class":3301,"line":8698},[2166,36729,36730],{"class":3331},"  }),\n",[2166,36732,36733],{"class":3301,"line":8704},[2166,36734,3460],{"class":3331},[2166,36736,36737],{"class":3301,"line":8710},[2166,36738,3339],{"emptyLinePlaceholder":3338},[2166,36740,36741,36743,36745,36747,36750,36753,36755,36757,36759,36761,36763,36766,36769,36772,36775],{"class":3301,"line":8716},[2166,36742,5474],{"class":3331},[2166,36744,3411],{"class":3309},[2166,36746,3351],{"class":3331},[2166,36748,36749],{"class":3316},"\"\u002F\"",[2166,36751,36752],{"class":3331},", (",[2166,36754,3379],{"class":3356},[2166,36756,3387],{"class":3331},[2166,36758,3390],{"class":3305},[2166,36760,3408],{"class":3331},[2166,36762,3445],{"class":3309},[2166,36764,36765],{"class":3331},"({ name: ",[2166,36767,36768],{"class":3316},"\"wbs-api\"",[2166,36770,36771],{"class":3331},", status: ",[2166,36773,36774],{"class":3316},"\"ok\"",[2166,36776,36777],{"class":3331}," }));\n",[2166,36779,36780,36782,36784,36786,36789,36791,36793,36795,36797,36799,36801,36804,36806],{"class":3301,"line":8721},[2166,36781,5474],{"class":3331},[2166,36783,3411],{"class":3309},[2166,36785,3351],{"class":3331},[2166,36787,36788],{"class":3316},"\"\u002Fhealthz\"",[2166,36790,36752],{"class":3331},[2166,36792,3379],{"class":3356},[2166,36794,3387],{"class":3331},[2166,36796,3390],{"class":3305},[2166,36798,3408],{"class":3331},[2166,36800,3445],{"class":3309},[2166,36802,36803],{"class":3331},"({ ok: ",[2166,36805,21876],{"class":3402},[2166,36807,36777],{"class":3331},[2166,36809,36810],{"class":3301,"line":8727},[2166,36811,3339],{"emptyLinePlaceholder":3338},[2166,36813,36814,36816,36819,36821,36824],{"class":3301,"line":8733},[2166,36815,5234],{"class":3305},[2166,36817,36818],{"class":3402}," WBS_KEY",[2166,36820,3313],{"class":3305},[2166,36822,36823],{"class":3316}," \"wbs\u002Fwbs.json\"",[2166,36825,3332],{"class":3331},[2166,36827,36828],{"class":3301,"line":8739},[2166,36829,3339],{"emptyLinePlaceholder":3338},[2166,36831,36832,36834,36836,36838,36841,36843,36845,36847,36849,36851,36853],{"class":3301,"line":8745},[2166,36833,5474],{"class":3331},[2166,36835,3411],{"class":3309},[2166,36837,3351],{"class":3331},[2166,36839,36840],{"class":3316},"\"\u002Fwbs\"",[2166,36842,105],{"class":3331},[2166,36844,5487],{"class":3305},[2166,36846,1305],{"class":3331},[2166,36848,3379],{"class":3356},[2166,36850,3387],{"class":3331},[2166,36852,3390],{"class":3305},[2166,36854,3393],{"class":3331},[2166,36856,36857,36859,36862,36864,36866,36869,36872,36874,36876,36878,36881],{"class":3301,"line":8751},[2166,36858,5317],{"class":3305},[2166,36860,36861],{"class":3402}," obj",[2166,36863,3313],{"class":3305},[2166,36865,5513],{"class":3305},[2166,36867,36868],{"class":3331}," c.env.",[2166,36870,36871],{"class":3402},"R2",[2166,36873,407],{"class":3331},[2166,36875,3411],{"class":3309},[2166,36877,3351],{"class":3331},[2166,36879,36880],{"class":3402},"WBS_KEY",[2166,36882,3460],{"class":3331},[2166,36884,36885,36887,36889,36891,36894,36896,36898,36900,36903,36905,36907,36910],{"class":3301,"line":8756},[2166,36886,5340],{"class":3305},[2166,36888,1305],{"class":3331},[2166,36890,3434],{"class":3305},[2166,36892,36893],{"class":3331},"obj) ",[2166,36895,3440],{"class":3305},[2166,36897,3408],{"class":3331},[2166,36899,3445],{"class":3309},[2166,36901,36902],{"class":3331},"({ exists: ",[2166,36904,26434],{"class":3402},[2166,36906,3454],{"class":3331},[2166,36908,36909],{"class":3402},"404",[2166,36911,3460],{"class":3331},[2166,36913,36914,36916,36919,36921,36923,36926,36928],{"class":3301,"line":8762},[2166,36915,5317],{"class":3305},[2166,36917,36918],{"class":3402}," body",[2166,36920,3313],{"class":3305},[2166,36922,5513],{"class":3305},[2166,36924,36925],{"class":3331}," obj.",[2166,36927,420],{"class":3309},[2166,36929,3547],{"class":3331},[2166,36931,36932,36934,36936,36939],{"class":3301,"line":8767},[2166,36933,3371],{"class":3305},[2166,36935,36448],{"class":3305},[2166,36937,36938],{"class":3309}," Response",[2166,36940,36941],{"class":3331},"(body, {\n",[2166,36943,36944],{"class":3301,"line":8773},[2166,36945,36946],{"class":3331},"    headers: {\n",[2166,36948,36949,36952,36954,36957],{"class":3301,"line":8779},[2166,36950,36951],{"class":3316},"      \"Content-Type\"",[2166,36953,4664],{"class":3331},[2166,36955,36956],{"class":3316},"\"application\u002Fjson; charset=utf-8\"",[2166,36958,5401],{"class":3331},[2166,36960,36961,36964,36966,36969],{"class":3301,"line":8785},[2166,36962,36963],{"class":3316},"      \"Cache-Control\"",[2166,36965,4664],{"class":3331},[2166,36967,36968],{"class":3316},"\"no-store\"",[2166,36970,5401],{"class":3331},[2166,36972,36973],{"class":3301,"line":8791},[2166,36974,36975],{"class":3331},"      ETag: obj.httpEtag,\n",[2166,36977,36978],{"class":3301,"line":8797},[2166,36979,36680],{"class":3331},[2166,36981,36982],{"class":3301,"line":8803},[2166,36983,36984],{"class":3331},"  });\n",[2166,36986,36987],{"class":3301,"line":8809},[2166,36988,5544],{"class":3331},[2166,36990,36991],{"class":3301,"line":8815},[2166,36992,3339],{"emptyLinePlaceholder":3338},[2166,36994,36995,36997,37000,37002,37004,37006,37008,37010,37012,37014,37016],{"class":3301,"line":8821},[2166,36996,5474],{"class":3331},[2166,36998,36999],{"class":3309},"put",[2166,37001,3351],{"class":3331},[2166,37003,36840],{"class":3316},[2166,37005,105],{"class":3331},[2166,37007,5487],{"class":3305},[2166,37009,1305],{"class":3331},[2166,37011,3379],{"class":3356},[2166,37013,3387],{"class":3331},[2166,37015,3390],{"class":3305},[2166,37017,3393],{"class":3331},[2166,37019,37020,37022,37025,37027,37029,37031,37033],{"class":3301,"line":8827},[2166,37021,5317],{"class":3305},[2166,37023,37024],{"class":3402}," text",[2166,37026,3313],{"class":3305},[2166,37028,5513],{"class":3305},[2166,37030,5325],{"class":3331},[2166,37032,420],{"class":3309},[2166,37034,3547],{"class":3331},[2166,37036,37037,37039],{"class":3301,"line":8832},[2166,37038,5370],{"class":3305},[2166,37040,3393],{"class":3331},[2166,37042,37043,37046,37048,37051],{"class":3301,"line":8838},[2166,37044,37045],{"class":3402},"    JSON",[2166,37047,407],{"class":3331},[2166,37049,37050],{"class":3309},"parse",[2166,37052,37053],{"class":3331},"(text);\n",[2166,37055,37056,37058,37060],{"class":3301,"line":8844},[2166,37057,5424],{"class":3331},[2166,37059,5427],{"class":3305},[2166,37061,3393],{"class":3331},[2166,37063,37064,37066,37068,37070,37072,37075,37077,37080],{"class":3301,"line":8849},[2166,37065,5435],{"class":3305},[2166,37067,3408],{"class":3331},[2166,37069,3445],{"class":3309},[2166,37071,3448],{"class":3331},[2166,37073,37074],{"class":3316},"\"invalid json\"",[2166,37076,3454],{"class":3331},[2166,37078,37079],{"class":3402},"400",[2166,37081,3460],{"class":3331},[2166,37083,37084],{"class":3301,"line":8855},[2166,37085,5456],{"class":3331},[2166,37087,37088,37090,37093,37096,37099,37102],{"class":3301,"line":8860},[2166,37089,5340],{"class":3305},[2166,37091,37092],{"class":3331}," (text.",[2166,37094,37095],{"class":3402},"length",[2166,37097,37098],{"class":3305}," >",[2166,37100,37101],{"class":3402}," 1_000_000",[2166,37103,5312],{"class":3331},[2166,37105,37106,37108,37110,37112,37114,37117,37119,37122],{"class":3301,"line":8866},[2166,37107,5435],{"class":3305},[2166,37109,3408],{"class":3331},[2166,37111,3445],{"class":3309},[2166,37113,3448],{"class":3331},[2166,37115,37116],{"class":3316},"\"payload too large\"",[2166,37118,3454],{"class":3331},[2166,37120,37121],{"class":3402},"413",[2166,37123,3460],{"class":3331},[2166,37125,37126],{"class":3301,"line":8871},[2166,37127,5456],{"class":3331},[2166,37129,37130,37132,37134,37136,37138,37140,37142,37144],{"class":3301,"line":8877},[2166,37131,5535],{"class":3305},[2166,37133,36868],{"class":3331},[2166,37135,36871],{"class":3402},[2166,37137,407],{"class":3331},[2166,37139,36999],{"class":3309},[2166,37141,3351],{"class":3331},[2166,37143,36880],{"class":3402},[2166,37145,37146],{"class":3331},", text, {\n",[2166,37148,37149,37152,37154],{"class":3301,"line":8883},[2166,37150,37151],{"class":3331},"    httpMetadata: { contentType: ",[2166,37153,36956],{"class":3316},[2166,37155,26375],{"class":3331},[2166,37157,37158],{"class":3301,"line":8888},[2166,37159,36984],{"class":3331},[2166,37161,37162,37164,37166,37168,37170,37172,37175,37177,37180,37183,37186,37188,37191],{"class":3301,"line":8894},[2166,37163,3371],{"class":3305},[2166,37165,3408],{"class":3331},[2166,37167,3445],{"class":3309},[2166,37169,36803],{"class":3331},[2166,37171,21876],{"class":3402},[2166,37173,37174],{"class":3331},", size: text.",[2166,37176,37095],{"class":3402},[2166,37178,37179],{"class":3331},", savedAt: ",[2166,37181,37182],{"class":3305},"new",[2166,37184,37185],{"class":3309}," Date",[2166,37187,25050],{"class":3331},[2166,37189,37190],{"class":3309},"toISOString",[2166,37192,37193],{"class":3331},"() });\n",[2166,37195,37196],{"class":3301,"line":8899},[2166,37197,5544],{"class":3331},[2166,37199,37200],{"class":3301,"line":8905},[2166,37201,3339],{"emptyLinePlaceholder":3338},[2166,37203,37204,37206,37208],{"class":3301,"line":8911},[2166,37205,5292],{"class":3305},[2166,37207,25858],{"class":3305},[2166,37209,37210],{"class":3331}," app;\n",[215,37212,37214,37215,37217],{"id":37213},"_5-3-packagejson-최소-의존","5-3. ",[16,37216,10090],{}," 최소 의존",[415,37219,37221],{"className":35930,"code":37220,"language":3445,"meta":423,"style":423},"{\n  \"dependencies\": { \"hono\": \"^4.0.0\" },\n  \"devDependencies\": { \"wrangler\": \"^4.0.0\", \"typescript\": \"^5.0.0\" }\n}\n",[16,37222,37223,37227,37245,37271],{"__ignoreMap":423},[2166,37224,37225],{"class":3301,"line":3302},[2166,37226,13095],{"class":3331},[2166,37228,37229,37232,37235,37238,37240,37243],{"class":3301,"line":3335},[2166,37230,37231],{"class":3402},"  \"dependencies\"",[2166,37233,37234],{"class":3331},": { ",[2166,37236,37237],{"class":3402},"\"hono\"",[2166,37239,4664],{"class":3331},[2166,37241,37242],{"class":3316},"\"^4.0.0\"",[2166,37244,26375],{"class":3331},[2166,37246,37247,37250,37252,37255,37257,37259,37261,37264,37266,37269],{"class":3301,"line":3342},[2166,37248,37249],{"class":3402},"  \"devDependencies\"",[2166,37251,37234],{"class":3331},[2166,37253,37254],{"class":3402},"\"wrangler\"",[2166,37256,4664],{"class":3331},[2166,37258,37242],{"class":3316},[2166,37260,105],{"class":3331},[2166,37262,37263],{"class":3402},"\"typescript\"",[2166,37265,4664],{"class":3331},[2166,37267,37268],{"class":3316},"\"^5.0.0\"",[2166,37270,25911],{"class":3331},[2166,37272,37273],{"class":3301,"line":3368},[2166,37274,3559],{"class":3331},[215,37276,37278],{"id":37277},"_5-4-셋업배포","5-4. 셋업·배포",[415,37280,37282],{"className":4632,"code":37281,"language":4634,"meta":423,"style":423},"# 1) R2 버킷 (대화형 프롬프트가 떠도 자동 거절)\necho \"no\" | wrangler r2 bucket create \u003Cyour-r2-bucket>\n\n# 2) 배포\npnpm run deploy\n# → 배포 URL: https:\u002F\u002F\u003Cworker-name>.\u003Csubdomain>.workers.dev\n",[16,37283,37284,37289,37320,37324,37329,37338],{"__ignoreMap":423},[2166,37285,37286],{"class":3301,"line":3302},[2166,37287,37288],{"class":3422},"# 1) R2 버킷 (대화형 프롬프트가 떠도 자동 거절)\n",[2166,37290,37291,37294,37297,37299,37302,37305,37308,37310,37312,37315,37318],{"class":3301,"line":3335},[2166,37292,37293],{"class":3402},"echo",[2166,37295,37296],{"class":3316}," \"no\"",[2166,37298,3320],{"class":3305},[2166,37300,37301],{"class":3309}," wrangler",[2166,37303,37304],{"class":3316}," r2",[2166,37306,37307],{"class":3316}," bucket",[2166,37309,26212],{"class":3316},[2166,37311,4644],{"class":3305},[2166,37313,37314],{"class":3316},"your-r2-bucke",[2166,37316,37317],{"class":3331},"t",[2166,37319,4741],{"class":3305},[2166,37321,37322],{"class":3301,"line":3342},[2166,37323,3339],{"emptyLinePlaceholder":3338},[2166,37325,37326],{"class":3301,"line":3368},[2166,37327,37328],{"class":3422},"# 2) 배포\n",[2166,37330,37331,37333,37336],{"class":3301,"line":3396},[2166,37332,4778],{"class":3309},[2166,37334,37335],{"class":3316}," run",[2166,37337,4781],{"class":3316},[2166,37339,37340],{"class":3301,"line":3426},[2166,37341,37342],{"class":3422},"# → 배포 URL: https:\u002F\u002F\u003Cworker-name>.\u003Csubdomain>.workers.dev\n",[215,37344,37346],{"id":37345},"_5-5-스모크-테스트","5-5. 스모크 테스트",[415,37348,37350],{"className":4632,"code":37349,"language":4634,"meta":423,"style":423},"curl -i https:\u002F\u002F\u003Capi>\u002Fhealthz\ncurl -X PUT https:\u002F\u002F\u003Capi>\u002Fwbs -H 'Content-Type: application\u002Fjson' \\\n  --data-binary @public\u002Fwbs.json\ncurl -s https:\u002F\u002F\u003Capi>\u002Fwbs | head -c 200\n",[16,37351,37352,37375,37405,37413],{"__ignoreMap":423},[2166,37353,37354,37356,37359,37362,37364,37367,37370,37372],{"class":3301,"line":3302},[2166,37355,5647],{"class":3309},[2166,37357,37358],{"class":3402}," -i",[2166,37360,37361],{"class":3316}," https:\u002F\u002F",[2166,37363,4732],{"class":3305},[2166,37365,37366],{"class":3316},"ap",[2166,37368,37369],{"class":3331},"i",[2166,37371,4653],{"class":3305},[2166,37373,37374],{"class":3316},"\u002Fhealthz\n",[2166,37376,37377,37379,37382,37385,37387,37389,37391,37393,37395,37397,37400,37403],{"class":3301,"line":3335},[2166,37378,5647],{"class":3309},[2166,37380,37381],{"class":3402}," -X",[2166,37383,37384],{"class":3316}," PUT",[2166,37386,37361],{"class":3316},[2166,37388,4732],{"class":3305},[2166,37390,37366],{"class":3316},[2166,37392,37369],{"class":3331},[2166,37394,4653],{"class":3305},[2166,37396,12910],{"class":3316},[2166,37398,37399],{"class":3402}," -H",[2166,37401,37402],{"class":3316}," 'Content-Type: application\u002Fjson'",[2166,37404,22558],{"class":3402},[2166,37406,37407,37410],{"class":3301,"line":3342},[2166,37408,37409],{"class":3402},"  --data-binary",[2166,37411,37412],{"class":3316}," @public\u002Fwbs.json\n",[2166,37414,37415,37417,37420,37422,37424,37426,37428,37430,37432,37434,37437,37440],{"class":3301,"line":3368},[2166,37416,5647],{"class":3309},[2166,37418,37419],{"class":3402}," -s",[2166,37421,37361],{"class":3316},[2166,37423,4732],{"class":3305},[2166,37425,37366],{"class":3316},[2166,37427,37369],{"class":3331},[2166,37429,4653],{"class":3305},[2166,37431,12910],{"class":3316},[2166,37433,3320],{"class":3305},[2166,37435,37436],{"class":3309}," head",[2166,37438,37439],{"class":3402}," -c",[2166,37441,37442],{"class":3402}," 200\n",[33,37444],{},[36,37446,37448],{"id":37447},"_6-프론트엔드-구현-nuxt-3","6. 프론트엔드 구현 (Nuxt 3)",[215,37450,37452],{"id":37451},"_6-1-전제","6-1. 전제",[54,37454,37455,37461,37467,37470],{},[57,37456,37457,37458,78],{},"Nuxt 3 + Cloudflare Pages 프리셋(",[16,37459,37460],{},"output dir = dist\u002F",[57,37462,37463,37464,37466],{},"Tailwind CSS v4 (",[16,37465,11272],{}," 직접 스캔 권장)",[57,37468,37469],{},"Pretendard Variable 폰트",[57,37471,37472,37473,37476],{},"@nuxt\u002Fui는 ",[28,37474,37475],{},"선택 사항",". 본 페이지는 순수 Tailwind 클래스만 사용",[215,37478,37480,37481,36368],{"id":37479},"_6-2-단일-파일-pageswbsvue-전체","6-2. 단일 파일 — ",[16,37482,37483],{},"pages\u002Fwbs.vue",[21,37485,37486],{},[24,37487,37488,37489,37491],{},"그대로 복사하면 동작한다. ",[16,37490,5584],{},"만 자기 Worker URL로 바꿀 것.",[415,37493,37497],{"className":37494,"code":37495,"language":37496,"meta":423,"style":423},"language-vue shiki shiki-themes github-light github-dark","\u003C!--\n  pages\u002Fwbs.vue\n  WBS Live Tracker — Soft SaaS (Notion\u002FLinear\u002FHeight 풍)\n  데이터: API GET \u002Fwbs (R2) → 없으면 \u002Fwbs.json fallback\n  편집: 모든 수정은 800ms 디바운스 후 PUT \u002Fwbs로 자동 영구 저장\n-->\n\u003Cscript setup lang=\"ts\">\nuseHead({ title: \"WBS\" });\n\ntype Status = \"done\" | \"in_progress\" | \"pending\" | \"blocked\";\n\ntype Task = {\n  id: string;\n  taskNo: string;\n  title: string;\n  status: Status;\n  note: string | null;\n  targetDate: string | null;\n  completionDate: string | null;\n  deliverableUrl: string | null;\n};\n\ntype Stage = {\n  id: string;\n  name: string;\n  weight: number;\n  progress: number;\n  summary: string;\n  tasks: Task[];\n};\n\ntype WbsDoc = {\n  _meta: { lastUpdated: string; project: string; source: string; editGuide: string };\n  phase1: { stages: Stage[] };\n};\n\n\u002F\u002F ⚠️ 자기 환경에 맞게 교체\nconst API_BASE = \"https:\u002F\u002F\u003Capi-worker-name>.\u003Csubdomain>.workers.dev\";\n\nconst wbs = ref\u003CWbsDoc | null>(null);\nconst pending = ref(true);\nconst error = ref\u003CError | null>(null);\n\ntype TaskPatch = Partial\u003C\n  Pick\u003CTask, \"deliverableUrl\" | \"status\" | \"targetDate\" | \"completionDate\" | \"note\">\n>;\n\nasync function loadWbs() {\n  pending.value = true;\n  error.value = null;\n  try {\n    const apiRes = await fetch(`${API_BASE}\u002Fwbs`, { cache: \"no-store\" });\n    if (apiRes.ok) {\n      wbs.value = (await apiRes.json()) as WbsDoc;\n    } else if (apiRes.status === 404) {\n      const seed = await fetch(\"\u002Fwbs.json\", { cache: \"no-store\" });\n      if (!seed.ok) throw new Error(`seed ${seed.status}`);\n      wbs.value = (await seed.json()) as WbsDoc;\n    } else {\n      throw new Error(`api ${apiRes.status}`);\n    }\n  } catch (e) {\n    error.value = e as Error;\n  } finally {\n    pending.value = false;\n  }\n}\nonMounted(loadWbs);\n\n\u002F\u002F ── 자동 저장 ──────────────────────────────────────────\ntype SaveState = \"idle\" | \"dirty\" | \"saving\" | \"saved\" | \"error\";\nconst saveState = ref\u003CSaveState>(\"idle\");\nconst lastSavedAt = ref\u003CDate | null>(null);\nconst saveError = ref\u003Cstring | null>(null);\nlet saveTimer: ReturnType\u003Ctypeof setTimeout> | null = null;\n\nasync function saveNow() {\n  if (!wbs.value) return;\n  if (saveTimer) { clearTimeout(saveTimer); saveTimer = null; }\n  const payload = {\n    ...wbs.value,\n    _meta: { ...wbs.value._meta, lastUpdated: new Date().toISOString().slice(0, 10) },\n  };\n  saveState.value = \"saving\";\n  saveError.value = null;\n  try {\n    const res = await fetch(`${API_BASE}\u002Fwbs`, {\n      method: \"PUT\",\n      headers: { \"Content-Type\": \"application\u002Fjson\" },\n      body: JSON.stringify(payload),\n    });\n    if (!res.ok) throw new Error(`save ${res.status}`);\n    lastSavedAt.value = new Date();\n    saveState.value = \"saved\";\n    wbs.value._meta = payload._meta;\n  } catch (e) {\n    saveError.value = (e as Error).message;\n    saveState.value = \"error\";\n  }\n}\n\nfunction scheduleSave() {\n  saveState.value = \"dirty\";\n  if (saveTimer) clearTimeout(saveTimer);\n  saveTimer = setTimeout(saveNow, 800);\n}\n\nfunction setOverride(taskId: string, patch: TaskPatch) {\n  if (!wbs.value) return;\n  for (const s of wbs.value.phase1.stages) {\n    const idx = s.tasks.findIndex((t) => t.id === taskId);\n    if (idx === -1) continue;\n    const cur = s.tasks[idx];\n    const next: Task = {\n      ...cur,\n      ...patch,\n      deliverableUrl: patch.deliverableUrl !== undefined ? patch.deliverableUrl || null : cur.deliverableUrl,\n      targetDate: patch.targetDate !== undefined ? patch.targetDate || null : cur.targetDate,\n      completionDate: patch.completionDate !== undefined ? patch.completionDate || null : cur.completionDate,\n      note: patch.note !== undefined ? patch.note || null : cur.note,\n    };\n    s.tasks.splice(idx, 1, next);\n    scheduleSave();\n    return;\n  }\n}\n\n\u002F\u002F ── 파생 상태 ──────────────────────────────────────────\nconst mergedStages = computed\u003CStage[]>(() => wbs.value?.phase1.stages ?? []);\nconst PROJECT_NAME = computed(() => wbs.value?._meta.project ?? \"Project\");\nconst LAST_UPDATED = computed(() => wbs.value?._meta.lastUpdated ?? \"—\");\n\nconst weightedAverage = computed(() => {\n  const st = mergedStages.value;\n  if (!st.length) return 0;\n  \u002F\u002F 가중평균(%) = Σ(weight × progress) \u002F Σ(weight). progress가 이미 %단위이므로 추가 \u002F100 없음.\n  const w = st.reduce((s, x) => s + x.weight, 0);\n  const p = st.reduce((s, x) => s + x.weight * x.progress, 0);\n  return Math.round((p \u002F w) * 10) \u002F 10;\n});\n\nconst allTasks = computed(() => mergedStages.value.flatMap((s) => s.tasks));\nconst totalCounts = computed(() => {\n  const acc: Record\u003CStatus, number> = { done: 0, in_progress: 0, pending: 0, blocked: 0 };\n  for (const t of allTasks.value) acc[t.status]++;\n  return acc;\n});\n\nfunction isOverdue(t: Task) {\n  if (t.status === \"done\" || !t.targetDate) return false;\n  return t.targetDate \u003C LAST_UPDATED.value;\n}\n\nconst statusMeta: Record\u003CStatus, { label: string; chipCls: string; emoji: string }> = {\n  done:        { label: \"완료\",   chipCls: \"bg-emerald-50 text-emerald-700 border-emerald-200\", emoji: \"✓\" },\n  in_progress: { label: \"진행 중\", chipCls: \"bg-amber-50 text-amber-700 border-amber-200\",       emoji: \"◐\" },\n  pending:     { label: \"대기\",   chipCls: \"bg-neutral-50 text-neutral-600 border-neutral-200\", emoji: \"○\" },\n  blocked:     { label: \"보류\",   chipCls: \"bg-rose-50 text-rose-700 border-rose-200\",          emoji: \"✕\" },\n};\n\nfunction progressFill(pct: number) {\n  if (pct >= 70) return \"bg-emerald-500\";\n  if (pct >= 30) return \"bg-amber-500\";\n  if (pct > 0)   return \"bg-neutral-400\";\n  return \"bg-neutral-200\";\n}\n\nconst stageEmoji = [\"🎯\", \"📐\", \"🛠️\", \"📚\", \"🧪\", \"🚀\"];\n\n\u002F\u002F ── 백업 다운로드 ─────────────────────────────────────\nconst currentJsonString = computed(() => wbs.value ? JSON.stringify(wbs.value, null, 2) + \"\\n\" : \"\");\nfunction downloadJson() {\n  const blob = new Blob([currentJsonString.value], { type: \"application\u002Fjson\" });\n  const url = URL.createObjectURL(blob);\n  const a = document.createElement(\"a\");\n  a.href = url; a.download = \"wbs.json\"; a.click();\n  setTimeout(() => URL.revokeObjectURL(url), 1000);\n}\n\n\u002F\u002F ── \"n초 전\" 갱신 ─────────────────────────────────────\nconst savedAgo = ref(\"\");\nlet agoTimer: ReturnType\u003Ctypeof setInterval> | null = null;\nfunction formatAgo(d: Date) {\n  const s = Math.floor((Date.now() - d.getTime()) \u002F 1000);\n  if (s \u003C 5) return \"방금\";\n  if (s \u003C 60) return `${s}초 전`;\n  const m = Math.floor(s \u002F 60);\n  if (m \u003C 60) return `${m}분 전`;\n  return `${Math.floor(m \u002F 60)}시간 전`;\n}\nonMounted(() => {\n  agoTimer = setInterval(() => {\n    savedAgo.value = lastSavedAt.value ? formatAgo(lastSavedAt.value) : \"\";\n  }, 1000);\n});\nonUnmounted(() => {\n  if (agoTimer) clearInterval(agoTimer);\n  if (saveTimer) clearTimeout(saveTimer);\n});\n\nfunction scrollToStage(stageId: string) {\n  document.getElementById(`stage-${stageId}`)?.scrollIntoView({ behavior: \"smooth\", block: \"start\" });\n}\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv class=\"min-h-screen bg-neutral-50\u002F60 pb-24\">\n    \u003Cdiv class=\"mx-auto max-w-5xl px-6 pt-10 sm:px-10 sm:pt-14\">\n      \u003C!-- HEADER -->\n      \u003Cheader class=\"mt-4 flex items-start justify-between gap-4\">\n        \u003Cdiv class=\"flex items-start gap-3\">\n          \u003Cspan class=\"mt-1 text-[30px]\">📋\u003C\u002Fspan>\n          \u003Cdiv>\n            \u003Ch1 class=\"text-[28px] font-semibold tracking-tight text-neutral-900\">\n              {{ PROJECT_NAME }} · Phase 1\n            \u003C\u002Fh1>\n            \u003Cp class=\"mt-1 text-[14px] text-neutral-500\">\n              마지막 현행화 {{ LAST_UPDATED }}\n            \u003C\u002Fp>\n          \u003C\u002Fdiv>\n        \u003C\u002Fdiv>\n      \u003C\u002Fheader>\n\n      \u003C!-- LOADING \u002F ERROR -->\n      \u003Cdiv v-if=\"pending\" class=\"mt-8 rounded-xl border border-neutral-200 bg-white p-6 text-[14px] text-neutral-500\">\n        로딩 중…\n      \u003C\u002Fdiv>\n      \u003Cdiv v-else-if=\"error\" class=\"mt-8 rounded-xl border border-rose-200 bg-rose-50 p-6 text-[14px] text-rose-700\">\n        로드 실패: {{ error.message }}\n      \u003C\u002Fdiv>\n\n      \u003Ctemplate v-else>\n        \u003C!-- HERO -->\n        \u003Csection class=\"mt-6 grid grid-cols-1 gap-3 sm:grid-cols-4\">\n          \u003Cdiv class=\"rounded-xl border border-neutral-200 bg-white p-5 sm:col-span-2\">\n            \u003Cp class=\"text-[12px] text-neutral-500\">전체 진행률\u003C\u002Fp>\n            \u003Cp class=\"mt-1 text-[36px] font-semibold tracking-tight text-neutral-900 tabular-nums\">\n              {{ weightedAverage }}\u003Cspan class=\"ml-0.5 text-[24px] text-neutral-400\">%\u003C\u002Fspan>\n            \u003C\u002Fp>\n            \u003Cdiv class=\"mt-4 h-1.5 overflow-hidden rounded-full bg-neutral-100\">\n              \u003Cdiv class=\"h-full rounded-full bg-neutral-900 transition-all\" :style=\"{ width: weightedAverage + '%' }\" \u002F>\n            \u003C\u002Fdiv>\n          \u003C\u002Fdiv>\n          \u003Cdiv class=\"rounded-xl border border-neutral-200 bg-white p-5\">\n            \u003Cdiv class=\"flex items-center gap-1.5\">\n              \u003Cspan class=\"inline-block size-1.5 rounded-full bg-emerald-500\" \u002F>\n              \u003Cp class=\"text-[12px] text-neutral-500\">완료\u003C\u002Fp>\n            \u003C\u002Fdiv>\n            \u003Cp class=\"mt-1 text-[30px] font-semibold text-neutral-900 tabular-nums\">\n              {{ totalCounts.done }}\u003Cspan class=\"text-[16px] text-neutral-400\">\u002F{{ allTasks.length }}\u003C\u002Fspan>\n            \u003C\u002Fp>\n          \u003C\u002Fdiv>\n          \u003Cdiv class=\"rounded-xl border border-neutral-200 bg-white p-5\">\n            \u003Cdiv class=\"flex items-center gap-1.5\">\n              \u003Cspan class=\"inline-block size-1.5 rounded-full bg-amber-500\" \u002F>\n              \u003Cp class=\"text-[12px] text-neutral-500\">진행 중\u003C\u002Fp>\n            \u003C\u002Fdiv>\n            \u003Cp class=\"mt-1 text-[30px] font-semibold text-neutral-900 tabular-nums\">\n              {{ totalCounts.in_progress }}\n            \u003C\u002Fp>\n          \u003C\u002Fdiv>\n        \u003C\u002Fsection>\n\n        \u003C!-- STAGES OVERVIEW -->\n        \u003Csection class=\"mt-8\">\n          \u003Ch2 class=\"mb-2 text-[14px] font-semibold text-neutral-700\">단계별 진행률\u003C\u002Fh2>\n          \u003Cul class=\"overflow-hidden rounded-xl border border-neutral-200 bg-white\">\n            \u003Cli\n              v-for=\"(s, i) in mergedStages\" :key=\"s.id\"\n              class=\"grid cursor-pointer grid-cols-[24px_24px_1fr_auto_140px_auto] items-center gap-4 px-4 py-3 hover:bg-neutral-50\"\n              :class=\"i > 0 ? 'border-t border-neutral-100' : ''\"\n              @click=\"scrollToStage(s.id)\"\n            >\n              \u003Cspan class=\"text-[18px] leading-none\">{{ stageEmoji[i] }}\u003C\u002Fspan>\n              \u003Cspan class=\"font-mono text-[14px] tabular-nums text-neutral-400\">{{ String(i + 1).padStart(2, \"0\") }}\u003C\u002Fspan>\n              \u003Cdiv class=\"min-w-0\">\n                \u003Cp class=\"truncate text-[14px] font-medium text-neutral-900\">{{ s.name }}\u003C\u002Fp>\n                \u003Cp class=\"truncate text-[14px] text-neutral-500\">{{ s.summary }}\u003C\u002Fp>\n              \u003C\u002Fdiv>\n              \u003Cspan class=\"text-[14px] text-neutral-400\">{{ s.tasks.length }}건\u003C\u002Fspan>\n              \u003Cdiv class=\"flex items-center gap-2.5\">\n                \u003Cdiv class=\"h-1 w-24 overflow-hidden rounded-full bg-neutral-100\">\n                  \u003Cdiv :class=\"['h-full rounded-full', progressFill(s.progress)]\" :style=\"{ width: s.progress + '%' }\" \u002F>\n                \u003C\u002Fdiv>\n                \u003Cspan class=\"w-9 text-right text-[14px] font-medium tabular-nums text-neutral-700\">{{ s.progress }}%\u003C\u002Fspan>\n              \u003C\u002Fdiv>\n              \u003Cspan class=\"text-neutral-300\">→\u003C\u002Fspan>\n            \u003C\u002Fli>\n          \u003C\u002Ful>\n        \u003C\u002Fsection>\n\n        \u003C!-- STAGE DETAILS -->\n        \u003Csection v-for=\"(s, sIdx) in mergedStages\" :key=\"s.id\" :id=\"`stage-${s.id}`\" class=\"mt-10\">\n          \u003Cdiv class=\"flex items-baseline justify-between gap-3\">\n            \u003Cdiv class=\"flex items-baseline gap-2.5\">\n              \u003Cspan class=\"text-[20px] leading-none\">{{ stageEmoji[sIdx] }}\u003C\u002Fspan>\n              \u003Ch2 class=\"text-[18px] font-semibold tracking-tight text-neutral-900\">{{ s.name }}\u003C\u002Fh2>\n              \u003Cspan class=\"font-mono text-[14px] text-neutral-400\">{{ s.id }}\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n            \u003Cdiv class=\"flex items-center gap-3 text-[14px] text-neutral-500\">\n              \u003Cspan>비중 {{ s.weight }}%\u003C\u002Fspan>\n              \u003Cspan class=\"text-neutral-200\">·\u003C\u002Fspan>\n              \u003Cspan class=\"font-medium text-neutral-700\">진행 {{ s.progress }}%\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fdiv>\n          \u003Cp class=\"mt-1 text-[14px] text-neutral-500\">{{ s.summary }}\u003C\u002Fp>\n          \u003Cdiv class=\"mt-3 h-1 overflow-hidden rounded-full bg-neutral-100\">\n            \u003Cdiv :class=\"['h-full rounded-full', progressFill(s.progress)]\" :style=\"{ width: s.progress + '%' }\" \u002F>\n          \u003C\u002Fdiv>\n\n          \u003Cdiv class=\"mt-4 overflow-hidden rounded-xl border border-neutral-200 bg-white\">\n            \u003Ctable class=\"w-full text-[14px]\">\n              \u003Cthead>\n                \u003Ctr class=\"border-b border-neutral-100 text-[14px] font-medium text-neutral-500\">\n                  \u003Cth class=\"w-20 px-3 py-2 text-left\">ID\u003C\u002Fth>\n                  \u003Cth class=\"px-3 py-2 text-left\">작업 · 산출물\u003C\u002Fth>\n                  \u003Cth class=\"w-36 px-3 py-2 text-left\">목표일\u003C\u002Fth>\n                  \u003Cth class=\"w-36 px-3 py-2 text-left\">완료일\u003C\u002Fth>\n                  \u003Cth class=\"w-28 px-3 py-2 text-left\">상태\u003C\u002Fth>\n                \u003C\u002Ftr>\n              \u003C\u002Fthead>\n              \u003Ctbody>\n                \u003Ctr\n                  v-for=\"(t, ti) in s.tasks\" :key=\"t.id\"\n                  class=\"align-top hover:bg-neutral-50\u002F60\"\n                  :class=\"ti > 0 ? 'border-t border-neutral-100' : ''\"\n                >\n                  \u003Ctd class=\"px-3 py-3 font-mono text-[14px] tabular-nums text-neutral-400\">{{ s.id }}-{{ t.taskNo }}\u003C\u002Ftd>\n                  \u003Ctd class=\"px-3 py-3\">\n                    \u003Cp class=\"text-[13.5px] font-medium text-neutral-900\">{{ t.title }}\u003C\u002Fp>\n                    \u003Cp v-if=\"t.note\" class=\"mt-0.5 text-[14px] leading-relaxed text-neutral-500\">{{ t.note }}\u003C\u002Fp>\n                    \u003Cdiv class=\"mt-2 flex items-center gap-2\">\n                      \u003Cspan class=\"text-[14px] text-neutral-400\">🔗\u003C\u002Fspan>\n                      \u003Cinput\n                        :value=\"t.deliverableUrl ?? ''\" type=\"url\" placeholder=\"산출물 URL 입력\"\n                        class=\"min-w-0 flex-1 rounded-md border border-transparent bg-transparent px-1.5 py-1 font-mono text-[13px] text-neutral-700 placeholder:text-neutral-400 hover:border-neutral-200 focus:border-neutral-300 focus:bg-white focus:outline-none focus:ring-1 focus:ring-neutral-200\"\n                        @change=\"(e) => setOverride(t.id, { deliverableUrl: (e.target as HTMLInputElement).value || null })\"\n                      \u002F>\n                      \u003Ca v-if=\"t.deliverableUrl\" :href=\"t.deliverableUrl\" target=\"_blank\" rel=\"noopener\"\n                         class=\"shrink-0 rounded-md px-1.5 py-1 text-[14px] text-neutral-500 hover:bg-neutral-100 hover:text-neutral-900\">\n                        열기 ↗\n                      \u003C\u002Fa>\n                    \u003C\u002Fdiv>\n                  \u003C\u002Ftd>\n                  \u003Ctd class=\"whitespace-nowrap px-2 py-3\">\n                    \u003Cinput\n                      type=\"date\" :value=\"t.targetDate ?? ''\"\n                      :class=\"['w-full rounded-md border border-transparent bg-transparent px-1.5 py-1 font-mono text-[12px] tabular-nums hover:border-neutral-200 focus:border-neutral-300 focus:bg-white focus:outline-none focus:ring-1 focus:ring-neutral-200',\n                               isOverdue(t) ? 'font-semibold text-rose-600' : 'text-neutral-600']\"\n                      @change=\"(e) => setOverride(t.id, { targetDate: (e.target as HTMLInputElement).value || null })\"\n                    \u002F>\n                  \u003C\u002Ftd>\n                  \u003Ctd class=\"whitespace-nowrap px-2 py-3\">\n                    \u003Cinput\n                      type=\"date\" :value=\"t.completionDate ?? ''\"\n                      class=\"w-full rounded-md border border-transparent bg-transparent px-1.5 py-1 font-mono text-[12px] tabular-nums text-emerald-700 hover:border-neutral-200 focus:border-neutral-300 focus:bg-white focus:outline-none focus:ring-1 focus:ring-neutral-200\"\n                      @change=\"(e) => setOverride(t.id, { completionDate: (e.target as HTMLInputElement).value || null })\"\n                    \u002F>\n                  \u003C\u002Ftd>\n                  \u003Ctd class=\"whitespace-nowrap px-3 py-3\">\n                    \u003Clabel :class=\"['relative inline-flex cursor-pointer items-center gap-1.5 whitespace-nowrap rounded-md border px-2 py-0.5 text-[13px] font-medium hover:brightness-95',\n                                    statusMeta[t.status].chipCls]\">\n                      \u003Cspan class=\"text-[13px]\">{{ statusMeta[t.status].emoji }}\u003C\u002Fspan>\n                      {{ statusMeta[t.status].label }}\n                      \u003Cselect\n                        :value=\"t.status\" class=\"absolute inset-0 cursor-pointer opacity-0\"\n                        @change=\"(e) => setOverride(t.id, { status: (e.target as HTMLSelectElement).value as Status })\"\n                      >\n                        \u003Coption v-for=\"(meta, key) in statusMeta\" :key=\"key\" :value=\"key\">\n                          {{ meta.emoji }} {{ meta.label }}\n                        \u003C\u002Foption>\n                      \u003C\u002Fselect>\n                    \u003C\u002Flabel>\n                  \u003C\u002Ftd>\n                \u003C\u002Ftr>\n              \u003C\u002Ftbody>\n            \u003C\u002Ftable>\n          \u003C\u002Fdiv>\n        \u003C\u002Fsection>\n      \u003C\u002Ftemplate>\n    \u003C\u002Fdiv>\n\n    \u003C!-- FLOATING AUTOSAVE STATUS -->\n    \u003Cdiv v-if=\"saveState !== 'idle'\"\n         class=\"fixed bottom-6 left-1\u002F2 z-50 flex -translate-x-1\u002F2 items-center gap-2.5 rounded-full border border-neutral-200 bg-white px-3 py-2 shadow-lg shadow-neutral-900\u002F10\">\n      \u003Cspan class=\"flex items-center gap-2 pl-1 text-[14px] text-neutral-700\">\n        \u003Ctemplate v-if=\"saveState === 'dirty'\">\n          \u003Cspan class=\"inline-block size-1.5 rounded-full bg-amber-500\" \u002F>\u003Cspan>수정 감지…\u003C\u002Fspan>\n        \u003C\u002Ftemplate>\n        \u003Ctemplate v-else-if=\"saveState === 'saving'\">\n          \u003Cspan class=\"inline-block size-1.5 animate-pulse rounded-full bg-sky-500\" \u002F>\u003Cspan>저장 중…\u003C\u002Fspan>\n        \u003C\u002Ftemplate>\n        \u003Ctemplate v-else-if=\"saveState === 'saved'\">\n          \u003Cspan class=\"inline-block size-1.5 rounded-full bg-emerald-500\" \u002F>\n          \u003Cspan>저장됨 \u003Cspan class=\"text-neutral-400\">· {{ savedAgo }}\u003C\u002Fspan>\u003C\u002Fspan>\n        \u003C\u002Ftemplate>\n        \u003Ctemplate v-else-if=\"saveState === 'error'\">\n          \u003Cspan class=\"inline-block size-1.5 rounded-full bg-rose-500\" \u002F>\n          \u003Cspan class=\"text-rose-700\">저장 실패: {{ saveError }}\u003C\u002Fspan>\n        \u003C\u002Ftemplate>\n      \u003C\u002Fspan>\n      \u003Cspan class=\"h-4 w-px bg-neutral-200\" \u002F>\n      \u003Cbutton v-if=\"saveState === 'error'\"\n              class=\"rounded-md bg-neutral-900 px-3 py-1 text-[14px] font-medium text-white hover:bg-neutral-700\"\n              @click=\"saveNow\">재시도\u003C\u002Fbutton>\n      \u003Cbutton class=\"rounded-md px-2.5 py-1 text-[14px] text-neutral-600 hover:bg-neutral-100\"\n              @click=\"downloadJson\" title=\"현재 상태를 wbs.json으로 다운로드\">↓ 백업\u003C\u002Fbutton>\n    \u003C\u002Fdiv>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n","vue",[16,37498,37499,37504,37509,37514,37519,37524,37529,37550,37564,37568,37592,37596,37606,37616,37626,37636,37646,37660,37674,37688,37702,37706,37710,37720,37730,37740,37750,37760,37770,37780,37784,37788,37798,37842,37858,37862,37866,37871,37885,37889,37917,37934,37960,37964,37979,38016,38021,38025,38037,38049,38060,38066,38096,38103,38129,38151,38176,38212,38235,38243,38268,38273,38282,38298,38307,38319,38323,38327,38335,38339,38344,38378,38401,38427,38453,38483,38487,38498,38513,38533,38544,38552,38586,38590,38601,38612,38618,38641,38650,38664,38680,38684,38717,38730,38741,38751,38759,38776,38786,38790,38794,38798,38807,38817,38829,38847,38851,38855,38882,38896,38914,38946,38967,38979,38993,39001,39008,39036,39059,39082,39105,39110,39126,39133,39139,39143,39147,39151,39156,39187,39213,39238,39242,39259,39271,39293,39298,39339,39380,39411,39415,39419,39451,39468,39517,39539,39547,39552,39557,39575,39602,39617,39622,39627,39677,39700,39723,39744,39766,39771,39776,39795,39818,39839,39860,39870,39875,39880,39924,39929,39935,39992,40002,40024,40044,40067,40091,40116,40121,40126,40132,40151,40180,40199,40240,40262,40288,40311,40337,40367,40372,40383,40400,40424,40434,40439,40451,40465,40476,40481,40486,40505,40543,40548,40558,40563,40573,40592,40609,40615,40632,40649,40671,40680,40697,40703,40713,40729,40735,40744,40754,40764,40774,40779,40785,40809,40815,40824,40848,40854,40863,40868,40880,40886,40903,40919,40940,40956,40978,40987,41003,41031,41040,41049,41065,41081,41099,41119,41128,41144,41166,41175,41184,41199,41214,41232,41252,41261,41276,41282,41291,41300,41309,41314,41320,41336,41357,41373,41381,41400,41411,41422,41433,41439,41460,41481,41497,41519,41540,41550,41571,41587,41603,41630,41640,41661,41670,41691,41700,41709,41718,41723,41729,41768,41784,41800,41821,41841,41862,41871,41887,41901,41922,41943,41952,41961,41980,41996,42019,42028,42033,42049,42065,42074,42090,42111,42132,42153,42173,42194,42203,42212,42221,42229,42247,42258,42269,42275,42296,42312,42334,42362,42378,42399,42407,42433,42444,42455,42461,42498,42511,42517,42527,42537,42547,42563,42570,42589,42600,42606,42617,42623,42632,42647,42654,42670,42681,42691,42696,42705,42721,42735,42743,42764,42770,42778,42795,42805,42811,42842,42848,42858,42867,42876,42885,42894,42903,42912,42921,42930,42939,42949,42954,42960,42974,42987,43003,43026,43053,43062,43084,43111,43120,43142,43159,43190,43199,43221,43239,43260,43269,43278,43296,43311,43321,43338,43352,43377,43386,43396],{"__ignoreMap":423},[2166,37500,37501],{"class":3301,"line":3302},[2166,37502,37503],{"class":3422},"\u003C!--\n",[2166,37505,37506],{"class":3301,"line":3335},[2166,37507,37508],{"class":3422},"  pages\u002Fwbs.vue\n",[2166,37510,37511],{"class":3301,"line":3342},[2166,37512,37513],{"class":3422},"  WBS Live Tracker — Soft SaaS (Notion\u002FLinear\u002FHeight 풍)\n",[2166,37515,37516],{"class":3301,"line":3368},[2166,37517,37518],{"class":3422},"  데이터: API GET \u002Fwbs (R2) → 없으면 \u002Fwbs.json fallback\n",[2166,37520,37521],{"class":3301,"line":3396},[2166,37522,37523],{"class":3422},"  편집: 모든 수정은 800ms 디바운스 후 PUT \u002Fwbs로 자동 영구 저장\n",[2166,37525,37526],{"class":3301,"line":3426},[2166,37527,37528],{"class":3422},"-->\n",[2166,37530,37531,37533,37537,37540,37543,37545,37548],{"class":3301,"line":3463},[2166,37532,4732],{"class":3331},[2166,37534,37536],{"class":37535},"s9eBZ","script",[2166,37538,37539],{"class":3309}," setup",[2166,37541,37542],{"class":3309}," lang",[2166,37544,2998],{"class":3331},[2166,37546,37547],{"class":3316},"\"ts\"",[2166,37549,4741],{"class":3331},[2166,37551,37552,37555,37558,37561],{"class":3301,"line":3504},[2166,37553,37554],{"class":3309},"useHead",[2166,37556,37557],{"class":3331},"({ title: ",[2166,37559,37560],{"class":3316},"\"WBS\"",[2166,37562,37563],{"class":3331}," });\n",[2166,37565,37566],{"class":3301,"line":3538},[2166,37567,3339],{"emptyLinePlaceholder":3338},[2166,37569,37570,37572,37574,37576,37578,37580,37582,37584,37586,37588,37590],{"class":3301,"line":3550},[2166,37571,3306],{"class":3305},[2166,37573,35553],{"class":3309},[2166,37575,3313],{"class":3305},[2166,37577,35558],{"class":3316},[2166,37579,3320],{"class":3305},[2166,37581,35563],{"class":3316},[2166,37583,3320],{"class":3305},[2166,37585,35568],{"class":3316},[2166,37587,3320],{"class":3305},[2166,37589,35573],{"class":3316},[2166,37591,3332],{"class":3331},[2166,37593,37594],{"class":3301,"line":3556},[2166,37595,3339],{"emptyLinePlaceholder":3338},[2166,37597,37598,37600,37602,37604],{"class":3301,"line":5367},[2166,37599,3306],{"class":3305},[2166,37601,35586],{"class":3309},[2166,37603,3313],{"class":3305},[2166,37605,3393],{"class":3331},[2166,37607,37608,37610,37612,37614],{"class":3301,"line":5375},[2166,37609,35595],{"class":3356},[2166,37611,3360],{"class":3305},[2166,37613,35600],{"class":3402},[2166,37615,3332],{"class":3331},[2166,37617,37618,37620,37622,37624],{"class":3301,"line":5392},[2166,37619,35611],{"class":3356},[2166,37621,3360],{"class":3305},[2166,37623,35600],{"class":3402},[2166,37625,3332],{"class":3331},[2166,37627,37628,37630,37632,37634],{"class":3301,"line":5404},[2166,37629,35626],{"class":3356},[2166,37631,3360],{"class":3305},[2166,37633,35600],{"class":3402},[2166,37635,3332],{"class":3331},[2166,37637,37638,37640,37642,37644],{"class":3301,"line":5415},[2166,37639,35637],{"class":3356},[2166,37641,3360],{"class":3305},[2166,37643,35553],{"class":3309},[2166,37645,3332],{"class":3331},[2166,37647,37648,37650,37652,37654,37656,37658],{"class":3301,"line":5421},[2166,37649,35648],{"class":3356},[2166,37651,3360],{"class":3305},[2166,37653,35600],{"class":3402},[2166,37655,3320],{"class":3305},[2166,37657,25741],{"class":3402},[2166,37659,3332],{"class":3331},[2166,37661,37662,37664,37666,37668,37670,37672],{"class":3301,"line":5432},[2166,37663,35663],{"class":3356},[2166,37665,3360],{"class":3305},[2166,37667,35600],{"class":3402},[2166,37669,3320],{"class":3305},[2166,37671,25741],{"class":3402},[2166,37673,3332],{"class":3331},[2166,37675,37676,37678,37680,37682,37684,37686],{"class":3301,"line":5453},[2166,37677,35682],{"class":3356},[2166,37679,3360],{"class":3305},[2166,37681,35600],{"class":3402},[2166,37683,3320],{"class":3305},[2166,37685,25741],{"class":3402},[2166,37687,3332],{"class":3331},[2166,37689,37690,37692,37694,37696,37698,37700],{"class":3301,"line":5459},[2166,37691,35700],{"class":3356},[2166,37693,3360],{"class":3305},[2166,37695,35600],{"class":3402},[2166,37697,3320],{"class":3305},[2166,37699,25741],{"class":3402},[2166,37701,3332],{"class":3331},[2166,37703,37704],{"class":3301,"line":8686},[2166,37705,35715],{"class":3331},[2166,37707,37708],{"class":3301,"line":8692},[2166,37709,3339],{"emptyLinePlaceholder":3338},[2166,37711,37712,37714,37716,37718],{"class":3301,"line":8698},[2166,37713,3306],{"class":3305},[2166,37715,35726],{"class":3309},[2166,37717,3313],{"class":3305},[2166,37719,3393],{"class":3331},[2166,37721,37722,37724,37726,37728],{"class":3301,"line":8704},[2166,37723,35595],{"class":3356},[2166,37725,3360],{"class":3305},[2166,37727,35600],{"class":3402},[2166,37729,3332],{"class":3331},[2166,37731,37732,37734,37736,37738],{"class":3301,"line":8710},[2166,37733,35749],{"class":3356},[2166,37735,3360],{"class":3305},[2166,37737,35600],{"class":3402},[2166,37739,3332],{"class":3331},[2166,37741,37742,37744,37746,37748],{"class":3301,"line":8716},[2166,37743,35760],{"class":3356},[2166,37745,3360],{"class":3305},[2166,37747,35765],{"class":3402},[2166,37749,3332],{"class":3331},[2166,37751,37752,37754,37756,37758],{"class":3301,"line":8721},[2166,37753,35776],{"class":3356},[2166,37755,3360],{"class":3305},[2166,37757,35765],{"class":3402},[2166,37759,3332],{"class":3331},[2166,37761,37762,37764,37766,37768],{"class":3301,"line":8727},[2166,37763,35790],{"class":3356},[2166,37765,3360],{"class":3305},[2166,37767,35600],{"class":3402},[2166,37769,3332],{"class":3331},[2166,37771,37772,37774,37776,37778],{"class":3301,"line":8733},[2166,37773,35801],{"class":3356},[2166,37775,3360],{"class":3305},[2166,37777,35586],{"class":3309},[2166,37779,35808],{"class":3331},[2166,37781,37782],{"class":3301,"line":8739},[2166,37783,35715],{"class":3331},[2166,37785,37786],{"class":3301,"line":8745},[2166,37787,3339],{"emptyLinePlaceholder":3338},[2166,37789,37790,37792,37794,37796],{"class":3301,"line":8751},[2166,37791,3306],{"class":3305},[2166,37793,35823],{"class":3309},[2166,37795,3313],{"class":3305},[2166,37797,3393],{"class":3331},[2166,37799,37800,37802,37804,37806,37809,37811,37813,37815,37818,37820,37822,37824,37826,37828,37830,37832,37835,37837,37839],{"class":3301,"line":8756},[2166,37801,35832],{"class":3356},[2166,37803,3360],{"class":3305},[2166,37805,25680],{"class":3331},[2166,37807,37808],{"class":3356},"lastUpdated",[2166,37810,3360],{"class":3305},[2166,37812,35600],{"class":3402},[2166,37814,5280],{"class":3331},[2166,37816,37817],{"class":3356},"project",[2166,37819,3360],{"class":3305},[2166,37821,35600],{"class":3402},[2166,37823,5280],{"class":3331},[2166,37825,2296],{"class":3356},[2166,37827,3360],{"class":3305},[2166,37829,35600],{"class":3402},[2166,37831,5280],{"class":3331},[2166,37833,37834],{"class":3356},"editGuide",[2166,37836,3360],{"class":3305},[2166,37838,35600],{"class":3402},[2166,37840,37841],{"class":3331}," };\n",[2166,37843,37844,37846,37848,37850,37852,37854,37856],{"class":3301,"line":8762},[2166,37845,35899],{"class":3356},[2166,37847,3360],{"class":3305},[2166,37849,25680],{"class":3331},[2166,37851,35906],{"class":3356},[2166,37853,3360],{"class":3305},[2166,37855,35726],{"class":3309},[2166,37857,35913],{"class":3331},[2166,37859,37860],{"class":3301,"line":8767},[2166,37861,35715],{"class":3331},[2166,37863,37864],{"class":3301,"line":8773},[2166,37865,3339],{"emptyLinePlaceholder":3338},[2166,37867,37868],{"class":3301,"line":8779},[2166,37869,37870],{"class":3422},"\u002F\u002F ⚠️ 자기 환경에 맞게 교체\n",[2166,37872,37873,37875,37878,37880,37883],{"class":3301,"line":8785},[2166,37874,5234],{"class":3305},[2166,37876,37877],{"class":3402}," API_BASE",[2166,37879,3313],{"class":3305},[2166,37881,37882],{"class":3316}," \"https:\u002F\u002F\u003Capi-worker-name>.\u003Csubdomain>.workers.dev\"",[2166,37884,3332],{"class":3331},[2166,37886,37887],{"class":3301,"line":8791},[2166,37888,3339],{"emptyLinePlaceholder":3338},[2166,37890,37891,37893,37896,37898,37901,37903,37906,37908,37910,37913,37915],{"class":3301,"line":8797},[2166,37892,5234],{"class":3305},[2166,37894,37895],{"class":3402}," wbs",[2166,37897,3313],{"class":3305},[2166,37899,37900],{"class":3309}," ref",[2166,37902,4732],{"class":3331},[2166,37904,37905],{"class":3309},"WbsDoc",[2166,37907,3320],{"class":3305},[2166,37909,25741],{"class":3402},[2166,37911,37912],{"class":3331},">(",[2166,37914,36143],{"class":3402},[2166,37916,3460],{"class":3331},[2166,37918,37919,37921,37924,37926,37928,37930,37932],{"class":3301,"line":8803},[2166,37920,5234],{"class":3305},[2166,37922,37923],{"class":3402}," pending",[2166,37925,3313],{"class":3305},[2166,37927,37900],{"class":3309},[2166,37929,3351],{"class":3331},[2166,37931,21876],{"class":3402},[2166,37933,3460],{"class":3331},[2166,37935,37936,37938,37941,37943,37945,37947,37950,37952,37954,37956,37958],{"class":3301,"line":8809},[2166,37937,5234],{"class":3305},[2166,37939,37940],{"class":3402}," error",[2166,37942,3313],{"class":3305},[2166,37944,37900],{"class":3309},[2166,37946,4732],{"class":3331},[2166,37948,37949],{"class":3309},"Error",[2166,37951,3320],{"class":3305},[2166,37953,25741],{"class":3402},[2166,37955,37912],{"class":3331},[2166,37957,36143],{"class":3402},[2166,37959,3460],{"class":3331},[2166,37961,37962],{"class":3301,"line":8815},[2166,37963,3339],{"emptyLinePlaceholder":3338},[2166,37965,37966,37968,37971,37973,37976],{"class":3301,"line":8821},[2166,37967,3306],{"class":3305},[2166,37969,37970],{"class":3309}," TaskPatch",[2166,37972,3313],{"class":3305},[2166,37974,37975],{"class":3309}," Partial",[2166,37977,37978],{"class":3331},"\u003C\n",[2166,37980,37981,37984,37986,37989,37991,37994,37996,37999,38001,38004,38006,38009,38011,38014],{"class":3301,"line":8827},[2166,37982,37983],{"class":3309},"  Pick",[2166,37985,4732],{"class":3331},[2166,37987,37988],{"class":3309},"Task",[2166,37990,105],{"class":3331},[2166,37992,37993],{"class":3316},"\"deliverableUrl\"",[2166,37995,3320],{"class":3305},[2166,37997,37998],{"class":3316}," \"status\"",[2166,38000,3320],{"class":3305},[2166,38002,38003],{"class":3316}," \"targetDate\"",[2166,38005,3320],{"class":3305},[2166,38007,38008],{"class":3316}," \"completionDate\"",[2166,38010,3320],{"class":3305},[2166,38012,38013],{"class":3316}," \"note\"",[2166,38015,4741],{"class":3331},[2166,38017,38018],{"class":3301,"line":8832},[2166,38019,38020],{"class":3331},">;\n",[2166,38022,38023],{"class":3301,"line":8838},[2166,38024,3339],{"emptyLinePlaceholder":3338},[2166,38026,38027,38029,38031,38034],{"class":3301,"line":8844},[2166,38028,5487],{"class":3305},[2166,38030,5297],{"class":3305},[2166,38032,38033],{"class":3309}," loadWbs",[2166,38035,38036],{"class":3331},"() {\n",[2166,38038,38039,38042,38044,38047],{"class":3301,"line":8849},[2166,38040,38041],{"class":3331},"  pending.value ",[2166,38043,2998],{"class":3305},[2166,38045,38046],{"class":3402}," true",[2166,38048,3332],{"class":3331},[2166,38050,38051,38054,38056,38058],{"class":3301,"line":8855},[2166,38052,38053],{"class":3331},"  error.value ",[2166,38055,2998],{"class":3305},[2166,38057,25741],{"class":3402},[2166,38059,3332],{"class":3331},[2166,38061,38062,38064],{"class":3301,"line":8860},[2166,38063,5370],{"class":3305},[2166,38065,3393],{"class":3331},[2166,38067,38068,38070,38073,38075,38077,38080,38082,38084,38086,38089,38092,38094],{"class":3301,"line":8866},[2166,38069,3399],{"class":3305},[2166,38071,38072],{"class":3402}," apiRes",[2166,38074,3313],{"class":3305},[2166,38076,5513],{"class":3305},[2166,38078,38079],{"class":3309}," fetch",[2166,38081,3351],{"class":3331},[2166,38083,5581],{"class":3316},[2166,38085,5584],{"class":3402},[2166,38087,38088],{"class":3316},"}\u002Fwbs`",[2166,38090,38091],{"class":3331},", { cache: ",[2166,38093,36968],{"class":3316},[2166,38095,37563],{"class":3331},[2166,38097,38098,38100],{"class":3301,"line":8871},[2166,38099,3429],{"class":3305},[2166,38101,38102],{"class":3331}," (apiRes.ok) {\n",[2166,38104,38105,38108,38110,38112,38115,38118,38120,38123,38125,38127],{"class":3301,"line":8877},[2166,38106,38107],{"class":3331},"      wbs.value ",[2166,38109,2998],{"class":3305},[2166,38111,1305],{"class":3331},[2166,38113,38114],{"class":3305},"await",[2166,38116,38117],{"class":3331}," apiRes.",[2166,38119,3445],{"class":3309},[2166,38121,38122],{"class":3331},"()) ",[2166,38124,25677],{"class":3305},[2166,38126,35823],{"class":3309},[2166,38128,3332],{"class":3331},[2166,38130,38131,38134,38137,38140,38143,38146,38149],{"class":3301,"line":8883},[2166,38132,38133],{"class":3331},"    } ",[2166,38135,38136],{"class":3305},"else",[2166,38138,38139],{"class":3305}," if",[2166,38141,38142],{"class":3331}," (apiRes.status ",[2166,38144,38145],{"class":3305},"===",[2166,38147,38148],{"class":3402}," 404",[2166,38150,5312],{"class":3331},[2166,38152,38153,38156,38159,38161,38163,38165,38167,38170,38172,38174],{"class":3301,"line":8888},[2166,38154,38155],{"class":3305},"      const",[2166,38157,38158],{"class":3402}," seed",[2166,38160,3313],{"class":3305},[2166,38162,5513],{"class":3305},[2166,38164,38079],{"class":3309},[2166,38166,3351],{"class":3331},[2166,38168,38169],{"class":3316},"\"\u002Fwbs.json\"",[2166,38171,38091],{"class":3331},[2166,38173,36968],{"class":3316},[2166,38175,37563],{"class":3331},[2166,38177,38178,38180,38182,38184,38187,38190,38192,38195,38197,38200,38203,38205,38207,38210],{"class":3301,"line":8894},[2166,38179,36512],{"class":3305},[2166,38181,1305],{"class":3331},[2166,38183,3434],{"class":3305},[2166,38185,38186],{"class":3331},"seed.ok) ",[2166,38188,38189],{"class":3305},"throw",[2166,38191,36448],{"class":3305},[2166,38193,38194],{"class":3309}," Error",[2166,38196,3351],{"class":3331},[2166,38198,38199],{"class":3316},"`seed ${",[2166,38201,38202],{"class":3331},"seed",[2166,38204,407],{"class":3316},[2166,38206,17939],{"class":3331},[2166,38208,38209],{"class":3316},"}`",[2166,38211,3460],{"class":3331},[2166,38213,38214,38216,38218,38220,38222,38225,38227,38229,38231,38233],{"class":3301,"line":8899},[2166,38215,38107],{"class":3331},[2166,38217,2998],{"class":3305},[2166,38219,1305],{"class":3331},[2166,38221,38114],{"class":3305},[2166,38223,38224],{"class":3331}," seed.",[2166,38226,3445],{"class":3309},[2166,38228,38122],{"class":3331},[2166,38230,25677],{"class":3305},[2166,38232,35823],{"class":3309},[2166,38234,3332],{"class":3331},[2166,38236,38237,38239,38241],{"class":3301,"line":8905},[2166,38238,38133],{"class":3331},[2166,38240,38136],{"class":3305},[2166,38242,3393],{"class":3331},[2166,38244,38245,38248,38250,38252,38254,38257,38260,38262,38264,38266],{"class":3301,"line":8911},[2166,38246,38247],{"class":3305},"      throw",[2166,38249,36448],{"class":3305},[2166,38251,38194],{"class":3309},[2166,38253,3351],{"class":3331},[2166,38255,38256],{"class":3316},"`api ${",[2166,38258,38259],{"class":3331},"apiRes",[2166,38261,407],{"class":3316},[2166,38263,17939],{"class":3331},[2166,38265,38209],{"class":3316},[2166,38267,3460],{"class":3331},[2166,38269,38270],{"class":3301,"line":8917},[2166,38271,38272],{"class":3331},"    }\n",[2166,38274,38275,38277,38279],{"class":3301,"line":8923},[2166,38276,5424],{"class":3331},[2166,38278,5427],{"class":3305},[2166,38280,38281],{"class":3331}," (e) {\n",[2166,38283,38284,38287,38289,38292,38294,38296],{"class":3301,"line":8929},[2166,38285,38286],{"class":3331},"    error.value ",[2166,38288,2998],{"class":3305},[2166,38290,38291],{"class":3331}," e ",[2166,38293,25677],{"class":3305},[2166,38295,38194],{"class":3309},[2166,38297,3332],{"class":3331},[2166,38299,38300,38302,38305],{"class":3301,"line":8935},[2166,38301,5424],{"class":3331},[2166,38303,38304],{"class":3305},"finally",[2166,38306,3393],{"class":3331},[2166,38308,38309,38312,38314,38317],{"class":3301,"line":8941},[2166,38310,38311],{"class":3331},"    pending.value ",[2166,38313,2998],{"class":3305},[2166,38315,38316],{"class":3402}," false",[2166,38318,3332],{"class":3331},[2166,38320,38321],{"class":3301,"line":8947},[2166,38322,5456],{"class":3331},[2166,38324,38325],{"class":3301,"line":19135},[2166,38326,3559],{"class":3331},[2166,38328,38329,38332],{"class":3301,"line":19141},[2166,38330,38331],{"class":3309},"onMounted",[2166,38333,38334],{"class":3331},"(loadWbs);\n",[2166,38336,38337],{"class":3301,"line":19147},[2166,38338,3339],{"emptyLinePlaceholder":3338},[2166,38340,38341],{"class":3301,"line":19153},[2166,38342,38343],{"class":3422},"\u002F\u002F ── 자동 저장 ──────────────────────────────────────────\n",[2166,38345,38346,38348,38351,38353,38356,38358,38361,38363,38366,38368,38371,38373,38376],{"class":3301,"line":19159},[2166,38347,3306],{"class":3305},[2166,38349,38350],{"class":3309}," SaveState",[2166,38352,3313],{"class":3305},[2166,38354,38355],{"class":3316}," \"idle\"",[2166,38357,3320],{"class":3305},[2166,38359,38360],{"class":3316}," \"dirty\"",[2166,38362,3320],{"class":3305},[2166,38364,38365],{"class":3316}," \"saving\"",[2166,38367,3320],{"class":3305},[2166,38369,38370],{"class":3316}," \"saved\"",[2166,38372,3320],{"class":3305},[2166,38374,38375],{"class":3316}," \"error\"",[2166,38377,3332],{"class":3331},[2166,38379,38380,38382,38385,38387,38389,38391,38394,38396,38399],{"class":3301,"line":19165},[2166,38381,5234],{"class":3305},[2166,38383,38384],{"class":3402}," saveState",[2166,38386,3313],{"class":3305},[2166,38388,37900],{"class":3309},[2166,38390,4732],{"class":3331},[2166,38392,38393],{"class":3309},"SaveState",[2166,38395,37912],{"class":3331},[2166,38397,38398],{"class":3316},"\"idle\"",[2166,38400,3460],{"class":3331},[2166,38402,38403,38405,38408,38410,38412,38414,38417,38419,38421,38423,38425],{"class":3301,"line":19170},[2166,38404,5234],{"class":3305},[2166,38406,38407],{"class":3402}," lastSavedAt",[2166,38409,3313],{"class":3305},[2166,38411,37900],{"class":3309},[2166,38413,4732],{"class":3331},[2166,38415,38416],{"class":3309},"Date",[2166,38418,3320],{"class":3305},[2166,38420,25741],{"class":3402},[2166,38422,37912],{"class":3331},[2166,38424,36143],{"class":3402},[2166,38426,3460],{"class":3331},[2166,38428,38429,38431,38434,38436,38438,38440,38443,38445,38447,38449,38451],{"class":3301,"line":19175},[2166,38430,5234],{"class":3305},[2166,38432,38433],{"class":3402}," saveError",[2166,38435,3313],{"class":3305},[2166,38437,37900],{"class":3309},[2166,38439,4732],{"class":3331},[2166,38441,38442],{"class":3402},"string",[2166,38444,3320],{"class":3305},[2166,38446,25741],{"class":3402},[2166,38448,37912],{"class":3331},[2166,38450,36143],{"class":3402},[2166,38452,3460],{"class":3331},[2166,38454,38455,38458,38461,38463,38466,38468,38470,38473,38475,38477,38479,38481],{"class":3301,"line":19180},[2166,38456,38457],{"class":3305},"let",[2166,38459,38460],{"class":3331}," saveTimer",[2166,38462,3360],{"class":3305},[2166,38464,38465],{"class":3309}," ReturnType",[2166,38467,4732],{"class":3331},[2166,38469,25633],{"class":3305},[2166,38471,38472],{"class":3331}," setTimeout> ",[2166,38474,25695],{"class":3305},[2166,38476,25741],{"class":3402},[2166,38478,3313],{"class":3305},[2166,38480,25741],{"class":3402},[2166,38482,3332],{"class":3331},[2166,38484,38485],{"class":3301,"line":19186},[2166,38486,3339],{"emptyLinePlaceholder":3338},[2166,38488,38489,38491,38493,38496],{"class":3301,"line":19192},[2166,38490,5487],{"class":3305},[2166,38492,5297],{"class":3305},[2166,38494,38495],{"class":3309}," saveNow",[2166,38497,38036],{"class":3331},[2166,38499,38500,38502,38504,38506,38509,38511],{"class":3301,"line":19198},[2166,38501,5340],{"class":3305},[2166,38503,1305],{"class":3331},[2166,38505,3434],{"class":3305},[2166,38507,38508],{"class":3331},"wbs.value) ",[2166,38510,3440],{"class":3305},[2166,38512,3332],{"class":3331},[2166,38514,38515,38517,38520,38523,38526,38528,38530],{"class":3301,"line":19204},[2166,38516,5340],{"class":3305},[2166,38518,38519],{"class":3331}," (saveTimer) { ",[2166,38521,38522],{"class":3309},"clearTimeout",[2166,38524,38525],{"class":3331},"(saveTimer); saveTimer ",[2166,38527,2998],{"class":3305},[2166,38529,25741],{"class":3402},[2166,38531,38532],{"class":3331},"; }\n",[2166,38534,38535,38537,38540,38542],{"class":3301,"line":19209},[2166,38536,5317],{"class":3305},[2166,38538,38539],{"class":3402}," payload",[2166,38541,3313],{"class":3305},[2166,38543,3393],{"class":3331},[2166,38545,38546,38549],{"class":3301,"line":19215},[2166,38547,38548],{"class":3305},"    ...",[2166,38550,38551],{"class":3331},"wbs.value,\n",[2166,38553,38554,38557,38559,38562,38564,38566,38568,38570,38572,38575,38577,38579,38581,38583],{"class":3301,"line":19221},[2166,38555,38556],{"class":3331},"    _meta: { ",[2166,38558,1900],{"class":3305},[2166,38560,38561],{"class":3331},"wbs.value._meta, lastUpdated: ",[2166,38563,37182],{"class":3305},[2166,38565,37185],{"class":3309},[2166,38567,25050],{"class":3331},[2166,38569,37190],{"class":3309},[2166,38571,25050],{"class":3331},[2166,38573,38574],{"class":3309},"slice",[2166,38576,3351],{"class":3331},[2166,38578,20067],{"class":3402},[2166,38580,105],{"class":3331},[2166,38582,23196],{"class":3402},[2166,38584,38585],{"class":3331},") },\n",[2166,38587,38588],{"class":3301,"line":19226},[2166,38589,3553],{"class":3331},[2166,38591,38592,38595,38597,38599],{"class":3301,"line":19231},[2166,38593,38594],{"class":3331},"  saveState.value ",[2166,38596,2998],{"class":3305},[2166,38598,38365],{"class":3316},[2166,38600,3332],{"class":3331},[2166,38602,38603,38606,38608,38610],{"class":3301,"line":19237},[2166,38604,38605],{"class":3331},"  saveError.value ",[2166,38607,2998],{"class":3305},[2166,38609,25741],{"class":3402},[2166,38611,3332],{"class":3331},[2166,38613,38614,38616],{"class":3301,"line":19243},[2166,38615,5370],{"class":3305},[2166,38617,3393],{"class":3331},[2166,38619,38620,38622,38625,38627,38629,38631,38633,38635,38637,38639],{"class":3301,"line":19249},[2166,38621,3399],{"class":3305},[2166,38623,38624],{"class":3402}," res",[2166,38626,3313],{"class":3305},[2166,38628,5513],{"class":3305},[2166,38630,38079],{"class":3309},[2166,38632,3351],{"class":3331},[2166,38634,5581],{"class":3316},[2166,38636,5584],{"class":3402},[2166,38638,38088],{"class":3316},[2166,38640,5389],{"class":3331},[2166,38642,38643,38646,38648],{"class":3301,"line":19255},[2166,38644,38645],{"class":3331},"      method: ",[2166,38647,36693],{"class":3316},[2166,38649,5401],{"class":3331},[2166,38651,38652,38655,38657,38659,38662],{"class":3301,"line":19261},[2166,38653,38654],{"class":3331},"      headers: { ",[2166,38656,36713],{"class":3316},[2166,38658,4664],{"class":3331},[2166,38660,38661],{"class":3316},"\"application\u002Fjson\"",[2166,38663,26375],{"class":3331},[2166,38665,38666,38669,38672,38674,38677],{"class":3301,"line":19267},[2166,38667,38668],{"class":3331},"      body: ",[2166,38670,38671],{"class":3402},"JSON",[2166,38673,407],{"class":3331},[2166,38675,38676],{"class":3309},"stringify",[2166,38678,38679],{"class":3331},"(payload),\n",[2166,38681,38682],{"class":3301,"line":19273},[2166,38683,5418],{"class":3331},[2166,38685,38686,38688,38690,38692,38695,38697,38699,38701,38703,38706,38709,38711,38713,38715],{"class":3301,"line":19279},[2166,38687,3429],{"class":3305},[2166,38689,1305],{"class":3331},[2166,38691,3434],{"class":3305},[2166,38693,38694],{"class":3331},"res.ok) ",[2166,38696,38189],{"class":3305},[2166,38698,36448],{"class":3305},[2166,38700,38194],{"class":3309},[2166,38702,3351],{"class":3331},[2166,38704,38705],{"class":3316},"`save ${",[2166,38707,38708],{"class":3331},"res",[2166,38710,407],{"class":3316},[2166,38712,17939],{"class":3331},[2166,38714,38209],{"class":3316},[2166,38716,3460],{"class":3331},[2166,38718,38719,38722,38724,38726,38728],{"class":3301,"line":19285},[2166,38720,38721],{"class":3331},"    lastSavedAt.value ",[2166,38723,2998],{"class":3305},[2166,38725,36448],{"class":3305},[2166,38727,37185],{"class":3309},[2166,38729,3547],{"class":3331},[2166,38731,38732,38735,38737,38739],{"class":3301,"line":19291},[2166,38733,38734],{"class":3331},"    saveState.value ",[2166,38736,2998],{"class":3305},[2166,38738,38370],{"class":3316},[2166,38740,3332],{"class":3331},[2166,38742,38743,38746,38748],{"class":3301,"line":19297},[2166,38744,38745],{"class":3331},"    wbs.value._meta ",[2166,38747,2998],{"class":3305},[2166,38749,38750],{"class":3331}," payload._meta;\n",[2166,38752,38753,38755,38757],{"class":3301,"line":19303},[2166,38754,5424],{"class":3331},[2166,38756,5427],{"class":3305},[2166,38758,38281],{"class":3331},[2166,38760,38761,38764,38766,38769,38771,38773],{"class":3301,"line":19309},[2166,38762,38763],{"class":3331},"    saveError.value ",[2166,38765,2998],{"class":3305},[2166,38767,38768],{"class":3331}," (e ",[2166,38770,25677],{"class":3305},[2166,38772,38194],{"class":3309},[2166,38774,38775],{"class":3331},").message;\n",[2166,38777,38778,38780,38782,38784],{"class":3301,"line":19315},[2166,38779,38734],{"class":3331},[2166,38781,2998],{"class":3305},[2166,38783,38375],{"class":3316},[2166,38785,3332],{"class":3331},[2166,38787,38788],{"class":3301,"line":19320},[2166,38789,5456],{"class":3331},[2166,38791,38792],{"class":3301,"line":19326},[2166,38793,3559],{"class":3331},[2166,38795,38796],{"class":3301,"line":19332},[2166,38797,3339],{"emptyLinePlaceholder":3338},[2166,38799,38800,38802,38805],{"class":3301,"line":19338},[2166,38801,3345],{"class":3305},[2166,38803,38804],{"class":3309}," scheduleSave",[2166,38806,38036],{"class":3331},[2166,38808,38809,38811,38813,38815],{"class":3301,"line":27528},[2166,38810,38594],{"class":3331},[2166,38812,2998],{"class":3305},[2166,38814,38360],{"class":3316},[2166,38816,3332],{"class":3331},[2166,38818,38819,38821,38824,38826],{"class":3301,"line":27534},[2166,38820,5340],{"class":3305},[2166,38822,38823],{"class":3331}," (saveTimer) ",[2166,38825,38522],{"class":3309},[2166,38827,38828],{"class":3331},"(saveTimer);\n",[2166,38830,38831,38834,38836,38839,38842,38845],{"class":3301,"line":27540},[2166,38832,38833],{"class":3331},"  saveTimer ",[2166,38835,2998],{"class":3305},[2166,38837,38838],{"class":3309}," setTimeout",[2166,38840,38841],{"class":3331},"(saveNow, ",[2166,38843,38844],{"class":3402},"800",[2166,38846,3460],{"class":3331},[2166,38848,38849],{"class":3301,"line":27546},[2166,38850,3559],{"class":3331},[2166,38852,38853],{"class":3301,"line":27552},[2166,38854,3339],{"emptyLinePlaceholder":3338},[2166,38856,38857,38859,38862,38864,38867,38869,38871,38873,38876,38878,38880],{"class":3301,"line":27557},[2166,38858,3345],{"class":3305},[2166,38860,38861],{"class":3309}," setOverride",[2166,38863,3351],{"class":3331},[2166,38865,38866],{"class":3356},"taskId",[2166,38868,3360],{"class":3305},[2166,38870,35600],{"class":3402},[2166,38872,105],{"class":3331},[2166,38874,38875],{"class":3356},"patch",[2166,38877,3360],{"class":3305},[2166,38879,37970],{"class":3309},[2166,38881,5312],{"class":3331},[2166,38883,38884,38886,38888,38890,38892,38894],{"class":3301,"line":27563},[2166,38885,5340],{"class":3305},[2166,38887,1305],{"class":3331},[2166,38889,3434],{"class":3305},[2166,38891,38508],{"class":3331},[2166,38893,3440],{"class":3305},[2166,38895,3332],{"class":3331},[2166,38897,38898,38901,38903,38905,38908,38911],{"class":3301,"line":27569},[2166,38899,38900],{"class":3305},"  for",[2166,38902,1305],{"class":3331},[2166,38904,5234],{"class":3305},[2166,38906,38907],{"class":3402}," s",[2166,38909,38910],{"class":3305}," of",[2166,38912,38913],{"class":3331}," wbs.value.phase1.stages) {\n",[2166,38915,38916,38918,38921,38923,38926,38929,38932,38934,38936,38938,38941,38943],{"class":3301,"line":27575},[2166,38917,3399],{"class":3305},[2166,38919,38920],{"class":3402}," idx",[2166,38922,3313],{"class":3305},[2166,38924,38925],{"class":3331}," s.tasks.",[2166,38927,38928],{"class":3309},"findIndex",[2166,38930,38931],{"class":3331},"((",[2166,38933,37317],{"class":3356},[2166,38935,3387],{"class":3331},[2166,38937,3390],{"class":3305},[2166,38939,38940],{"class":3331}," t.id ",[2166,38942,38145],{"class":3305},[2166,38944,38945],{"class":3331}," taskId);\n",[2166,38947,38948,38950,38953,38955,38958,38960,38962,38965],{"class":3301,"line":27581},[2166,38949,3429],{"class":3305},[2166,38951,38952],{"class":3331}," (idx ",[2166,38954,38145],{"class":3305},[2166,38956,38957],{"class":3305}," -",[2166,38959,6055],{"class":3402},[2166,38961,3387],{"class":3331},[2166,38963,38964],{"class":3305},"continue",[2166,38966,3332],{"class":3331},[2166,38968,38969,38971,38974,38976],{"class":3301,"line":27586},[2166,38970,3399],{"class":3305},[2166,38972,38973],{"class":3402}," cur",[2166,38975,3313],{"class":3305},[2166,38977,38978],{"class":3331}," s.tasks[idx];\n",[2166,38980,38981,38983,38985,38987,38989,38991],{"class":3301,"line":27592},[2166,38982,3399],{"class":3305},[2166,38984,3544],{"class":3402},[2166,38986,3360],{"class":3305},[2166,38988,35586],{"class":3309},[2166,38990,3313],{"class":3305},[2166,38992,3393],{"class":3331},[2166,38994,38995,38998],{"class":3301,"line":27597},[2166,38996,38997],{"class":3305},"      ...",[2166,38999,39000],{"class":3331},"cur,\n",[2166,39002,39003,39005],{"class":3301,"line":27603},[2166,39004,38997],{"class":3305},[2166,39006,39007],{"class":3331},"patch,\n",[2166,39009,39010,39013,39016,39019,39022,39025,39028,39030,39033],{"class":3301,"line":27609},[2166,39011,39012],{"class":3331},"      deliverableUrl: patch.deliverableUrl ",[2166,39014,39015],{"class":3305},"!==",[2166,39017,39018],{"class":3402}," undefined",[2166,39020,39021],{"class":3305}," ?",[2166,39023,39024],{"class":3331}," patch.deliverableUrl ",[2166,39026,39027],{"class":3305},"||",[2166,39029,25741],{"class":3402},[2166,39031,39032],{"class":3305}," :",[2166,39034,39035],{"class":3331}," cur.deliverableUrl,\n",[2166,39037,39038,39041,39043,39045,39047,39050,39052,39054,39056],{"class":3301,"line":27615},[2166,39039,39040],{"class":3331},"      targetDate: patch.targetDate ",[2166,39042,39015],{"class":3305},[2166,39044,39018],{"class":3402},[2166,39046,39021],{"class":3305},[2166,39048,39049],{"class":3331}," patch.targetDate ",[2166,39051,39027],{"class":3305},[2166,39053,25741],{"class":3402},[2166,39055,39032],{"class":3305},[2166,39057,39058],{"class":3331}," cur.targetDate,\n",[2166,39060,39061,39064,39066,39068,39070,39073,39075,39077,39079],{"class":3301,"line":27620},[2166,39062,39063],{"class":3331},"      completionDate: patch.completionDate ",[2166,39065,39015],{"class":3305},[2166,39067,39018],{"class":3402},[2166,39069,39021],{"class":3305},[2166,39071,39072],{"class":3331}," patch.completionDate ",[2166,39074,39027],{"class":3305},[2166,39076,25741],{"class":3402},[2166,39078,39032],{"class":3305},[2166,39080,39081],{"class":3331}," cur.completionDate,\n",[2166,39083,39084,39087,39089,39091,39093,39096,39098,39100,39102],{"class":3301,"line":27626},[2166,39085,39086],{"class":3331},"      note: patch.note ",[2166,39088,39015],{"class":3305},[2166,39090,39018],{"class":3402},[2166,39092,39021],{"class":3305},[2166,39094,39095],{"class":3331}," patch.note ",[2166,39097,39027],{"class":3305},[2166,39099,25741],{"class":3402},[2166,39101,39032],{"class":3305},[2166,39103,39104],{"class":3331}," cur.note,\n",[2166,39106,39107],{"class":3301,"line":27632},[2166,39108,39109],{"class":3331},"    };\n",[2166,39111,39112,39115,39118,39121,39123],{"class":3301,"line":27637},[2166,39113,39114],{"class":3331},"    s.tasks.",[2166,39116,39117],{"class":3309},"splice",[2166,39119,39120],{"class":3331},"(idx, ",[2166,39122,6055],{"class":3402},[2166,39124,39125],{"class":3331},", next);\n",[2166,39127,39128,39131],{"class":3301,"line":27643},[2166,39129,39130],{"class":3309},"    scheduleSave",[2166,39132,3547],{"class":3331},[2166,39134,39135,39137],{"class":3301,"line":27649},[2166,39136,5435],{"class":3305},[2166,39138,3332],{"class":3331},[2166,39140,39141],{"class":3301,"line":27654},[2166,39142,5456],{"class":3331},[2166,39144,39145],{"class":3301,"line":27660},[2166,39146,3559],{"class":3331},[2166,39148,39149],{"class":3301,"line":27665},[2166,39150,3339],{"emptyLinePlaceholder":3338},[2166,39152,39153],{"class":3301,"line":27671},[2166,39154,39155],{"class":3422},"\u002F\u002F ── 파생 상태 ──────────────────────────────────────────\n",[2166,39157,39158,39160,39163,39165,39168,39170,39173,39176,39178,39181,39184],{"class":3301,"line":27677},[2166,39159,5234],{"class":3305},[2166,39161,39162],{"class":3402}," mergedStages",[2166,39164,3313],{"class":3305},[2166,39166,39167],{"class":3309}," computed",[2166,39169,4732],{"class":3331},[2166,39171,39172],{"class":3309},"Stage",[2166,39174,39175],{"class":3331},"[]>(() ",[2166,39177,3390],{"class":3305},[2166,39179,39180],{"class":3331}," wbs.value?.phase1.stages ",[2166,39182,39183],{"class":3305},"??",[2166,39185,39186],{"class":3331}," []);\n",[2166,39188,39189,39191,39194,39196,39198,39201,39203,39206,39208,39211],{"class":3301,"line":27683},[2166,39190,5234],{"class":3305},[2166,39192,39193],{"class":3402}," PROJECT_NAME",[2166,39195,3313],{"class":3305},[2166,39197,39167],{"class":3309},[2166,39199,39200],{"class":3331},"(() ",[2166,39202,3390],{"class":3305},[2166,39204,39205],{"class":3331}," wbs.value?._meta.project ",[2166,39207,39183],{"class":3305},[2166,39209,39210],{"class":3316}," \"Project\"",[2166,39212,3460],{"class":3331},[2166,39214,39215,39217,39220,39222,39224,39226,39228,39231,39233,39236],{"class":3301,"line":27688},[2166,39216,5234],{"class":3305},[2166,39218,39219],{"class":3402}," LAST_UPDATED",[2166,39221,3313],{"class":3305},[2166,39223,39167],{"class":3309},[2166,39225,39200],{"class":3331},[2166,39227,3390],{"class":3305},[2166,39229,39230],{"class":3331}," wbs.value?._meta.lastUpdated ",[2166,39232,39183],{"class":3305},[2166,39234,39235],{"class":3316}," \"—\"",[2166,39237,3460],{"class":3331},[2166,39239,39240],{"class":3301,"line":27693},[2166,39241,3339],{"emptyLinePlaceholder":3338},[2166,39243,39244,39246,39249,39251,39253,39255,39257],{"class":3301,"line":27698},[2166,39245,5234],{"class":3305},[2166,39247,39248],{"class":3402}," weightedAverage",[2166,39250,3313],{"class":3305},[2166,39252,39167],{"class":3309},[2166,39254,39200],{"class":3331},[2166,39256,3390],{"class":3305},[2166,39258,3393],{"class":3331},[2166,39260,39261,39263,39266,39268],{"class":3301,"line":27703},[2166,39262,5317],{"class":3305},[2166,39264,39265],{"class":3402}," st",[2166,39267,3313],{"class":3305},[2166,39269,39270],{"class":3331}," mergedStages.value;\n",[2166,39272,39273,39275,39277,39279,39282,39284,39286,39288,39291],{"class":3301,"line":27709},[2166,39274,5340],{"class":3305},[2166,39276,1305],{"class":3331},[2166,39278,3434],{"class":3305},[2166,39280,39281],{"class":3331},"st.",[2166,39283,37095],{"class":3402},[2166,39285,3387],{"class":3331},[2166,39287,3440],{"class":3305},[2166,39289,39290],{"class":3402}," 0",[2166,39292,3332],{"class":3331},[2166,39294,39295],{"class":3301,"line":27715},[2166,39296,39297],{"class":3422},"  \u002F\u002F 가중평균(%) = Σ(weight × progress) \u002F Σ(weight). progress가 이미 %단위이므로 추가 \u002F100 없음.\n",[2166,39299,39300,39302,39305,39307,39310,39313,39315,39318,39320,39323,39325,39327,39330,39332,39335,39337],{"class":3301,"line":27721},[2166,39301,5317],{"class":3305},[2166,39303,39304],{"class":3402}," w",[2166,39306,3313],{"class":3305},[2166,39308,39309],{"class":3331}," st.",[2166,39311,39312],{"class":3309},"reduce",[2166,39314,38931],{"class":3331},[2166,39316,39317],{"class":3356},"s",[2166,39319,105],{"class":3331},[2166,39321,39322],{"class":3356},"x",[2166,39324,3387],{"class":3331},[2166,39326,3390],{"class":3305},[2166,39328,39329],{"class":3331}," s ",[2166,39331,36649],{"class":3305},[2166,39333,39334],{"class":3331}," x.weight, ",[2166,39336,20067],{"class":3402},[2166,39338,3460],{"class":3331},[2166,39340,39341,39343,39346,39348,39350,39352,39354,39356,39358,39360,39362,39364,39366,39368,39371,39373,39376,39378],{"class":3301,"line":27727},[2166,39342,5317],{"class":3305},[2166,39344,39345],{"class":3402}," p",[2166,39347,3313],{"class":3305},[2166,39349,39309],{"class":3331},[2166,39351,39312],{"class":3309},[2166,39353,38931],{"class":3331},[2166,39355,39317],{"class":3356},[2166,39357,105],{"class":3331},[2166,39359,39322],{"class":3356},[2166,39361,3387],{"class":3331},[2166,39363,3390],{"class":3305},[2166,39365,39329],{"class":3331},[2166,39367,36649],{"class":3305},[2166,39369,39370],{"class":3331}," x.weight ",[2166,39372,5824],{"class":3305},[2166,39374,39375],{"class":3331}," x.progress, ",[2166,39377,20067],{"class":3402},[2166,39379,3460],{"class":3331},[2166,39381,39382,39384,39387,39390,39393,39395,39398,39400,39403,39405,39407,39409],{"class":3301,"line":27733},[2166,39383,3371],{"class":3305},[2166,39385,39386],{"class":3331}," Math.",[2166,39388,39389],{"class":3309},"round",[2166,39391,39392],{"class":3331},"((p ",[2166,39394,530],{"class":3305},[2166,39396,39397],{"class":3331}," w) ",[2166,39399,5824],{"class":3305},[2166,39401,39402],{"class":3402}," 10",[2166,39404,3387],{"class":3331},[2166,39406,530],{"class":3305},[2166,39408,39402],{"class":3402},[2166,39410,3332],{"class":3331},[2166,39412,39413],{"class":3301,"line":27739},[2166,39414,5544],{"class":3331},[2166,39416,39417],{"class":3301,"line":27745},[2166,39418,3339],{"emptyLinePlaceholder":3338},[2166,39420,39421,39423,39426,39428,39430,39432,39434,39437,39440,39442,39444,39446,39448],{"class":3301,"line":27751},[2166,39422,5234],{"class":3305},[2166,39424,39425],{"class":3402}," allTasks",[2166,39427,3313],{"class":3305},[2166,39429,39167],{"class":3309},[2166,39431,39200],{"class":3331},[2166,39433,3390],{"class":3305},[2166,39435,39436],{"class":3331}," mergedStages.value.",[2166,39438,39439],{"class":3309},"flatMap",[2166,39441,38931],{"class":3331},[2166,39443,39317],{"class":3356},[2166,39445,3387],{"class":3331},[2166,39447,3390],{"class":3305},[2166,39449,39450],{"class":3331}," s.tasks));\n",[2166,39452,39453,39455,39458,39460,39462,39464,39466],{"class":3301,"line":27757},[2166,39454,5234],{"class":3305},[2166,39456,39457],{"class":3402}," totalCounts",[2166,39459,3313],{"class":3305},[2166,39461,39167],{"class":3309},[2166,39463,39200],{"class":3331},[2166,39465,3390],{"class":3305},[2166,39467,3393],{"class":3331},[2166,39469,39470,39472,39475,39477,39480,39482,39485,39487,39490,39493,39495,39498,39500,39503,39505,39508,39510,39513,39515],{"class":3301,"line":27763},[2166,39471,5317],{"class":3305},[2166,39473,39474],{"class":3402}," acc",[2166,39476,3360],{"class":3305},[2166,39478,39479],{"class":3309}," Record",[2166,39481,4732],{"class":3331},[2166,39483,39484],{"class":3309},"Status",[2166,39486,105],{"class":3331},[2166,39488,39489],{"class":3402},"number",[2166,39491,39492],{"class":3331},"> ",[2166,39494,2998],{"class":3305},[2166,39496,39497],{"class":3331}," { done: ",[2166,39499,20067],{"class":3402},[2166,39501,39502],{"class":3331},", in_progress: ",[2166,39504,20067],{"class":3402},[2166,39506,39507],{"class":3331},", pending: ",[2166,39509,20067],{"class":3402},[2166,39511,39512],{"class":3331},", blocked: ",[2166,39514,20067],{"class":3402},[2166,39516,37841],{"class":3331},[2166,39518,39520,39522,39524,39526,39529,39531,39534,39537],{"class":3301,"line":39519},145,[2166,39521,38900],{"class":3305},[2166,39523,1305],{"class":3331},[2166,39525,5234],{"class":3305},[2166,39527,39528],{"class":3402}," t",[2166,39530,38910],{"class":3305},[2166,39532,39533],{"class":3331}," allTasks.value) acc[t.status]",[2166,39535,39536],{"class":3305},"++",[2166,39538,3332],{"class":3331},[2166,39540,39542,39544],{"class":3301,"line":39541},146,[2166,39543,3371],{"class":3305},[2166,39545,39546],{"class":3331}," acc;\n",[2166,39548,39550],{"class":3301,"line":39549},147,[2166,39551,5544],{"class":3331},[2166,39553,39555],{"class":3301,"line":39554},148,[2166,39556,3339],{"emptyLinePlaceholder":3338},[2166,39558,39560,39562,39565,39567,39569,39571,39573],{"class":3301,"line":39559},149,[2166,39561,3345],{"class":3305},[2166,39563,39564],{"class":3309}," isOverdue",[2166,39566,3351],{"class":3331},[2166,39568,37317],{"class":3356},[2166,39570,3360],{"class":3305},[2166,39572,35586],{"class":3309},[2166,39574,5312],{"class":3331},[2166,39576,39578,39580,39583,39585,39587,39590,39593,39596,39598,39600],{"class":3301,"line":39577},150,[2166,39579,5340],{"class":3305},[2166,39581,39582],{"class":3331}," (t.status ",[2166,39584,38145],{"class":3305},[2166,39586,35558],{"class":3316},[2166,39588,39589],{"class":3305}," ||",[2166,39591,39592],{"class":3305}," !",[2166,39594,39595],{"class":3331},"t.targetDate) ",[2166,39597,3440],{"class":3305},[2166,39599,38316],{"class":3402},[2166,39601,3332],{"class":3331},[2166,39603,39605,39607,39610,39612,39614],{"class":3301,"line":39604},151,[2166,39606,3371],{"class":3305},[2166,39608,39609],{"class":3331}," t.targetDate ",[2166,39611,4732],{"class":3305},[2166,39613,39219],{"class":3402},[2166,39615,39616],{"class":3331},".value;\n",[2166,39618,39620],{"class":3301,"line":39619},152,[2166,39621,3559],{"class":3331},[2166,39623,39625],{"class":3301,"line":39624},153,[2166,39626,3339],{"emptyLinePlaceholder":3338},[2166,39628,39630,39632,39635,39637,39639,39641,39643,39646,39648,39650,39652,39654,39657,39659,39661,39663,39666,39668,39670,39673,39675],{"class":3301,"line":39629},154,[2166,39631,5234],{"class":3305},[2166,39633,39634],{"class":3402}," statusMeta",[2166,39636,3360],{"class":3305},[2166,39638,39479],{"class":3309},[2166,39640,4732],{"class":3331},[2166,39642,39484],{"class":3309},[2166,39644,39645],{"class":3331},", { ",[2166,39647,3022],{"class":3356},[2166,39649,3360],{"class":3305},[2166,39651,35600],{"class":3402},[2166,39653,5280],{"class":3331},[2166,39655,39656],{"class":3356},"chipCls",[2166,39658,3360],{"class":3305},[2166,39660,35600],{"class":3402},[2166,39662,5280],{"class":3331},[2166,39664,39665],{"class":3356},"emoji",[2166,39667,3360],{"class":3305},[2166,39669,35600],{"class":3402},[2166,39671,39672],{"class":3331}," }> ",[2166,39674,2998],{"class":3305},[2166,39676,3393],{"class":3331},[2166,39678,39680,39683,39686,39689,39692,39695,39698],{"class":3301,"line":39679},155,[2166,39681,39682],{"class":3331},"  done:        { label: ",[2166,39684,39685],{"class":3316},"\"완료\"",[2166,39687,39688],{"class":3331},",   chipCls: ",[2166,39690,39691],{"class":3316},"\"bg-emerald-50 text-emerald-700 border-emerald-200\"",[2166,39693,39694],{"class":3331},", emoji: ",[2166,39696,39697],{"class":3316},"\"✓\"",[2166,39699,26375],{"class":3331},[2166,39701,39703,39706,39709,39712,39715,39718,39721],{"class":3301,"line":39702},156,[2166,39704,39705],{"class":3331},"  in_progress: { label: ",[2166,39707,39708],{"class":3316},"\"진행 중\"",[2166,39710,39711],{"class":3331},", chipCls: ",[2166,39713,39714],{"class":3316},"\"bg-amber-50 text-amber-700 border-amber-200\"",[2166,39716,39717],{"class":3331},",       emoji: ",[2166,39719,39720],{"class":3316},"\"◐\"",[2166,39722,26375],{"class":3331},[2166,39724,39726,39729,39732,39734,39737,39739,39742],{"class":3301,"line":39725},157,[2166,39727,39728],{"class":3331},"  pending:     { label: ",[2166,39730,39731],{"class":3316},"\"대기\"",[2166,39733,39688],{"class":3331},[2166,39735,39736],{"class":3316},"\"bg-neutral-50 text-neutral-600 border-neutral-200\"",[2166,39738,39694],{"class":3331},[2166,39740,39741],{"class":3316},"\"○\"",[2166,39743,26375],{"class":3331},[2166,39745,39747,39750,39753,39755,39758,39761,39764],{"class":3301,"line":39746},158,[2166,39748,39749],{"class":3331},"  blocked:     { label: ",[2166,39751,39752],{"class":3316},"\"보류\"",[2166,39754,39688],{"class":3331},[2166,39756,39757],{"class":3316},"\"bg-rose-50 text-rose-700 border-rose-200\"",[2166,39759,39760],{"class":3331},",          emoji: ",[2166,39762,39763],{"class":3316},"\"✕\"",[2166,39765,26375],{"class":3331},[2166,39767,39769],{"class":3301,"line":39768},159,[2166,39770,35715],{"class":3331},[2166,39772,39774],{"class":3301,"line":39773},160,[2166,39775,3339],{"emptyLinePlaceholder":3338},[2166,39777,39779,39781,39784,39786,39789,39791,39793],{"class":3301,"line":39778},161,[2166,39780,3345],{"class":3305},[2166,39782,39783],{"class":3309}," progressFill",[2166,39785,3351],{"class":3331},[2166,39787,39788],{"class":3356},"pct",[2166,39790,3360],{"class":3305},[2166,39792,35765],{"class":3402},[2166,39794,5312],{"class":3331},[2166,39796,39798,39800,39803,39806,39809,39811,39813,39816],{"class":3301,"line":39797},162,[2166,39799,5340],{"class":3305},[2166,39801,39802],{"class":3331}," (pct ",[2166,39804,39805],{"class":3305},">=",[2166,39807,39808],{"class":3402}," 70",[2166,39810,3387],{"class":3331},[2166,39812,3440],{"class":3305},[2166,39814,39815],{"class":3316}," \"bg-emerald-500\"",[2166,39817,3332],{"class":3331},[2166,39819,39821,39823,39825,39827,39830,39832,39834,39837],{"class":3301,"line":39820},163,[2166,39822,5340],{"class":3305},[2166,39824,39802],{"class":3331},[2166,39826,39805],{"class":3305},[2166,39828,39829],{"class":3402}," 30",[2166,39831,3387],{"class":3331},[2166,39833,3440],{"class":3305},[2166,39835,39836],{"class":3316}," \"bg-amber-500\"",[2166,39838,3332],{"class":3331},[2166,39840,39842,39844,39846,39848,39850,39853,39855,39858],{"class":3301,"line":39841},164,[2166,39843,5340],{"class":3305},[2166,39845,39802],{"class":3331},[2166,39847,4653],{"class":3305},[2166,39849,39290],{"class":3402},[2166,39851,39852],{"class":3331},")   ",[2166,39854,3440],{"class":3305},[2166,39856,39857],{"class":3316}," \"bg-neutral-400\"",[2166,39859,3332],{"class":3331},[2166,39861,39863,39865,39868],{"class":3301,"line":39862},165,[2166,39864,3371],{"class":3305},[2166,39866,39867],{"class":3316}," \"bg-neutral-200\"",[2166,39869,3332],{"class":3331},[2166,39871,39873],{"class":3301,"line":39872},166,[2166,39874,3559],{"class":3331},[2166,39876,39878],{"class":3301,"line":39877},167,[2166,39879,3339],{"emptyLinePlaceholder":3338},[2166,39881,39883,39885,39888,39890,39893,39896,39898,39901,39903,39906,39908,39911,39913,39916,39918,39921],{"class":3301,"line":39882},168,[2166,39884,5234],{"class":3305},[2166,39886,39887],{"class":3402}," stageEmoji",[2166,39889,3313],{"class":3305},[2166,39891,39892],{"class":3331}," [",[2166,39894,39895],{"class":3316},"\"🎯\"",[2166,39897,105],{"class":3331},[2166,39899,39900],{"class":3316},"\"📐\"",[2166,39902,105],{"class":3331},[2166,39904,39905],{"class":3316},"\"🛠️\"",[2166,39907,105],{"class":3331},[2166,39909,39910],{"class":3316},"\"📚\"",[2166,39912,105],{"class":3331},[2166,39914,39915],{"class":3316},"\"🧪\"",[2166,39917,105],{"class":3331},[2166,39919,39920],{"class":3316},"\"🚀\"",[2166,39922,39923],{"class":3331},"];\n",[2166,39925,39927],{"class":3301,"line":39926},169,[2166,39928,3339],{"emptyLinePlaceholder":3338},[2166,39930,39932],{"class":3301,"line":39931},170,[2166,39933,39934],{"class":3422},"\u002F\u002F ── 백업 다운로드 ─────────────────────────────────────\n",[2166,39936,39938,39940,39943,39945,39947,39949,39951,39954,39956,39959,39961,39963,39966,39968,39970,39972,39974,39976,39979,39982,39985,39987,39990],{"class":3301,"line":39937},171,[2166,39939,5234],{"class":3305},[2166,39941,39942],{"class":3402}," currentJsonString",[2166,39944,3313],{"class":3305},[2166,39946,39167],{"class":3309},[2166,39948,39200],{"class":3331},[2166,39950,3390],{"class":3305},[2166,39952,39953],{"class":3331}," wbs.value ",[2166,39955,25723],{"class":3305},[2166,39957,39958],{"class":3402}," JSON",[2166,39960,407],{"class":3331},[2166,39962,38676],{"class":3309},[2166,39964,39965],{"class":3331},"(wbs.value, ",[2166,39967,36143],{"class":3402},[2166,39969,105],{"class":3331},[2166,39971,7685],{"class":3402},[2166,39973,3387],{"class":3331},[2166,39975,36649],{"class":3305},[2166,39977,39978],{"class":3316}," \"",[2166,39980,39981],{"class":3402},"\\n",[2166,39983,39984],{"class":3316},"\"",[2166,39986,39032],{"class":3305},[2166,39988,39989],{"class":3316}," \"\"",[2166,39991,3460],{"class":3331},[2166,39993,39995,39997,40000],{"class":3301,"line":39994},172,[2166,39996,3345],{"class":3305},[2166,39998,39999],{"class":3309}," downloadJson",[2166,40001,38036],{"class":3331},[2166,40003,40005,40007,40010,40012,40014,40017,40020,40022],{"class":3301,"line":40004},173,[2166,40006,5317],{"class":3305},[2166,40008,40009],{"class":3402}," blob",[2166,40011,3313],{"class":3305},[2166,40013,36448],{"class":3305},[2166,40015,40016],{"class":3309}," Blob",[2166,40018,40019],{"class":3331},"([currentJsonString.value], { type: ",[2166,40021,38661],{"class":3316},[2166,40023,37563],{"class":3331},[2166,40025,40027,40029,40032,40034,40036,40038,40041],{"class":3301,"line":40026},174,[2166,40028,5317],{"class":3305},[2166,40030,40031],{"class":3402}," url",[2166,40033,3313],{"class":3305},[2166,40035,5253],{"class":3402},[2166,40037,407],{"class":3331},[2166,40039,40040],{"class":3309},"createObjectURL",[2166,40042,40043],{"class":3331},"(blob);\n",[2166,40045,40047,40049,40052,40054,40057,40060,40062,40065],{"class":3301,"line":40046},175,[2166,40048,5317],{"class":3305},[2166,40050,40051],{"class":3402}," a",[2166,40053,3313],{"class":3305},[2166,40055,40056],{"class":3331}," document.",[2166,40058,40059],{"class":3309},"createElement",[2166,40061,3351],{"class":3331},[2166,40063,40064],{"class":3316},"\"a\"",[2166,40066,3460],{"class":3331},[2166,40068,40070,40073,40075,40078,40080,40083,40086,40089],{"class":3301,"line":40069},176,[2166,40071,40072],{"class":3331},"  a.href ",[2166,40074,2998],{"class":3305},[2166,40076,40077],{"class":3331}," url; a.download ",[2166,40079,2998],{"class":3305},[2166,40081,40082],{"class":3316}," \"wbs.json\"",[2166,40084,40085],{"class":3331},"; a.",[2166,40087,40088],{"class":3309},"click",[2166,40090,3547],{"class":3331},[2166,40092,40094,40097,40099,40101,40103,40105,40108,40111,40114],{"class":3301,"line":40093},177,[2166,40095,40096],{"class":3309},"  setTimeout",[2166,40098,39200],{"class":3331},[2166,40100,3390],{"class":3305},[2166,40102,5253],{"class":3402},[2166,40104,407],{"class":3331},[2166,40106,40107],{"class":3309},"revokeObjectURL",[2166,40109,40110],{"class":3331},"(url), ",[2166,40112,40113],{"class":3402},"1000",[2166,40115,3460],{"class":3331},[2166,40117,40119],{"class":3301,"line":40118},178,[2166,40120,3559],{"class":3331},[2166,40122,40124],{"class":3301,"line":40123},179,[2166,40125,3339],{"emptyLinePlaceholder":3338},[2166,40127,40129],{"class":3301,"line":40128},180,[2166,40130,40131],{"class":3422},"\u002F\u002F ── \"n초 전\" 갱신 ─────────────────────────────────────\n",[2166,40133,40135,40137,40140,40142,40144,40146,40149],{"class":3301,"line":40134},181,[2166,40136,5234],{"class":3305},[2166,40138,40139],{"class":3402}," savedAgo",[2166,40141,3313],{"class":3305},[2166,40143,37900],{"class":3309},[2166,40145,3351],{"class":3331},[2166,40147,40148],{"class":3316},"\"\"",[2166,40150,3460],{"class":3331},[2166,40152,40154,40156,40159,40161,40163,40165,40167,40170,40172,40174,40176,40178],{"class":3301,"line":40153},182,[2166,40155,38457],{"class":3305},[2166,40157,40158],{"class":3331}," agoTimer",[2166,40160,3360],{"class":3305},[2166,40162,38465],{"class":3309},[2166,40164,4732],{"class":3331},[2166,40166,25633],{"class":3305},[2166,40168,40169],{"class":3331}," setInterval> ",[2166,40171,25695],{"class":3305},[2166,40173,25741],{"class":3402},[2166,40175,3313],{"class":3305},[2166,40177,25741],{"class":3402},[2166,40179,3332],{"class":3331},[2166,40181,40183,40185,40188,40190,40193,40195,40197],{"class":3301,"line":40182},183,[2166,40184,3345],{"class":3305},[2166,40186,40187],{"class":3309}," formatAgo",[2166,40189,3351],{"class":3331},[2166,40191,40192],{"class":3356},"d",[2166,40194,3360],{"class":3305},[2166,40196,37185],{"class":3309},[2166,40198,5312],{"class":3331},[2166,40200,40202,40204,40206,40208,40210,40213,40216,40219,40222,40225,40228,40231,40233,40235,40238],{"class":3301,"line":40201},184,[2166,40203,5317],{"class":3305},[2166,40205,38907],{"class":3402},[2166,40207,3313],{"class":3305},[2166,40209,39386],{"class":3331},[2166,40211,40212],{"class":3309},"floor",[2166,40214,40215],{"class":3331},"((Date.",[2166,40217,40218],{"class":3309},"now",[2166,40220,40221],{"class":3331},"() ",[2166,40223,40224],{"class":3305},"-",[2166,40226,40227],{"class":3331}," d.",[2166,40229,40230],{"class":3309},"getTime",[2166,40232,38122],{"class":3331},[2166,40234,530],{"class":3305},[2166,40236,40237],{"class":3402}," 1000",[2166,40239,3460],{"class":3331},[2166,40241,40243,40245,40248,40250,40253,40255,40257,40260],{"class":3301,"line":40242},185,[2166,40244,5340],{"class":3305},[2166,40246,40247],{"class":3331}," (s ",[2166,40249,4732],{"class":3305},[2166,40251,40252],{"class":3402}," 5",[2166,40254,3387],{"class":3331},[2166,40256,3440],{"class":3305},[2166,40258,40259],{"class":3316}," \"방금\"",[2166,40261,3332],{"class":3331},[2166,40263,40265,40267,40269,40271,40274,40276,40278,40281,40283,40286],{"class":3301,"line":40264},186,[2166,40266,5340],{"class":3305},[2166,40268,40247],{"class":3331},[2166,40270,4732],{"class":3305},[2166,40272,40273],{"class":3402}," 60",[2166,40275,3387],{"class":3331},[2166,40277,3440],{"class":3305},[2166,40279,40280],{"class":3316}," `${",[2166,40282,39317],{"class":3331},[2166,40284,40285],{"class":3316},"}초 전`",[2166,40287,3332],{"class":3331},[2166,40289,40291,40293,40296,40298,40300,40302,40305,40307,40309],{"class":3301,"line":40290},187,[2166,40292,5317],{"class":3305},[2166,40294,40295],{"class":3402}," m",[2166,40297,3313],{"class":3305},[2166,40299,39386],{"class":3331},[2166,40301,40212],{"class":3309},[2166,40303,40304],{"class":3331},"(s ",[2166,40306,530],{"class":3305},[2166,40308,40273],{"class":3402},[2166,40310,3460],{"class":3331},[2166,40312,40314,40316,40319,40321,40323,40325,40327,40329,40332,40335],{"class":3301,"line":40313},188,[2166,40315,5340],{"class":3305},[2166,40317,40318],{"class":3331}," (m ",[2166,40320,4732],{"class":3305},[2166,40322,40273],{"class":3402},[2166,40324,3387],{"class":3331},[2166,40326,3440],{"class":3305},[2166,40328,40280],{"class":3316},[2166,40330,40331],{"class":3331},"m",[2166,40333,40334],{"class":3316},"}분 전`",[2166,40336,3332],{"class":3331},[2166,40338,40340,40342,40344,40347,40349,40351,40353,40355,40358,40360,40362,40365],{"class":3301,"line":40339},189,[2166,40341,3371],{"class":3305},[2166,40343,40280],{"class":3316},[2166,40345,40346],{"class":3331},"Math",[2166,40348,407],{"class":3316},[2166,40350,40212],{"class":3309},[2166,40352,3351],{"class":3316},[2166,40354,40331],{"class":3331},[2166,40356,40357],{"class":3305}," \u002F",[2166,40359,40273],{"class":3402},[2166,40361,78],{"class":3316},[2166,40363,40364],{"class":3316},"}시간 전`",[2166,40366,3332],{"class":3331},[2166,40368,40370],{"class":3301,"line":40369},190,[2166,40371,3559],{"class":3331},[2166,40373,40375,40377,40379,40381],{"class":3301,"line":40374},191,[2166,40376,38331],{"class":3309},[2166,40378,39200],{"class":3331},[2166,40380,3390],{"class":3305},[2166,40382,3393],{"class":3331},[2166,40384,40386,40389,40391,40394,40396,40398],{"class":3301,"line":40385},192,[2166,40387,40388],{"class":3331},"  agoTimer ",[2166,40390,2998],{"class":3305},[2166,40392,40393],{"class":3309}," setInterval",[2166,40395,39200],{"class":3331},[2166,40397,3390],{"class":3305},[2166,40399,3393],{"class":3331},[2166,40401,40403,40406,40408,40411,40413,40415,40418,40420,40422],{"class":3301,"line":40402},193,[2166,40404,40405],{"class":3331},"    savedAgo.value ",[2166,40407,2998],{"class":3305},[2166,40409,40410],{"class":3331}," lastSavedAt.value ",[2166,40412,25723],{"class":3305},[2166,40414,40187],{"class":3309},[2166,40416,40417],{"class":3331},"(lastSavedAt.value) ",[2166,40419,3360],{"class":3305},[2166,40421,39989],{"class":3316},[2166,40423,3332],{"class":3331},[2166,40425,40427,40430,40432],{"class":3301,"line":40426},194,[2166,40428,40429],{"class":3331},"  }, ",[2166,40431,40113],{"class":3402},[2166,40433,3460],{"class":3331},[2166,40435,40437],{"class":3301,"line":40436},195,[2166,40438,5544],{"class":3331},[2166,40440,40442,40445,40447,40449],{"class":3301,"line":40441},196,[2166,40443,40444],{"class":3309},"onUnmounted",[2166,40446,39200],{"class":3331},[2166,40448,3390],{"class":3305},[2166,40450,3393],{"class":3331},[2166,40452,40454,40456,40459,40462],{"class":3301,"line":40453},197,[2166,40455,5340],{"class":3305},[2166,40457,40458],{"class":3331}," (agoTimer) ",[2166,40460,40461],{"class":3309},"clearInterval",[2166,40463,40464],{"class":3331},"(agoTimer);\n",[2166,40466,40468,40470,40472,40474],{"class":3301,"line":40467},198,[2166,40469,5340],{"class":3305},[2166,40471,38823],{"class":3331},[2166,40473,38522],{"class":3309},[2166,40475,38828],{"class":3331},[2166,40477,40479],{"class":3301,"line":40478},199,[2166,40480,5544],{"class":3331},[2166,40482,40484],{"class":3301,"line":40483},200,[2166,40485,3339],{"emptyLinePlaceholder":3338},[2166,40487,40489,40491,40494,40496,40499,40501,40503],{"class":3301,"line":40488},201,[2166,40490,3345],{"class":3305},[2166,40492,40493],{"class":3309}," scrollToStage",[2166,40495,3351],{"class":3331},[2166,40497,40498],{"class":3356},"stageId",[2166,40500,3360],{"class":3305},[2166,40502,35600],{"class":3402},[2166,40504,5312],{"class":3331},[2166,40506,40508,40511,40514,40516,40519,40521,40523,40526,40529,40532,40535,40538,40541],{"class":3301,"line":40507},202,[2166,40509,40510],{"class":3331},"  document.",[2166,40512,40513],{"class":3309},"getElementById",[2166,40515,3351],{"class":3331},[2166,40517,40518],{"class":3316},"`stage-${",[2166,40520,40498],{"class":3331},[2166,40522,38209],{"class":3316},[2166,40524,40525],{"class":3331},")?.",[2166,40527,40528],{"class":3309},"scrollIntoView",[2166,40530,40531],{"class":3331},"({ behavior: ",[2166,40533,40534],{"class":3316},"\"smooth\"",[2166,40536,40537],{"class":3331},", block: ",[2166,40539,40540],{"class":3316},"\"start\"",[2166,40542,37563],{"class":3331},[2166,40544,40546],{"class":3301,"line":40545},203,[2166,40547,3559],{"class":3331},[2166,40549,40551,40554,40556],{"class":3301,"line":40550},204,[2166,40552,40553],{"class":3331},"\u003C\u002F",[2166,40555,37536],{"class":37535},[2166,40557,4741],{"class":3331},[2166,40559,40561],{"class":3301,"line":40560},205,[2166,40562,3339],{"emptyLinePlaceholder":3338},[2166,40564,40566,40568,40571],{"class":3301,"line":40565},206,[2166,40567,4732],{"class":3331},[2166,40569,40570],{"class":37535},"template",[2166,40572,4741],{"class":3331},[2166,40574,40576,40579,40582,40585,40587,40590],{"class":3301,"line":40575},207,[2166,40577,40578],{"class":3331},"  \u003C",[2166,40580,40581],{"class":37535},"div",[2166,40583,40584],{"class":3309}," class",[2166,40586,2998],{"class":3331},[2166,40588,40589],{"class":3316},"\"min-h-screen bg-neutral-50\u002F60 pb-24\"",[2166,40591,4741],{"class":3331},[2166,40593,40595,40598,40600,40602,40604,40607],{"class":3301,"line":40594},208,[2166,40596,40597],{"class":3331},"    \u003C",[2166,40599,40581],{"class":37535},[2166,40601,40584],{"class":3309},[2166,40603,2998],{"class":3331},[2166,40605,40606],{"class":3316},"\"mx-auto max-w-5xl px-6 pt-10 sm:px-10 sm:pt-14\"",[2166,40608,4741],{"class":3331},[2166,40610,40612],{"class":3301,"line":40611},209,[2166,40613,40614],{"class":3422},"      \u003C!-- HEADER -->\n",[2166,40616,40618,40621,40623,40625,40627,40630],{"class":3301,"line":40617},210,[2166,40619,40620],{"class":3331},"      \u003C",[2166,40622,5328],{"class":37535},[2166,40624,40584],{"class":3309},[2166,40626,2998],{"class":3331},[2166,40628,40629],{"class":3316},"\"mt-4 flex items-start justify-between gap-4\"",[2166,40631,4741],{"class":3331},[2166,40633,40635,40638,40640,40642,40644,40647],{"class":3301,"line":40634},211,[2166,40636,40637],{"class":3331},"        \u003C",[2166,40639,40581],{"class":37535},[2166,40641,40584],{"class":3309},[2166,40643,2998],{"class":3331},[2166,40645,40646],{"class":3316},"\"flex items-start gap-3\"",[2166,40648,4741],{"class":3331},[2166,40650,40652,40655,40657,40659,40661,40664,40667,40669],{"class":3301,"line":40651},212,[2166,40653,40654],{"class":3331},"          \u003C",[2166,40656,2166],{"class":37535},[2166,40658,40584],{"class":3309},[2166,40660,2998],{"class":3331},[2166,40662,40663],{"class":3316},"\"mt-1 text-[30px]\"",[2166,40665,40666],{"class":3331},">📋\u003C\u002F",[2166,40668,2166],{"class":37535},[2166,40670,4741],{"class":3331},[2166,40672,40674,40676,40678],{"class":3301,"line":40673},213,[2166,40675,40654],{"class":3331},[2166,40677,40581],{"class":37535},[2166,40679,4741],{"class":3331},[2166,40681,40683,40686,40688,40690,40692,40695],{"class":3301,"line":40682},214,[2166,40684,40685],{"class":3331},"            \u003C",[2166,40687,11],{"class":37535},[2166,40689,40584],{"class":3309},[2166,40691,2998],{"class":3331},[2166,40693,40694],{"class":3316},"\"text-[28px] font-semibold tracking-tight text-neutral-900\"",[2166,40696,4741],{"class":3331},[2166,40698,40700],{"class":3301,"line":40699},215,[2166,40701,40702],{"class":3331},"              {{ PROJECT_NAME }} · Phase 1\n",[2166,40704,40706,40709,40711],{"class":3301,"line":40705},216,[2166,40707,40708],{"class":3331},"            \u003C\u002F",[2166,40710,11],{"class":37535},[2166,40712,4741],{"class":3331},[2166,40714,40716,40718,40720,40722,40724,40727],{"class":3301,"line":40715},217,[2166,40717,40685],{"class":3331},[2166,40719,24],{"class":37535},[2166,40721,40584],{"class":3309},[2166,40723,2998],{"class":3331},[2166,40725,40726],{"class":3316},"\"mt-1 text-[14px] text-neutral-500\"",[2166,40728,4741],{"class":3331},[2166,40730,40732],{"class":3301,"line":40731},218,[2166,40733,40734],{"class":3331},"              마지막 현행화 {{ LAST_UPDATED }}\n",[2166,40736,40738,40740,40742],{"class":3301,"line":40737},219,[2166,40739,40708],{"class":3331},[2166,40741,24],{"class":37535},[2166,40743,4741],{"class":3331},[2166,40745,40747,40750,40752],{"class":3301,"line":40746},220,[2166,40748,40749],{"class":3331},"          \u003C\u002F",[2166,40751,40581],{"class":37535},[2166,40753,4741],{"class":3331},[2166,40755,40757,40760,40762],{"class":3301,"line":40756},221,[2166,40758,40759],{"class":3331},"        \u003C\u002F",[2166,40761,40581],{"class":37535},[2166,40763,4741],{"class":3331},[2166,40765,40767,40770,40772],{"class":3301,"line":40766},222,[2166,40768,40769],{"class":3331},"      \u003C\u002F",[2166,40771,5328],{"class":37535},[2166,40773,4741],{"class":3331},[2166,40775,40777],{"class":3301,"line":40776},223,[2166,40778,3339],{"emptyLinePlaceholder":3338},[2166,40780,40782],{"class":3301,"line":40781},224,[2166,40783,40784],{"class":3422},"      \u003C!-- LOADING \u002F ERROR -->\n",[2166,40786,40788,40790,40792,40795,40797,40800,40802,40804,40807],{"class":3301,"line":40787},225,[2166,40789,40620],{"class":3331},[2166,40791,40581],{"class":37535},[2166,40793,40794],{"class":3309}," v-if",[2166,40796,2998],{"class":3331},[2166,40798,40799],{"class":3316},"\"pending\"",[2166,40801,40584],{"class":3309},[2166,40803,2998],{"class":3331},[2166,40805,40806],{"class":3316},"\"mt-8 rounded-xl border border-neutral-200 bg-white p-6 text-[14px] text-neutral-500\"",[2166,40808,4741],{"class":3331},[2166,40810,40812],{"class":3301,"line":40811},226,[2166,40813,40814],{"class":3331},"        로딩 중…\n",[2166,40816,40818,40820,40822],{"class":3301,"line":40817},227,[2166,40819,40769],{"class":3331},[2166,40821,40581],{"class":37535},[2166,40823,4741],{"class":3331},[2166,40825,40827,40829,40831,40834,40836,40839,40841,40843,40846],{"class":3301,"line":40826},228,[2166,40828,40620],{"class":3331},[2166,40830,40581],{"class":37535},[2166,40832,40833],{"class":3309}," v-else-if",[2166,40835,2998],{"class":3331},[2166,40837,40838],{"class":3316},"\"error\"",[2166,40840,40584],{"class":3309},[2166,40842,2998],{"class":3331},[2166,40844,40845],{"class":3316},"\"mt-8 rounded-xl border border-rose-200 bg-rose-50 p-6 text-[14px] text-rose-700\"",[2166,40847,4741],{"class":3331},[2166,40849,40851],{"class":3301,"line":40850},229,[2166,40852,40853],{"class":3331},"        로드 실패: {{ error.message }}\n",[2166,40855,40857,40859,40861],{"class":3301,"line":40856},230,[2166,40858,40769],{"class":3331},[2166,40860,40581],{"class":37535},[2166,40862,4741],{"class":3331},[2166,40864,40866],{"class":3301,"line":40865},231,[2166,40867,3339],{"emptyLinePlaceholder":3338},[2166,40869,40871,40873,40875,40878],{"class":3301,"line":40870},232,[2166,40872,40620],{"class":3331},[2166,40874,40570],{"class":37535},[2166,40876,40877],{"class":3305}," v-else",[2166,40879,4741],{"class":3331},[2166,40881,40883],{"class":3301,"line":40882},233,[2166,40884,40885],{"class":3422},"        \u003C!-- HERO -->\n",[2166,40887,40889,40891,40894,40896,40898,40901],{"class":3301,"line":40888},234,[2166,40890,40637],{"class":3331},[2166,40892,40893],{"class":37535},"section",[2166,40895,40584],{"class":3309},[2166,40897,2998],{"class":3331},[2166,40899,40900],{"class":3316},"\"mt-6 grid grid-cols-1 gap-3 sm:grid-cols-4\"",[2166,40902,4741],{"class":3331},[2166,40904,40906,40908,40910,40912,40914,40917],{"class":3301,"line":40905},235,[2166,40907,40654],{"class":3331},[2166,40909,40581],{"class":37535},[2166,40911,40584],{"class":3309},[2166,40913,2998],{"class":3331},[2166,40915,40916],{"class":3316},"\"rounded-xl border border-neutral-200 bg-white p-5 sm:col-span-2\"",[2166,40918,4741],{"class":3331},[2166,40920,40922,40924,40926,40928,40930,40933,40936,40938],{"class":3301,"line":40921},236,[2166,40923,40685],{"class":3331},[2166,40925,24],{"class":37535},[2166,40927,40584],{"class":3309},[2166,40929,2998],{"class":3331},[2166,40931,40932],{"class":3316},"\"text-[12px] text-neutral-500\"",[2166,40934,40935],{"class":3331},">전체 진행률\u003C\u002F",[2166,40937,24],{"class":37535},[2166,40939,4741],{"class":3331},[2166,40941,40943,40945,40947,40949,40951,40954],{"class":3301,"line":40942},237,[2166,40944,40685],{"class":3331},[2166,40946,24],{"class":37535},[2166,40948,40584],{"class":3309},[2166,40950,2998],{"class":3331},[2166,40952,40953],{"class":3316},"\"mt-1 text-[36px] font-semibold tracking-tight text-neutral-900 tabular-nums\"",[2166,40955,4741],{"class":3331},[2166,40957,40959,40962,40964,40966,40968,40971,40974,40976],{"class":3301,"line":40958},238,[2166,40960,40961],{"class":3331},"              {{ weightedAverage }}\u003C",[2166,40963,2166],{"class":37535},[2166,40965,40584],{"class":3309},[2166,40967,2998],{"class":3331},[2166,40969,40970],{"class":3316},"\"ml-0.5 text-[24px] text-neutral-400\"",[2166,40972,40973],{"class":3331},">%\u003C\u002F",[2166,40975,2166],{"class":37535},[2166,40977,4741],{"class":3331},[2166,40979,40981,40983,40985],{"class":3301,"line":40980},239,[2166,40982,40708],{"class":3331},[2166,40984,24],{"class":37535},[2166,40986,4741],{"class":3331},[2166,40988,40990,40992,40994,40996,40998,41001],{"class":3301,"line":40989},240,[2166,40991,40685],{"class":3331},[2166,40993,40581],{"class":37535},[2166,40995,40584],{"class":3309},[2166,40997,2998],{"class":3331},[2166,40999,41000],{"class":3316},"\"mt-4 h-1.5 overflow-hidden rounded-full bg-neutral-100\"",[2166,41002,4741],{"class":3331},[2166,41004,41006,41009,41011,41013,41015,41018,41021,41023,41026,41029],{"class":3301,"line":41005},241,[2166,41007,41008],{"class":3331},"              \u003C",[2166,41010,40581],{"class":37535},[2166,41012,40584],{"class":3309},[2166,41014,2998],{"class":3331},[2166,41016,41017],{"class":3316},"\"h-full rounded-full bg-neutral-900 transition-all\"",[2166,41019,41020],{"class":3309}," :style",[2166,41022,2998],{"class":3331},[2166,41024,41025],{"class":3316},"\"{ width: weightedAverage + '%' }\"",[2166,41027,40357],{"class":41028},"s7hpK",[2166,41030,4741],{"class":3331},[2166,41032,41034,41036,41038],{"class":3301,"line":41033},242,[2166,41035,40708],{"class":3331},[2166,41037,40581],{"class":37535},[2166,41039,4741],{"class":3331},[2166,41041,41043,41045,41047],{"class":3301,"line":41042},243,[2166,41044,40749],{"class":3331},[2166,41046,40581],{"class":37535},[2166,41048,4741],{"class":3331},[2166,41050,41052,41054,41056,41058,41060,41063],{"class":3301,"line":41051},244,[2166,41053,40654],{"class":3331},[2166,41055,40581],{"class":37535},[2166,41057,40584],{"class":3309},[2166,41059,2998],{"class":3331},[2166,41061,41062],{"class":3316},"\"rounded-xl border border-neutral-200 bg-white p-5\"",[2166,41064,4741],{"class":3331},[2166,41066,41068,41070,41072,41074,41076,41079],{"class":3301,"line":41067},245,[2166,41069,40685],{"class":3331},[2166,41071,40581],{"class":37535},[2166,41073,40584],{"class":3309},[2166,41075,2998],{"class":3331},[2166,41077,41078],{"class":3316},"\"flex items-center gap-1.5\"",[2166,41080,4741],{"class":3331},[2166,41082,41084,41086,41088,41090,41092,41095,41097],{"class":3301,"line":41083},246,[2166,41085,41008],{"class":3331},[2166,41087,2166],{"class":37535},[2166,41089,40584],{"class":3309},[2166,41091,2998],{"class":3331},[2166,41093,41094],{"class":3316},"\"inline-block size-1.5 rounded-full bg-emerald-500\"",[2166,41096,40357],{"class":41028},[2166,41098,4741],{"class":3331},[2166,41100,41102,41104,41106,41108,41110,41112,41115,41117],{"class":3301,"line":41101},247,[2166,41103,41008],{"class":3331},[2166,41105,24],{"class":37535},[2166,41107,40584],{"class":3309},[2166,41109,2998],{"class":3331},[2166,41111,40932],{"class":3316},[2166,41113,41114],{"class":3331},">완료\u003C\u002F",[2166,41116,24],{"class":37535},[2166,41118,4741],{"class":3331},[2166,41120,41122,41124,41126],{"class":3301,"line":41121},248,[2166,41123,40708],{"class":3331},[2166,41125,40581],{"class":37535},[2166,41127,4741],{"class":3331},[2166,41129,41131,41133,41135,41137,41139,41142],{"class":3301,"line":41130},249,[2166,41132,40685],{"class":3331},[2166,41134,24],{"class":37535},[2166,41136,40584],{"class":3309},[2166,41138,2998],{"class":3331},[2166,41140,41141],{"class":3316},"\"mt-1 text-[30px] font-semibold text-neutral-900 tabular-nums\"",[2166,41143,4741],{"class":3331},[2166,41145,41147,41150,41152,41154,41156,41159,41162,41164],{"class":3301,"line":41146},250,[2166,41148,41149],{"class":3331},"              {{ totalCounts.done }}\u003C",[2166,41151,2166],{"class":37535},[2166,41153,40584],{"class":3309},[2166,41155,2998],{"class":3331},[2166,41157,41158],{"class":3316},"\"text-[16px] text-neutral-400\"",[2166,41160,41161],{"class":3331},">\u002F{{ allTasks.length }}\u003C\u002F",[2166,41163,2166],{"class":37535},[2166,41165,4741],{"class":3331},[2166,41167,41169,41171,41173],{"class":3301,"line":41168},251,[2166,41170,40708],{"class":3331},[2166,41172,24],{"class":37535},[2166,41174,4741],{"class":3331},[2166,41176,41178,41180,41182],{"class":3301,"line":41177},252,[2166,41179,40749],{"class":3331},[2166,41181,40581],{"class":37535},[2166,41183,4741],{"class":3331},[2166,41185,41187,41189,41191,41193,41195,41197],{"class":3301,"line":41186},253,[2166,41188,40654],{"class":3331},[2166,41190,40581],{"class":37535},[2166,41192,40584],{"class":3309},[2166,41194,2998],{"class":3331},[2166,41196,41062],{"class":3316},[2166,41198,4741],{"class":3331},[2166,41200,41202,41204,41206,41208,41210,41212],{"class":3301,"line":41201},254,[2166,41203,40685],{"class":3331},[2166,41205,40581],{"class":37535},[2166,41207,40584],{"class":3309},[2166,41209,2998],{"class":3331},[2166,41211,41078],{"class":3316},[2166,41213,4741],{"class":3331},[2166,41215,41217,41219,41221,41223,41225,41228,41230],{"class":3301,"line":41216},255,[2166,41218,41008],{"class":3331},[2166,41220,2166],{"class":37535},[2166,41222,40584],{"class":3309},[2166,41224,2998],{"class":3331},[2166,41226,41227],{"class":3316},"\"inline-block size-1.5 rounded-full bg-amber-500\"",[2166,41229,40357],{"class":41028},[2166,41231,4741],{"class":3331},[2166,41233,41235,41237,41239,41241,41243,41245,41248,41250],{"class":3301,"line":41234},256,[2166,41236,41008],{"class":3331},[2166,41238,24],{"class":37535},[2166,41240,40584],{"class":3309},[2166,41242,2998],{"class":3331},[2166,41244,40932],{"class":3316},[2166,41246,41247],{"class":3331},">진행 중\u003C\u002F",[2166,41249,24],{"class":37535},[2166,41251,4741],{"class":3331},[2166,41253,41255,41257,41259],{"class":3301,"line":41254},257,[2166,41256,40708],{"class":3331},[2166,41258,40581],{"class":37535},[2166,41260,4741],{"class":3331},[2166,41262,41264,41266,41268,41270,41272,41274],{"class":3301,"line":41263},258,[2166,41265,40685],{"class":3331},[2166,41267,24],{"class":37535},[2166,41269,40584],{"class":3309},[2166,41271,2998],{"class":3331},[2166,41273,41141],{"class":3316},[2166,41275,4741],{"class":3331},[2166,41277,41279],{"class":3301,"line":41278},259,[2166,41280,41281],{"class":3331},"              {{ totalCounts.in_progress }}\n",[2166,41283,41285,41287,41289],{"class":3301,"line":41284},260,[2166,41286,40708],{"class":3331},[2166,41288,24],{"class":37535},[2166,41290,4741],{"class":3331},[2166,41292,41294,41296,41298],{"class":3301,"line":41293},261,[2166,41295,40749],{"class":3331},[2166,41297,40581],{"class":37535},[2166,41299,4741],{"class":3331},[2166,41301,41303,41305,41307],{"class":3301,"line":41302},262,[2166,41304,40759],{"class":3331},[2166,41306,40893],{"class":37535},[2166,41308,4741],{"class":3331},[2166,41310,41312],{"class":3301,"line":41311},263,[2166,41313,3339],{"emptyLinePlaceholder":3338},[2166,41315,41317],{"class":3301,"line":41316},264,[2166,41318,41319],{"class":3422},"        \u003C!-- STAGES OVERVIEW -->\n",[2166,41321,41323,41325,41327,41329,41331,41334],{"class":3301,"line":41322},265,[2166,41324,40637],{"class":3331},[2166,41326,40893],{"class":37535},[2166,41328,40584],{"class":3309},[2166,41330,2998],{"class":3331},[2166,41332,41333],{"class":3316},"\"mt-8\"",[2166,41335,4741],{"class":3331},[2166,41337,41339,41341,41343,41345,41347,41350,41353,41355],{"class":3301,"line":41338},266,[2166,41340,40654],{"class":3331},[2166,41342,36],{"class":37535},[2166,41344,40584],{"class":3309},[2166,41346,2998],{"class":3331},[2166,41348,41349],{"class":3316},"\"mb-2 text-[14px] font-semibold text-neutral-700\"",[2166,41351,41352],{"class":3331},">단계별 진행률\u003C\u002F",[2166,41354,36],{"class":37535},[2166,41356,4741],{"class":3331},[2166,41358,41360,41362,41364,41366,41368,41371],{"class":3301,"line":41359},267,[2166,41361,40654],{"class":3331},[2166,41363,54],{"class":37535},[2166,41365,40584],{"class":3309},[2166,41367,2998],{"class":3331},[2166,41369,41370],{"class":3316},"\"overflow-hidden rounded-xl border border-neutral-200 bg-white\"",[2166,41372,4741],{"class":3331},[2166,41374,41376,41378],{"class":3301,"line":41375},268,[2166,41377,40685],{"class":3331},[2166,41379,41380],{"class":37535},"li\n",[2166,41382,41384,41387,41389,41392,41395,41397],{"class":3301,"line":41383},269,[2166,41385,41386],{"class":3309},"              v-for",[2166,41388,2998],{"class":3331},[2166,41390,41391],{"class":3316},"\"(s, i) in mergedStages\"",[2166,41393,41394],{"class":3309}," :key",[2166,41396,2998],{"class":3331},[2166,41398,41399],{"class":3316},"\"s.id\"\n",[2166,41401,41403,41406,41408],{"class":3301,"line":41402},270,[2166,41404,41405],{"class":3309},"              class",[2166,41407,2998],{"class":3331},[2166,41409,41410],{"class":3316},"\"grid cursor-pointer grid-cols-[24px_24px_1fr_auto_140px_auto] items-center gap-4 px-4 py-3 hover:bg-neutral-50\"\n",[2166,41412,41414,41417,41419],{"class":3301,"line":41413},271,[2166,41415,41416],{"class":3309},"              :class",[2166,41418,2998],{"class":3331},[2166,41420,41421],{"class":3316},"\"i > 0 ? 'border-t border-neutral-100' : ''\"\n",[2166,41423,41425,41428,41430],{"class":3301,"line":41424},272,[2166,41426,41427],{"class":3309},"              @click",[2166,41429,2998],{"class":3331},[2166,41431,41432],{"class":3316},"\"scrollToStage(s.id)\"\n",[2166,41434,41436],{"class":3301,"line":41435},273,[2166,41437,41438],{"class":3331},"            >\n",[2166,41440,41442,41444,41446,41448,41450,41453,41456,41458],{"class":3301,"line":41441},274,[2166,41443,41008],{"class":3331},[2166,41445,2166],{"class":37535},[2166,41447,40584],{"class":3309},[2166,41449,2998],{"class":3331},[2166,41451,41452],{"class":3316},"\"text-[18px] leading-none\"",[2166,41454,41455],{"class":3331},">{{ stageEmoji[i] }}\u003C\u002F",[2166,41457,2166],{"class":37535},[2166,41459,4741],{"class":3331},[2166,41461,41463,41465,41467,41469,41471,41474,41477,41479],{"class":3301,"line":41462},275,[2166,41464,41008],{"class":3331},[2166,41466,2166],{"class":37535},[2166,41468,40584],{"class":3309},[2166,41470,2998],{"class":3331},[2166,41472,41473],{"class":3316},"\"font-mono text-[14px] tabular-nums text-neutral-400\"",[2166,41475,41476],{"class":3331},">{{ String(i + 1).padStart(2, \"0\") }}\u003C\u002F",[2166,41478,2166],{"class":37535},[2166,41480,4741],{"class":3331},[2166,41482,41484,41486,41488,41490,41492,41495],{"class":3301,"line":41483},276,[2166,41485,41008],{"class":3331},[2166,41487,40581],{"class":37535},[2166,41489,40584],{"class":3309},[2166,41491,2998],{"class":3331},[2166,41493,41494],{"class":3316},"\"min-w-0\"",[2166,41496,4741],{"class":3331},[2166,41498,41500,41503,41505,41507,41509,41512,41515,41517],{"class":3301,"line":41499},277,[2166,41501,41502],{"class":3331},"                \u003C",[2166,41504,24],{"class":37535},[2166,41506,40584],{"class":3309},[2166,41508,2998],{"class":3331},[2166,41510,41511],{"class":3316},"\"truncate text-[14px] font-medium text-neutral-900\"",[2166,41513,41514],{"class":3331},">{{ s.name }}\u003C\u002F",[2166,41516,24],{"class":37535},[2166,41518,4741],{"class":3331},[2166,41520,41522,41524,41526,41528,41530,41533,41536,41538],{"class":3301,"line":41521},278,[2166,41523,41502],{"class":3331},[2166,41525,24],{"class":37535},[2166,41527,40584],{"class":3309},[2166,41529,2998],{"class":3331},[2166,41531,41532],{"class":3316},"\"truncate text-[14px] text-neutral-500\"",[2166,41534,41535],{"class":3331},">{{ s.summary }}\u003C\u002F",[2166,41537,24],{"class":37535},[2166,41539,4741],{"class":3331},[2166,41541,41543,41546,41548],{"class":3301,"line":41542},279,[2166,41544,41545],{"class":3331},"              \u003C\u002F",[2166,41547,40581],{"class":37535},[2166,41549,4741],{"class":3331},[2166,41551,41553,41555,41557,41559,41561,41564,41567,41569],{"class":3301,"line":41552},280,[2166,41554,41008],{"class":3331},[2166,41556,2166],{"class":37535},[2166,41558,40584],{"class":3309},[2166,41560,2998],{"class":3331},[2166,41562,41563],{"class":3316},"\"text-[14px] text-neutral-400\"",[2166,41565,41566],{"class":3331},">{{ s.tasks.length }}건\u003C\u002F",[2166,41568,2166],{"class":37535},[2166,41570,4741],{"class":3331},[2166,41572,41574,41576,41578,41580,41582,41585],{"class":3301,"line":41573},281,[2166,41575,41008],{"class":3331},[2166,41577,40581],{"class":37535},[2166,41579,40584],{"class":3309},[2166,41581,2998],{"class":3331},[2166,41583,41584],{"class":3316},"\"flex items-center gap-2.5\"",[2166,41586,4741],{"class":3331},[2166,41588,41590,41592,41594,41596,41598,41601],{"class":3301,"line":41589},282,[2166,41591,41502],{"class":3331},[2166,41593,40581],{"class":37535},[2166,41595,40584],{"class":3309},[2166,41597,2998],{"class":3331},[2166,41599,41600],{"class":3316},"\"h-1 w-24 overflow-hidden rounded-full bg-neutral-100\"",[2166,41602,4741],{"class":3331},[2166,41604,41606,41609,41611,41614,41616,41619,41621,41623,41626,41628],{"class":3301,"line":41605},283,[2166,41607,41608],{"class":3331},"                  \u003C",[2166,41610,40581],{"class":37535},[2166,41612,41613],{"class":3309}," :class",[2166,41615,2998],{"class":3331},[2166,41617,41618],{"class":3316},"\"['h-full rounded-full', progressFill(s.progress)]\"",[2166,41620,41020],{"class":3309},[2166,41622,2998],{"class":3331},[2166,41624,41625],{"class":3316},"\"{ width: s.progress + '%' }\"",[2166,41627,40357],{"class":41028},[2166,41629,4741],{"class":3331},[2166,41631,41633,41636,41638],{"class":3301,"line":41632},284,[2166,41634,41635],{"class":3331},"                \u003C\u002F",[2166,41637,40581],{"class":37535},[2166,41639,4741],{"class":3331},[2166,41641,41643,41645,41647,41649,41651,41654,41657,41659],{"class":3301,"line":41642},285,[2166,41644,41502],{"class":3331},[2166,41646,2166],{"class":37535},[2166,41648,40584],{"class":3309},[2166,41650,2998],{"class":3331},[2166,41652,41653],{"class":3316},"\"w-9 text-right text-[14px] font-medium tabular-nums text-neutral-700\"",[2166,41655,41656],{"class":3331},">{{ s.progress }}%\u003C\u002F",[2166,41658,2166],{"class":37535},[2166,41660,4741],{"class":3331},[2166,41662,41664,41666,41668],{"class":3301,"line":41663},286,[2166,41665,41545],{"class":3331},[2166,41667,40581],{"class":37535},[2166,41669,4741],{"class":3331},[2166,41671,41673,41675,41677,41679,41681,41684,41687,41689],{"class":3301,"line":41672},287,[2166,41674,41008],{"class":3331},[2166,41676,2166],{"class":37535},[2166,41678,40584],{"class":3309},[2166,41680,2998],{"class":3331},[2166,41682,41683],{"class":3316},"\"text-neutral-300\"",[2166,41685,41686],{"class":3331},">→\u003C\u002F",[2166,41688,2166],{"class":37535},[2166,41690,4741],{"class":3331},[2166,41692,41694,41696,41698],{"class":3301,"line":41693},288,[2166,41695,40708],{"class":3331},[2166,41697,57],{"class":37535},[2166,41699,4741],{"class":3331},[2166,41701,41703,41705,41707],{"class":3301,"line":41702},289,[2166,41704,40749],{"class":3331},[2166,41706,54],{"class":37535},[2166,41708,4741],{"class":3331},[2166,41710,41712,41714,41716],{"class":3301,"line":41711},290,[2166,41713,40759],{"class":3331},[2166,41715,40893],{"class":37535},[2166,41717,4741],{"class":3331},[2166,41719,41721],{"class":3301,"line":41720},291,[2166,41722,3339],{"emptyLinePlaceholder":3338},[2166,41724,41726],{"class":3301,"line":41725},292,[2166,41727,41728],{"class":3422},"        \u003C!-- STAGE DETAILS -->\n",[2166,41730,41732,41734,41736,41739,41741,41744,41746,41748,41751,41754,41756,41759,41761,41763,41766],{"class":3301,"line":41731},293,[2166,41733,40637],{"class":3331},[2166,41735,40893],{"class":37535},[2166,41737,41738],{"class":3309}," v-for",[2166,41740,2998],{"class":3331},[2166,41742,41743],{"class":3316},"\"(s, sIdx) in mergedStages\"",[2166,41745,41394],{"class":3309},[2166,41747,2998],{"class":3331},[2166,41749,41750],{"class":3316},"\"s.id\"",[2166,41752,41753],{"class":3309}," :id",[2166,41755,2998],{"class":3331},[2166,41757,41758],{"class":3316},"\"`stage-${s.id}`\"",[2166,41760,40584],{"class":3309},[2166,41762,2998],{"class":3331},[2166,41764,41765],{"class":3316},"\"mt-10\"",[2166,41767,4741],{"class":3331},[2166,41769,41771,41773,41775,41777,41779,41782],{"class":3301,"line":41770},294,[2166,41772,40654],{"class":3331},[2166,41774,40581],{"class":37535},[2166,41776,40584],{"class":3309},[2166,41778,2998],{"class":3331},[2166,41780,41781],{"class":3316},"\"flex items-baseline justify-between gap-3\"",[2166,41783,4741],{"class":3331},[2166,41785,41787,41789,41791,41793,41795,41798],{"class":3301,"line":41786},295,[2166,41788,40685],{"class":3331},[2166,41790,40581],{"class":37535},[2166,41792,40584],{"class":3309},[2166,41794,2998],{"class":3331},[2166,41796,41797],{"class":3316},"\"flex items-baseline gap-2.5\"",[2166,41799,4741],{"class":3331},[2166,41801,41803,41805,41807,41809,41811,41814,41817,41819],{"class":3301,"line":41802},296,[2166,41804,41008],{"class":3331},[2166,41806,2166],{"class":37535},[2166,41808,40584],{"class":3309},[2166,41810,2998],{"class":3331},[2166,41812,41813],{"class":3316},"\"text-[20px] leading-none\"",[2166,41815,41816],{"class":3331},">{{ stageEmoji[sIdx] }}\u003C\u002F",[2166,41818,2166],{"class":37535},[2166,41820,4741],{"class":3331},[2166,41822,41824,41826,41828,41830,41832,41835,41837,41839],{"class":3301,"line":41823},297,[2166,41825,41008],{"class":3331},[2166,41827,36],{"class":37535},[2166,41829,40584],{"class":3309},[2166,41831,2998],{"class":3331},[2166,41833,41834],{"class":3316},"\"text-[18px] font-semibold tracking-tight text-neutral-900\"",[2166,41836,41514],{"class":3331},[2166,41838,36],{"class":37535},[2166,41840,4741],{"class":3331},[2166,41842,41844,41846,41848,41850,41852,41855,41858,41860],{"class":3301,"line":41843},298,[2166,41845,41008],{"class":3331},[2166,41847,2166],{"class":37535},[2166,41849,40584],{"class":3309},[2166,41851,2998],{"class":3331},[2166,41853,41854],{"class":3316},"\"font-mono text-[14px] text-neutral-400\"",[2166,41856,41857],{"class":3331},">{{ s.id }}\u003C\u002F",[2166,41859,2166],{"class":37535},[2166,41861,4741],{"class":3331},[2166,41863,41865,41867,41869],{"class":3301,"line":41864},299,[2166,41866,40708],{"class":3331},[2166,41868,40581],{"class":37535},[2166,41870,4741],{"class":3331},[2166,41872,41874,41876,41878,41880,41882,41885],{"class":3301,"line":41873},300,[2166,41875,40685],{"class":3331},[2166,41877,40581],{"class":37535},[2166,41879,40584],{"class":3309},[2166,41881,2998],{"class":3331},[2166,41883,41884],{"class":3316},"\"flex items-center gap-3 text-[14px] text-neutral-500\"",[2166,41886,4741],{"class":3331},[2166,41888,41890,41892,41894,41897,41899],{"class":3301,"line":41889},301,[2166,41891,41008],{"class":3331},[2166,41893,2166],{"class":37535},[2166,41895,41896],{"class":3331},">비중 {{ s.weight }}%\u003C\u002F",[2166,41898,2166],{"class":37535},[2166,41900,4741],{"class":3331},[2166,41902,41904,41906,41908,41910,41912,41915,41918,41920],{"class":3301,"line":41903},302,[2166,41905,41008],{"class":3331},[2166,41907,2166],{"class":37535},[2166,41909,40584],{"class":3309},[2166,41911,2998],{"class":3331},[2166,41913,41914],{"class":3316},"\"text-neutral-200\"",[2166,41916,41917],{"class":3331},">·\u003C\u002F",[2166,41919,2166],{"class":37535},[2166,41921,4741],{"class":3331},[2166,41923,41925,41927,41929,41931,41933,41936,41939,41941],{"class":3301,"line":41924},303,[2166,41926,41008],{"class":3331},[2166,41928,2166],{"class":37535},[2166,41930,40584],{"class":3309},[2166,41932,2998],{"class":3331},[2166,41934,41935],{"class":3316},"\"font-medium text-neutral-700\"",[2166,41937,41938],{"class":3331},">진행 {{ s.progress }}%\u003C\u002F",[2166,41940,2166],{"class":37535},[2166,41942,4741],{"class":3331},[2166,41944,41946,41948,41950],{"class":3301,"line":41945},304,[2166,41947,40708],{"class":3331},[2166,41949,40581],{"class":37535},[2166,41951,4741],{"class":3331},[2166,41953,41955,41957,41959],{"class":3301,"line":41954},305,[2166,41956,40749],{"class":3331},[2166,41958,40581],{"class":37535},[2166,41960,4741],{"class":3331},[2166,41962,41964,41966,41968,41970,41972,41974,41976,41978],{"class":3301,"line":41963},306,[2166,41965,40654],{"class":3331},[2166,41967,24],{"class":37535},[2166,41969,40584],{"class":3309},[2166,41971,2998],{"class":3331},[2166,41973,40726],{"class":3316},[2166,41975,41535],{"class":3331},[2166,41977,24],{"class":37535},[2166,41979,4741],{"class":3331},[2166,41981,41983,41985,41987,41989,41991,41994],{"class":3301,"line":41982},307,[2166,41984,40654],{"class":3331},[2166,41986,40581],{"class":37535},[2166,41988,40584],{"class":3309},[2166,41990,2998],{"class":3331},[2166,41992,41993],{"class":3316},"\"mt-3 h-1 overflow-hidden rounded-full bg-neutral-100\"",[2166,41995,4741],{"class":3331},[2166,41997,41999,42001,42003,42005,42007,42009,42011,42013,42015,42017],{"class":3301,"line":41998},308,[2166,42000,40685],{"class":3331},[2166,42002,40581],{"class":37535},[2166,42004,41613],{"class":3309},[2166,42006,2998],{"class":3331},[2166,42008,41618],{"class":3316},[2166,42010,41020],{"class":3309},[2166,42012,2998],{"class":3331},[2166,42014,41625],{"class":3316},[2166,42016,40357],{"class":41028},[2166,42018,4741],{"class":3331},[2166,42020,42022,42024,42026],{"class":3301,"line":42021},309,[2166,42023,40749],{"class":3331},[2166,42025,40581],{"class":37535},[2166,42027,4741],{"class":3331},[2166,42029,42031],{"class":3301,"line":42030},310,[2166,42032,3339],{"emptyLinePlaceholder":3338},[2166,42034,42036,42038,42040,42042,42044,42047],{"class":3301,"line":42035},311,[2166,42037,40654],{"class":3331},[2166,42039,40581],{"class":37535},[2166,42041,40584],{"class":3309},[2166,42043,2998],{"class":3331},[2166,42045,42046],{"class":3316},"\"mt-4 overflow-hidden rounded-xl border border-neutral-200 bg-white\"",[2166,42048,4741],{"class":3331},[2166,42050,42052,42054,42056,42058,42060,42063],{"class":3301,"line":42051},312,[2166,42053,40685],{"class":3331},[2166,42055,135],{"class":37535},[2166,42057,40584],{"class":3309},[2166,42059,2998],{"class":3331},[2166,42061,42062],{"class":3316},"\"w-full text-[14px]\"",[2166,42064,4741],{"class":3331},[2166,42066,42068,42070,42072],{"class":3301,"line":42067},313,[2166,42069,41008],{"class":3331},[2166,42071,138],{"class":37535},[2166,42073,4741],{"class":3331},[2166,42075,42077,42079,42081,42083,42085,42088],{"class":3301,"line":42076},314,[2166,42078,41502],{"class":3331},[2166,42080,141],{"class":37535},[2166,42082,40584],{"class":3309},[2166,42084,2998],{"class":3331},[2166,42086,42087],{"class":3316},"\"border-b border-neutral-100 text-[14px] font-medium text-neutral-500\"",[2166,42089,4741],{"class":3331},[2166,42091,42093,42095,42097,42099,42101,42104,42107,42109],{"class":3301,"line":42092},315,[2166,42094,41608],{"class":3331},[2166,42096,144],{"class":37535},[2166,42098,40584],{"class":3309},[2166,42100,2998],{"class":3331},[2166,42102,42103],{"class":3316},"\"w-20 px-3 py-2 text-left\"",[2166,42105,42106],{"class":3331},">ID\u003C\u002F",[2166,42108,144],{"class":37535},[2166,42110,4741],{"class":3331},[2166,42112,42114,42116,42118,42120,42122,42125,42128,42130],{"class":3301,"line":42113},316,[2166,42115,41608],{"class":3331},[2166,42117,144],{"class":37535},[2166,42119,40584],{"class":3309},[2166,42121,2998],{"class":3331},[2166,42123,42124],{"class":3316},"\"px-3 py-2 text-left\"",[2166,42126,42127],{"class":3331},">작업 · 산출물\u003C\u002F",[2166,42129,144],{"class":37535},[2166,42131,4741],{"class":3331},[2166,42133,42135,42137,42139,42141,42143,42146,42149,42151],{"class":3301,"line":42134},317,[2166,42136,41608],{"class":3331},[2166,42138,144],{"class":37535},[2166,42140,40584],{"class":3309},[2166,42142,2998],{"class":3331},[2166,42144,42145],{"class":3316},"\"w-36 px-3 py-2 text-left\"",[2166,42147,42148],{"class":3331},">목표일\u003C\u002F",[2166,42150,144],{"class":37535},[2166,42152,4741],{"class":3331},[2166,42154,42156,42158,42160,42162,42164,42166,42169,42171],{"class":3301,"line":42155},318,[2166,42157,41608],{"class":3331},[2166,42159,144],{"class":37535},[2166,42161,40584],{"class":3309},[2166,42163,2998],{"class":3331},[2166,42165,42145],{"class":3316},[2166,42167,42168],{"class":3331},">완료일\u003C\u002F",[2166,42170,144],{"class":37535},[2166,42172,4741],{"class":3331},[2166,42174,42176,42178,42180,42182,42184,42187,42190,42192],{"class":3301,"line":42175},319,[2166,42177,41608],{"class":3331},[2166,42179,144],{"class":37535},[2166,42181,40584],{"class":3309},[2166,42183,2998],{"class":3331},[2166,42185,42186],{"class":3316},"\"w-28 px-3 py-2 text-left\"",[2166,42188,42189],{"class":3331},">상태\u003C\u002F",[2166,42191,144],{"class":37535},[2166,42193,4741],{"class":3331},[2166,42195,42197,42199,42201],{"class":3301,"line":42196},320,[2166,42198,41635],{"class":3331},[2166,42200,141],{"class":37535},[2166,42202,4741],{"class":3331},[2166,42204,42206,42208,42210],{"class":3301,"line":42205},321,[2166,42207,41545],{"class":3331},[2166,42209,138],{"class":37535},[2166,42211,4741],{"class":3331},[2166,42213,42215,42217,42219],{"class":3301,"line":42214},322,[2166,42216,41008],{"class":3331},[2166,42218,157],{"class":37535},[2166,42220,4741],{"class":3331},[2166,42222,42224,42226],{"class":3301,"line":42223},323,[2166,42225,41502],{"class":3331},[2166,42227,42228],{"class":37535},"tr\n",[2166,42230,42232,42235,42237,42240,42242,42244],{"class":3301,"line":42231},324,[2166,42233,42234],{"class":3309},"                  v-for",[2166,42236,2998],{"class":3331},[2166,42238,42239],{"class":3316},"\"(t, ti) in s.tasks\"",[2166,42241,41394],{"class":3309},[2166,42243,2998],{"class":3331},[2166,42245,42246],{"class":3316},"\"t.id\"\n",[2166,42248,42250,42253,42255],{"class":3301,"line":42249},325,[2166,42251,42252],{"class":3309},"                  class",[2166,42254,2998],{"class":3331},[2166,42256,42257],{"class":3316},"\"align-top hover:bg-neutral-50\u002F60\"\n",[2166,42259,42261,42264,42266],{"class":3301,"line":42260},326,[2166,42262,42263],{"class":3309},"                  :class",[2166,42265,2998],{"class":3331},[2166,42267,42268],{"class":3316},"\"ti > 0 ? 'border-t border-neutral-100' : ''\"\n",[2166,42270,42272],{"class":3301,"line":42271},327,[2166,42273,42274],{"class":3331},"                >\n",[2166,42276,42278,42280,42282,42284,42286,42289,42292,42294],{"class":3301,"line":42277},328,[2166,42279,41608],{"class":3331},[2166,42281,162],{"class":37535},[2166,42283,40584],{"class":3309},[2166,42285,2998],{"class":3331},[2166,42287,42288],{"class":3316},"\"px-3 py-3 font-mono text-[14px] tabular-nums text-neutral-400\"",[2166,42290,42291],{"class":3331},">{{ s.id }}-{{ t.taskNo }}\u003C\u002F",[2166,42293,162],{"class":37535},[2166,42295,4741],{"class":3331},[2166,42297,42299,42301,42303,42305,42307,42310],{"class":3301,"line":42298},329,[2166,42300,41608],{"class":3331},[2166,42302,162],{"class":37535},[2166,42304,40584],{"class":3309},[2166,42306,2998],{"class":3331},[2166,42308,42309],{"class":3316},"\"px-3 py-3\"",[2166,42311,4741],{"class":3331},[2166,42313,42315,42318,42320,42322,42324,42327,42330,42332],{"class":3301,"line":42314},330,[2166,42316,42317],{"class":3331},"                    \u003C",[2166,42319,24],{"class":37535},[2166,42321,40584],{"class":3309},[2166,42323,2998],{"class":3331},[2166,42325,42326],{"class":3316},"\"text-[13.5px] font-medium text-neutral-900\"",[2166,42328,42329],{"class":3331},">{{ t.title }}\u003C\u002F",[2166,42331,24],{"class":37535},[2166,42333,4741],{"class":3331},[2166,42335,42337,42339,42341,42343,42345,42348,42350,42352,42355,42358,42360],{"class":3301,"line":42336},331,[2166,42338,42317],{"class":3331},[2166,42340,24],{"class":37535},[2166,42342,40794],{"class":3309},[2166,42344,2998],{"class":3331},[2166,42346,42347],{"class":3316},"\"t.note\"",[2166,42349,40584],{"class":3309},[2166,42351,2998],{"class":3331},[2166,42353,42354],{"class":3316},"\"mt-0.5 text-[14px] leading-relaxed text-neutral-500\"",[2166,42356,42357],{"class":3331},">{{ t.note }}\u003C\u002F",[2166,42359,24],{"class":37535},[2166,42361,4741],{"class":3331},[2166,42363,42365,42367,42369,42371,42373,42376],{"class":3301,"line":42364},332,[2166,42366,42317],{"class":3331},[2166,42368,40581],{"class":37535},[2166,42370,40584],{"class":3309},[2166,42372,2998],{"class":3331},[2166,42374,42375],{"class":3316},"\"mt-2 flex items-center gap-2\"",[2166,42377,4741],{"class":3331},[2166,42379,42381,42384,42386,42388,42390,42392,42395,42397],{"class":3301,"line":42380},333,[2166,42382,42383],{"class":3331},"                      \u003C",[2166,42385,2166],{"class":37535},[2166,42387,40584],{"class":3309},[2166,42389,2998],{"class":3331},[2166,42391,41563],{"class":3316},[2166,42393,42394],{"class":3331},">🔗\u003C\u002F",[2166,42396,2166],{"class":37535},[2166,42398,4741],{"class":3331},[2166,42400,42402,42404],{"class":3301,"line":42401},334,[2166,42403,42383],{"class":3331},[2166,42405,42406],{"class":37535},"input\n",[2166,42408,42410,42413,42415,42418,42420,42422,42425,42428,42430],{"class":3301,"line":42409},335,[2166,42411,42412],{"class":3309},"                        :value",[2166,42414,2998],{"class":3331},[2166,42416,42417],{"class":3316},"\"t.deliverableUrl ?? ''\"",[2166,42419,25590],{"class":3309},[2166,42421,2998],{"class":3331},[2166,42423,42424],{"class":3316},"\"url\"",[2166,42426,42427],{"class":3309}," placeholder",[2166,42429,2998],{"class":3331},[2166,42431,42432],{"class":3316},"\"산출물 URL 입력\"\n",[2166,42434,42436,42439,42441],{"class":3301,"line":42435},336,[2166,42437,42438],{"class":3309},"                        class",[2166,42440,2998],{"class":3331},[2166,42442,42443],{"class":3316},"\"min-w-0 flex-1 rounded-md border border-transparent bg-transparent px-1.5 py-1 font-mono text-[13px] text-neutral-700 placeholder:text-neutral-400 hover:border-neutral-200 focus:border-neutral-300 focus:bg-white focus:outline-none focus:ring-1 focus:ring-neutral-200\"\n",[2166,42445,42447,42450,42452],{"class":3301,"line":42446},337,[2166,42448,42449],{"class":3309},"                        @change",[2166,42451,2998],{"class":3331},[2166,42453,42454],{"class":3316},"\"(e) => setOverride(t.id, { deliverableUrl: (e.target as HTMLInputElement).value || null })\"\n",[2166,42456,42458],{"class":3301,"line":42457},338,[2166,42459,42460],{"class":3331},"                      \u002F>\n",[2166,42462,42464,42466,42468,42470,42472,42475,42478,42480,42482,42485,42487,42490,42493,42495],{"class":3301,"line":42463},339,[2166,42465,42383],{"class":3331},[2166,42467,3257],{"class":37535},[2166,42469,40794],{"class":3309},[2166,42471,2998],{"class":3331},[2166,42473,42474],{"class":3316},"\"t.deliverableUrl\"",[2166,42476,42477],{"class":3309}," :href",[2166,42479,2998],{"class":3331},[2166,42481,42474],{"class":3316},[2166,42483,42484],{"class":3309}," target",[2166,42486,2998],{"class":3331},[2166,42488,42489],{"class":3316},"\"_blank\"",[2166,42491,42492],{"class":3309}," rel",[2166,42494,2998],{"class":3331},[2166,42496,42497],{"class":3316},"\"noopener\"\n",[2166,42499,42501,42504,42506,42509],{"class":3301,"line":42500},340,[2166,42502,42503],{"class":3309},"                         class",[2166,42505,2998],{"class":3331},[2166,42507,42508],{"class":3316},"\"shrink-0 rounded-md px-1.5 py-1 text-[14px] text-neutral-500 hover:bg-neutral-100 hover:text-neutral-900\"",[2166,42510,4741],{"class":3331},[2166,42512,42514],{"class":3301,"line":42513},341,[2166,42515,42516],{"class":3331},"                        열기 ↗\n",[2166,42518,42520,42523,42525],{"class":3301,"line":42519},342,[2166,42521,42522],{"class":3331},"                      \u003C\u002F",[2166,42524,3257],{"class":37535},[2166,42526,4741],{"class":3331},[2166,42528,42530,42533,42535],{"class":3301,"line":42529},343,[2166,42531,42532],{"class":3331},"                    \u003C\u002F",[2166,42534,40581],{"class":37535},[2166,42536,4741],{"class":3331},[2166,42538,42540,42543,42545],{"class":3301,"line":42539},344,[2166,42541,42542],{"class":3331},"                  \u003C\u002F",[2166,42544,162],{"class":37535},[2166,42546,4741],{"class":3331},[2166,42548,42550,42552,42554,42556,42558,42561],{"class":3301,"line":42549},345,[2166,42551,41608],{"class":3331},[2166,42553,162],{"class":37535},[2166,42555,40584],{"class":3309},[2166,42557,2998],{"class":3331},[2166,42559,42560],{"class":3316},"\"whitespace-nowrap px-2 py-3\"",[2166,42562,4741],{"class":3331},[2166,42564,42566,42568],{"class":3301,"line":42565},346,[2166,42567,42317],{"class":3331},[2166,42569,42406],{"class":37535},[2166,42571,42573,42576,42578,42581,42584,42586],{"class":3301,"line":42572},347,[2166,42574,42575],{"class":3309},"                      type",[2166,42577,2998],{"class":3331},[2166,42579,42580],{"class":3316},"\"date\"",[2166,42582,42583],{"class":3309}," :value",[2166,42585,2998],{"class":3331},[2166,42587,42588],{"class":3316},"\"t.targetDate ?? ''\"\n",[2166,42590,42592,42595,42597],{"class":3301,"line":42591},348,[2166,42593,42594],{"class":3309},"                      :class",[2166,42596,2998],{"class":3331},[2166,42598,42599],{"class":3316},"\"['w-full rounded-md border border-transparent bg-transparent px-1.5 py-1 font-mono text-[12px] tabular-nums hover:border-neutral-200 focus:border-neutral-300 focus:bg-white focus:outline-none focus:ring-1 focus:ring-neutral-200',\n",[2166,42601,42603],{"class":3301,"line":42602},349,[2166,42604,42605],{"class":3316},"                               isOverdue(t) ? 'font-semibold text-rose-600' : 'text-neutral-600']\"\n",[2166,42607,42609,42612,42614],{"class":3301,"line":42608},350,[2166,42610,42611],{"class":3309},"                      @change",[2166,42613,2998],{"class":3331},[2166,42615,42616],{"class":3316},"\"(e) => setOverride(t.id, { targetDate: (e.target as HTMLInputElement).value || null })\"\n",[2166,42618,42620],{"class":3301,"line":42619},351,[2166,42621,42622],{"class":3331},"                    \u002F>\n",[2166,42624,42626,42628,42630],{"class":3301,"line":42625},352,[2166,42627,42542],{"class":3331},[2166,42629,162],{"class":37535},[2166,42631,4741],{"class":3331},[2166,42633,42635,42637,42639,42641,42643,42645],{"class":3301,"line":42634},353,[2166,42636,41608],{"class":3331},[2166,42638,162],{"class":37535},[2166,42640,40584],{"class":3309},[2166,42642,2998],{"class":3331},[2166,42644,42560],{"class":3316},[2166,42646,4741],{"class":3331},[2166,42648,42650,42652],{"class":3301,"line":42649},354,[2166,42651,42317],{"class":3331},[2166,42653,42406],{"class":37535},[2166,42655,42657,42659,42661,42663,42665,42667],{"class":3301,"line":42656},355,[2166,42658,42575],{"class":3309},[2166,42660,2998],{"class":3331},[2166,42662,42580],{"class":3316},[2166,42664,42583],{"class":3309},[2166,42666,2998],{"class":3331},[2166,42668,42669],{"class":3316},"\"t.completionDate ?? ''\"\n",[2166,42671,42673,42676,42678],{"class":3301,"line":42672},356,[2166,42674,42675],{"class":3309},"                      class",[2166,42677,2998],{"class":3331},[2166,42679,42680],{"class":3316},"\"w-full rounded-md border border-transparent bg-transparent px-1.5 py-1 font-mono text-[12px] tabular-nums text-emerald-700 hover:border-neutral-200 focus:border-neutral-300 focus:bg-white focus:outline-none focus:ring-1 focus:ring-neutral-200\"\n",[2166,42682,42684,42686,42688],{"class":3301,"line":42683},357,[2166,42685,42611],{"class":3309},[2166,42687,2998],{"class":3331},[2166,42689,42690],{"class":3316},"\"(e) => setOverride(t.id, { completionDate: (e.target as HTMLInputElement).value || null })\"\n",[2166,42692,42694],{"class":3301,"line":42693},358,[2166,42695,42622],{"class":3331},[2166,42697,42699,42701,42703],{"class":3301,"line":42698},359,[2166,42700,42542],{"class":3331},[2166,42702,162],{"class":37535},[2166,42704,4741],{"class":3331},[2166,42706,42708,42710,42712,42714,42716,42719],{"class":3301,"line":42707},360,[2166,42709,41608],{"class":3331},[2166,42711,162],{"class":37535},[2166,42713,40584],{"class":3309},[2166,42715,2998],{"class":3331},[2166,42717,42718],{"class":3316},"\"whitespace-nowrap px-3 py-3\"",[2166,42720,4741],{"class":3331},[2166,42722,42724,42726,42728,42730,42732],{"class":3301,"line":42723},361,[2166,42725,42317],{"class":3331},[2166,42727,3022],{"class":37535},[2166,42729,41613],{"class":3309},[2166,42731,2998],{"class":3331},[2166,42733,42734],{"class":3316},"\"['relative inline-flex cursor-pointer items-center gap-1.5 whitespace-nowrap rounded-md border px-2 py-0.5 text-[13px] font-medium hover:brightness-95',\n",[2166,42736,42738,42741],{"class":3301,"line":42737},362,[2166,42739,42740],{"class":3316},"                                    statusMeta[t.status].chipCls]\"",[2166,42742,4741],{"class":3331},[2166,42744,42746,42748,42750,42752,42754,42757,42760,42762],{"class":3301,"line":42745},363,[2166,42747,42383],{"class":3331},[2166,42749,2166],{"class":37535},[2166,42751,40584],{"class":3309},[2166,42753,2998],{"class":3331},[2166,42755,42756],{"class":3316},"\"text-[13px]\"",[2166,42758,42759],{"class":3331},">{{ statusMeta[t.status].emoji }}\u003C\u002F",[2166,42761,2166],{"class":37535},[2166,42763,4741],{"class":3331},[2166,42765,42767],{"class":3301,"line":42766},364,[2166,42768,42769],{"class":3331},"                      {{ statusMeta[t.status].label }}\n",[2166,42771,42773,42775],{"class":3301,"line":42772},365,[2166,42774,42383],{"class":3331},[2166,42776,42777],{"class":37535},"select\n",[2166,42779,42781,42783,42785,42788,42790,42792],{"class":3301,"line":42780},366,[2166,42782,42412],{"class":3309},[2166,42784,2998],{"class":3331},[2166,42786,42787],{"class":3316},"\"t.status\"",[2166,42789,40584],{"class":3309},[2166,42791,2998],{"class":3331},[2166,42793,42794],{"class":3316},"\"absolute inset-0 cursor-pointer opacity-0\"\n",[2166,42796,42798,42800,42802],{"class":3301,"line":42797},367,[2166,42799,42449],{"class":3309},[2166,42801,2998],{"class":3331},[2166,42803,42804],{"class":3316},"\"(e) => setOverride(t.id, { status: (e.target as HTMLSelectElement).value as Status })\"\n",[2166,42806,42808],{"class":3301,"line":42807},368,[2166,42809,42810],{"class":3331},"                      >\n",[2166,42812,42814,42817,42820,42822,42824,42827,42829,42831,42834,42836,42838,42840],{"class":3301,"line":42813},369,[2166,42815,42816],{"class":3331},"                        \u003C",[2166,42818,42819],{"class":37535},"option",[2166,42821,41738],{"class":3309},[2166,42823,2998],{"class":3331},[2166,42825,42826],{"class":3316},"\"(meta, key) in statusMeta\"",[2166,42828,41394],{"class":3309},[2166,42830,2998],{"class":3331},[2166,42832,42833],{"class":3316},"\"key\"",[2166,42835,42583],{"class":3309},[2166,42837,2998],{"class":3331},[2166,42839,42833],{"class":3316},[2166,42841,4741],{"class":3331},[2166,42843,42845],{"class":3301,"line":42844},370,[2166,42846,42847],{"class":3331},"                          {{ meta.emoji }} {{ meta.label }}\n",[2166,42849,42851,42854,42856],{"class":3301,"line":42850},371,[2166,42852,42853],{"class":3331},"                        \u003C\u002F",[2166,42855,42819],{"class":37535},[2166,42857,4741],{"class":3331},[2166,42859,42861,42863,42865],{"class":3301,"line":42860},372,[2166,42862,42522],{"class":3331},[2166,42864,25928],{"class":37535},[2166,42866,4741],{"class":3331},[2166,42868,42870,42872,42874],{"class":3301,"line":42869},373,[2166,42871,42532],{"class":3331},[2166,42873,3022],{"class":37535},[2166,42875,4741],{"class":3331},[2166,42877,42879,42881,42883],{"class":3301,"line":42878},374,[2166,42880,42542],{"class":3331},[2166,42882,162],{"class":37535},[2166,42884,4741],{"class":3331},[2166,42886,42888,42890,42892],{"class":3301,"line":42887},375,[2166,42889,41635],{"class":3331},[2166,42891,141],{"class":37535},[2166,42893,4741],{"class":3331},[2166,42895,42897,42899,42901],{"class":3301,"line":42896},376,[2166,42898,41545],{"class":3331},[2166,42900,157],{"class":37535},[2166,42902,4741],{"class":3331},[2166,42904,42906,42908,42910],{"class":3301,"line":42905},377,[2166,42907,40708],{"class":3331},[2166,42909,135],{"class":37535},[2166,42911,4741],{"class":3331},[2166,42913,42915,42917,42919],{"class":3301,"line":42914},378,[2166,42916,40749],{"class":3331},[2166,42918,40581],{"class":37535},[2166,42920,4741],{"class":3331},[2166,42922,42924,42926,42928],{"class":3301,"line":42923},379,[2166,42925,40759],{"class":3331},[2166,42927,40893],{"class":37535},[2166,42929,4741],{"class":3331},[2166,42931,42933,42935,42937],{"class":3301,"line":42932},380,[2166,42934,40769],{"class":3331},[2166,42936,40570],{"class":37535},[2166,42938,4741],{"class":3331},[2166,42940,42942,42945,42947],{"class":3301,"line":42941},381,[2166,42943,42944],{"class":3331},"    \u003C\u002F",[2166,42946,40581],{"class":37535},[2166,42948,4741],{"class":3331},[2166,42950,42952],{"class":3301,"line":42951},382,[2166,42953,3339],{"emptyLinePlaceholder":3338},[2166,42955,42957],{"class":3301,"line":42956},383,[2166,42958,42959],{"class":3422},"    \u003C!-- FLOATING AUTOSAVE STATUS -->\n",[2166,42961,42963,42965,42967,42969,42971],{"class":3301,"line":42962},384,[2166,42964,40597],{"class":3331},[2166,42966,40581],{"class":37535},[2166,42968,40794],{"class":3309},[2166,42970,2998],{"class":3331},[2166,42972,42973],{"class":3316},"\"saveState !== 'idle'\"\n",[2166,42975,42977,42980,42982,42985],{"class":3301,"line":42976},385,[2166,42978,42979],{"class":3309},"         class",[2166,42981,2998],{"class":3331},[2166,42983,42984],{"class":3316},"\"fixed bottom-6 left-1\u002F2 z-50 flex -translate-x-1\u002F2 items-center gap-2.5 rounded-full border border-neutral-200 bg-white px-3 py-2 shadow-lg shadow-neutral-900\u002F10\"",[2166,42986,4741],{"class":3331},[2166,42988,42990,42992,42994,42996,42998,43001],{"class":3301,"line":42989},386,[2166,42991,40620],{"class":3331},[2166,42993,2166],{"class":37535},[2166,42995,40584],{"class":3309},[2166,42997,2998],{"class":3331},[2166,42999,43000],{"class":3316},"\"flex items-center gap-2 pl-1 text-[14px] text-neutral-700\"",[2166,43002,4741],{"class":3331},[2166,43004,43006,43008,43010,43012,43014,43016,43019,43021,43024],{"class":3301,"line":43005},387,[2166,43007,40637],{"class":3331},[2166,43009,40570],{"class":37535},[2166,43011,40794],{"class":3305},[2166,43013,2998],{"class":3331},[2166,43015,39984],{"class":3316},[2166,43017,43018],{"class":3331},"saveState ",[2166,43020,38145],{"class":3305},[2166,43022,43023],{"class":3316}," 'dirty'\"",[2166,43025,4741],{"class":3331},[2166,43027,43029,43031,43033,43035,43037,43039,43041,43044,43046,43049,43051],{"class":3301,"line":43028},388,[2166,43030,40654],{"class":3331},[2166,43032,2166],{"class":37535},[2166,43034,40584],{"class":3309},[2166,43036,2998],{"class":3331},[2166,43038,41227],{"class":3316},[2166,43040,40357],{"class":41028},[2166,43042,43043],{"class":3331},">\u003C",[2166,43045,2166],{"class":37535},[2166,43047,43048],{"class":3331},">수정 감지…\u003C\u002F",[2166,43050,2166],{"class":37535},[2166,43052,4741],{"class":3331},[2166,43054,43056,43058,43060],{"class":3301,"line":43055},389,[2166,43057,40759],{"class":3331},[2166,43059,40570],{"class":37535},[2166,43061,4741],{"class":3331},[2166,43063,43065,43067,43069,43071,43073,43075,43077,43079,43082],{"class":3301,"line":43064},390,[2166,43066,40637],{"class":3331},[2166,43068,40570],{"class":37535},[2166,43070,40833],{"class":3305},[2166,43072,2998],{"class":3331},[2166,43074,39984],{"class":3316},[2166,43076,43018],{"class":3331},[2166,43078,38145],{"class":3305},[2166,43080,43081],{"class":3316}," 'saving'\"",[2166,43083,4741],{"class":3331},[2166,43085,43087,43089,43091,43093,43095,43098,43100,43102,43104,43107,43109],{"class":3301,"line":43086},391,[2166,43088,40654],{"class":3331},[2166,43090,2166],{"class":37535},[2166,43092,40584],{"class":3309},[2166,43094,2998],{"class":3331},[2166,43096,43097],{"class":3316},"\"inline-block size-1.5 animate-pulse rounded-full bg-sky-500\"",[2166,43099,40357],{"class":41028},[2166,43101,43043],{"class":3331},[2166,43103,2166],{"class":37535},[2166,43105,43106],{"class":3331},">저장 중…\u003C\u002F",[2166,43108,2166],{"class":37535},[2166,43110,4741],{"class":3331},[2166,43112,43114,43116,43118],{"class":3301,"line":43113},392,[2166,43115,40759],{"class":3331},[2166,43117,40570],{"class":37535},[2166,43119,4741],{"class":3331},[2166,43121,43123,43125,43127,43129,43131,43133,43135,43137,43140],{"class":3301,"line":43122},393,[2166,43124,40637],{"class":3331},[2166,43126,40570],{"class":37535},[2166,43128,40833],{"class":3305},[2166,43130,2998],{"class":3331},[2166,43132,39984],{"class":3316},[2166,43134,43018],{"class":3331},[2166,43136,38145],{"class":3305},[2166,43138,43139],{"class":3316}," 'saved'\"",[2166,43141,4741],{"class":3331},[2166,43143,43145,43147,43149,43151,43153,43155,43157],{"class":3301,"line":43144},394,[2166,43146,40654],{"class":3331},[2166,43148,2166],{"class":37535},[2166,43150,40584],{"class":3309},[2166,43152,2998],{"class":3331},[2166,43154,41094],{"class":3316},[2166,43156,40357],{"class":41028},[2166,43158,4741],{"class":3331},[2166,43160,43162,43164,43166,43169,43171,43173,43175,43178,43181,43183,43186,43188],{"class":3301,"line":43161},395,[2166,43163,40654],{"class":3331},[2166,43165,2166],{"class":37535},[2166,43167,43168],{"class":3331},">저장됨 \u003C",[2166,43170,2166],{"class":37535},[2166,43172,40584],{"class":3309},[2166,43174,2998],{"class":3331},[2166,43176,43177],{"class":3316},"\"text-neutral-400\"",[2166,43179,43180],{"class":3331},">· {{ savedAgo }}\u003C\u002F",[2166,43182,2166],{"class":37535},[2166,43184,43185],{"class":3331},">\u003C\u002F",[2166,43187,2166],{"class":37535},[2166,43189,4741],{"class":3331},[2166,43191,43193,43195,43197],{"class":3301,"line":43192},396,[2166,43194,40759],{"class":3331},[2166,43196,40570],{"class":37535},[2166,43198,4741],{"class":3331},[2166,43200,43202,43204,43206,43208,43210,43212,43214,43216,43219],{"class":3301,"line":43201},397,[2166,43203,40637],{"class":3331},[2166,43205,40570],{"class":37535},[2166,43207,40833],{"class":3305},[2166,43209,2998],{"class":3331},[2166,43211,39984],{"class":3316},[2166,43213,43018],{"class":3331},[2166,43215,38145],{"class":3305},[2166,43217,43218],{"class":3316}," 'error'\"",[2166,43220,4741],{"class":3331},[2166,43222,43224,43226,43228,43230,43232,43235,43237],{"class":3301,"line":43223},398,[2166,43225,40654],{"class":3331},[2166,43227,2166],{"class":37535},[2166,43229,40584],{"class":3309},[2166,43231,2998],{"class":3331},[2166,43233,43234],{"class":3316},"\"inline-block size-1.5 rounded-full bg-rose-500\"",[2166,43236,40357],{"class":41028},[2166,43238,4741],{"class":3331},[2166,43240,43242,43244,43246,43248,43250,43253,43256,43258],{"class":3301,"line":43241},399,[2166,43243,40654],{"class":3331},[2166,43245,2166],{"class":37535},[2166,43247,40584],{"class":3309},[2166,43249,2998],{"class":3331},[2166,43251,43252],{"class":3316},"\"text-rose-700\"",[2166,43254,43255],{"class":3331},">저장 실패: {{ saveError }}\u003C\u002F",[2166,43257,2166],{"class":37535},[2166,43259,4741],{"class":3331},[2166,43261,43263,43265,43267],{"class":3301,"line":43262},400,[2166,43264,40759],{"class":3331},[2166,43266,40570],{"class":37535},[2166,43268,4741],{"class":3331},[2166,43270,43272,43274,43276],{"class":3301,"line":43271},401,[2166,43273,40769],{"class":3331},[2166,43275,2166],{"class":37535},[2166,43277,4741],{"class":3331},[2166,43279,43281,43283,43285,43287,43289,43292,43294],{"class":3301,"line":43280},402,[2166,43282,40620],{"class":3331},[2166,43284,2166],{"class":37535},[2166,43286,40584],{"class":3309},[2166,43288,2998],{"class":3331},[2166,43290,43291],{"class":3316},"\"h-4 w-px bg-neutral-200\"",[2166,43293,40357],{"class":41028},[2166,43295,4741],{"class":3331},[2166,43297,43299,43301,43304,43306,43308],{"class":3301,"line":43298},403,[2166,43300,40620],{"class":3331},[2166,43302,43303],{"class":37535},"button",[2166,43305,40794],{"class":3309},[2166,43307,2998],{"class":3331},[2166,43309,43310],{"class":3316},"\"saveState === 'error'\"\n",[2166,43312,43314,43316,43318],{"class":3301,"line":43313},404,[2166,43315,41405],{"class":3309},[2166,43317,2998],{"class":3331},[2166,43319,43320],{"class":3316},"\"rounded-md bg-neutral-900 px-3 py-1 text-[14px] font-medium text-white hover:bg-neutral-700\"\n",[2166,43322,43324,43326,43328,43331,43334,43336],{"class":3301,"line":43323},405,[2166,43325,41427],{"class":3309},[2166,43327,2998],{"class":3331},[2166,43329,43330],{"class":3316},"\"saveNow\"",[2166,43332,43333],{"class":3331},">재시도\u003C\u002F",[2166,43335,43303],{"class":37535},[2166,43337,4741],{"class":3331},[2166,43339,43341,43343,43345,43347,43349],{"class":3301,"line":43340},406,[2166,43342,40620],{"class":3331},[2166,43344,43303],{"class":37535},[2166,43346,40584],{"class":3309},[2166,43348,2998],{"class":3331},[2166,43350,43351],{"class":3316},"\"rounded-md px-2.5 py-1 text-[14px] text-neutral-600 hover:bg-neutral-100\"\n",[2166,43353,43355,43357,43359,43362,43365,43367,43370,43373,43375],{"class":3301,"line":43354},407,[2166,43356,41427],{"class":3309},[2166,43358,2998],{"class":3331},[2166,43360,43361],{"class":3316},"\"downloadJson\"",[2166,43363,43364],{"class":3309}," title",[2166,43366,2998],{"class":3331},[2166,43368,43369],{"class":3316},"\"현재 상태를 wbs.json으로 다운로드\"",[2166,43371,43372],{"class":3331},">↓ 백업\u003C\u002F",[2166,43374,43303],{"class":37535},[2166,43376,4741],{"class":3331},[2166,43378,43380,43382,43384],{"class":3301,"line":43379},408,[2166,43381,42944],{"class":3331},[2166,43383,40581],{"class":37535},[2166,43385,4741],{"class":3331},[2166,43387,43389,43392,43394],{"class":3301,"line":43388},409,[2166,43390,43391],{"class":3331},"  \u003C\u002F",[2166,43393,40581],{"class":37535},[2166,43395,4741],{"class":3331},[2166,43397,43399,43401,43403],{"class":3301,"line":43398},410,[2166,43400,40553],{"class":3331},[2166,43402,40570],{"class":37535},[2166,43404,4741],{"class":3331},[215,43406,43408],{"id":43407},"_6-3-자동-저장-상태-머신","6-3. 자동 저장 상태 머신",[415,43410,43413],{"className":43411,"code":43412,"language":420},[418],"[idle] ─ 첫 편집 ─▶ [dirty] ─ 800ms 무편집 ─▶ [saving] ─ 200 OK ─▶ [saved]\n                       │                              │\n                       └─ 추가 편집 시 타이머 재시작     └─ 실패 시 ▶ [error] ─ 재시도 ─▶ [saving]\n",[16,43414,43412],{"__ignoreMap":423},[54,43416,43417,43420,43426,43429],{},[57,43418,43419],{},"새 편집이 들어오면 timer 갱신 → 디바운스 보장",[57,43421,43422,43425],{},[16,43423,43424],{},"saving"," 중 새 편집은 다음 사이클에서 통째로 PUT (변경 단위가 아닌 문서 단위)",[57,43427,43428],{},"페이지 unmount 시 timer cleanup. 저장 누락 위험은 디바운스 800ms로 한정됨",[57,43430,43431,43432,43435,43436,43439,43440,43443],{},"더 강건하게 가려면 ",[16,43433,43434],{},"beforeunload"," 핸들러에서 ",[16,43437,43438],{},"saveState === 'dirty'","일 때 ",[16,43441,43442],{},"navigator.sendBeacon","으로 마지막 PUT을 보낼 수 있음",[33,43445],{},[36,43447,43449],{"id":43448},"_7-새-프로젝트에서-초기화하기-체크리스트","7. 새 프로젝트에서 초기화하기 — 체크리스트",[1925,43451,43452,43466,43502,43529,43542],{},[57,43453,43454,43456],{},[28,43455,4474],{},[54,43457,43458,43461],{},[57,43459,43460],{},"계정에서 R2 활성화",[57,43462,43463],{},[16,43464,43465],{},"wrangler r2 bucket create \u003Cmy-bucket>",[57,43467,43468,43475],{},[28,43469,43470,43471,43474],{},"백엔드 (",[16,43472,43473],{},"\u003Capi>"," 레포)",[54,43476,43477,43485,43496],{},[57,43478,43479,1365,43482],{},[16,43480,43481],{},"pnpm add hono",[16,43483,43484],{},"pnpm add -D wrangler typescript",[57,43486,43487,43488,105,43490,105,43492,43495],{},"위 §5-1, §5-2 그대로 복사. ",[16,43489,3038],{},[16,43491,4825],{},[16,43493,43494],{},"bucket_name","만 교체",[57,43497,43498,43501],{},[16,43499,43500],{},"pnpm wrangler deploy"," → API URL 확보",[57,43503,43504,43511],{},[28,43505,43506,43507,43510],{},"프론트엔드 (",[16,43508,43509],{},"\u003Cpages>"," 레포, Nuxt 3)",[54,43512,43513,43521,43526],{},[57,43514,43515,43517,43518,43520],{},[16,43516,37483],{}," 생성 → §6-2 복사 → ",[16,43519,5584],{},"를 자기 API URL로 교체",[57,43522,43523,43525],{},[16,43524,35924],{},"에 §3-2 형태의 초기 시드 작성",[57,43527,43528],{},"한 번 빌드·배포 후 페이지 접속 → 첫 편집 시 R2에 자동 시드됨",[57,43530,43531,43534],{},[28,43532,43533],{},"CORS 확인",[54,43535,43536],{},[57,43537,43538,43539,43541],{},"§5-2의 ",[16,43540,36501],{}," 함수에 자기 페이지 도메인 패턴 추가",[57,43543,43544,43546],{},[28,43545,3763],{},[54,43547,43548,43551],{},[57,43549,43550],{},"다른 브라우저에서 같은 URL을 열어 변경 즉시 반영되는지 확인",[57,43552,43553],{},"네트워크 탭에서 PUT이 800ms 디바운스 후 1회만 가는지 확인",[21,43555,43556],{},[24,43557,43558,43559,24613,43562,43564,43565,43568],{},"인증이 필요한 환경이면 ",[28,43560,43561],{},"Cloudflare Access",[16,43563,43509],{}," 도메인과 ",[16,43566,43567],{},"\u003Capi>\u002Fwbs"," 라우트를 동시에 보호하는 것이 가장 단순. 인증 코드 작성 불필요.",[33,43570],{},[36,43572,43574],{"id":43573},"_8-운영-메모","8. 운영 메모",[135,43576,43577,43585],{},[138,43578,43579],{},[141,43580,43581,43583],{},[144,43582,4143],{},[144,43584,19452],{},[157,43586,43587,43595,43606,43620,43635,43647],{},[141,43588,43589,43592],{},[162,43590,43591],{},"동시 편집 충돌",[162,43593,43594],{},"last-write-wins. ETag 기반 conditional PUT은 미적용 (사내 1~3명 운영 가정)",[141,43596,43597,43599],{},[162,43598,19515],{},[162,43600,43601,43602,43605],{},"우하단 ",[16,43603,43604],{},"↓ 백업"," 버튼으로 수시 다운로드. 또는 R2 versioning 활성화 권장",[141,43607,43608,43611],{},[162,43609,43610],{},"시드 갱신",[162,43612,43613,43615,43616,43619],{},[16,43614,35924],{}," 수정은 ",[28,43617,43618],{},"R2가 비어 있을 때만"," 의미가 있음. 운영 중에는 R2가 정본",[141,43621,43622,43624],{},[162,43623,32251],{},[162,43625,43626,43627,43630,43631,43634],{},"스키마 변경 시 ",[16,43628,43629],{},"_meta.schemaVersion"," 필드를 추가하고 ",[16,43632,43633],{},"app.put","에서 변환",[141,43636,43637,43640],{},[162,43638,43639],{},"모니터링",[162,43641,43642,43643,43646],{},"Workers ",[16,43644,43645],{},"observability: true","로 PUT 실패 로그 추적",[141,43648,43649,43652],{},[162,43650,43651],{},"보안",[162,43653,43654],{},"현재 무인증. 공개 도메인에 둘 거라면 반드시 Access 또는 토큰 헤더 검증 추가",[33,43656],{},[36,43658,43660],{"id":43659},"_9-디자인-변형-가이드","9. 디자인 변형 가이드",[24,43662,43663],{},"이 페이지의 디자인 토큰은 의도적으로 단순하다. 다음 한 줄만 바꿔도 분위기가 크게 달라진다.",[54,43665,43666,43693,43711,43726],{},[57,43667,43668,43671,43672,1358,43675,43678,43679,1358,43682,43685,43686,1358,43689,43692],{},[28,43669,43670],{},"다크 모드",": 컨테이너 ",[16,43673,43674],{},"bg-neutral-50\u002F60",[16,43676,43677],{},"bg-neutral-950",", 카드 ",[16,43680,43681],{},"bg-white",[16,43683,43684],{},"bg-neutral-900",", 라인 ",[16,43687,43688],{},"border-neutral-200",[16,43690,43691],{},"border-neutral-800",". 텍스트 명도만 반전",[57,43694,43695,4664,43698,1358,43701,43704,43705,1358,43708],{},[28,43696,43697],{},"밀도 ↑",[16,43699,43700],{},"px-3 py-3",[16,43702,43703],{},"px-2 py-2",", 본문 ",[16,43706,43707],{},"text-[14px]",[16,43709,43710],{},"text-[13px]",[57,43712,43713,43716,43717,43720,43721,1358,43723],{},[28,43714,43715],{},"에디토리얼",": 헤더에 serif 디스플레이 폰트(",[16,43718,43719],{},"Instrument Serif"," 등) + 본문 mono. 카드 모서리 ",[16,43722,35394],{},[16,43724,43725],{},"rounded-none",[57,43727,43728,43731,43732,43734],{},[28,43729,43730],{},"터미널\u002FIDE",": 카드 제거, 단일 ",[16,43733,415],{},", JetBrains Mono, 좌측 라인 거터 추가",[24,43736,43737],{},"색·간격은 토큰화돼 있어서 한 파일에서 전체 분위기를 바꿀 수 있다.",[33,43739],{},[36,43741,43743],{"id":43742},"_10-알려진-한계","10. 알려진 한계",[54,43745,43746,43752,43758,43768],{},[57,43747,43748,43751],{},[28,43749,43750],{},"다중 사용자 동시 편집 시 마지막 저장이 이김"," — 실시간 동기화(WebSocket\u002FSSE)는 없음",[57,43753,43754,43757],{},[28,43755,43756],{},"인증 없음"," — 외부 노출 시 Cloudflare Access 등으로 별도 보호 필요",[57,43759,43760,43763,43764,43767],{},[28,43761,43762],{},"이력 추적 없음"," — R2 versioning을 켜거나, PUT 시점에 ",[16,43765,43766],{},"wbs\u002Fhistory\u002F\u003Cts>.json","로 스냅샷 저장하면 해결 가능",[57,43769,43770,2448,43773,43776],{},[28,43771,43772],{},"Phase 1만 모델링",[16,43774,43775],{},"phase1.stages[]"," 구조. Phase 2 이상은 동일 패턴으로 키 추가 후 컴포넌트에서 반복 렌더링",[33,43778],{},[36,43780,43782],{"id":43781},"_11-본-프로젝트의-실제-값-참고","11. 본 프로젝트의 실제 값 (참고)",[135,43784,43785,43794],{},[138,43786,43787],{},[141,43788,43789,43792],{},[144,43790,43791],{},"키",[144,43793,1540],{},[157,43795,43796,43805,43815,43825,43837,43846,43855],{},[141,43797,43798,43801],{},[162,43799,43800],{},"API URL",[162,43802,43803],{},[16,43804,10806],{},[141,43806,43807,43810],{},[162,43808,43809],{},"API 레포",[162,43811,43812],{},[16,43813,43814],{},"~\u002FProjects\u002Fmalgn-helper-api",[141,43816,43817,43820],{},[162,43818,43819],{},"Pages 레포",[162,43821,43822],{},[16,43823,43824],{},"~\u002FProjects\u002Fmalgn-helper-pms",[141,43826,43827,43830],{},[162,43828,43829],{},"R2 버킷",[162,43831,43832,43834,43835,78],{},[16,43833,12096],{}," (key: ",[16,43836,36253],{},[141,43838,43839,43842],{},[162,43840,43841],{},"페이지 URL",[162,43843,43844],{},[16,43845,12676],{},[141,43847,43848,43851],{},[162,43849,43850],{},"시드 위치",[162,43852,43853],{},[16,43854,13018],{},[141,43856,43857,43860],{},[162,43858,43859],{},"Cloudflare account_id",[162,43861,43862,1305,43864,78],{},[16,43863,10186],{},[3257,43865,10183],{"href":10182},[4258,43867,43868],{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .snhLl, html code.shiki .snhLl{--shiki-default:#22863A;--shiki-default-font-weight:bold;--shiki-dark:#85E89D;--shiki-dark-font-weight:bold}html pre.shiki code .sA_wV, html code.shiki .sA_wV{--shiki-default:#032F62;--shiki-dark:#DBEDFF}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .s7hpK, html code.shiki .s7hpK{--shiki-default:#B31D28;--shiki-default-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic}",{"title":423,"searchDepth":3342,"depth":3342,"links":43870},[43871,43872,43873,43880,43881,43891,43897,43898,43899,43900,43901],{"id":35293,"depth":3335,"text":35294},{"id":35343,"depth":3335,"text":35344},{"id":35534,"depth":3335,"text":35535,"children":43874},[43875,43877,43879],{"id":35538,"depth":3342,"text":43876},"3-1. wbs.json 스키마",{"id":35920,"depth":3342,"text":43878},"3-2. 초기 시드 예시 (public\u002Fwbs.json)",{"id":36207,"depth":3342,"text":36208},{"id":36231,"depth":3335,"text":36232},{"id":36287,"depth":3335,"text":36288,"children":43882},[43883,43885,43887,43889,43890],{"id":36291,"depth":3342,"text":43884},"5-1. wrangler.jsonc",{"id":36364,"depth":3342,"text":43886},"5-2. src\u002Findex.ts (전체)",{"id":37213,"depth":3342,"text":43888},"5-3. package.json 최소 의존",{"id":37277,"depth":3342,"text":37278},{"id":37345,"depth":3342,"text":37346},{"id":37447,"depth":3335,"text":37448,"children":43892},[43893,43894,43896],{"id":37451,"depth":3342,"text":37452},{"id":37479,"depth":3342,"text":43895},"6-2. 단일 파일 — pages\u002Fwbs.vue (전체)",{"id":43407,"depth":3342,"text":43408},{"id":43448,"depth":3335,"text":43449},{"id":43573,"depth":3335,"text":43574},{"id":43659,"depth":3335,"text":43660},{"id":43742,"depth":3335,"text":43743},{"id":43781,"depth":3335,"text":43782},"이 문서 하나만 있으면 어떤 프로젝트에서도 동일한 WBS Live Tracker 페이지를 처음부터 만들 수 있다.\n프론트엔드(Nuxt) + 백엔드(Hono on Workers) + 영속화(R2) + 자동 저장 흐름을 전부 포함한다.",{},"\u002Fwbs-tracker",{"title":35255,"description":43902},"i086HB2qpUcUTC6DGKmfExYH4514OCpCFKzdA3zgwug",1780986551102]