[친구하자] Capacitor 앱 Custom Splash Screen 구현하기
in ProjectDiary
Capacitor로 빌드한 앱에서 Splash Screen을 React로 직접 구현한 내용에 대해 다룹니다.
- 이번 포스팅에선 Capacitor로 빌드한 앱에서 여러 아이콘이 순차적으로 표시되는 커스텀 스플래시 스크린을 구현하는 방법을 정리했다.
- 왜 Custom splash screen이 필요했나?
- Capacitor의 기본 splash screen은 단일 정적 이미지만 지원한다.🔗링크
- 나는 여러 아이콘을 순차적으로 보여주는 애니메이션을 구현하고 싶어 React 컴포넌트로 직접 구현하였다!
목차
1. 필요한 패키지 설치
먼저 스플래시 스크린 관련 패키지를 설치하자.
나는 pnpm을 사용하고 있었으므로 pnpm으로 설치했다.
pnpm add @capacitor/splash-screen
pnpm add -D @capacitor/assets
2. Capacitor 설정
capacitor.config.ts파일에 스플래시 스크린 설정을 추가하자.- ‼️ 커스텀 스플래시를 사용하므로 네이티브 스플래시는 최소화!
/// <reference types="@capacitor/splash-screen" />
import type { CapacitorConfig } from "@capacitor/cli";
const config: CapacitorConfig = {
// ... 기타 설정
plugins: {
SplashScreen: {
launchShowDuration: 0, // 커스텀 스플래시를 사용하므로 0으로 설정
launchAutoHide: true, // 자동으로 숨길지 여부
launchFadeOutDuration: 0, // 페이드 아웃 애니메이션 시간 (커스텀 스플래시에서 처리)
backgroundColor: "#ffffff", // 배경색 (hex 형식) - 커스텀 스플래시와 동일하게 설정
// ... 기타 설정
},
},
};
export default config;
3. 커스텀 스플래시 스크린 컴포넌트 생성
client/components/CustomSplashScreen.tsx 파일을 생성한다.
Props 정의
interface CustomSplashScreenProps {
onComplete: () => void; // 스플래시 완료 시 콜백
icons?: string[]; // 표시할 아이콘 배열
iconDuration?: number; // 각 아이콘 표시 시간(ms)
minDisplayDuration?: number; // 최소 표시 시간(ms)
animationType?: "slide-up" | "fade" | "none";
backgroundColor?: string;
}
핵심 로직
export const CustomSplashScreen = ({
onComplete,
icons = [],
iconDuration = 500,
minDisplayDuration = 2000,
animationType = "slide-up",
backgroundColor = "#ffffff",
}: CustomSplashScreenProps) => {
const [currentIconIndex, setCurrentIconIndex] = useState(0);
const [isVisible, setIsVisible] = useState(true);
// 1. 네이티브 스플래시 스크린 즉시 숨기기
useEffect(() => {
const hideNativeSplash = async () => {
try {
await SplashScreen.hide();
} catch (error) {
// 웹 환경에서는 에러가 발생할 수 있으므로 무시
}
};
hideNativeSplash();
}, []);
// 2. 아이콘 순차 표시 로직
useEffect(() => {
if (icons.length === 0) {
const timer = setTimeout(() => {
setIsVisible(false);
setTimeout(onComplete, 300);
}, minDisplayDuration);
return () => clearTimeout(timer);
}
// 아이콘 전환 인터벌
const iconInterval = setInterval(() => {
setCurrentIconIndex((prev) => {
if (prev < icons.length - 1) {
return prev + 1;
}
return prev;
});
}, iconDuration);
// 총 표시 시간 계산
const totalAnimationDuration = icons.length * iconDuration;
const actualDuration = Math.max(totalAnimationDuration, minDisplayDuration);
const completeTimer = setTimeout(() => {
setIsVisible(false);
setTimeout(onComplete, 300);
}, actualDuration);
return () => {
clearInterval(iconInterval);
clearTimeout(completeTimer);
};
}, [icons, iconDuration, minDisplayDuration, onComplete]);
// ... 렌더링 로직
};
- 아이콘 슬라이드 애니메이션과 텍스트 추가 등 개인의 디자인에 맞게 React 코드를 수정해서 꾸며주면 된다!!
4. App.tsx에 통합
메인 앱 컴포넌트에 커스텀 스플래시 스크린을 통합합니다.
import { CustomSplashScreen } from "./components/CustomSplashScreen";
const AppRoutes = () => {
const [showSplash, setShowSplash] = useState(true);
// 스플래시 스크린에 표시할 아이콘들
const splashIcons = [
"/splash-icons/icon1.png",
"/splash-icons/icon2.png",
"/splash-icons/icon3.png",
// ... 더 많은 아이콘
];
const handleSplashComplete = () => {
setShowSplash(false);
};
if (showSplash) {
return (
<CustomSplashScreen
onComplete={handleSplashComplete}
icons={splashIcons}
iconDuration={400}
minDisplayDuration={2000}
animationType="slide-up"
/>
);
}
// ... 나머지 앱 로직
};
🍎 핵심 구현 포인트 🍎
1. 네이티브 스플래시와 커스텀 스플래시 분리
launchShowDuration: 0으로 설정하여 네이티브 스플래시를 즉시 숨김SplashScreen.hide()를 컴포넌트 마운트 시 호출
2. 텍스트 깜빡임 방지
아이콘과 텍스트를 별도의 div로 렌더링하여 아이콘이 변경될 때 텍스트가 깜빡이지 않도록 구현
3. 부드러운 애니메이션
CSS transition과 cubic-bezier 타이밍 함수를 사용하여 자연스러운 전환 효과 구현
4. 최소 표시 시간 보장
minDisplayDuration을 설정하여 애니메이션이 너무 빨리 끝나도 최소 시간은 보장
5. 이미지 준비
아이콘 이미지는 public/splash-icons/ 디렉토리에 저장합니다.
public/
splash-icons/
icon1.png
icon2.png
icon3.png
‼️ 주의사항
- 이미지는 반드시
public폴더에 저장 (빌드 시 자동 포함) - 웹 환경에서는
SplashScreen.hide()가 에러를 발생시킬 수 있으므로 try-catch 처리 필요 - Android 12 이상에서는 네이티브 스플래시 API가 강제 적용되므로 초기 0.5초는 네이티브 스플래시가 보일 수 있음