[React Native] 플랫폼별 코드 작성

크로스 플랫폼 앱을 만들 때, 가능한 많은 코드를 재사용하고 싶을 것입니다. 하지만 특정 상황에서는 코드를 다르게 구현하는 것이 합리적일 수 있습니다. 예를 들어 Android와 iOS에서 각각 다른 시각적 컴포넌트를 구현하고 싶을 때가 있습니다. react native는 코드를 플랫폼별로 분리하고 구성하는 두 가지 방법을 제공합니다.

  •  Platform 모듈 사용
  • 플랫폼별 파일 확장자 사용

특정 컴포넌트는 한 플랫폼에서만 작동하는 속성을 가질 수 있습니다. 이러한 속성은 @platform으로 주석이 달려 있으며, 웹사이트에서 작은 배지로 표시됩니다.

Platform 모듈

react native는 앱이 실행 중인 플랫폼을 감지하는 모듈을 제공합니다. 이 감지 로직을 사용하여 플랫폼별 코드를 구현할 수 있습니다. 이 옵션은 컴포넌트의 일부분만 플랫폼별로 다를 때 유용합니다.

import { Platform, StyleSheet } from 'react-native'

const styles = StyleSheet.create({
 height: Platform.OS === 'ios' ? 200 : 100
})

Platform.OS는 iOS에서 실행될 때 ios를 반환하고, Android에서 실행될 때 andorid를 반환합니다. 또한 Platform.select 메서드도 사용할 수 있습니다. 이 메서드는 'ios' | 'android' | 'native' | 'default' 중 하나를 키로 갖는 객체를 받아 현재 실행중인 플랫폼에 가장 적합한 값을 반환합니다. 이 키들이 지정되지 않으면 native 키가 사용되고, 그 다음으로 default 키가 사용됩니다.

import { Platform, StyleSheet } from 'react-native'

const styles = StyleSheet.create({
 container: {
  flex: 1,
  ...Platform.select({
   ios: {
    backgroundColor:'red'
   },
   android: {
    backgroundColor: 'green'
   },
   default: {
    backgroundCOlor: 'blue'
   }
  })
 }
})

이렇게 하면 모든 플랫폼에서 flex:1이 적용되고 ios에서는 빨간색 배경, android에서는 초록생 배경, 다른 플랫폼에서는 파란색 배경이 적용됩니다. 이 메서드는 값을 반환하므로 아래와 같이 플랫폼별 컴포너느를 반환하는 데에도 사용할 수 있습니다.

const Component = Platform.select({
 ios: () => require('ComponentIOS'),
 android: () => require('ComponentAndroid')
})()

<Component />
const Component = Platform.select({
 native: () => require('ComponentNative'),
 default: () => requre('ComponentDefault')
})()

<Component />

Android 버전 감지

Android에서는 Platform 모듈을 사용하여 앱이 실행 중인 Android 플랫폼의 버전을 감지할 수 있습니다.

import { Platform } from 'react-native'
if(Platform.Version === 25) {
 console.log('Nougat에서 실행 중')
}

Version은 Android OS 버전이 아니라 Android API 버전으로 설정됩니다.

iOS 버전 감지

iOS에서는 Version이 -[UIDevice systemVersion]의 결과로, 현재 운영 체제 버전을 나타내는 문자열입니다. 예를 들어, 시스템 버전이 10.3일 수 있습니다. iOS의 주요 버전 번호를 감지하려면 다음과 같이 할 수 있습니다.

import { Platform } from 'react-native'

const majorVersionIOS = parseInt(Platform.Version, 10)
if(majorVersionIOS <= 9) {
 console.log('9 버전 이하')
}

플랫폼별 확장자

플랫폼별 코드가 더 복잡해지면 코드를 별도의 파일로 분리하는 것이 좋습니다. react native는 파일에 .ios. 또는 .android. 확장자가 있을 때 해당 플랫폼 파일을 자동으로 감지하고 로드합니다.

예를 들어, 프로젝트에 다음과 같은 파일이 있다고 가정해 보겠습니다.

  • BigButton.ios.js
  • BigButton.android.js

그런 다음 컴포넌트를 다음과 같이 임포트할 수 있습니다.

import BigButton from './BigButton'

react native는 실행 중인 플랫폼에 따라 올바른 파일을 자동으로 선택합니다.

네이티브 전용 확장자(NodeJS 및 Web과 코드 공유)

Android/iOS 차이 없이 NodeJS/Web과 React Native 간에 모듈을 공유해야 할 때 .native.js 확장자를 사용할 수 있습니다. 이는 특히 react native와 reactjs간에 공통 코드를 공유하는 프로젝트에 유용합니다.

예를 들어, 프로젝트에 다음과 같은 파일이 있다고 가정해 보겟습니다.

  • Container.js : 웹 번들러(webpack, Rollup 등)에 의해 선택됨
  • Container.native.js: React Native 번들러(Metro)에 의해 Android와 iOS에서 모두 선택됨

여전히 .native 확장자 없이 다음과 같이 임포트할 수 있습니다.

import Container from './Container'

웹 번들러를 구성하여 .native.js 확장자를 무시하게 하여, 프로덕션 번드레 사용되지 않는 코드가 포함되지 않도록 하여 최종 번들 크기를 줄일 수 있습니다.