프로젝트 일기

Capacitor 앱 Custom Splash Screen 구현하기

은나노 2025. 11. 21. 11:02
  • 이번 포스팅에선 Capacitor로 빌드한 앱에서 여러 아이콘이 순차적으로 표시되는 커스텀 스플래시 스크린을 구현하는 방법을 정리해 보았다..
  • 왜 Custom splash screen이 필요했나?
    • Capacitor의 기본 splash screen은 단일 정적 이미지만 지원한다.🔗링크
    • 나는 여러 아이콘을 순차적으로 보여주는 애니메이션을 구현하고 싶어 React 컴포넌트로 직접 구현하였다!

내가 구현하고자 했던 splash screen

 

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초는 네이티브 스플래시가 보일 수 있음

🍀 참고 문헌 

 

[친구하자] Capacitor 앱 Custom Splash Screen 구현하기

Capacitor로 빌드한 Android 앱에서의 웹소켓 오류 중 X-Frame-Options 에러 트러블슈팅을 다룹니다.

nan0silver.github.io

 

LIST