stack-analysis
CHAPTER 69 / 90
읽기 약 2분
FUNCTION
온보딩 UX: 첫 경험 설계
핵심 개념
체크리스트·툴팁·empty state·activation metric — 7일 retention 향상.
본문
온보딩 5단계
1. Sign-up (가입)
2. Welcome (환영 + 목표 확인)
3. Setup (초기 설정 — 워크스페이스, 팀)
4. First Win (첫 성공 경험 — 5분 내)
5. Activation (핵심 기능 사용)
[성공 지표]
Sign-up → Activation 전환율 > 40%
1주 retention > 30%회원가입 → Welcome
// app/welcome/page.tsx
'use client';
export default function WelcomePage() {
const [step, setStep] = useState(1);
const [data, setData] = useState({
workspaceName: '',
teamSize: '',
goal: '',
});
return (
<div className="max-w-md mx-auto p-8">
<ProgressBar current={step} total={4} />
{step === 1 && (
<>
<h1>환영합니다 👋</h1>
<p>2분만에 셋업 완료</p>
<button onClick={() => setStep(2)}>시작하기</button>
</>
)}
{step === 2 && (
<>
<h2>워크스페이스 이름은?</h2>
<input
value={data.workspaceName}
onChange={e => setData({ ...data, workspaceName: e.target.value })}
placeholder="예: Acme Inc"
autoFocus
/>
<button disabled={!data.workspaceName} onClick={() => setStep(3)}>다음</button>
</>
)}
{step === 3 && (
<>
<h2>팀 규모는?</h2>
<RadioGroup value={data.teamSize} onChange={v => setData({ ...data, teamSize: v })}>
<Radio value="solo">혼자 사용</Radio>
<Radio value="2-10">2~10명</Radio>
<Radio value="11-50">11~50명</Radio>
<Radio value="50+">50명+</Radio>
</RadioGroup>
<button onClick={() => setStep(4)}>다음</button>
</>
)}
{step === 4 && (
<>
<h2>이 도구로 무엇을 하고 싶나요?</h2>
<CheckboxGroup>
<Checkbox value="task">할 일 관리</Checkbox>
<Checkbox value="docs">문서 협업</Checkbox>
<Checkbox value="kanban">프로젝트 칸반</Checkbox>
</CheckboxGroup>
<button onClick={async () => {
await fetch('/api/onboarding/complete', {
method: 'POST', body: JSON.stringify(data),
});
router.push('/dashboard');
}}>시작하기</button>
</>
)}
</div>
);
}체크리스트 — 점진 활성화
// 대시보드 사이드바
function OnboardingChecklist({ user }: { user: User }) {
const tasks = [
{ id: 'profile', label: '프로필 사진 추가', done: !!user.avatarUrl, action: '/settings' },
{ id: 'project', label: '첫 프로젝트 만들기', done: user.projectsCount > 0, action: '/projects/new' },
{ id: 'invite', label: '팀원 초대', done: user.tenantMembersCount > 1, action: '/team' },
{ id: 'integration', label: 'Slack 연결', done: user.hasSlack, action: '/settings/integrations' },
];
const completed = tasks.filter(t => t.done).length;
const pct = (completed / tasks.length) * 100;
if (pct === 100) return null; // 모두 완료 시 숨김
return (
<Card>
<h3>시작하기 ({completed}/{tasks.length})</h3>
<ProgressBar value={pct} />
<ul>
{tasks.map(task => (
<li key={task.id} className={task.done ? 'line-through' : ''}>
{task.done ? '✅' : '○'}
<Link href={task.action}>{task.label}</Link>
</li>
))}
</ul>
</Card>
);
}툴팁 투어 (driver.js)
import { driver } from 'driver.js';
const tour = driver({
showProgress: true,
steps: [
{
element: '#sidebar-projects',
popover: { title: '프로젝트', description: '여기서 프로젝트를 관리합니다' },
},
{
element: '#new-project-btn',
popover: { title: '새 프로젝트', description: '클릭해서 만들기' },
},
{
element: '#search-bar',
popover: { title: '빠른 검색', description: 'Cmd+K로 어디서나 검색' },
},
],
onDestroyed: () => {
fetch('/api/onboarding/tour-completed', { method: 'POST' });
},
});
// 새 사용자만 1회
useEffect(() => {
if (user.firstLogin && !user.tourCompleted) {
tour.drive();
}
}, [user]);Empty State (빈 상태 → 다음 행동 유도)
function ProjectsList({ projects }: { projects: Project[] }) {
if (projects.length === 0) {
return (
<div className="text-center py-16">
<img src="/empty-projects.svg" className="w-48 mx-auto" />
<h2 className="mt-4">아직 프로젝트가 없어요</h2>
<p className="text-gray-500 mt-2">
첫 프로젝트를 만들어 시작하세요. 30초 안에 끝납니다.
</p>
<Button href="/projects/new" className="mt-4">
첫 프로젝트 만들기 →
</Button>
<p className="mt-4 text-sm">
또는 <Link href="/templates">템플릿에서 시작</Link>
</p>
</div>
);
}
// ...
}활성화 지표 추적
// services/activation.ts
type ActivationEvent =
| 'signed_up'
| 'workspace_created'
| 'first_project_created'
| 'team_member_invited'
| 'integration_connected';
export async function trackActivation(userId: string, event: ActivationEvent) {
await db.userActivation.upsert({
where: { userId_event: { userId, event } },
create: { userId, event, completedAt: new Date() },
update: {},
});
// PostHog/Mixpanel
posthog.capture({
distinctId: userId,
event: 'activation:' + event,
});
}
// 핵심 funnel
SELECT
COUNT(*) FILTER (WHERE event = 'signed_up') as signed_up,
COUNT(*) FILTER (WHERE event = 'workspace_created') as workspace,
COUNT(*) FILTER (WHERE event = 'first_project_created') as first_project,
COUNT(*) FILTER (WHERE event = 'team_member_invited') as invited
FROM user_activation
WHERE completed_at > NOW() - INTERVAL '30 days';다음 챕터
CH.70 "SaaS 종합: 완성된 SaaS 보일러플레이트".
AI 프롬프트
🤖 AI에게 잘 물어보는 법 — 모델·전략별 프롬프트
Claude
무료: Sonnet 4.6 / Pro $20/mo: Opus 4.6
내 프로젝트의 온보딩 UX 부분을 분석해서 실전 분석 + 개선 우선순위를 알려줘.
ChatGPT
무료: GPT-5.5 / Plus $20/mo: GPT-5.5 Pro
온보딩 UX 관련 실제 서비스 5개를 비교 분석해서 패턴 추출를 알려줘.
Gemini
무료: 2.5 Flash / Pro $19.99/mo: 3.1 Pro
내 코드베이스에서 온보딩 UX 최적화 가능 위치를 보고해줘.
Grok
무료: Grok 4.1 / SuperGrok $30/mo
2026년 한국 풀스택 시장의 온보딩 UX 트렌드를 솔직히 알려줘.
⭐ 이것만 기억하세요
온보딩 UX: 첫 경험 설계는 이 3가지만 확실히 잡으세요
1.온보딩 5단계 — Sign-up → Welcome → Setup → First Win → Activation
2.체크리스트로 점진 활성화 — 사이드바에 진행률 표시
3.활성화 funnel 측정 — 핵심 이벤트별 전환율 추적
공유하기
진행도 69 / 90