ADR-20: 스켈레톤 로딩 패턴
| Date | Author | Repos |
|---|---|---|
| 2025-12-20 | @KubrickCode | web |
Context
문제 상황
웹 플랫폼은 데이터 로딩 중 시각적 피드백 필요:
- 분석 페이지: 2-10초 (큐 기반 비동기 처리)
- 대시보드: 페이지네이션 및 무한 스크롤
- 초기 페이지 로드: Server Component 데이터 페칭
사용자는 시스템 상태를 이해하고 대기 시간 동안 몰입을 유지하기 위해 즉각적인 시각적 피드백 필요.
초기 접근 방식의 문제점
초기 로딩 구현은 일반적인 플레이스홀더 div 사용:
<div className="h-4 w-full animate-pulse rounded bg-muted" />이 접근 방식의 한계:
- 레이아웃 미리보기 없음: 사용자가 콘텐츠 구조를 예측할 수 없음
- 레이아웃 시프트: 콘텐츠 로드 시 시각적 불안정
- 수동적 대기: 진행 상황이나 구조에 대한 감각 없음
UX 리서치 컨텍스트
Nielsen Norman Group과 Viget의 연구 결과:
- 스켈레톤 스크린은 스피너보다 20-30% 더 빠르게 인지됨
- 능동적 대기(구조 확인)가 수동적 대기(스피너 관찰)보다 빠르게 느껴짐
- 레이아웃 안정성이 인지 부하를 줄임
Decision
모든 데이터 로딩 상태에 스피너 대신 콘텐츠 인식 스켈레톤 로딩 패턴 채택.
핵심 원칙:
- 레이아웃 일치: 스켈레톤은 최종 콘텐츠 치수와 구조와 일치해야 함
- 기능별 전용: 각 기능은 전용 스켈레톤 컴포넌트 보유
- 상태 인식: 장시간 작업은 컨텍스트에 맞는 상태 배너 표시
- 접근성: 스크린 리더 호환성을 위한 ARIA 속성
Options Considered
Option A: 스피너/로딩 인디케이터
작동 방식:
- 로딩 중 중앙 스피너 애니메이션
- 기존 아이콘으로 간단한 구현
장점:
- 최소한의 개발 노력
- 보편적 인지도
- "무언가 진행 중" 명확한 신호
단점:
- 수동적 대기 경험
- 콘텐츠 미리보기 없음
- 콘텐츠 로드 시 레이아웃 시프트
- 연구에서 낮은 체감 성능
Option B: 프로그레스 바
작동 방식:
- 완료 비율을 보여주는 선형 진행 표시기
- 파일 업로드/다운로드에서 일반적
장점:
- 완료 진행 상황 표시
- 알려진 시간에 적합
- 익숙한 패턴
단점:
- 알려진 작업 시간 필요
- 응답 시간을 알 수 없는 API 호출에 부적합
- 콘텐츠 구조 미리보기 없음
- 콘텐츠 로딩 사용 사례에 부적절
Option C: 스켈레톤 스크린 (선택됨)
작동 방식:
- 최종 콘텐츠 레이아웃과 일치하는 플레이스홀더 UI
- 펄스 애니메이션으로 활동 표시
- 데이터 로드에 따른 점진적 콘텐츠 공개
장점:
- 능동적 대기 경험 (20-30% 체감 속도 향상)
- 레이아웃 안정성 (콘텐츠 시프트 없음)
- 사용자의 멘탈 모델 형성
- 적절한 ARIA 속성으로 접근성 준수
단점:
- 기능별 더 많은 개발 노력
- 레이아웃 변경 시 유지보수
- 완화: 공유 베이스를 가진 중앙화된 스켈레톤 컴포넌트
Option D: 로딩 상태 없음
작동 방식:
- 콘텐츠 준비될 때까지 아무것도 표시 안 함
- 매우 빠른 작업(<1초)에만 적합
평가:
- 즉각적인 작업에는 허용
- 2-10초 대기에는 문제
- 기각: 분석 작업이 1초 임계값 초과
Implementation
컴포넌트 계층
Skeleton (shadcn/ui 베이스)
├── StatsCardSkeleton (분석 통계)
├── TestListSkeleton (테스트 아코디언 항목)
├── AnalysisSkeleton (전체 분석 페이지)
└── RepositorySkeleton (대시보드 카드)디자인 패턴
1. 레이아웃 매칭
스켈레톤 치수와 실제 콘텐츠 일치:
- 저장소 이름:
h-5 w-32 - 통계 카드: 그리드 레이아웃 유지
- 테스트 목록: 6개 아코디언 스타일 항목
2. 상태 인식 배너
장시간 작업용:
| 상태 | 색상 | 사용 사례 |
|---|---|---|
| loading | 회색 | 초기 페이지 로드 |
| queued | 파랑 | 분석이 큐에서 대기 중 |
| analyzing | 주황 | 분석 진행 중 |
3. 접근성
- 로딩 컨테이너에
aria-busy="true" - 상태 업데이트에
aria-live="polite" - 라이브 영역에
role="status" - 스켈레톤 컴포넌트에
aria-label
Consequences
Positive
1. 체감 성능 향상
- 연구 기반 20-30% 체감 속도 개선
- 능동적 대기로 좌절감 감소
2. 레이아웃 안정성
- 데이터 로드 시 콘텐츠 시프트 없음
- 일관된 시각적 경험
3. 멘탈 모델 형성
- 사용자가 로드 전 콘텐츠 구조 이해
- 콘텐츠 공개 시 인지 부하 감소
4. 접근성 준수
- ARIA 속성을 통한 스크린 리더 지원
- 모든 사용자를 위한 포용적 디자인
Negative
1. 개발 오버헤드
- 각 기능마다 전용 스켈레톤 컴포넌트 필요
- 완화: 공유 베이스 컴포넌트, 일관된 패턴
2. 유지보수 부담
- 레이아웃 변경 시 스켈레톤 업데이트 필요
- 완화: 기능 컴포넌트와 스켈레톤 컴포넌트 같은 위치 배치
3. 불일치 가능성
- 스켈레톤 레이아웃이 실제 콘텐츠와 달라질 수 있음
- 완화: 코드 리뷰 체크리스트, 시각적 회귀 테스트
References
- Nielsen Norman Group: Skeleton Screens 101
- LogRocket: Skeleton Loading Screen Design
- Related Commits:
ff30530,55fb993,93f0189
