본문으로 건너뛰기

Guide

이 컨트롤은 무엇인가요?

Guide는 화면 안내(온보딩) 컨트롤입니다. 화면에 이미 존재하는 다른 요소들(버튼, 입력창, 목록 등)을 순서대로 하이라이트하면서 "이게 뭐고 어떻게 쓰는지"를 설명해 주는 투어 기능을 만들 때 사용합니다.

syn_guide 태그 자체는 화면에 아무것도 그리지 않습니다(ContextMenu처럼 로드 후 display:none 처리됨). 대신 syn-optionsitems 배열에 "어떤 요소(selector)를 어떤 방식(helpType)으로 안내할지"를 정의해 두면, Guide가 내부적으로 아래 3가지 외부 라이브러리 중 하나를 골라 연결해 줍니다.

  • helpType: 'I'intro.js 기반 단계별 투어(스포트라이트 + 다음/이전 버튼)
  • helpType: 'T'tippy.js 기반 툴팁(마우스 올리면 뜨는 설명)
  • helpType: 'P'superplaceholder 기반 입력창 placeholder 타이핑 애니메이션
  • helpType: 'U' → 프로그램(화면) 도움말 링크/팝업 (별도 "도움말" 버튼 등에서 openUIHelp로 호출)

언제 사용하나요?

  • 신규 사용자에게 화면의 주요 버튼/입력창을 순서대로 소개하는 "처음 사용 가이드"가 필요할 때 (helpType: 'I')
  • 특정 항목에 마우스를 올렸을 때 짧은 설명을 보여주고 싶을 때 (helpType: 'T')
  • 검색창/입력창에 "이렇게 입력하세요" 같은 예시 문구를 타이핑 애니메이션으로 계속 보여주고 싶을 때 (helpType: 'P')
  • 화면 우측 상단 "도움말(?)" 버튼을 눌렀을 때 외부 매뉴얼 링크를 열거나, 팝업 창으로 도움말 본문을 보여주고 싶을 때 (helpType: 'U')

빠른 시작

<div id="divRangeButtonGroup">조회 기간 버튼 그룹</div>
<div id="divTransactionDetail">거래 상세 영역</div>

<syn_guide id="hlpDataSource" syn-options="{
items: [
{ helpType: 'I', selector: '#divRangeButtonGroup', subject: '조회 기간을 설정합니다.', sentence: '오늘/일주일/한달 단위로 조회 기간을 선택할 수 있습니다.', sortingNo: 1 },
{ helpType: 'I', selector: '#divTransactionDetail', subject: '거래 상세 내역입니다.', sentence: '선택한 기간의 거래 내역이 표시됩니다.', sortingNo: 2 }
]
}" syn-events="['complete', 'exit']"></syn_guide>

<input type="button" id="btnStartGuide" value="사용법 안내 시작" syn-events="['click']" />
'use strict';
let $samplePage = {
event: {
btnStartGuide_click() {
// 버튼을 눌러야 투어가 시작됩니다(페이지 로드시 자동 시작되지 않음).
syn.uicontrols.$guide.introStart('hlpDataSource');
},

hlpDataSource_complete() {
syn.$l.eventLog('hlpDataSource_complete', '투어를 끝까지 마쳤습니다.');
},

hlpDataSource_exit() {
syn.$l.eventLog('hlpDataSource_exit', '투어를 중간에 닫았습니다.');
}
}
}

핵심 포인트:

  • items의 각 항목은 "안내할 방식(helpType)"과 "안내 대상(selector)", "제목(subject)", "본문(sentence)"으로 구성됩니다.
  • selector가 가리키는 요소는 Guide보다 먼저(또는 같은 시점에) 화면에 존재해야 합니다. 존재하지 않으면 해당 단계는 조용히 건너뜁니다.
  • helpType: 'I' 투어는 자동 시작되지 않습니다. 반드시 syn.uicontrols.$guide.introStart(elID)를 버튼 클릭 등에서 직접 호출해야 합니다.
  • sortingNo로 intro 단계 순서를 정할 수 있습니다.
  • 페이지에 <script src="/js/syn.loader.js"></script> 한 줄만 있으면 intro.js, tippy.js, popper.js, superplaceholder와 Guide의 CSS/JS가 모두 자동으로 로드됩니다(추가 pageLoadFiles 설정이 필요 없습니다).

예제 실행하기

example/ 폴더의 각 HTML 파일을 handstack의 wwwroot 정적 서버(예: rdy 프로젝트) 경로 아래에 두고 브라우저로 열면 바로 동작을 확인할 수 있습니다.

  • basic.html : 화면 요소 3개를 순서대로 안내하는 intro.js 투어(helpType: 'I') 예제. 버튼을 눌러 투어를 시작하고, complete/exit 이벤트를 로그로 확인합니다.
  • help-types.html : 툴팁(T), 입력창 placeholder 애니메이션(P), 도움말 링크/팝업(U)까지 나머지 3가지 helpType을 한 화면에서 비교하는 예제.

각 예제는 화면 하단 로그 영역(syn.$l.eventLog 출력)에서 이벤트 발생 순서와 전달값을 확인할 수 있습니다.

더 알아보기

실전 예제 페이지

/uicontrols/Guide/example/ 경로의 예제를 아래 iframe에서 바로 확인할 수 있습니다.

basic.html

help-types.html

소스와 로드 파일

항목내용
컨트롤Guide
전역 별칭syn.uicontrols.$guide
버전v2025.3.1
소스uicontrols/Guide/Guide.js
스타일uicontrols/Guide/Guide.css

API 참조

싱글턴 객체: syn.uicontrols.$guide 소스 파일: wwwroot/uicontrols/Guide/Guide.js (version: 'v2025.3.1'), wwwroot/uicontrols/Guide/Guide.css

마크업

<syn_guide id="hlpDataSource" syn-options="{
items: [
{ helpType: 'I', selector: '#btnNewDataSource', subject: '신규 데이터 원본을 설정하세요.', sentence: 'SqlServer, Oracle, MySQL & MariaDB, PostgreSQL, SQLite 데이터베이스를 연동하세요.', sortingNo: 1 },
{ helpType: 'I', selector: '#lstDataSource', subject: '연결 가능한 데이터 원본입니다.', sentence: '앱에서 데이터베이스 요청을 실행하는 dbclient 모듈의 계약 정보에 사용하는 DataSourceID 목록입니다.', sortingNo: 2 },
{ helpType: 'T', selector: 'span.badge.bg-primary', subject: '앱에서 사용하는 기본 데이터베이스 입니다.', sentence: '기본 데이터 원본 정보는 제공자와 연결 문자열을 편집할 수 없습니다.', applyDelay: 1000 },
{ helpType: 'P', selector: '#txtConnectionString', subject: '중요', sentence: '개발 및 테스트 목적의 데이터베이스 연결문자열을 입력해야 합니다.' },
{ helpType: 'U', subject: '설치 가이드', sentence: 'https://handstack.kr/docs/startup/install/지원-운영체제', options: '{"contentType": "link"}' }
]
}" syn-events="['complete', 'exit']"></syn_guide>
  • id는 페이지 내에서 유일해야 하며, syn.uicontrols.$guide의 각종 메서드에서 이 id(elID)를 사용합니다.
  • 태그 자체는 controlLoad 실행 후 display:none으로 숨겨집니다(화면에 그려지는 요소가 아니라 안내 동작 정의용 태그입니다). 내부적으로 <input>처럼 value 속성을 가지므로 getValue/setValue/clear가 존재하지만, 실질적인 값(투어 진행 상태 등)을 담는 용도로 쓰이지는 않습니다.
  • Guide는 자기 자신이 아니라 items[].selector로 지정한 다른 화면 요소들 위에서 동작합니다. 따라서 각 selector가 가리키는 요소는 Guide 태그보다 먼저(또는 같은 시점에) 화면(DOM)에 존재해야 합니다. controlLoad 시점에 selector로 요소를 찾지 못하면:
    • helpType: 'I' 항목은 해당 단계를 건너뜁니다(steps에 추가되지 않음).
    • helpType: 'T' 항목은 applyDelay가 0이면 건너뛰고, applyDelay가 있으면 지연 이후 시점에 다시 셀렉터로 찾아 연결을 시도합니다.
    • helpType: 'P' 항목은 해당 항목을 건너뜁니다.
    • helpType: 'U' 항목은 selector를 사용하지 않으므로 영향이 없습니다.

Options (defaultSetting)

속성타입기본값설명
itemsarray[]안내 단계 목록. 아래 "items 배열 구조" 참고
introOptionsobjectintro.js 기본 옵션(아래)helpType: 'I' 투어 전체에 적용되는 intro.js 옵션. intro.js 옵션 문서 참고
tooltipOptionsobject객체 설정helpType: 'T' 툴팁 전체에 적용되는 tippy.js 기본 옵션
placeholderOptionsobject객체 설정helpType: 'P' 애니메이션 전체에 적용되는 superplaceholder 기본 옵션

introOptions 기본값

{
prevLabel: '<svg ... chevron-left ... />', // 이전 버튼 아이콘(SVG)
nextLabel: '<svg ... chevron-right ... />', // 다음 버튼 아이콘(SVG)
doneLabel: '완료',
skipLabel: '<svg ... x(닫기) ... />',
dontShowAgainLabel: '다시 안보기',
exitOnEsc: true,
showStepNumbers: true,
showBullets: false,
tooltipPosition: 'auto',
overlayOpacity: 0.2,
steps: [] // Guide가 items(helpType:'I')로부터 자동 생성하여 채움
}

items 배열 구조 (itemTemplate)

속성타입필수설명
helpTypestring필수안내 방식. 'I'(intro.js 투어) / 'T'(tippy 툴팁) / 'P'(superplaceholder) / 'U'(도움말 링크·팝업) 중 하나
selectorstring (CSS 셀렉터)I/T/P에 필수, U는 미사용안내 대상 요소를 찾는 셀렉터(syn.$l.querySelector 사용)
subjectstring (HTML 가능)선택제목. I는 스텝 제목, T는 툴팁 상단에 <strong>으로 굵게 표시, P는 문장 앞에 [제목] 으로 붙음, U는 팝업 제목(<h1>)
sentencestring | array (HTML 가능)선택본문. I/T는 문자열, P는 문자열 또는 문자열 배열(여러 문구를 순환 타이핑), UcontentType:'link'일 때 이동할 URL, 그 외엔 팝업에 표시할 HTML 본문
optionsstring (JSON 문자열, HTML 엔티티 이스케이프 가능)선택해당 항목에만 적용할 추가 옵션. IintroOptions에, TtooltipOptions에, PplaceholderOptions에 병합됨. U객체 설정 또는 객체 설정 지정에 사용(내부에서 $string.toCharHtml로 언이스케이프 후 JSON.parse)
sortingNonumber선택(기본 0)helpType: 'I' 단계 순서 정렬 기준($array.objectSort로 오름차순 정렬)
applyDelaynumber (ms)T에서만 사용지정 시 해당 시간(ms) 후에 tippy를 지연 연결. 아직 DOM에 없는 요소(동적 렌더링)에 툴팁을 붙일 때 사용

helpType: 'U'는 실제로는 하나의 "도움말" 링크/본문 역할만 하며, 여러 개를 넣어도 openUIHelpitems에서 첫 번째로 발견되는 helpType:'U' 항목만 사용합니다.

메서드

syn.uicontrols.$guide.<메서드명>(...) 형태로 호출합니다.

메서드설명
introStart(elID)helpType:'I' 로 구성된 intro.js 투어를 시작합니다(intro.start()). 페이지 로드시 자동 시작되지 않으므로 버튼 클릭 등에서 직접 호출해야 합니다.
openUIHelp(elID)items에서 첫 번째 helpType:'U' 항목을 찾아 도움말을 엽니다. options.contentType === 'link'이면 sentence(URL)를 새 창(window.open(url, 'help'))으로 열고, 그 외에는 subject/sentence로 구성한 HTML을 팝업 창에 출력합니다. 팝업이 차단되면 syn.$w.alert로 안내합니다.
getGuideControl(elID)내부 등록 정보 객체 설정를 반환합니다(디버깅/직접 제어용). tooltip은 tippy 인스턴스 배열, intro는 introJs 인스턴스, placeholder는 superplaceholder 인스턴스 배열입니다.
dataRefresh(elID, items)기존 안내 구성(tooltip/intro/placeholder)을 모두 정리(clear)한 뒤, 전달한 새 items 배열로 다시 구성합니다. 서버 응답 등으로 안내 항목을 동적으로 교체할 때 사용합니다.
getValue(elID)syn.$l.get(elID).value를 반환(다른 컨트롤과 인터페이스를 맞추기 위한 자리표시자, Guide 고유 값 개념 없음)
setValue(elID, value)elID 요소의 value를 설정(위와 동일한 이유의 자리표시자)
clear(elID)value를 비우고, 등록된 tippy 인스턴스를 모두 destroy(), intro.js 투어를 exit(), superplaceholder 인스턴스를 모두 destroy()합니다.
setLocale(elID, translations, control, options)다국어 텍스트 적용 훅(Guide는 별도 구현 없음, 빈 함수)

이벤트 (syn-events)

syn-events 배열에 이름을 넣으면 페이지 스크립트의 event 객체에서 {elID}_{이벤트명} 함수를 자동으로 연결해 줍니다. 이 이벤트들은 helpType: 'I'(intro.js) 투어에만 연결됩니다. T/P/U 항목에는 syn-events 훅이 연결되지 않습니다(Guide.js 소스상 intros.on... 호출만 존재).

이벤트명intro.js API발생 시점
completeintro.oncomplete(fn)마지막 단계에서 "완료" 버튼을 눌러 투어를 정상적으로 끝냈을 때
exitintro.onexit(fn)투어가 (완료 여부와 관계없이) 종료될 때 — ESC, 닫기(X) 버튼, clear() 호출 등
beforeexitintro.onbeforeexit(fn)투어가 종료되기 직전
changeintro.onchange(fn)스텝이 전환된 직후
beforechangeintro.onbeforechange(fn)스텝이 전환되기 직전
afterchangeintro.onafterchange(fn)스텝 전환 애니메이션까지 끝난 직후

핸들러 등록 예:

let $samplePage = {
event: {
hlpDataSource_complete() {
syn.$l.eventLog('hlpDataSource_complete', '투어 완료');
},
hlpDataSource_exit() {
syn.$l.eventLog('hlpDataSource_exit', '투어 종료');
}
}
}

각 콜백의 인자 형태(예: change/beforechange/afterchange가 전달하는 대상 엘리먼트 등)는 intro.js 원본 API 문서를 따릅니다: https://introjs.com/docs/intro/api

참고

  • 이 컨트롤은 wwwroot/sample/uicontrol/에 별도 샘플 페이지가 없습니다. 위 Options/메서드/이벤트 표는 모두 wwwroot/uicontrols/Guide/Guide.js 소스 코드(defaultSetting, itemTemplate, controlLoad, introStart, openUIHelp, dataRefresh, clear 함수)를 직접 읽고 확정한 내용입니다.
  • 마크업 형태(items 배열에 helpType/selector/subject/sentence를 넣는 방식)는 실사용 프로젝트인 qcn.groupware의 코드 패턴을 참고했습니다.
  • helpType: 'I'/'T'/'P'가 동작하려면 각각 window.introJs, window.tippy, window.superplaceholder가 로드되어 있어야 합니다. syn.loader.jssyn_guide 태그를 인식하면 intro.js, tippy.js(+popper.js), superplaceholder, Guide.js/Guide.css를 자동으로 함께 로드하므로 별도 설정 없이 사용할 수 있습니다.
  • intro.js 옵션/API 원본 문서: https://introjs.com/docs/intro/api
  • tippy.js 옵션 원본 문서: https://atomiks.github.io/tippyjs/v6/all-props/
  • superplaceholder 옵션 원본 문서: https://github.com/fabiospampinato/superplaceholder.js