구현 목표

기존에는 화면 중앙에 로딩 스피너를 배치했는데,
데이터를 불러온 뒤에 시선이 다시 화면 상단으로 이동해야 하는 점이 다소 불편하다고 느꼈다.
그래서 시선 이동을 최소화하고 사용자 경험을 높이기 위해
홈 화면 로딩 시 로딩 스피너 대신 스켈레톤 UI를 적용하기로 했다.
shimmer 패키지

플러터에서 손쉽게 shimmer 효과를 적용할 수 있도록 도와주는 패키지다.
스켈레톤 UI를 만들 때 자주 활용되며, `baseColor`, `highlightColor`, `child`만 지정하면 간단하게 적용할 수 있다.

그 외에는 다음과 같은 옵션들을 제공한다.
shimmer | Flutter package
A package provides an easy way to add shimmer effect in Flutter project
pub.dev
공용 스켈레톤 위젯 만들기

홈 화면 구조가 단순하기 때문에, 공통 스켈레톤 카드 위젯을 만들고 높이만 전달하기로 했다.
import 'package:flutter/material.dart';
import 'package:shimmer/shimmer.dart';
// 공용 스켈레톤 카드
class SkeletonCard extends StatelessWidget {
final double height;
const SkeletonCard({
super.key,
required this.height,
});
@override
Widget build(BuildContext context) {
return Shimmer.fromColors(
baseColor: Colors.grey[200]!,
highlightColor: Colors.grey[100]!,
child: Padding(
padding: const EdgeInsets.all(2.0),
child: Container(
height: height,
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: BorderRadius.circular(12),
),
),
),
);
}
}
홈 화면 전용 스켈레톤 UI
// 로딩 시 표시하는 스켈레톤 UI 위젯
class HomeBodySkeleton extends StatelessWidget {
const HomeBodySkeleton({super.key});
@override
Widget build(BuildContext context) {
return const Padding(
padding: EdgeInsets.symmetric(horizontal: 2.0),
child: Column(
children: [
SizedBox(height: 1),
SkeletonCard(height: 110), // 첫 번째 카드
SizedBox(height: 11),
SkeletonCard(height: 60), // 두 번째 카드
],
),
);
}
}
홈 화면의 구조와 크기에 맞춰 `HomeBodySkeleton`이라는 위젯을 따로 만들었다.
isLoading ? const HomeBodySkeleton() : Column(...)
`isLoading` 여부에 따라 스켈레톤 UI 또는 실제 화면을 보여준다.