iOS의 SafeAreaView와 SafeAreaViewProvider

에러 발생

아래와 같은 코드의 앱을 실행했을 때 사진과 같은 에러가 발생했다. 에러 메세지를 해석해보면 SafeAreaProvider가 없다는 뜻이다. SafeAreaView는 있는데 SafeAreaProvider는 또 무엇일까?

export default function App(): ReactElement {
  return (
  <SafeAreaView style={styles.safeAreaView}>
    <Text style={styles.text}>Hello React Native</Text>
    <MainNavigator />
  </SafeAreaView>
  );
}

error

SafeAreaView

SafeAreaView의 목적은 디바이스의 안전한 영역(the safe area) 내부에 컨텐츠를 렌더링하는 것이다. iOS11 이상의 iOS 기기에 대해서만 지원된다.

SafeAreaViewnavigation bar, tab bar, toolbar, status bar 등에 의해 가려지지 않는 영역에 컨텐츠를 렌더링한다. 또한, 기기별 물리적 제약(limitation)을 고려하여 컨텐츠를 안전하게 렌더링 한다. SafeAreaView 속의 컨텐츠는 iPhone13의 카메라 notch를 피해서 컨텐츠가 렌더링된다.

SafeAreaView 없음 SafeAreaView 적용

  • 왼쪽 - <Text> 컴포넌트를 <SafeAreaView> 하위에 포함하여 노치 영역을 피해 안전하게 렌더링 되었다.
  • 오른쪽 - <Text> 컴포넌트가 <SafeAreaView> 하위에 포함되지 않아 정상적으로 렌더링되지 않았다.

컴포넌트는 기본적으로 status bar를 무시하고 화면의 최상단부터 home indicator를 무시하고 최하단까지 위치하게 된다. 노치가 없더라도 <SafeAreaView>를 사용하지 않으면 컴포넌트가 status bar를 침범하여 렌더링된다.

SafeArea 조사



<SafeAreaProvider> - 앱의 최상단 컴포넌트

  1. SafeAreaView 내부의 컨텐츠가 status bar, physical limitation(notch)를 피해서 렌더링 되었다.

  2. 안전한 영역이기 때문에 굳이 <SafeAreaView>를 사용하지 않아도 정상적으로 렌더링된다.

  3. 5번 영역과 6번 영역의 부모 컴포넌트(React native paper 라이브러리BottomNavigation 컴포넌트)이다.

  4. <SafeAreaView>로 감싸지 않으면 정상적으로 렌더링 되지 않는다.(막대 영역을 침범한다)

옆의 사진은 아래의 코드를 실행한 것이다.

export default function App(): ReactElement {
  return (
    <SafeAreaProvider style={styles.rootBackGround}>
      <SafeAreaView style=>
        <Text style={styles.text}>Hello React Native</Text>
      </SafeAreaView>
      <Text style={[styles.text, {backgroundColor: MD2Colors.grey500}]}>Hello React Native</Text>
      <MainNavigator />
      <SafeAreaView>
        <Text style={[styles.text, {backgroundColor: MD2Colors.grey700}]}>Hello React Native</Text>
      </SafeAreaView>
    </SafeAreaProvider>
  );
}

react-native-safe-area-context

v5 이상의 reactive native paper라이브러리를 사용하려면 react-native-safe-area-context 라이브러리를 추가로 설치해야 한다.

$ npm install react-native-safe-area-context

이 라이브러리에서 중요한 것은 ProviderConsumer이다.

Provider

Provider는 descendent element들에게 inset 값을 제공하는 View 컴포넌트이다. `inset`이란 status bar, notch 등과 같은 system ui이다. 일반적으로 앱의 최상단에 한 개를 사용한다. Modal을 사용할 경우 Modal의 루트에도 사용해야 한다.

Consumer

가장 가까운 parent element인 Provider로부터 inset 값을 받아 사용하는 컴포넌트 또는 hook이다.

해결

react-native-safe-area-context 모듈을 설치한 뒤 코드를 수정하면 된다.

App 컴포넌트를 <SafeAreaProvider>로 감싸면 된다.

$ npm i react-native-safe-area-context
export default function App(): ReactElement {
  return (
    <SafeAreaProvider style={styles.safeAreaView}>
      <SafeAreaView>
        <Text style={styles.text}>Hello React Native</Text>
      </SafeAreaView>
      <MainNavigator />
    </SafeAreaProvider>
  );
}

reference

Comments