본문 바로가기
개발 및 알고리즘/알고리즘

[React Native] 리액트 네이티브에서 스플래시 스크린에 애니메이션 구현하기 (lottie + react-native-bootsplash)

by 0xseo 2024. 7. 12.
반응형

앱의 첫인상이 앱 아이콘이라면 스플래시 스크린은 앱을 만나러 가는 길이라고 정의할 수 있다. (중요하단 뜻이다.)

이번에는 react-native-bootsplash 모듈을 통해서 스플래시스크린을 지정하는 방법을 알아보려 한다.

 


 

우선 스플래시스크린이 무엇인가?

 

앱에 처음 접속했을 때 뜨는 로딩화면으로서 프론트단에서의 앱 로딩 - 백엔드에서 정보를 가져오는 등 복잡한 구동이 진행되고 있을 때 사용자에게서 그것을 숨기고 덜 지루한 느낌(ux)을 주기 위해 구현한다.

 

로고만 있는 정적인 화면부터 누구나 아는 넷플릭스 스크린같은 동적인 화면도 많다.

다만 아무리 검색해봐도 정적인 화면이 1초도 안 나오고 애니메이션부터 시작하는 스플래시 스크린을 구현하는 방법을 찾지는 못했다.

그럼 어떻게 할까?

 

애니메이션의 배경색만으로 채운 화면이나 애니메이션의 시작 부분을 이미지화하여 만든 화면을 띄운 상태에서 프론트단에서의 구동을 마치고, 그 직후에 애니메이션을 시작하여 강제로 몇초간 사용자를 스플래시 스크린에 붙잡아놓으면서 백엔드 로딩 등을 구동하는 방식으로 보통 구현한다. (솔직히 일반적으로 정적인 화면이 나오는 시간은 1초도 안되기 때문에 자연스럽다)

 

그리하여 오늘의 글은 두 단계로 나뉠 것이다.

1. 정적인 스플래시 스크린 띄우기

2. 끝난 직후 로띠 애니메이션 띄우기 (lottie 구현 방법)

 

보통 스플래시 스크린을 제작할 때 react-native-splash-screen이나 react-native-bootsplash를 많이 사용하는데,

필자는 후자를 더 선호한다. 정적인 로딩에서 svg를 사용하기 때문이다.

로띠 애니메이션은 아주 선명한 화질이기 때문에, 정적인 화면에서 png를 사용하게 되면 프론트단 구동이 끝나고 애니메이션이 시작될 때 이미지와 로띠 간의 화질 차이가 두드러질 수 있다.

물론 정적인 화면에서 이미지 없이 배경색만 채우거나, 동적인 애니메이션을 넣지 않는 경우에는 전혀 상관이 없다.

 


 

모듈을 다운받는 것으로 시작한다.

npm i —save react-native-bootsplash
cd iOS
pod install

 

준비물: svg 파일

bootsplash는 배경색을 깔고, 그 정 가운데에 svg를 올리는 스플래시스크린이다.

즉 애니메이션의 시작 부분과 연동되는 (혹은 단색의) svg 파일이 필요하다.

 

해당 svg파일을 루트 폴더에 놔둔 후 다음 명령어를 실행한다.

npx react-native generate-bootsplash ./logo.svg \
  --platforms=android,ios \
  --background=FFFFFF \
  --logo-width=200
./logo.svg를 활용한다는 이야기이고, platform이 android와 ios라는 이야기이며, 배경색은 #FFF, 배경 위에 얹을 svg의 크기는 200*200으로 지정한다는 이야기이다. (더 다양한 옵션이 많으니 공식문서를 확인해보자.)

 

명령어를 실행하면 android/app/src/main/res, ios/RNBootSplashExample에 수많은 파일들이 생길 것이다.

android/app/src/main/res/values/colors.xml
android/app/src/main/res/drawable-hdpi/bootsplash_logo.png
android/app/src/main/res/drawable-mdpi/bootsplash_logo.png
android/app/src/main/res/drawable-xhdpi/bootsplash_logo.png
android/app/src/main/res/drawable-xxhdpi/bootsplash_logo.png
android/app/src/main/res/drawable-xxxhdpi/bootsplash_logo.png

ios/RNBootSplashExample/BootSplash.storyboard
ios/RNBootSplashExample.xcodeproj/project.pbxproj
ios/RNBootSplashExample/Info.plist
ios/RNBootSplashExample/Images.xcassets/BootSplashLogo.imageset/Contents.json
ios/RNBootSplashExample/Images.xcassets/BootSplashLogo.imageset/bootsplash_logo-<hash>.png
ios/RNBootSplashExample/Images.xcassets/BootSplashLogo.imageset/bootsplash_logo-<hash>@2x.png
ios/RNBootSplashExample/Images.xcassets/BootSplashLogo.imageset/bootsplash_logo-<hash>@3x.png

 

 

이제 bootsplash를 사용하기 위한 빌드 세팅이 필요하다.

 

- iOS

ios/projectName/AppDelegate.mm 파일에 다음 명령어를 넣는다.

 

#import "RNBootSpash.h" // 맨 위에 추가

- (void)customizeRootView:(RCTRootView *)rootView {
  [RNBootSplash initWithStoryboard:@"BootSplash" rootView:rootView];
}
// @implementation AppDelegate 안에 추가 (@end 전에)

 

- android

1. android/app/src/main/res/values/styles.xml

<resources>
  <style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
  </style>

  <!--여기 아래를 추가한다-->
  <style name="BootTheme" parent="Theme.BootSplash">
    <item name="bootSplashBackground">@color/bootsplash_background</item>
    <item name="bootSplashLogo">@drawable/bootsplash_logo</item>
    <item name="postBootSplashTheme">@style/AppTheme</item>
  </style>
  <!--여기 위를 추가한다-->
</resources>

 

2. android/app/src/main/AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android">

  <!-- … -->

  <application
    android:name=".MainApplication"
    android:label="@string/app_name"
    android:icon="@mipmap/ic_launcher"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:allowBackup="false"
    android:theme="@style/AppTheme"> <!-- 이 줄 있는지 확인하고 없으면 추가 -->
    <activity
      android:name=".MainActivity"
      android:label="@string/app_name"
      android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
      android:launchMode="singleTask"
      android:windowSoftInputMode="adjustResize"
      android:exported="true"
      android:theme="@style/BootTheme"> <!-- 이 줄을 추가한다 -->
      <!-- … -->
    </activity>
  </application>
</manifest>

 

3. android/app/src/main/java/com/projectName/MainActivity.kt

// 여기 아래를 추가한다
import android.os.Bundle
import com.zoontek.rnbootsplash.RNBootSplash
// 여기 위를 추가한다

class MainActivity : ReactActivity() {

  // …

  // 여기 이 함수가 없으면 통째로, 있으면 아래 표기한 줄만 추가한다.
  override fun onCreate(savedInstanceState: Bundle?) {
    RNBootSplash.init(this, R.style.BootTheme) // 이 줄을 확인하고 추가한다.
    super.onCreate(savedInstanceState)
  }
  // 여기 이 함수가 없으면 통째로, 있으면 위에 표기한 줄만 추가한다.
}

 

준비는 끝났다. 상위 App.tsx (or AppInner.tsx)에 useEffect 구문을 추가한다.

import { useEffect } from "react";
import { Text } from "react-native";
import BootSplash from "react-native-bootsplash";

const App = () => {
  useEffect(() => {
    const init = async () => {
      // do multiple sync or async tasks
    };

    init().finally(async () => {
      await BootSplash.hide({ fade: true });
    });
  }, []);

  return <Text>My awesome app</Text>;
};

 

정적인 스플래시스크린 구현이 끝났다. 이제 동적인 애니메이션을 붙여보자.

 


 

[React Native] 리액트 네이티브에서 Lottie 사용하여 애니메이션 넣기 (RN 0.73)

해당 글을 읽고 로띠 import(구현)까지 끝났다고 가정한다.

 

const App = () => {
  useEffect(() => {
    const init = async () => {
      // 여기서 백엔드 로딩을 시작한다.
    };

    init().finally(async () => {
      setShowCustomSplash(true);
      await BootSplash.hide({fade:true});
      setTimeout(() => {
        setShowCustomSplash(false);
      }, 3000);
      // 애니메이션 로딩을 3초로 지정한다.
    });
  }, []);

  const [showCustomSplash, setShowCustomSplash] = useState(false);

  return showCustomSplash ? (
    <View
      style={{
        backgroundColor:’#FFFFFF’,
        {/* 아까 스플래시스크린 설정할 때 입력한 배경색과 동일한 색으로 설정한다. */}
        flex:1,
        {/* 화면을 전부 덮고 */}
        justifyContent:’center’,
        alignItems:’center’,
        {/* 가운데로 맞춘다. */}
      }}
    >

      <ExampleAnimation />
      {/* 가로세로 크기를 스플래시스크린 설정할 때 입력한 logo-width와 같게 설정한다. */}

    </View>

  ) : (
    <NavigationContainer></NavigationContainer>
    {/* 스플래시스크린 끝난 후 앱 내비게이터 진입 */}
  )
}

 

프론트단 구동 중 정적인 svg 스플래시 스크린이 작동한 후 백엔드 로딩을 시작하면서 동적인 로띠 스플래시 스크린이 작동, 3초 후 앱 메인화면에 진입하는 것을 확인할 수 있다.

반응형