AEO · GEO · 홈페이지 기획

질문형 콘텐츠만으로는 부족합니다:
AI와 포털이 이해하는 키워드 설계법

홈페이지에 질문과 답변을 많이 넣으면 AI와 포털에 잘 노출될까요? 방향은 맞지만 그것만으로는 부족합니다. 고객이 실제로 묻는 질문과 그 질문을 설명하는 명확한 키워드가 같은 페이지 안에서 연결돼야 합니다.

최근 AEO·GEO를 준비한다며 기존 홈페이지에 FAQ 몇 개를 추가하거나 페이지 하단에 질문형 문장만 잔뜩 넣는 경우가 많습니다. 시작으로는 의미가 있습니다. 그러나 질문과 서비스 페이지가 따로 놀고 제목·메뉴·본문에는 정작 핵심 용어가 없다면, 검색엔진과 AI가 그 회사의 전문 분야를 정확하게 이해하기 어렵습니다.

매스티지는 홈페이지를 제작할 때 질문지도를 먼저 받는 방식이 필요하다고 생각합니다. 여기에 한 단계가 더 필요합니다. 질문마다 연결되는 핵심 키워드와 연관 용어를 정리하고 이를 사이트맵과 화면설계에 함께 녹이는 작업입니다.

먼저 결론부터

질문은 고객의 의도를 보여 주고, 키워드는 그 질문이 어떤 회사·서비스·지역·문제에 관한 것인지 구체적으로 알려 줍니다. 둘은 따로가 아니라 하나의 페이지 구조로 설계해야 합니다.

질문형 콘텐츠가 왜 중요합니까?

질문형 콘텐츠는 고객의 검색 의도를 홈페이지 문서와 연결하는 장치입니다. 고객은 회사가 사용하는 내부 용어보다 자신의 문제를 그대로 묻습니다.

예를 들어 법무법인은 홈페이지 메뉴에 ‘기업법무’, ‘민사’, ‘형사’라고 적을 수 있습니다. 하지만 실제 고객은 다음처럼 질문합니다.

  • 퇴직금을 받지 못했는데 어떻게 해야 합니까?
  • 상속재산을 형제와 나누지 못하면 소송해야 합니까?
  • 법인 회생을 신청하면 대표자에게 어떤 영향이 있습니까?

병원도 마찬가지입니다. 병원은 ‘척추센터’나 ‘통증클리닉’이라고 분류하지만 환자는 “허리가 아픈데 어느 진료과로 가야 하나요?”라고 검색합니다. 기업 홈페이지는 ‘스마트팩토리 솔루션’이라고 말하지만 고객은 “기존 생산설비에도 자동화 시스템을 연결할 수 있나요?”라고 묻습니다.

이러한 질문을 수집하면 고객이 어떤 말로 문제를 표현하는지 알 수 있습니다. 그리고 그 질문에 바로 답하는 페이지를 만들면 사람도 이해하기 쉽고, 검색엔진과 AI도 해당 문서의 목적을 파악하기 쉬워집니다.

다만 모든 소제목을 억지로 물음표로 끝낸다고 AEO가 되는 것은 아닙니다. 질문 바로 아래에 구체적인 답이 있어야 하며, 그 답을 확인할 수 있는 조건·절차·근거가 함께 있어야 합니다.

질문만 있고 키워드가 없으면 무엇이 부족합니까?

질문만으로는 대상과 범위를 정확하게 구분하기 어렵습니다. 다음 두 문장을 비교해 보겠습니다.

비용은 얼마입니까?
법무법인 홈페이지 제작비는 얼마입니까?

첫 번째 질문만 보면 무엇의 비용인지 알 수 없습니다. 두 번째 질문에는 ‘법무법인’, ‘홈페이지 제작’, ‘제작비’라는 핵심 정보가 들어 있습니다. 사람뿐 아니라 검색엔진과 AI도 이 표현을 바탕으로 문서의 주제를 더 분명하게 이해할 수 있습니다.

키워드란 같은 단어를 여러 번 반복하는 장치가 아닙니다. 페이지가 답해야 할 주제를 정확한 언어로 선언하는 기준에 가깝습니다.

예를 들어 ‘병원 홈페이지 제작’ 페이지라면 병원 홈페이지 제작, 진료과 페이지, 의료진 소개, 진료시간과 예약 방법, 의료광고 심의, 병원 위치와 주차 안내, 검색엔진 최적화, AEO·GEO 구조 같은 표현이 문맥에 맞게 함께 등장할 수 있습니다.

이 단어들을 한 문단에 몰아넣을 필요는 없습니다. 각 질문에 답하는 과정에서 필요한 표현을 자연스럽게 사용하면 됩니다. 구글도 독자가 사용할 검색어를 예상해 작성하는 것이 도움이 될 수 있다고 설명하면서, 모든 검색어 변형을 정확하게 넣을 필요는 없다고 안내합니다. 같은 단어를 과도하게 반복하는 키워드 채우기는 오히려 스팸 정책에 어긋날 수 있습니다. Google SEO 기본 가이드

키워드는 홈페이지 어디에 넣어야 합니까?

키워드는 별도의 목록으로 숨겨 두는 것이 아니라 사용자가 읽는 실제 콘텐츠 구조에 배치해야 합니다. 중요한 것은 제목, 소제목, 답변, 사례와 내부 링크가 하나의 주제를 일관되게 설명하는 것입니다.

홈페이지 안에서 키워드가 맡는 역할
위치 역할 작성 원칙
페이지 제목과 </th><td>페이지의 핵심 주제 선언</td><td>페이지마다 고유하고 구체적으로 작성</td></tr> <tr><th scope="row">H1</th><td>방문자가 확인하는 대표 제목</td><td>한 페이지에 하나의 중심 주제 사용</td></tr> <tr><th scope="row">H2·H3</th><td>세부 질문과 하위 주제 구분</td><td>실제 고객 질문과 연결</td></tr> <tr><th scope="row">첫 문단</th><td>질문에 대한 직접 답변</td><td>도입부를 길게 끌지 않고 답부터 작성</td></tr> <tr><th scope="row">본문</th><td>조건·과정·차이·근거 설명</td><td>키워드를 반복하기보다 의미를 확장</td></tr> <tr><th scope="row">내부 링크</th><td>관련 페이지의 관계 설명</td><td>‘자세히 보기’보다 목적이 보이는 문구 사용</td></tr> <tr><th scope="row">대체텍스트·구조화 데이터</th><td>이미지와 문서의 의미 보조</td><td>화면에 보이는 실제 내용과 일치</td></tr> </tbody> </table> </div> </section> <section> <h2>질문지도와 키워드는 사이트맵보다 먼저 만들어야 합니까?</h2> <p><strong>네. AI와 포털 노출까지 고려한다면 메뉴보다 고객의 질문과 검색 의도를 먼저 정리하는 편이 좋습니다.</strong> 회사소개, 사업소개, 포트폴리오, 문의하기를 먼저 정한 뒤 내용을 채우는 기존 순서를 바꿔야 합니다.</p> <ol class="mk-qk-flow"> <li><strong>실제 고객 질문을 수집합니다</strong></li> <li><strong>핵심·연관 키워드를 연결합니다</strong></li> <li><strong>페이지별 답변 범위를 정합니다</strong></li> <li><strong>메뉴와 사이트맵을 설계합니다</strong></li> </ol> <h3>고객 질문을 수집합니다</h3> <p>영업 상담, 전화 문의, 이메일, 검색어와 고객 미팅에서 반복되는 질문을 모읍니다. 내부 직원이 중요하다고 생각하는 질문보다 실제 고객이 계약 전에 확인하는 질문을 우선합니다.</p> <h3>질문마다 키워드를 연결합니다</h3> <p>질문을 대표하는 핵심어와 세부 조건을 구분합니다. ‘홈페이지 제작’처럼 넓은 단어만 정하지 말고 ‘법무법인 홈페이지 제작’, ‘병원 다국어 홈페이지’, ‘수출바우처 홈페이지 제작’처럼 대상과 목적이 드러나는 표현을 함께 정합니다.</p> <h3>한 페이지가 답할 범위를 결정합니다</h3> <p>서로 다른 검색 의도를 한 페이지에 모두 넣지 않습니다. 제작비, 제작 과정, 유지보수, AEO·GEO 적용은 서로 연결되지만 사용자가 원하는 답이 다릅니다. 내용이 충분하다면 각각 독립된 페이지나 인사이트로 구성하고 내부 링크로 연결합니다.</p> <h3>그다음에 메뉴와 사이트맵을 만듭니다</h3> <p>질문과 키워드가 정리되면 필요한 서비스 페이지가 보입니다. 메뉴명도 회사 내부의 추상적인 표현보다 고객이 이해하는 용어로 정할 수 있습니다. 사이트맵은 페이지 목록이 아니라 <strong>회사가 어떤 질문에 어떤 문서로 답할지 정리한 답변 구조</strong>가 됩니다.</p> </section> <section> <h2>화면설계에는 질문과 답이 어떻게 들어가야 합니까?</h2> <p><strong>질문지도와 키워드는 원고 작성 단계에서만 쓰는 자료가 아닙니다. 화면설계서에 어느 질문을 어디에서 보여 줄지 표시해야 실제 홈페이지에 반영됩니다.</strong></p> <ol> <li>첫 화면에서 서비스 대상과 핵심 가치를 설명합니다.</li> <li>고객이 가장 먼저 묻는 질문에 짧게 답합니다.</li> <li>제공 범위와 진행 과정을 구체적으로 보여 줍니다.</li> <li>실제 사례·수치·제작 범위로 주장을 증명합니다.</li> <li>비용, 기간, 준비 자료처럼 계약 직전의 질문에 답합니다.</li> <li>관련 서비스와 인사이트를 내부 링크로 연결합니다.</li> <li>상담 전에 확인할 내용을 정리하고 문의 행동으로 이어 줍니다.</li> </ol> <p>이 흐름을 사용하면 디자인도 달라집니다. 멋진 이미지와 추상적인 슬로건만 크게 배치하는 것이 아니라, 사용자가 필요한 답을 찾는 순서에 맞춰 정보의 우선순위를 정하게 됩니다. AEO·GEO가 콘텐츠팀만의 일이 아니라 기획자와 UI/UX 디자이너, 퍼블리셔, 개발자가 함께 다뤄야 하는 이유입니다.</p> </section> <section> <h2>키워드보다 먼저 갖춰야 할 조건도 있습니까?</h2> <p><strong>좋은 질문과 키워드를 넣었더라도 검색로봇이 페이지를 읽지 못하면 노출될 수 없습니다.</strong> 구글은 AI 검색에 등장하기 위한 별도의 비밀 마크업은 없으며 기존 SEO 기본 조건이 그대로 중요하다고 안내합니다. 페이지가 색인 가능하고, 내부 링크로 발견되며, 중요한 내용이 텍스트로 제공돼야 합니다. 구조화 데이터도 화면에 보이는 내용과 일치해야 합니다. <a href="https://developers.google.com/search/docs/appearance/ai-features" target="_blank" rel="noopener noreferrer">Google AI 검색 공식 가이드</a></p> <p>네이버 역시 콘텐츠 정보를 검색엔진이 이해할 수 있도록 정리하고, 페이지마다 주제를 정확히 설명하는 제목을 사용하며, 사이트맵과 표준 링크를 제공하도록 안내합니다. <a href="https://searchadvisor.naver.com/guide/seo-basic-intro" target="_blank" rel="noopener noreferrer">네이버 서치어드바이저</a></p> <div class="mk-qk-check"> <ul> <li>검색로봇이 접근할 수 있는가</li> <li>페이지마다 고유한 URL이 있는가</li> <li>서버가 전달하는 HTML에 핵심 본문이 포함되는가</li> <li>제목, 설명, H1이 페이지 내용과 일치하는가</li> <li>사이트맵과 내부 링크가 정상적으로 연결되는가</li> <li>중복 URL과 잘못된 리디렉션이 없는가</li> <li>회사명, 주소, 연락처와 서비스 정보가 일관적인가</li> <li>작성자, 발행일, 수정일과 근거 자료를 확인할 수 있는가</li> </ul> </div> <p>질문형 콘텐츠와 키워드는 이 기반 위에서 작동합니다. 문이 닫힌 홈페이지에 좋은 답을 써 두는 것만으로는 검색엔진과 AI가 그 답을 가져갈 수 없습니다.</p> </section> <section> <h2>질문과 키워드가 있으면 AI 인용을 보장할 수 있습니까?</h2> <p><strong>아닙니다. 질문형 콘텐츠와 키워드 설계는 문서의 의미를 분명하게 만드는 작업이지 AI 인용 보장 장치가 아닙니다.</strong></p> <p>AI는 질문에 따라 여러 문서를 비교하고 자사 홈페이지뿐 아니라 기관 문서·언론·전문 자료·외부 평가를 함께 참고할 수 있습니다. 같은 질문에도 시점과 모델에 따라 답변과 출처가 달라질 수 있습니다. 따라서 홈페이지를 한 번 고친 뒤 끝내지 말고 실제 질문을 정해 반복적으로 확인해야 합니다.</p> <p>포털 검색 노출 페이지와 유입 검색어, AI 답변의 회사명 언급, 출처 링크, 오정보, 경쟁사와 비교해 빠진 정보, 문의 전환까지 함께 측정해야 합니다.</p> </section> <section> <h2>매스티지는 어떻게 홈페이지에 반영합니까?</h2> <p><strong>매스티지는 AEO·GEO를 기존 홈페이지에 선언문 몇 줄 추가하는 작업으로 보지 않습니다.</strong> 제작을 시작할 때 고객에게 노출되고 싶은 질문만 받는 것이 아니라 실제 고객이 무엇을 묻는지 함께 정리합니다. 그 질문에 대응하는 키워드와 근거를 분류하고 사이트맵·메뉴명·화면설계·본문·CMS 구조에 연결합니다.</p> <p>기획자는 질문과 페이지의 관계를 정하고, 디자이너는 답을 쉽게 찾을 수 있도록 정보의 우선순위를 설계합니다. 퍼블리셔와 개발자는 검색로봇이 읽을 수 있는 HTML, 고유 URL, 내부 링크, 메타정보와 구조화 데이터를 구현합니다. 오픈 후에는 검색과 AI 답변에서 실제로 어떻게 설명되는지 확인하고 부족한 내용을 보완합니다.</p> <p>사람에게 보기 좋은 홈페이지와 AI가 이해하기 쉬운 홈페이지는 서로 반대가 아닙니다. 제대로 설계하면 명확한 정보 구조가 사용자 경험을 높이고, 좋은 UI/UX가 중요한 답변을 더 쉽게 발견하게 합니다.</p> <div class="mk-qk-principle"> <b>MASSTIGE POINT OF VIEW</b> <p>중요한 것은 질문을 많이 만드는 일이 아니라, 우리 회사가 어떤 질문에 가장 정확하게 답할 수 있는지 정하고 그 답을 홈페이지 전체에 일관되게 구현하는 일입니다.</p> </div> </section> <section> <h2>결론: 질문과 키워드를 하나의 구조로 연결해야 합니다</h2> <p>AI와 포털 노출을 높이려면 질문형 콘텐츠를 넣는 것에서 멈추면 안 됩니다. <strong>고객의 질문, 명확한 키워드, 구체적인 답변, 검증 가능한 근거를 하나의 페이지 구조 안에서 연결해야 합니다.</strong> 그리고 그 구조가 사이트맵과 화면설계, HTML, 내부 링크와 측정 체계까지 이어져야 합니다.</p> </section> <div class="mk-qk-contact"> <h2>무엇이든 물어보세요!<br>매스티지가 해결해드립니다.</h2> <p><a href="tel:023350527">02-335-0527</a> · <a href="mailto:nice@masstige.biz">nice@masstige.biz</a></p> <p>서울특별시 강서구 마곡중앙8로 57, B동 219-222호</p> </div> </div></div> </div> </div> </div> </div> <div class="main-inquiry-btn wow fadeInUp main-inquiry-btn-2"> <a href="/insights/?bmain=list&" class="btn-2"> 리스트 </a> </div> </div> </section> </main> <!-- E : Main --> <footer id="footer" class="section footer wow fadeInUp"> <div class="footer-bg"> <div class="flex-bx"> <div class="left-bx"> <div class="top-bx"> <p class="common-text-22"> 매스티지와 <br class="d-none d-xl-block" /> 성공적인 협력을<br /> 시작해 보세요. </p> <p class="tel-txt common-text-40 font-weight-bold"><a href="tel:023350527">02-335-0527</a></p> </div> <div class="bottom-bx"> <p class="common-text-24"> MASSTIGE® is a global creative agency driven by <br class="d-none d-sm-block" /> innovation, design, and technology. </p> <p id="footer-address" class="common-text-18 mt-5" itemprop="address" itemscope itemtype="https://schema.org/PostalAddress">주소:  <span itemprop="streetAddress">서울시 강서구 마곡중앙8로7길 57 마곡 아이파크 디어반 B동 219호-222호</span></p> <ul class="sns-link"> <li> <a href="https://www.facebook.com/freewebclub" target="_blank" title="새창열림"> <img src="../assets/images/icon/facebook-icon.svg" alt="페이스북" width="40" height="40" loading="lazy"/> </a> </li> <li> <a href="https://blog.naver.com/freewebclub2001" target="_blank" title="새창열림"> <img src="../assets/images/icon/blog-icon.svg" alt="네이버블로그" width="40" height="40" loading="lazy"/> </a> </li> <li> <a href="https://www.instagram.com/masstige2011/" target="_blank" title="새창열림"> <img src="../assets/images/icon/instagram-icon.svg" alt="인스타그램" width="40" height="40" loading="lazy"/> </a> </li> <li class="download-bx"> <a href="../assets/images/download/masstige_2026.pdf" download>회사소개서 다운로드</a> </li> </ul> </div> </div> <div class="right-bx"> <div class="inquiry-form"> <form id="signformfooter" name="signformfooter" method="POST" enctype="multipart/form-data" onsubmit="return CheckSignformfooter();"> <input type="hidden" name="check_key" id="check_key_footer" value="1789796064_33676"> <input type="hidden" name="index_key" id="index_key_footer" readonly> <input type="hidden" name="index_type" id="index_type_footer" readonly> <input type="hidden" name="index_sort" id="index_sort_footer" readonly> <div class="inquiry-bx"> <div class="inquiry-item"> <div class="input-bx"> <label class="tit" for="ft-utitle">회사명</label> <input type="text" name="title" maxlength="20" placeholder="회사명을 입력해주세요." id="ft-utitle" required aria-required="true" autocomplete="organization"/> </div> <div class="input-bx"> <label class="tit" for="ft-uname">담당자</label> <input type="text" name="uname" maxlength="20" class="w-100" placeholder="담당자를 입력해주세요." id="ft-uname" required aria-required="true" autocomplete="name"/> </div> </div> <div class="inquiry-item"> <div class="input-bx"> <label class="tit" for="ft-uemail">이메일</label> <input type="text" name="uemail" maxlength="30" class=" w-100" id="ft-uemail" placeholder="이메일 주소를 입력해주세요." required aria-required="true" autocomplete="email" /> </div> <div class="input-bx"> <label class="tit" for="ft-utel">연락처</label> <input type="text" name="utel" maxlength="20" class="w-100 AutoHyphen" placeholder="연락처를 입력해주세요." id="ft-utel" required aria-required="true" autocomplete="tel"/> </div> </div> <div class="inquiry-item"> <div class="input-bx content-bx"> <label class="tit" for="ft-content">문의내용</label> <textarea name="content" id="ft-content" required aria-required="true" autocomplete="off"></textarea> </div> </div> <div class="inquiry-item"> <div class="fileupload custom-fileupload wow fadeInUp"> <label class="file-label"> <input type="file" id="file1_name_footer" class="real-file" onchange="file_proc('file1_name_footer','1',50);" autocomplete="off"/> <span class="file-btn">파일 선택</span> <span class="file-name">최대 50MB까지 업로드가 가능합니다.</span> </label> </div> </div> </div> <div class="yark-bx"> <div class="chk-bx"> <input type="checkbox" title="개인정보 수집 및 이용에 동의합니다." value="Y" id="yarkfooter" /> <label for="yarkfooter">개인정보수집 및 이용에 동의합니다.</label> </div> <a href="../pop/privary-popup.html" class="agree-popup popup-link"><span>전문보기</span></a> </div> <div class="main-inquiry-btn wow fadeInUp"> <button type="submit" class="apply-btn"> 문의하기 <div class="circle-bx black"> <span></span> </div> </button> </div> </form> </div> <address class="site-info" itemscope itemtype="https://schema.org/Organization" itemref="footer-address"> <meta itemprop="name" content="주식회사 매스티지" /> <ul> <li class="common-text-16"> <span class="tit">상호: </span> <span class="desc" itemprop="legalName">주식회사 매스티지</span> </li> <li class="common-text-16"> <span class="tit">대표자명: </span> <span class="desc" itemprop="founder" itemscope itemtype="https://schema.org/Person"> <span itemprop="name">강천용</span> </span> </li> <li class="common-text-16"> <span class="tit">사업자등록번호:</span> <span class="desc" itemprop="taxID">137-86-14528</span> </li> </ul> <ul> <li class="common-text-16"> <span class="tit">대표전화: </span> <span class="desc" itemprop="telephone"><a href="tel:02-335-0527">02-335-0527</a></span> </li> <li class="common-text-16"> <span class="tit">이메일: </span> <span class="desc" itemprop="email"><a href="mailto:nice@masstige.biz">nice@masstige.biz</a></span> </li> </ul> <p class="copyright common-text-16 mgt-10">ⓒ 2004–2026 MASSTIGE</p> </address> </div> </div> <!-- S : AI·검색엔진 수집 현황 --> <div class="aibot_bar" id="aibotBar" data-view="crawl"> <div class="aibot_row"> <p class="aibot_title"><span class="aibot_live" aria-hidden="true"></span>AI·검색엔진 실시간·수집</p> <span class="aibot_sep" aria-hidden="true"></span> <p class="aibot_count">전체 누적 <b data-crawl="12,839" data-realtime="3,521">12,839</b> </p> <p class="aibot_count">현재 페이지 <b data-crawl="0" data-realtime="0">0</b> </p> <span class="aibot_sep" aria-hidden="true"></span> <ul class="aibot_engine_list"> <li class="aibot_engine aibot_engine--google"> <span class="aibot_dot" aria-hidden="true"></span> <span class="aibot_engine_name">Google-Gemini</span> <b data-crawl="0" data-realtime="0">0</b> </li> <li class="aibot_engine aibot_engine--naver"> <span class="aibot_dot" aria-hidden="true"></span> <span class="aibot_engine_name">Naver</span> <b data-crawl="0" data-realtime="0">0</b> </li> <li class="aibot_engine aibot_engine--chatgpt"> <span class="aibot_dot" aria-hidden="true"></span> <span class="aibot_engine_name">ChatGPT</span> <b data-crawl="0" data-realtime="0">0</b> </li> <li class="aibot_engine aibot_engine--perplexity"> <span class="aibot_dot" aria-hidden="true"></span> <span class="aibot_engine_name">Perplexity</span> <b data-crawl="0" data-realtime="0">0</b> </li> <li class="aibot_engine aibot_engine--claude"> <span class="aibot_dot" aria-hidden="true"></span> <span class="aibot_engine_name">Claude</span> <b data-crawl="0" data-realtime="0">0</b> </li> </ul> <p class="aibot_meta">집계 2026-08-12~</p> <!--button type="button" class="aibot_toggle" aria-label="수집 구분 전환"> <span class="aibot_toggle_text">정기</span> <i aria-hidden="true">▼</i> </button--> </div> </div> <!-- E : AI·검색엔진 수집 현황 --> </div> </footer> <style> /* AI·검색엔진 수집 현황 배너 푸터 카드 바깥은 배경색이 지정되어 있지 않으므로 배너가 자체 배경을 갖습니다. 오른쪽은 AI 상담사·TOP 버튼이 떠 있어 여백을 둡니다. */ .aibot_bar { margin-top: 24px; padding: 14px 20px; border: 1px solid rgba(125, 103, 255, 0.22); border-radius: 10px; background: #f5f3ff; font-size: 14px; line-height: 1.5; color: #6a6786; } @media (min-width: 768px) { .aibot_bar { padding-right: 170px; } } .aibot_row { display: flex; align-items: center; flex-wrap: nowrap; gap: 8px 12px; white-space: nowrap; } .aibot_title { display: flex; align-items: center; gap: 8px; font-weight: 600; color: #4228b3; } .aibot_live { width: 7px; height: 7px; border-radius: 50%; background: #00d47e; box-shadow: 0 0 0 0 rgba(0, 212, 126, 0.6); animation: aibot_pulse 2s infinite; } @keyframes aibot_pulse { 70% { box-shadow: 0 0 0 7px rgba(0, 212, 126, 0); } 100% { box-shadow: 0 0 0 0 rgba(0, 212, 126, 0); } } .aibot_sep { width: 1px; height: 12px; background: rgba(125, 103, 255, 0.3); } .aibot_count b, .aibot_engine b { margin-left: 6px; font-weight: 700; color: #4228b3; } .aibot_toggle { display: inline-flex; align-items: center; gap: 6px; margin-left: auto; padding: 4px 10px; border: 1px solid rgba(125, 103, 255, 0.35); border-radius: 6px; background: #fff; color: #4228b3; font-size: 13px; cursor: pointer; } .aibot_toggle:hover { border-color: #7d67ff; background: #7d67ff; color: #fff; } .aibot_toggle i { font-size: 10px; font-style: normal; } .aibot_label { font-size: 13px; color: rgba(66, 40, 179, 0.5); } .aibot_engine_list { display: flex; align-items: center; flex-wrap: nowrap; gap: 6px 12px; margin: 0; padding: 0; list-style: none; } .aibot_engine { display: flex; align-items: center; gap: 6px; } .aibot_dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; } .aibot_engine--google { color: #4285f4; } .aibot_engine--naver { color: #03c75a; } .aibot_engine--chatgpt { color: #10a37f; } .aibot_engine--perplexity { color: #20b8cd; } .aibot_engine--claude { color: #d97757; } .aibot_engine_name { color: #55527a; } .aibot_meta { margin-left: auto; flex-shrink: 0; font-size: 13px; color: rgba(66, 40, 179, 0.45); } .aibot_meta_sep { margin: 0 8px; } @media (max-width: 1199px) { .aibot_bar { overflow-x: auto; -webkit-overflow-scrolling: touch; } .aibot_toggle, .aibot_meta { margin-left: 0; } } @media (max-width: 767px) { .aibot_bar { margin-top: 24px; padding: 12px 14px; font-size: 13px; } } </style> <script> (function () { var bar = document.getElementById('aibotBar'); if (!bar) return; var btn = bar.querySelector('.aibot_toggle'); var btnText = bar.querySelector('.aibot_toggle_text'); var labels = { crawl: '정기', realtime: '실시간' }; btn.addEventListener('click', function () { var next = bar.getAttribute('data-view') === 'crawl' ? 'realtime' : 'crawl'; bar.setAttribute('data-view', next); btnText.textContent = labels[next]; var values = bar.querySelectorAll('b[data-' + next + ']'); for (var i = 0; i < values.length; i++) { values[i].textContent = values[i].getAttribute('data-' + next); } }); })(); </script> <div class="sub-link-bx"> <a href="../inquiry/inquiry.html" class="common-text-16 font-weight-bold color-1"> 견적<br>문의 </a> </div> <div class="topBtn"> <button type="button">TOP</button> </div> <!-- footer.html 하단 쯤에 추가 --> <div class="ai_chat_wrap"> <button type="button" class="btn_ai_chat_open" aria-label="AI 상담사 열기"> <!-- <span class="btn_ai_chat_text">AI 상담사</span> <span class="btn_ai_chat_icon"> <svg xmlns="http://www.w3.org/2000/svg" width="27" height="26" viewBox="0 0 27 26" fill="none"> <path fill-rule="evenodd" clip-rule="evenodd" d="M12.6523 3.03306C12.1504 2.75194 11.8088 2.22625 11.8088 1.625C11.8088 0.728 12.5637 0 13.4958 0C14.4278 0 15.1828 0.728 15.1828 1.625C15.1828 2.22544 14.8454 2.75031 14.3393 3.03184L14.3435 4.06737C15.6678 4.08281 16.9456 4.13481 18.2151 4.21728C18.2151 4.21769 18.2151 4.21769 18.2193 4.21769C21.6734 4.4525 24.4147 7.02163 24.828 10.2574C25.3172 10.3866 25.7727 10.6368 26.1354 10.9891C26.6921 11.5225 27 12.2456 27 13C27 13.7544 26.6921 14.4775 26.1354 15.0109C25.7685 15.3648 25.313 15.6158 24.8196 15.7446C24.5117 18.1772 22.8838 20.2329 20.6275 21.2018C20.8636 21.3614 21.0871 21.5414 21.2938 21.7401C22.2427 22.6541 22.7741 23.8948 22.7741 25.1875C22.7741 25.6364 22.3988 26 21.9306 26H5.06092C4.59278 26 4.21743 25.6364 4.21743 25.1875C4.21743 23.8948 4.74883 22.6541 5.69775 21.7401C5.90441 21.5438 6.12369 21.3659 6.35565 21.2079C4.0951 20.2361 2.46719 18.1764 2.15932 15.7397C1.67432 15.6097 1.22729 15.3603 0.864594 15.0109C0.31211 14.4775 0 13.7544 0 13C0 12.2456 0.31211 11.5225 0.864594 10.9891C1.23151 10.6372 1.68277 10.3874 2.17199 10.2578C2.58108 7.02609 5.32242 4.46063 8.77228 4.22581C10.0459 4.13644 11.328 4.08322 12.6565 4.06737L12.6523 3.03306ZM20.9817 24.375H6.00984C6.16167 23.8176 6.46109 23.3033 6.89127 22.8893C7.52388 22.28 8.38425 21.9375 9.27835 21.9375H17.7132C18.6073 21.9375 19.4677 22.28 20.1003 22.8893C20.5305 23.3033 20.8299 23.8176 20.9817 24.375ZM18.4302 5.87072L18.0084 7.49734C17.7258 8.58244 16.7137 9.34375 15.5539 9.34375C14.3646 9.34375 12.627 9.34375 11.4377 9.34375C10.2779 9.34375 9.26572 8.58244 8.98315 7.49734L8.56563 5.87844C5.85804 6.21969 3.80413 8.44594 3.80413 11.1073V11.1122C3.7957 12.3492 3.79569 13.6634 3.79569 14.9C3.79569 17.6743 6.02248 19.9757 8.89877 20.1687C10.396 20.2629 11.9058 20.3129 13.4958 20.3125C15.0857 20.3121 16.5956 20.2621 18.0928 20.1597C20.9606 19.9672 23.1874 17.6694 23.1874 14.8992C23.1874 14.8972 23.1874 14.8956 23.1874 14.8939C23.1959 13.6577 23.1959 12.3435 23.1959 11.1069C23.1959 8.44147 21.1377 6.21238 18.4302 5.87072ZM12.6523 17.875H14.3393C14.8032 17.875 15.1828 17.511 15.1828 17.0625C15.1828 16.614 14.8032 16.25 14.3393 16.25H12.6523C12.1884 16.25 11.8088 16.614 11.8088 17.0625C11.8088 17.511 12.1884 17.875 12.6523 17.875ZM8.8566 12.1875V13.8125C8.8566 14.261 9.23617 14.625 9.70009 14.625C10.164 14.625 10.5436 14.261 10.5436 13.8125V12.1875C10.5436 11.739 10.164 11.375 9.70009 11.375C9.23617 11.375 8.8566 11.739 8.8566 12.1875ZM16.448 12.1875V13.8125C16.448 14.261 16.8275 14.625 17.2915 14.625C17.7554 14.625 18.135 14.261 18.135 13.8125V12.1875C18.135 11.739 17.7554 11.375 17.2915 11.375C16.8275 11.375 16.448 11.739 16.448 12.1875ZM24.8828 12.0835C24.8828 12.6925 24.8828 13.31 24.8786 13.9193C24.8997 13.9007 24.925 13.8816 24.9419 13.8617C25.1823 13.6333 25.313 13.3234 25.313 13C25.313 12.6766 25.1823 12.3667 24.9419 12.1383C24.925 12.1193 24.9039 12.101 24.8828 12.0835ZM2.11294 12.0888C2.09185 12.1046 2.07498 12.1213 2.05811 12.1383C1.82193 12.3667 1.68697 12.6766 1.68697 13C1.68697 13.3234 1.82193 13.6333 2.05811 13.8617C2.07498 13.8779 2.09185 13.8933 2.10872 13.9084C2.10872 13.3047 2.10872 12.6929 2.11294 12.0888ZM16.7179 5.76184C15.6678 5.71309 14.6007 5.6875 13.4958 5.6875C12.3908 5.6875 11.3238 5.7135 10.2737 5.76469L10.6195 7.10328C10.7123 7.46484 11.0497 7.71875 11.4377 7.71875H15.5539C15.9419 7.71875 16.2793 7.46484 16.372 7.10328L16.7179 5.76184Z" fill="#7D67FF" /> </svg> </span> --> <video id="alphaVideo" autoplay muted loop playsinline preload="none"></video> </button> <div class="ai_chat_dim" aria-hidden="true"></div> <div class="ai_chat_popup" aria-hidden="true"> <aside class="ai_chat_aside"> <div class="ai_chat_aside_inner"> <div class="ai_chat_brand_block"> <div class="ai_chat_mascot"> <img src="../assets/images/icon/ai_logo.webp" alt="로고" width="80" height="80" loading="lazy"/> </div> <p class="ai_chat_aside_title">Masstige AI</p> <p class="ai_chat_aside_caption">Your Premium Assistant</p> </div> <p class="ai_chat_welcome">안녕하세요!<br /> 매스티지 AI 컨시어지입니다.</p> <div class="ai_chat_suggest"> <button type="button" class="ai_chat_suggest_btn">매스티지는 어떤회사야?</button> <button type="button" class="ai_chat_suggest_btn">매스티지의 포트폴리오가 궁금해.</button> <button type="button" class="ai_chat_suggest_btn">홈페이지제작 단가가 어떻게 될까?</button> </div> </div> </aside> <div class="ai_chat_main"> <header class="ai_chat_topbar"> <div class="ai_chat_topbar_title"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none"> <path d="M0 20V2C0 1.45 0.195833 0.979167 0.5875 0.5875C0.979167 0.195833 1.45 0 2 0H18C18.55 0 19.0208 0.195833 19.4125 0.5875C19.8042 0.979167 20 1.45 20 2V14C20 14.55 19.8042 15.0208 19.4125 15.4125C19.0208 15.8042 18.55 16 18 16H4L0 20ZM3.15 14H18V2H2V15.125L3.15 14ZM2 14V2V14Z" fill="#4228B3" /> </svg> <span>무엇이든지 물어보세요! 매스티지 AI입니다.</span> </div> <button type="button" class="popup_btn_close" aria-label="채팅 닫기"> <i class="xi-close-thin"></i> </button> </header> <div class="ai_chat_scroll"> <div class="chat_message_list"> <div class="chat_message chat_message--bot"> <div class="chat_message_avatar chat_message_avatar--bot" aria-hidden="true"> <img src="../assets/images/icon/chatbot_icon.webp" alt="챗봇" width="19" height="16" loading="lazy"/> </div> <div class="chat_message_block"> <div class="chat_message_bubble"> 안녕하세요! 매스티지 AI 컨시어지입니다. 귀사의 비즈니스 성장을 위한 디지털 전략과 홈페이지 제작에 대해 무엇이든 물어보세요. </div> <time class="chat_message_time" datetime=""></time> </div> </div> </div> </div> <div class="ai_chat_bottom"> <div class="chat_cta_grid"> <div class="chat_cta_card"> <span class="chat_cta_icon" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="20" viewBox="0 0 16 20" fill="none"> <path d="M7 17H9V16H10C10.2833 16 10.5208 15.9042 10.7125 15.7125C10.9042 15.5208 11 15.2833 11 15V12C11 11.7167 10.9042 11.4792 10.7125 11.2875C10.5208 11.0958 10.2833 11 10 11H7V10H11V8H9V7H7V8H6C5.71667 8 5.47917 8.09583 5.2875 8.2875C5.09583 8.47917 5 8.71667 5 9V12C5 12.2833 5.09583 12.5208 5.2875 12.7125C5.47917 12.9042 5.71667 13 6 13H9V14H5V16H7V17ZM2 20C1.45 20 0.979167 19.8042 0.5875 19.4125C0.195833 19.0208 0 18.55 0 18V2C0 1.45 0.195833 0.979167 0.5875 0.5875C0.979167 0.195833 1.45 0 2 0H10L16 6V18C16 18.55 15.8042 19.0208 15.4125 19.4125C15.0208 19.8042 14.55 20 14 20H2ZM9 6V2H2V18H14V6H9ZM2 2V6V2V6V18V2Z" fill="#4228B3" /> </svg> </span> <p class="chat_cta_label">홈페이지 제작 견적 문의</p> <button type="button" class="chat_cta_action" data-page="contact">상담 시작</button> </div> <div class="chat_cta_card"> <span class="chat_cta_icon" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="12" viewBox="0 0 20 12" fill="none"> <path d="M1.4 12L0 10.6L7.4 3.15L11.4 7.15L16.6 2H14V0H20V6H18V3.4L11.4 10L7.4 6L1.4 12Z" fill="#4228B3" /> </svg> </span> <p class="chat_cta_label">SEO, GEO, AEO 상담</p> <button type="button" class="chat_cta_action" data-page="">신청하기</button> </div> <div class="chat_cta_card"> <span class="chat_cta_icon" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none"> <path d="M2 20C1.45 20 0.979167 19.8042 0.5875 19.4125C0.195833 19.0208 0 18.55 0 18V8C0 7.45 0.195833 6.97917 0.5875 6.5875C0.979167 6.19583 1.45 6 2 6H18C18.55 6 19.0208 6.19583 19.4125 6.5875C19.8042 6.97917 20 7.45 20 8V18C20 18.55 19.8042 19.0208 19.4125 19.4125C19.0208 19.8042 18.55 20 18 20H2ZM2 18H18V8H2V18ZM8 17L14 13L8 9V17ZM2 5V3H18V5H2ZM5 2V0H15V2H5ZM2 18V8V18Z" fill="#4228B3" /> </svg> </span> <p class="chat_cta_label">디자인 구독서비스</p> <button type="button" class="chat_cta_action" data-page="subscription">보러가기</button> </div> </div> <div class="chat_composer"> <div class="chat_composer_field"> <button type="button" class="chat_composer_plus" aria-label="첨부"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none"> <path d="M9 15H11V11H15V9H11V5H9V9H5V11H9V15ZM10 20C8.61667 20 7.31667 19.7375 6.1 19.2125C4.88333 18.6875 3.825 17.975 2.925 17.075C2.025 16.175 1.3125 15.1167 0.7875 13.9C0.2625 12.6833 0 11.3833 0 10C0 8.61667 0.2625 7.31667 0.7875 6.1C1.3125 4.88333 2.025 3.825 2.925 2.925C3.825 2.025 4.88333 1.3125 6.1 0.7875C7.31667 0.2625 8.61667 0 10 0C11.3833 0 12.6833 0.2625 13.9 0.7875C15.1167 1.3125 16.175 2.025 17.075 2.925C17.975 3.825 18.6875 4.88333 19.2125 6.1C19.7375 7.31667 20 8.61667 20 10C20 11.3833 19.7375 12.6833 19.2125 13.9C18.6875 15.1167 17.975 16.175 17.075 17.075C16.175 17.975 15.1167 18.6875 13.9 19.2125C12.6833 19.7375 11.3833 20 10 20ZM10 18C12.2333 18 14.125 17.225 15.675 15.675C17.225 14.125 18 12.2333 18 10C18 7.76667 17.225 5.875 15.675 4.325C14.125 2.775 12.2333 2 10 2C7.76667 2 5.875 2.775 4.325 4.325C2.775 5.875 2 7.76667 2 10C2 12.2333 2.775 14.125 4.325 15.675C5.875 17.225 7.76667 18 10 18Z" fill="#787585" /> </svg> </button> <input type="text" class="chat_composer_input" placeholder="궁금한 점을 물어보세요." aria-label="AI 상담사에게 보낼 질문" /> <button type="button" class="chat_composer_mic" aria-label="음성입력"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="19" viewBox="0 0 14 19" fill="none"> <path d="M7 12C6.16667 12 5.45833 11.7083 4.875 11.125C4.29167 10.5417 4 9.83333 4 9V3C4 2.16667 4.29167 1.45833 4.875 0.875C5.45833 0.291667 6.16667 0 7 0C7.83333 0 8.54167 0.291667 9.125 0.875C9.70833 1.45833 10 2.16667 10 3V9C10 9.83333 9.70833 10.5417 9.125 11.125C8.54167 11.7083 7.83333 12 7 12ZM6 19V15.925C4.26667 15.6917 2.83333 14.9167 1.7 13.6C0.566667 12.2833 0 10.75 0 9H2C2 10.3833 2.4875 11.5625 3.4625 12.5375C4.4375 13.5125 5.61667 14 7 14C8.38333 14 9.5625 13.5125 10.5375 12.5375C11.5125 11.5625 12 10.3833 12 9H14C14 10.75 13.4333 12.2833 12.3 13.6C11.1667 14.9167 9.73333 15.6917 8 15.925V19H6ZM7 10C7.28333 10 7.52083 9.90417 7.7125 9.7125C7.90417 9.52083 8 9.28333 8 9V3C8 2.71667 7.90417 2.47917 7.7125 2.2875C7.52083 2.09583 7.28333 2 7 2C6.71667 2 6.47917 2.09583 6.2875 2.2875C6.09583 2.47917 6 2.71667 6 3V9C6 9.28333 6.09583 9.52083 6.2875 9.7125C6.47917 9.90417 6.71667 10 7 10Z" fill="#787585" /> </svg> </button> <button type="button" class="chat_composer_send" aria-label="보내기"> <svg xmlns="http://www.w3.org/2000/svg" width="19" height="16" viewBox="0 0 19 16" fill="none"> <path d="M0 16V0L19 8L0 16ZM2 13L13.85 8L2 3V6.5L8 8L2 9.5V13ZM2 13V8V3V6.5V9.5V13Z" fill="white" /> </svg> </button> </div> </p> </div> </div> </div> </div> </div> <style> /* AI 챗봇 페이지 링크 스타일 */ .ai_chat_page_links { margin-top: 12px; display: flex; flex-direction: column; gap: 8px; } .ai_chat_page_link { display: inline-flex; align-items: center; gap: 8px; padding: 10px 16px; background-color: #7D67FF; color: #ffffff; text-decoration: none; border-radius: 8px; font-size: 14px; font-weight: 500; transition: all 0.3s ease; cursor: pointer; } .ai_chat_page_link:hover { background-color: #6a56e6; transform: translateY(-2px); box-shadow: 0 4px 12px rgba(125, 103, 255, 0.3); } .ai_chat_page_link_icon { font-size: 16px; font-weight: bold; } .ai_chat_page_link_text { flex: 1; } .ai_chat_message_bubble { word-wrap: break-word; word-break: break-word; } /* AI 챗봇 메시지 리스트 스크롤 스타일 */ .ai_chat_message_list { overflow-y: auto !important; overflow-x: hidden !important; -webkit-overflow-scrolling: touch; scroll-behavior: smooth; } /* 스크롤바 스타일 (선택사항) */ .ai_chat_message_list::-webkit-scrollbar { width: 6px; } .ai_chat_message_list::-webkit-scrollbar-track { background: #f1f1f1; border-radius: 10px; } .ai_chat_message_list::-webkit-scrollbar-thumb { background: #888; border-radius: 10px; } .ai_chat_message_list::-webkit-scrollbar-thumb:hover { background: #555; } </style> <script> function updateFileName(input) { const fileName = input.files.length > 0 ? input.files[0].name : "최대 50MB까지 업로드가 가능합니다."; input.nextElementSibling.nextElementSibling.textContent = fileName; } </script> <script> $(document).ready(function () { $(".topBtn").click(function () { $("html, body").animate( { scrollTop: 0, }, 500 ); }); $(window).scroll(function () { var curr = $(this).scrollTop(); if (curr > 500) { $(".main-body .sub-link-bx, .sub-body .sub-link-bx").addClass("show"); $(".main-body .topBtn, .sub-body .topBtn").addClass("show"); } else { $(".main-body .sub-link-bx, .sub-body .sub-link-bx").removeClass("show"); $(".main-body .topBtn, .sub-body .topBtn").removeClass("show"); } }); }); document.addEventListener("DOMContentLoaded", function () { var wrap = document.querySelector(".ai_chat_wrap"); if (!wrap) return; var btnOpen = wrap.querySelector(".btn_ai_chat_open"); var popup = wrap.querySelector(".ai_chat_popup"); var btnClose = wrap.querySelector(".popup_btn_close"); var chatScroll = wrap.querySelector(".ai_chat_scroll"); function scrollChatToBottom() { if (!chatScroll) return; chatScroll.scrollTop = chatScroll.scrollHeight; } function openPopup() { popup.style.display = "flex"; popup.setAttribute("aria-hidden", "false"); requestAnimationFrame(function () { document.body.classList.add("body-fixed") popup.classList.add("is_open"); wrap.classList.add("is_chat_open"); scrollChatToBottom(); requestAnimationFrame(scrollChatToBottom) // 팝업 열림 상태 저장 localStorage.setItem(STORAGE_OPEN_KEY, 'true'); // 팝업이 열린 후 스크롤을 마지막으로 이동 (여러 번 시도) setTimeout(function() { scrollToBottom(); setTimeout(function() { scrollToBottom(); // 한 번 더 (이미지 로드 등 대비) setTimeout(function() { scrollToBottom(); }, 200); }, 200); }, 300); }); } function closePopup() { if (!popup.classList.contains("is_open")) return; popup.classList.remove("is_open"); function hide(e) { if (e.target !== popup || e.propertyName !== "opacity") return; popup.style.display = "none"; popup.setAttribute("aria-hidden", "true"); document.body.classList.remove("body-fixed"); wrap.classList.remove("is_chat_open"); popup.removeEventListener("transitionend", hide); // 팝업 닫힘 상태 저장 localStorage.setItem(STORAGE_OPEN_KEY, 'false'); } popup.addEventListener("transitionend", hide); } btnOpen.addEventListener("click", function () { if (popup.classList.contains("is_open")) { closePopup(); } else { openPopup(); } }); if (btnClose) { btnClose.addEventListener("click", closePopup); } // Escape 키로 닫히는 기능 제거 (닫기 버튼만 작동) // document.addEventListener("keydown", function (e) { // if (e.key === "Escape") closePopup(); // }); // AI 챗봇 기능 구현 var messageList = wrap.querySelector(".chat_message_list"); var inputText = wrap.querySelector(".chat_composer_input"); var btnSend = wrap.querySelector(".chat_composer_send"); var suggestBtns = wrap.querySelectorAll(".ai_chat_suggest_btn"); var ctaActionBtns = wrap.querySelectorAll(".chat_cta_action"); var conversationHistory = []; // localStorage 키 var STORAGE_KEY = 'ai_chat_conversation'; var STORAGE_HISTORY_KEY = 'ai_chat_history'; var STORAGE_OPEN_KEY = 'ai_chat_is_open'; var STORAGE_SESSION_KEY = 'ai_chat_session_id'; // 세션 ID 가져오기 또는 생성 function getSessionId() { var sessionId = localStorage.getItem(STORAGE_SESSION_KEY); if (!sessionId) { // 고유한 세션 ID 생성 sessionId = 'chat_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9); localStorage.setItem(STORAGE_SESSION_KEY, sessionId); } return sessionId; } // 대화 내용 저장 function saveConversation() { try { var messagesHtml = messageList.innerHTML; localStorage.setItem(STORAGE_KEY, messagesHtml); localStorage.setItem(STORAGE_HISTORY_KEY, JSON.stringify(conversationHistory)); } catch (e) { console.error('대화 내용 저장 실패:', e); } } // 대화 내용 복원 function restoreConversation() { try { var savedMessages = localStorage.getItem(STORAGE_KEY); var savedHistory = localStorage.getItem(STORAGE_HISTORY_KEY); var wasOpen = localStorage.getItem(STORAGE_OPEN_KEY) === 'true'; if (savedMessages && savedHistory) { // 기본 환영 메시지 제거 (복원할 메시지가 있는 경우) var defaultMessage = messageList.querySelector('.chat_message.chat_message--bot'); if (defaultMessage && savedMessages.indexOf('안녕하세요! 매스티지 AI') === -1) { // 저장된 메시지에 기본 메시지가 없으면 제거 messageList.innerHTML = savedMessages; } else if (savedMessages) { messageList.innerHTML = savedMessages; } conversationHistory = JSON.parse(savedHistory) || []; // 팝업이 열려있었으면 자동으로 열기 if (wasOpen) { openPopup(); // 팝업이 열린 후 스크롤을 마지막으로 이동 (여러 번 시도) setTimeout(function() { scrollToBottom(); setTimeout(function() { scrollToBottom(); }, 200); }, 300); } else { // 팝업이 닫혀있어도 스크롤 위치 조정 setTimeout(function() { scrollToBottom(); }, 100); } } } catch (e) { console.error('대화 내용 복원 실패:', e); } } // 페이지 이동 시 대화 내용 저장 및 이동 function navigateToPage(url) { saveConversation(); localStorage.setItem(STORAGE_OPEN_KEY, 'true'); // 팝업이 열려있음을 표시 if (url && url.length > 1) url = url.replace(/\/+$/, ''); // 맨 뒤 슬래시 제거 window.location.href = url; } // 페이지 맵핑 (맨 뒤 슬래시 없음) var pageMap = { 'portfolio': '/portfolio', 'about': '/about', 'contact': '/contact', 'ai': '/ai/resources', 'insights': '/insights', 'people': '/people', 'faq': '/faq', 'cs': '/faq', 'subscription': '/subscription' }; // 페이지 이름 맵핑 var pageNameMap = { 'portfolio': '포트폴리오', 'about': '회사소개', 'contact': '견적문의', 'ai': 'AI 스튜디오', 'insights': '뉴스', 'people': '팀 소개', 'faq': 'FAQ', 'cs': 'FAQ' }; // 페이지 이동 키워드 감지 function detectPageNavigation(message) { var lowerMessage = message.toLowerCase().trim(); // 이동 관련 키워드 패턴 var navigationPatterns = [ /(?:이동|가|가줘|가자|보여|보여줘|보기|열어|열어줘|열기|이동해|이동해줘|이동하|이동하자|이동할|이동하고|이동하려|이동하려고)/, ]; // 페이지 키워드 매핑 (다양한 표현 포함) var pageKeywords = { 'portfolio': ['포트폴리오', '포트폴리오페이지', '포트폴리오 페이지', '작업물', '프로젝트', '프로젝트목록'], 'about': ['회사소개', '회사소개페이지', '회사소개 페이지', '회사', '회사정보', '소개', '회사소개서', '연혁', '히스토리'], 'contact': ['견적문의', '견적', '문의', '문의하기', '견적문의페이지', '견적문의 페이지', '상담', '상담문의'], 'ai': ['ai', 'ai스튜디오', 'ai 스튜디오', 'ai페이지', 'ai 페이지', 'ai리소스', 'ai 리소스'], 'insights': ['뉴스', '뉴스페이지', '뉴스 페이지', '소식', '공지', '공지사항'], 'people': ['팀소개', '팀 소개', '팀', '팀페이지', '팀 페이지', '멤버', '인물'], 'faq': ['faq', '자주묻는질문', '자주 묻는 질문', '질문', '질문답변', 'qna', '문의사항', '고객문의'] }; // 이동 키워드가 있는지 확인 var hasNavigationKeyword = navigationPatterns.some(function(pattern) { return pattern.test(lowerMessage); }); if (!hasNavigationKeyword) { return null; } // 페이지 키워드 매칭 for (var pageKey in pageKeywords) { var keywords = pageKeywords[pageKey]; for (var i = 0; i < keywords.length; i++) { if (lowerMessage.indexOf(keywords[i].toLowerCase()) !== -1) { return pageKey; } } } return null; } // 메시지에서 페이지 링크 처리 function processMessageLinks(message) { // [PAGE:페이지명] 형식 찾기 var pageLinkRegex = /\[PAGE:(\w+)\]/g; var processedMessage = message; var pageLinks = []; var match; while ((match = pageLinkRegex.exec(message)) !== null) { var pageKey = match[1].toLowerCase(); if (pageMap[pageKey]) { var pageUrl = pageMap[pageKey].replace(/\/+$/, ''); pageLinks.push({ key: pageKey, url: pageUrl, name: pageNameMap[pageKey] || pageKey }); // 링크를 제거하고 텍스트만 남김 processedMessage = processedMessage.replace(match[0], ''); } } return { text: processedMessage.trim(), links: pageLinks }; } // 스크롤을 마지막으로 이동 (강제) function scrollToBottom() { var scrollEl = chatScroll || messageList; if (!scrollEl) return; function doScroll() { if (scrollEl) { scrollEl.scrollTop = scrollEl.scrollHeight; var lastMessage = messageList ? messageList.lastElementChild : scrollEl.lastElementChild; if (lastMessage) { lastMessage.scrollIntoView({ behavior: 'smooth', block: 'end' }); } } } doScroll(); requestAnimationFrame(function() { doScroll(); setTimeout(function() { if (scrollEl) { scrollEl.scrollTop = scrollEl.scrollHeight; } }, 100); }); } // 메시지 추가 함수 function addMessage(message, isFromUser) { var messageDiv = document.createElement("div"); var timeStr = '방금'; if (isFromUser) { messageDiv.className = "chat_message chat_message--user"; messageDiv.innerHTML = '<div class="chat_message_user_inner">' + '<div class="chat_message_block chat_message_block--user">' + '<div class="chat_message_bubble">' + escapeHtml(message) + '</div>' + '<time class="chat_message_time" datetime="">' + timeStr + '</time>' + '</div>' + '<div class="chat_message_avatar chat_message_avatar--user" aria-hidden="true">' + '<img src="../assets/images/icon/user_icon.webp" width="14" height="14" alt="유저" aria-hidden="true" />' + '</div>' + '</div>'; } else { // AI 메시지인 경우 페이지 링크 처리 var processed = processMessageLinks(message); var bubbleContent = escapeHtml(processed.text); // 페이지 링크 버튼 추가 if (processed.links.length > 0) { bubbleContent += '<div class="ai_chat_page_links">'; processed.links.forEach(function(link) { bubbleContent += '<a href="' + link.url + '" class="ai_chat_page_link" data-navigate="true">' + '<span class="ai_chat_page_link_icon">→</span>' + '<span class="ai_chat_page_link_text">' + link.name + ' 페이지로 이동</span>' + '</a>'; }); bubbleContent += '</div>'; } messageDiv.className = "chat_message chat_message--bot"; messageDiv.innerHTML = '<div class="chat_message_avatar chat_message_avatar--bot" aria-hidden="true">' + '<img src="../assets/images/icon/chatbot_icon.webp" width="19" height="16" alt="챗봇" aria-hidden="true" />' + '</div>' + '<div class="chat_message_block">' + '<div class="chat_message_bubble">' + bubbleContent + '</div>' + '<time class="chat_message_time" datetime="">' + timeStr + '</time>' + '</div>'; } messageList.appendChild(messageDiv); // 이미지 로드 완료를 기다린 후 스크롤 var images = messageDiv.querySelectorAll('img'); if (images.length > 0) { var loadedCount = 0; var totalImages = images.length; images.forEach(function(img) { if (img.complete) { loadedCount++; } else { img.onload = function() { loadedCount++; if (loadedCount === totalImages) { scrollToBottom(); } }; img.onerror = function() { loadedCount++; if (loadedCount === totalImages) { scrollToBottom(); } }; } }); if (loadedCount === totalImages) { scrollToBottom(); } } else { scrollToBottom(); } // 대화 히스토리에 추가 (원본 메시지 저장) conversationHistory.push({ role: isFromUser ? 'user' : 'assistant', content: message }); // 대화 내용 저장 saveConversation(); } // HTML 이스케이프 함수 function escapeHtml(text) { var div = document.createElement('div'); div.textContent = text; return div.innerHTML.replace(/\n/g, '<br>'); } // AI 응답 가져오기 function sendMessage(userMessage) { if (!userMessage.trim()) return; // 페이지 이동 요청 감지 var targetPage = detectPageNavigation(userMessage); if (targetPage && pageMap[targetPage]) { // 사용자 메시지 표시 addMessage(userMessage, true); if (inputText) inputText.value = ''; // AI 응답 메시지 표시 var pageName = pageNameMap[targetPage] || targetPage; addMessage(pageName + ' 페이지로 이동하겠습니다.', false); // 잠시 후 페이지 이동 setTimeout(function() { navigateToPage(pageMap[targetPage]); }, 500); return; } // 사용자 메시지 표시 addMessage(userMessage, true); inputText.value = ''; // 로딩 메시지 표시 var loadingDiv = document.createElement("div"); loadingDiv.className = "chat_message chat_message--bot"; loadingDiv.innerHTML = '<div class="chat_message_avatar chat_message_avatar--bot" aria-hidden="true">' + '<img src="../assets/images/icon/chatbot_icon.webp" width="19" height="16" alt="챗봇" aria-hidden="true" />' + '</div>' + '<div class="chat_message_block">' + '<div class="chat_message_bubble">답변을 생성하고 있습니다...</div>' + '</div>'; messageList.appendChild(loadingDiv); // 로딩 메시지 추가 후 즉시 스크롤 setTimeout(function() { scrollToBottom(); }, 50); // API 호출 fetch('../api/chat_ai.php', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ message: userMessage, history: conversationHistory, session_id: getSessionId() }) }) .then(response => response.json()) .then(data => { // 로딩 메시지 제거 if (loadingDiv.parentNode) { messageList.removeChild(loadingDiv); } if (data.success) { addMessage(data.message, false); // AI 응답에서도 페이지 이동 요청 감지 var responsePage = detectPageNavigation(data.message); if (responsePage && pageMap[responsePage]) { setTimeout(function() { navigateToPage(pageMap[responsePage]); }, 1000); } } else { addMessage('죄송합니다. 오류가 발생했습니다: ' + (data.error || '알 수 없는 오류'), false); } }) .catch(error => { // 로딩 메시지 제거 if (loadingDiv.parentNode) { messageList.removeChild(loadingDiv); } addMessage('죄송합니다. 네트워크 오류가 발생했습니다.', false); console.error('Error:', error); }); } // 전송 버튼 클릭 if (btnSend) { btnSend.addEventListener('click', function() { if (!inputText) return; var message = inputText.value.trim(); if (message) { sendMessage(message); } }); } // Enter 키 입력 if (inputText) { inputText.addEventListener('keypress', function(e) { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); var message = inputText.value.trim(); if (message) { sendMessage(message); } } }); } // 추천 질문 버튼 클릭 suggestBtns.forEach(function(btn) { btn.addEventListener('click', function() { var question = this.getAttribute('data-question') || this.textContent.trim(); var page = this.getAttribute('data-page'); if (page && pageMap[page]) { navigateToPage(pageMap[page]); return; } if (question) { // 팝업이 닫혀있으면 열기 if (!popup.classList.contains('is_open')) { openPopup(); } sendMessage(question); } }); }); // CTA 카드 버튼 클릭 var ctaPageMap = ['contact', '', 'subscription']; ctaActionBtns.forEach(function(btn, idx) { btn.addEventListener('click', function() { var page = this.getAttribute('data-page') || ctaPageMap[idx] || ''; //alert(page + ' ' + idx + ' ' + ctaPageMap[idx]); if (page && pageMap[page]) { navigateToPage(pageMap[page]); } else{ alert('준비중입니다.'); } }); }); // 페이지 링크 클릭 이벤트 (동적으로 생성된 링크) messageList.addEventListener('click', function(e) { var link = e.target.closest('.ai_chat_page_link'); if (link && link.getAttribute('data-navigate') === 'true') { e.preventDefault(); var url = link.getAttribute('href'); if (url) { navigateToPage(url); } } }); // MutationObserver를 사용하여 메시지 리스트 변경 시 자동 스크롤 if (typeof MutationObserver !== 'undefined' && messageList) { var observer = new MutationObserver(function(mutations) { // 변경이 있을 때만 스크롤 var hasChanges = mutations.some(function(mutation) { return mutation.addedNodes.length > 0 || mutation.removedNodes.length > 0; }); if (hasChanges) { // 약간의 딜레이를 주어 DOM이 완전히 업데이트된 후 스크롤 setTimeout(function() { scrollToBottom(); }, 50); } }); observer.observe(messageList, { childList: true, subtree: true, attributes: false, characterData: false }); } // 스크롤 가능한지 확인하고 스크롤 설정 function ensureScrollable() { var scrollEl = chatScroll || messageList; if (scrollEl) { var style = window.getComputedStyle(scrollEl); if (style.overflowY === 'visible' || style.overflowY === '') { scrollEl.style.overflowY = 'auto'; } } } // 초기화 시 스크롤 가능 확인 ensureScrollable(); // 페이지 로드 시 대화 내용 복원 restoreConversation(); }); </script> <script src="/lib/file/file.js"></script> <script> var check_key = "1789796064_33676"; var tablename = "tb_online"; function CheckSignformfooter(){ if (!$('#yarkfooter').is(':checked')) { alert("개인정보 보호정책에 동의 해 주세요."); return false; } $("#check_key_footer").val(check_key); var params = new FormData($('#signformfooter')[0]); params.set('tablename', tablename); params.set('formmode', 'inquirysave'); params.set('intype', '매스티지하단'); $.ajax({ type : 'POST' , processData: false , contentType: false , url : '/lib/board/board_ajax_proc.php' , dataType : 'JSON' , data : params , success : function(res){ if(res.code!='0'){ alert('견적문의가 성공적으로 접수되었습니다.\n담당자 배정 후 연락드리겠습니다.'); wptg_tagscript_vars.push( (function() { return { wp_hcuid:"", /*고객 이메일 등 Unique ID (ex. 이메일을 기준, 혹은 고객 아이디 / 고객 번호 등의 정보)를 암호화하여 대입. *주의 : 로그인 하지 않은 사용자는 어떠한 값도 대입하지 않습니다.*/ ti:"30744", /*광고주 코드 */ ty:"PurchaseComplete", /*트래킹태그 타입 */ device:"web", /*디바이스 종류 (web 또는 mobile)*/ items:[{i:"하단상담", /*전환 식별 코드 (한글 , English , 번호 , 공백 허용 )*/ t:$('#signformfooter input[name=uname]').val()+" 상담", /*전환명 (한글 , English , 번호 , 공백 허용 )*/ p:"1", /*전환가격 (전환 가격이 없을경우 1로 설정 )*/ q:"1" /*전환수량 (전환 수량이 고정적으로 1개 이하일 경우 1로 설정 )*/ }] }; })); location.reload(); }else{ alert(res.data); } } , beforeSend: function () { $('.loading-image').show(); } , complete: function () { $('.loading-image').fadeOut(300); } }); return false; } // 파일 선택 시 파일명 표시 $(document).ready(function(){ $('#file1_name_footer').on('change', function() { const filenameDisplay = $(this).closest('.file-label').find('.file-name'); if (this.files.length > 0) { filenameDisplay.text(this.files[0].name); } else { filenameDisplay.text('최대 50MB까지 업로드가 가능합니다.'); } }); }); </script> <script> (function () { const video = document.getElementById('alphaVideo'); const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent); if (isSafari) { video.innerHTML = ` <source src="../assets/videos/mac_video3.mp4" type="video/mp4"> `; document.documentElement.classList.add('is-safari'); } else { video.innerHTML = ` <source src="../assets/videos/window_video2.webm" type="video/webm"> `; } video.load(); })(); </script> <!-- WIDERPLANET SCRIPT START 2026.3.16 --> <div id="wp_tg_cts" style="display:none;"></div> <script type="text/javascript"> var wptg_tagscript_vars = wptg_tagscript_vars || []; wptg_tagscript_vars.push( (function() { return { wp_hcuid:"", /*고객 이메일 등 Unique ID (ex. 이메일을 기준, 혹은 고객 아이디 / 고객 번호 등의 정보)를 암호화하여 대입. *주의 : 로그인 하지 않은 사용자는 어떠한 값도 대입하지 않습니다.*/ ti:"30744", /*광고주 코드 */ ty:"Home", /*트래킹태그 타입 */ device:"web" /*디바이스 종류 (web 또는 mobile)*/ }; })); </script> <script type="text/javascript" async src="//cdn-aitg.widerplanet.com/js/wp_astg_4.0.js"></script> <!-- // WIDERPLANET SCRIPT END 2026.3.16 --> <script src="../assets/js/lib/popper.min.js"></script> <!-- <script src="../assets/js/lib/bootstrap.min.js"></script> --> <script src="../assets/js/lib/wow.min.js"></script> <script src="../assets/js/lib/aos.min.js"></script> <script src="../assets/js/lib/jquery.magnific-popup.min.js"></script> <script src="../assets/js/lib/easings.min.js" defer></script> <script src="../assets/js/lib/fullpage.min.js" defer></script> <script src="../assets/js/lib/swiper.min.js"></script> <script src="../assets/js/lib/jquery.scrollbar.min.js" defer></script> <script src="../assets/js/lib/jquery.mCustomScrollbar.min.js" defer></script> <!-- <script src="../assets/js/lib/jquery.rwdImageMaps.min.js"></script> 이미지맵 반응형 플러그인 --> <!-- for Board Template--> <script src="../assets/js/custom/clipboard.js" defer></script> <!-- masonry Library --> <script src="https://unpkg.com/masonry-layout@4/dist/masonry.pkgd.min.js" defer></script> <!-- Custom Library --> <script src="../assets/js/custom/nav_active-1.1.6.masstige.min.js" defer></script> <script src="../assets/js/custom/tab-1.1.0.masstige.js" defer></script> <script src="../assets/js/custom/resizingCheck-1.0.0.masstige.js" defer></script> <script src="../assets/js/custom/nav_drop-1.0.1.masstige.min.js" defer></script> <script src="../assets/js/custom/scroll_track-1.0.1.masstige.min.js" defer></script> <!-- COMMON --> <script src="../assets/js/lib/TweenMax.min.js"></script> <script src="../assets/js/lib/ScrollMagic.min.js"></script> <script src="../assets/js/lib/animation.gsap.min.js"></script> <script src="../assets/js/lib/split-type.min.js"></script> <script src="../assets/js/lib/gsap.min.js"></script> <script src="../assets/js/lib/CustomEase.min.js"></script> <script src="../assets/js/lib/ScrollTrigger.min.js"></script> <script src="../assets/js/lib/SmoothScroll.js"></script> <script src="../assets/js/lib/jquery.counterup.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/waypoints/4.0.1/jquery.waypoints.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.4/gsap.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.4/ScrollTrigger.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/smoothscroll/1.5.1/SmoothScroll.min.js"></script> <script src="../assets/js/common.js"></script> <script src="/js/setting.js"></script> <script src="../assets/js/sub.js"></script> <script> $(document).ready(function(){ }); </script> </body> </html>