Files
sam-docs/features/rd/onboarding-guide.md

7.8 KiB

온보딩 도움말기능 (Driver.js 기반)

작성일: 2026-03-22 상태: 운영 중 (알려진 제약 있음) 프로젝트: SAM MNG (관리자 웹) 라우트: /rd/onboarding-guide


1. 개요

1.1 목적

SAM MNG의 각 화면에 처음 진입하는 사용자에게 주요 기능을 단계별로 안내하는 인터랙티브 투어를 제공한다. 배경을 흐리게(Dimming) 처리하고 대상 요소를 하이라이트하며, 툴팁으로 사용 방법을 설명한다.

1.2 핵심 원칙

  • Driver.js 라이브러리 기반 (NPM, Vite 번들)
  • SamOnboarding JS 래퍼 클래스로 프로젝트 전역에서 일관된 사용
  • localStorage로 완료 상태 저장 (첫 방문 시에만 자동 시작)
  • 각 페이지 Blade 파일에서 간단한 코드 추가로 적용 가능
  • Driver.js CSS는 동적 로드 (가이드 start() 시점에만 로드, 전역 레이아웃 충돌 방지)

2. 알려진 제약 및 주의사항

경고: MNG 환경에서 Driver.js + HTMX 조합의 구조적 제약이 있다.

2.1 HTMX 레이아웃 충돌

접근 방식 레이아웃 가이드 동작
URL 직접 입력 / F5 새로고침 정상 정상
사이드바 메뉴 클릭 (HTMX 네비게이션) 깨짐 -

2.2 원인

MNG는 HTMX 듀얼 로드 환경이다:

  • CDN: htmx.org@1.9.10 (레이아웃 <head>에서 동기 로드)
  • NPM: htmx.org@2.0.8 (Vite 번들에서 모듈 로드)

사이드바의 hx-boost="true" + hx-swap="outerHTML" + HX-Redirect 응답 조합에서 두 HTMX 인스턴스 간 처리 충돌이 발생하여, 페이지 전체 리로드 시 레이아웃이 깨진다.

2.3 현재 대응

  • 컨트롤러에서 HX-Redirect로 전체 페이지 리로드를 강제한다 (다른 RD 페이지와 동일 패턴)
  • Driver.js CSS는 start() 호출 시에만 동적 import()로 로드한다
  • SAM 커스텀 테마는 JS에서 <style> 태그를 동적 생성하여 주입한다

2.4 이관 시 해결 방향

서비스 이관(API + React) 시 다음을 적용하면 문제가 해결된다:

  1. HTMX 버전 단일화: CDN 1.9.10 제거, NPM 2.0.8만 사용
  2. React 환경: HTMX 대신 React Router 사용 → hx-boost 충돌 자체가 없음
  3. Driver.js React 래퍼: React 컴포넌트로 래핑하여 lifecycle과 통합
이관 우선순위:
1단계 — HTMX 단일화 (MNG 내에서 해결 가능)
2단계 — React 이관 시 온보딩 컴포넌트로 재구현

3. 기술 스택

항목 내용
라이브러리 driver.js (NPM)
번들링 Vite (resources/js/app.js에서 import)
래퍼 모듈 resources/js/onboarding-guide.js
상태 저장 localStorage (sam_onboarding_{pageKey})
전역 객체 window.SamOnboarding, window.GuideRegistry
CSS 로드 동적 import('driver.js/dist/driver.css') (가이드 시작 시에만)
커스텀 테마 JS 동적 <style> 주입 (loadDriverCss() 함수 내)

4. 파일 구조

mng/
├── resources/
│   ├── js/
│   │   ├── app.js                          ← SamOnboarding, GuideRegistry 전역 등록
│   │   └── onboarding-guide.js             ← SamOnboarding 클래스, GuideRegistry, CSS 동적 로드
│   └── css/
│       └── app.css                         ← #app-container overflow 보호 규칙
├── app/Http/Controllers/
│   └── RdController.php                    ← onboardingGuide() (HX-Redirect 사용)
├── routes/
│   └── web.php                             ← /rd/onboarding-guide 라우트
└── resources/views/rd/
    ├── onboarding-guide/
    │   └── index.blade.php                 ← 관리 페이지 (데모 체험, 개발자 가이드)
    └── index.blade.php                     ← RD 대시보드 (시범 적용)

5. 사용법

5.1 기본 사용 (Blade 파일)

// @push('scripts') 안에 추가
// ❌ <script type="module"> 사용 금지 — HTMX 스왑 시 실행 안됨
// ✅ <script> 사용 + SamOnboarding 로드 대기 패턴

var _guide = null;
function startGuide() { if (_guide) { _guide.reset(); _guide.start(); } }

(function waitForOnboarding() {
    if (typeof SamOnboarding === 'undefined') { setTimeout(waitForOnboarding, 100); return; }

    _guide = new SamOnboarding('page-key', [
        { element: '#target-id', title: '제목', description: '설명', side: 'bottom' },
        { element: '.another', title: '두 번째', description: '설명' },
    ]);

    // 첫 방문 시에만 자동 시작
    _guide.startIfFirstVisit();
})();

5.2 도움말 버튼 패턴

<button onclick="startGuide()" class="bg-white hover:bg-gray-100 text-gray-500 px-3 py-2 rounded-lg border transition" title="도움말 보기">
    <i class="ri-question-line"></i>
</button>

5.3 SamOnboarding 클래스 API

메서드 설명
start() 가이드 즉시 시작 (Driver.js CSS 동적 로드 + 커스텀 테마 주입)
startIfFirstVisit() 첫 방문(미완료) 시에만 자동 시작 (500ms 딜레이)
reset() 완료 상태 초기화 (다시 보기)
isCompleted() 완료 여부 반환 (boolean)

5.4 스텝 옵션

속성 필수 설명
element * CSS 셀렉터 (#id, .class)
title * 툴팁 제목
description * 설명 텍스트 (HTML 지원)
side 툴팁 위치: top, bottom, left, right
align 정렬: start, center, end

6. 적용 현황

페이지 pageKey 스텝 수 자동 시작 도움말 버튼
RD 대시보드 rd-dashboard 4 첫 방문 ? 버튼
온보딩 데모 onboarding-demo 6 수동 데모 버튼

7. 스크립트 작성 시 주의사항

7.1 <script type="module"> 금지

❌ <script type="module"> — Vite 모듈보다 늦게 실행되지만 HTMX 스왑 시 실행 안됨
✅ <script> + SamOnboarding 로드 대기 패턴 (setTimeout 폴링)

7.2 전역 함수 즉시 정의

onclick 핸들러에서 사용하는 함수는 스크립트 최상단에 즉시 정의한다. SamOnboarding 로드 전 클릭 시 ReferenceError 방지.

// ✅ 즉시 정의 (SamOnboarding 로드 전에도 에러 없음)
var _guide = null;
function startGuide() { if (!_guide) return; _guide.start(); }

// ❌ init() 안에서 window.startGuide = ... (로드 전 클릭 시 에러)

7.3 Driver.js CSS 동적 로드

Driver.js CSS를 전역 번들에 포함하면 all:unset, :has() 등 공격적 CSS 규칙이 MNG 레이아웃(flex, overflow)과 충돌한다. 반드시 start() 시점에만 동적 로드한다.

❌ import 'driver.js/dist/driver.css'  — app.js 전역 import 금지
✅ import('driver.js/dist/driver.css') — start() 내에서 동적 import

8. GuideRegistry (선택 사용)

여러 페이지의 가이드를 중앙에서 관리할 때 사용한다.

GuideRegistry.register('my-page', [
    { element: '#btn', title: '버튼', description: '설명' },
]);

var guide = GuideRegistry.create('my-page');
guide.start();

var keys = GuideRegistry.keys(); // ['my-page', ...]

9. 새 페이지에 가이드 추가하기

  1. 가이드 대상 요소에 id 부여 (예: id="btn-create", id="data-table")
  2. Blade 파일의 @push('scripts') 안에 일반 <script> + 로드 대기 패턴 추가
  3. onclick 핸들러 함수를 스크립트 최상단에 즉시 정의
  4. (선택) 페이지 헤더에 ? 도움말 버튼 추가

관련 문서


최종 업데이트: 2026-03-22