[{"data":1,"prerenderedAt":587},["ShallowReactive",2],{"doc:\u002Ftech-stack":3},{"id":4,"title":5,"body":6,"description":442,"extension":580,"meta":581,"navigation":582,"path":583,"seo":584,"stem":585,"__hash__":586},"docs\u002FTECH-STACK.md","기술 스택",{"type":7,"value":8,"toc":553},"minimark",[9,13,26,29,34,143,145,149,159,188,195,225,227,234,278,280,284,288,308,312,325,329,376,378,382,429,433,443,445,449,453,461,465,488,490,494,530,532,536],[10,11,5],"h1",{"id":12},"기술-스택",[14,15,16],"blockquote",{},[17,18,19,20,25],"p",{},"고객상담 AI 챗봇 (Malgn Helper) 기술 스택 정의 문서.\n변경 시 본 문서와 ",[21,22,24],"a",{"href":23},"..\u002FCLAUDE","CLAUDE.md","를 함께 갱신한다.",[27,28],"hr",{},[30,31,33],"h2",{"id":32},"_1-전체-개요","1. 전체 개요",[35,36,37,53],"table",{},[38,39,40],"thead",{},[41,42,43,47,50],"tr",{},[44,45,46],"th",{},"레이어",[44,48,49],{},"기술",[44,51,52],{},"비고",[54,55,56,68,77,88,99,110,121,132],"tbody",{},[41,57,58,62,65],{},[59,60,61],"td",{},"사용자 프론트엔드",[59,63,64],{},"Nuxt 3",[59,66,67],{},"Cloudflare Pages",[41,69,70,73,75],{},[59,71,72],{},"관리자 프론트엔드",[59,74,64],{},[59,76,67],{},[41,78,79,82,85],{},[59,80,81],{},"API 서버",[59,83,84],{},"Hono",[59,86,87],{},"Cloudflare Workers",[41,89,90,93,96],{},[59,91,92],{},"RDB",[59,94,95],{},"Aurora MySQL",[59,97,98],{},"Hyperdrive 경유",[41,100,101,104,107],{},[59,102,103],{},"검색",[59,105,106],{},"AWS OpenSearch Service",[59,108,109],{},"k-NN(벡터) + BM25 하이브리드",[41,111,112,115,118],{},[59,113,114],{},"객체 스토리지",[59,116,117],{},"Cloudflare R2",[59,119,120],{},"원본 파일(매뉴얼·동영상 등)",[41,122,123,126,129],{},[59,124,125],{},"LLM",[59,127,128],{},"Claude",[59,130,131],{},"Cloudflare AI Gateway 경유",[41,133,134,137,140],{},[59,135,136],{},"인덱싱",[59,138,139],{},"동기 처리(MVP) → Cloudflare Queues(추후)",[59,141,142],{},"2단계 도입",[27,144],{},[30,146,148],{"id":147},"_2-프론트엔드","2. 프론트엔드",[150,151,153,154,158],"h3",{"id":152},"_21-사용자-malgn-helper","2.1 사용자 (",[155,156,157],"code",{},"malgn-helper",")",[160,161,162,170,176,182],"ul",{},[163,164,165,169],"li",{},[166,167,168],"strong",{},"프레임워크",": Nuxt 3",[163,171,172,175],{},[166,173,174],{},"배포",": Cloudflare Pages",[163,177,178,181],{},[166,179,180],{},"주요 화면",": 챗봇 대화 UI, 출처 인용 표시, 에스컬레이션 요청",[163,183,184,187],{},[166,185,186],{},"인증",": 필요 시 추가 (게스트 허용 여부는 운영 정책으로 결정)",[150,189,191,192,158],{"id":190},"_22-관리자-malgn-helper-admin","2.2 관리자 (",[155,193,194],{},"malgn-helper-admin",[160,196,197,201,205],{},[163,198,199,169],{},[166,200,168],{},[163,202,203,175],{},[166,204,174],{},[163,206,207,210,211],{},[166,208,209],{},"주요 기능",":\n",[160,212,213,216,219,222],{},[163,214,215],{},"자료(매뉴얼·동영상·Q&A) 업로드 및 메타데이터 관리",[163,217,218],{},"표준 답변 등록·검토",[163,220,221],{},"상담 로그 열람 \u002F 에스컬레이션 큐 처리",[163,223,224],{},"인덱싱 상태 모니터링",[27,226],{},[30,228,230,231,158],{"id":229},"_3-api-서버-malgn-helper-api","3. API 서버 (",[155,232,233],{},"malgn-helper-api",[160,235,236,241,247,266,272],{},[163,237,238,240],{},[166,239,168],{},": Hono",[163,242,243,246],{},[166,244,245],{},"런타임",": Cloudflare Workers",[163,248,249,210,252],{},[166,250,251],{},"주요 책임",[160,253,254,257,260,263],{},[163,255,256],{},"챗 요청 처리 (검색 → 컨텍스트 구성 → LLM 호출 → 응답)",[163,258,259],{},"표준 답변 우선 매칭 로직",[163,261,262],{},"자료 업로드 → R2 저장 → 인덱싱 트리거",[163,264,265],{},"관리자 CRUD 엔드포인트",[163,267,268,271],{},[166,269,270],{},"DB 접근",": Hyperdrive 바인딩만 사용. 직접 커넥션 금지.",[163,273,274,277],{},[166,275,276],{},"외부 호출",": AI Gateway, OpenSearch는 fetch 기반 클라이언트.",[27,279],{},[30,281,283],{"id":282},"_4-데이터-저장소","4. 데이터 저장소",[150,285,287],{"id":286},"_41-aurora-mysql-via-hyperdrive","4.1 Aurora MySQL (via Hyperdrive)",[160,289,290,296,302],{},[163,291,292,295],{},[166,293,294],{},"용도",": 사용자, 대화 세션, 메시지, 표준 답변, 자료 메타데이터, 에스컬레이션 티켓.",[163,297,298,301],{},[166,299,300],{},"접근 방식",": Cloudflare Hyperdrive 바인딩으로 Worker에서 풀링 + 캐싱.",[163,303,304,307],{},[166,305,306],{},"마이그레이션",": 도구 미정 (Drizzle \u002F Prisma \u002F 직접 SQL 중 결정 필요).",[150,309,311],{"id":310},"_42-cloudflare-r2","4.2 Cloudflare R2",[160,313,314,319],{},[163,315,316,318],{},[166,317,294],{},": 업로드된 원본 파일(PDF, 동영상, 첨부 이미지).",[163,320,321,324],{},[166,322,323],{},"참조",": DB에는 R2 키만 저장. 다운로드는 서명 URL로 발급.",[150,326,328],{"id":327},"_43-aws-opensearch-service","4.3 AWS OpenSearch Service",[160,330,331,336,358],{},[163,332,333,335],{},[166,334,294],{},": 청크 단위 본문\u002F임베딩 인덱싱, 하이브리드 검색.",[163,337,338,210,341],{},[166,339,340],{},"검색 전략",[160,342,343,349,355],{},[163,344,345,348],{},[166,346,347],{},"BM25",": 키워드 기반 정확 매칭",[163,350,351,354],{},[166,352,353],{},"k-NN (벡터)",": 의미 기반 유사도",[163,356,357],{},"두 결과를 가중치로 결합(RRF 또는 직접 스코어 합산) — 구체 가중치는 운영 중 튜닝.",[163,359,360,363,364,367,368,371,372,375],{},[166,361,362],{},"인덱스 설계",": ",[155,365,366],{},"documents","(원본), ",[155,369,370],{},"chunks","(청크+벡터), ",[155,373,374],{},"standard_answers","(표준 답변).",[27,377],{},[30,379,381],{"id":380},"_5-ai-llm","5. AI \u002F LLM",[160,383,384,398,404,423],{},[163,385,386,389,390,393,394,397],{},[166,387,388],{},"모델",": Claude (기본 ",[155,391,392],{},"claude-opus-4-7"," 또는 비용 균형이 필요할 때 ",[155,395,396],{},"claude-sonnet-4-6",").",[163,399,400,403],{},[166,401,402],{},"호출 경로",": Cloudflare AI Gateway → Anthropic API.",[163,405,406,210,409],{},[166,407,408],{},"AI Gateway 사용 이유",[160,410,411,414,417,420],{},[163,412,413],{},"캐싱(동일 프롬프트 응답 재사용)",[163,415,416],{},"로깅·분석",[163,418,419],{},"rate limit \u002F 비용 제어",[163,421,422],{},"실패 시 폴백 전략 적용",[163,424,425,428],{},[166,426,427],{},"프롬프트 캐싱",": 시스템 프롬프트 + 표준 답변 카탈로그 등 고정 컨텍스트에 적극 적용.",[150,430,432],{"id":431},"_51-답변-파이프라인","5.1 답변 파이프라인",[434,435,440],"pre",{"className":436,"code":438,"language":439},[437],"language-text","질의\n ├─ (1) 표준 답변 매칭 → hit 시 즉시 반환\n ├─ (2) 하이브리드 검색 (BM25 + k-NN) → top-k 청크 추출\n ├─ (3) Claude에 컨텍스트 + 인용 지시와 함께 전달\n └─ (4) 응답 신뢰도 부족 시 \"모름 + 상담사 연결\" 반환\n","text",[155,441,438],{"__ignoreMap":442},"",[27,444],{},[30,446,448],{"id":447},"_6-인덱싱-파이프라인","6. 인덱싱 파이프라인",[150,450,452],{"id":451},"mvp-현재-단계","MVP (현재 단계)",[160,454,455,458],{},[163,456,457],{},"관리자 업로드 → API가 동기로 텍스트 추출 → 청킹 → 임베딩 → OpenSearch upsert.",[163,459,460],{},"텍스트 위주 자료 전제. Worker CPU 제한 내 처리 가능한 크기만 허용.",[150,462,464],{"id":463},"_2단계-동영상대용량-도입-시","2단계 (동영상\u002F대용량 도입 시)",[160,466,467,470,485],{},[163,468,469],{},"업로드 후 Cloudflare Queue에 인덱싱 작업 enqueue.",[163,471,472,473,476,477],{},"별도 ",[166,474,475],{},"Indexer Worker","가 consumer로 동작:\n",[160,478,479,482],{},[163,480,481],{},"동영상 → 트랜스크립트 추출",[163,483,484],{},"대용량 PDF → 분할 처리, 재시도, 진행률 기록",[163,486,487],{},"관리자 화면에서 인덱싱 상태(pending\u002Fprocessing\u002Fdone\u002Ffailed) 표시.",[27,489],{},[30,491,493],{"id":492},"_7-인프라-배포","7. 인프라 \u002F 배포",[160,495,496,502,518,524],{},[163,497,498,501],{},[166,499,500],{},"호스팅",": Cloudflare (Pages + Workers + R2 + Hyperdrive + AI Gateway)",[163,503,504,210,507],{},[166,505,506],{},"외부 서비스",[160,508,509,512,515],{},[163,510,511],{},"Aurora MySQL (AWS)",[163,513,514],{},"OpenSearch Service (AWS)",[163,516,517],{},"Anthropic API (AI Gateway 경유)",[163,519,520,523],{},[166,521,522],{},"환경 분리",": dev \u002F staging \u002F prod — Cloudflare 환경별 바인딩과 시크릿으로 분리.",[163,525,526,529],{},[166,527,528],{},"시크릿 관리",": Cloudflare Workers 시크릿 \u002F Pages 환경변수.",[27,531],{},[30,533,535],{"id":534},"_8-미결-사항-tbd","8. 미결 사항 (TBD)",[160,537,538,541,544,547,550],{},[163,539,540],{},"ORM\u002F마이그레이션 도구 선정",[163,542,543],{},"임베딩 모델 (Anthropic 자체 \u002F OpenAI \u002F 한국어 특화 오픈모델) 결정",[163,545,546],{},"인증 방식 (사용자\u002F관리자 각각)",[163,548,549],{},"관측: 로깅·메트릭·알람 스택 (Cloudflare Logs \u002F 외부 APM)",[163,551,552],{},"에스컬레이션 채널 (이메일 \u002F Slack \u002F 자체 티켓 시스템)",{"title":442,"searchDepth":554,"depth":554,"links":555},3,[556,558,564,566,571,574,578,579],{"id":32,"depth":557,"text":33},2,{"id":147,"depth":557,"text":148,"children":559},[560,562],{"id":152,"depth":554,"text":561},"2.1 사용자 (malgn-helper)",{"id":190,"depth":554,"text":563},"2.2 관리자 (malgn-helper-admin)",{"id":229,"depth":557,"text":565},"3. API 서버 (malgn-helper-api)",{"id":282,"depth":557,"text":283,"children":567},[568,569,570],{"id":286,"depth":554,"text":287},{"id":310,"depth":554,"text":311},{"id":327,"depth":554,"text":328},{"id":380,"depth":557,"text":381,"children":572},[573],{"id":431,"depth":554,"text":432},{"id":447,"depth":557,"text":448,"children":575},[576,577],{"id":451,"depth":554,"text":452},{"id":463,"depth":554,"text":464},{"id":492,"depth":557,"text":493},{"id":534,"depth":557,"text":535},"md",{},true,"\u002Ftech-stack",{"title":5,"description":442},"TECH-STACK","40pPM5aiKaugqPGvve22xmZ1-fLbMhhYoCgnpu7brkk",1780990720862]