Neoself의 기술 블로그

React Native 라이브러리 없이 SplashScreen 구현하기(iOS) 본문

개발지식 정리/React Native

React Native 라이브러리 없이 SplashScreen 구현하기(iOS)

Neoself 2024. 7. 9. 00:28

React Native 앱의 경우 대표적으로 react-native-splash-screen 라이브러리를 통해 초기 SplashScreen 구현이 가능하다. 하지만 라이브러리들을 일괄적으로 업데이트할때마다 각 라이브러리의 네이티브 코드끼리 충돌이 생기는 이슈를 겪으면서, 라이브러리들을 자체적으로 모듈화하는 것이 유지보수에 더 용이할 것이라는 판단 하에, react-native-splash-screen 라이브러리의 대체방안을 모색하게 되었다.

 

가장 먼저 시도한 방안은 iOS가 기본 제공하는 LaunchScreen으로 SplashScreen을 구현하는 것이였다.

 

하지만, React Native로 구현된 앱의 경우 네이티브 앱과 달리 앱 초기 로드 간에 추가적인 단계가 필요하기에 일반적으로 더 많은 시간이 소요된다. 따라서, 네이티브 앱 생명주기만 고려된 LaunchScreen을 별도 조작없이 사용하게 될 경우, UI 렌더링이 완료되지 않은 시점에 SplashScreen이 내려가 빈 화면이 일시적으로 보이는 White Flash 현상을 확인할 수 있었다.

 

White Flash 현상

 

 

따라서 라이브러리를 사용하지 않고, SplashScreen이 올바른 시점에 내려가게 할 수 있는 방안은 크게 2가지가 존재한다.

  1. LaunchScreen이 사라지는 시점을 의도적으로 딜레이 시켜 Splash Screen 구현
  2. LaunchScreen이 사라지는 시점을 Javascript 단에서 직접 조작할 수 있는 네이티브 모듈 구현

1번의 경우, 네이티브와 Javascript 간의 통신이 불필요하기 때문에 쉽게 구현이 가능하다. 하지만, 기기사양에 따라 로드 완료 시점이 다르기에 최적의 앱 시작 시간을 보장해주지 않으며, 최악의 경우 WhiteFlash를 해결하지 못할 수도 있다. 하지만, 2번의 경우 앱 로딩이 완료된 이후에 실행되는 Javascript 단과 통신하기 때문에 정확한 앱 로드완료 시점을 파악할 수 있다. 따라서 2개 방법 중 자신의 상황에 맞는 LaunchScreen을 구현하면 되겠다.

 

본 게시글은 1번째 방안 즉, iOS LaunchScreen에 수동적으로 딜레이를 추가하는 방법을 다루고 있다. 만일 2번째 방법으로 SplashScreen을 구현하고자 할 경우, 다음 포스트를 확인하면 된다.

https://neoself.tistory.com/8

 

React Native 라이브러리 없이 SplashScreen 구현하기(iOS 네이티브 모듈)

React Native 앱의 경우 대표적으로 react-native-splash-screen 라이브러리를 통해 초기 SplashScreen 구현이 가능하다. 하지만 라이브러리들을 일괄적으로 업데이트할때마다 각 라이브러리의 네이티브 코드

neoself.tistory.com

 


 

하기와 같이, AppDelegate.mm 파일 내부에 선언되어있는 didFinishLaunchingWithOptions 함수를 수정하면 된다. 해당 함수는 앱이 처음 실행될때 호출되는 함수인데, 함수 내부에 React Native 프레임워크에서 제공하는 전용 뷰 컨트롤러인 RCTRootView를 호출하는 것을 볼 수 있다. 특히 RCTRootView 클래스에서 제공하는 setLoadingView 메서드에 launchScreen 인터페이스 기반의 view를 인자로 넘기는데, RCTRootView 클래스 정의 파일을 살펴보면, 인자로 전달한 view 객체를 SubView로써 화면에 렌더하는 것을 확인할 수 있다.

 

-RCTRootView 정의 파일 코드

더보기
더보기
- (void)setLoadingView:(UIView *)loadingView
{
  // UIView 클래스를 상속받은 loadingView 전역변수에 전달받은 view 전달
  _loadingView = loadingView;
  if (!_contentView.contentHasAppeared) {
    [self showLoadingView];
  }
}

- (void)showLoadingView
{
  if (_loadingView && !_contentView.contentHasAppeared) {
    _loadingView.hidden = NO;
    // 앞서 전달받은 loadingView를 subView로서 추가
    [self addSubview:_loadingView];
  }
}

 

White Flash가 발생하는 동안에 SubView를 계속 띄워줘야하기 때문에 loadingView가 사라지는 시점을 관여하는 loadingViewFadeDelay 속성을 설정해준다. 아래 설정한 0.5는 임의의 값이며, 앱이 사용되는 기기의 평균 성능을 고려해 조율하면 된다. 그리고 RCTRootView를 분석하던 중 loadingViewFadeDuration이라는 재밌는 속성값을 찾을 수 있었는데, 해당 속성값에 0보다 큰 값을 지정할 경우 Fade 애니메이션이 진행된다..! 자연스러운 메인화면 진입경험을 위해 해당 값도 설정해주었다.

#import <React/RCTRootView.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  
  self.moduleName = @"exampleApp";
  self.initialProps = @{};
  BOOL didFinish = [super application:application didFinishLaunchingWithOptions:launchOptions];
  if (didFinish) {
    RCTRootView *rootView = (RCTRootView *)self.window.rootViewController.view;
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"LaunchScreen" bundle:nil];
    [rootView setLoadingView:[[storyboard instantiateInitialViewController] view]];
    rootView.loadingViewFadeDelay = 0.5;
    rootView.loadingViewFadeDuration = 0.5;
  }
  
  return didFinish;
}

 

위 과정을 완료하고 나면, White Flash 현상이 보이지 않게 되는 것을 확인할 수 있으며, 덤으로 부드러운 Fade 애니메이션도 추가할 수 있게 된다...

 

 

 

 

 


Reference

https://velog.io/@chloedev/React-native-Splash-Screen-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0-

iOS-android

 

[React-native] Splash Screen 적용하기 (iOS & android)

스플래쉬 스크린이란 일반적으로 애플리케이션 실행 시 페이지의 컨텐츠가 로딩되기까지 일시적으로 보여주는 화면을 말한다. 회원정보를 불러오거나 보여주기 싫은 처리를 하고 있을 때 스플

velog.io