앱의 첫인상이 앱 아이콘이라면 스플래시 스크린은 앱을 만나러 가는 길이라고 정의할 수 있다. (중요하단 뜻이다.)
이번에는 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초 후 앱 메인화면에 진입하는 것을 확인할 수 있다.
'개발 및 알고리즘 > 알고리즘' 카테고리의 다른 글
| [React Native] 리액트 네이티브에서 구글로그인 구현하기 (@react-native-google-signin/google-signin) (2) | 2024.07.23 |
|---|---|
| [JS/typescript] Null 병합 연산자 ?? (물음표 2개) (1) | 2024.07.23 |
| [React Native] 리액트 네이티브에서 기기 설정 언어 확인하기 (react-native-localize) (1) | 2024.07.11 |
| [Programmers] 두 개 뽑아서 더하기* (0) | 2024.04.01 |
| 배열 (0) | 2024.03.20 |