태그
목차

플랫폼별 코드

생성일: 2024-04-10

수정일: 2024-04-10

크로스 플랫폼 앱을 개발할 때는 코드 재사용성을 극대화하는 것이 중요하다. 하지만 때로는 플랫폼별로 코드를 다르게 구현해야 할 상황이 생길 수 있다. 대표적인 예로 Android와 iOS에서 서로 다른 UI 컴포넌트를 사용하고 싶은 경우다.

React Native는 플랫폼별로 코드를 구성하고 분리할 수 있는 두 가지 방법을 제공한다:

일부 컴포넌트는 특정 플랫폼에서만 지원되는 props을 가지고 있다. React Native 공식 문서에서는 이런 속성들을 쉽게 구분할 수 있도록 @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에서 실행할 때는 android가 된다.

Platform.select 메서드를 사용하면 현재 실행 중인 플랫폼에 따라 동적으로 값을 선택할 수 있다. 이 메서드는 ios, android, native, default 중 하나를 키로 가지는 객체를 인자로 받는다.

메서드 내부적으로는 현재 플랫폼을 감지하여, 해당 플랫폼에 맞는 키의 값을 반환한다. 만약 앱이 iOS나 Android 같은 모바일 기기에서 실행 중이라면 iosandroid 키에 해당하는 값이 우선적으로 사용되고, 그 외의 경우에는 nativedefault 키 값이 사용된다.

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

const styles = StyleSheet.create({
  container: {
    flex: 1,
    ...Platform.select({
      ios: {
        backgroundColor: 'red',
      },
      android: {
        backgroundColor: 'green',
      },
      default: {
        // 웹 같은 다른 플랫폼
        backgroundColor: 'blue',
      },
    }),
  },
});

위 예시 코드는 Platform.select 를 활용하여 플랫폼에 따라 다른 스타일을 적용하는 방법을 보여준다. 모든 플랫폼에서는 flex: 1 이라는 공통 스타일을 가지지만, iOS에서는 배경색이 빨간색, Android에서는 녹색, 그 외의 플랫폼에서는 파란색으로 지정된다.

Platform.select 는 단순히 스타일뿐만 아니라 어떤 값이든 플랫폼별로 다르게 반환할 수 있다. 예를 들어, 아래와 같이 플랫폼에 따라 서로 다른 컴포넌트를 반환하는 것도 가능하다.

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

<Component />;
const Component = Platform.select({
  native: () => require('ComponentForNative'),
  default: () => require('ComponentForWeb'),
})();

<Component />;

Android 버전 감지

Android에서는 Platform 모듈을 사용하여 현재 실행 중인 Android 플랫폼의 버전을 감지할 수도 있다:

import { Platform } from 'react-native';

if (Platform.Version === 25) {
  console.log('Nougat에서 실행 중!');
}

Note

Version 은 Android OS 버전이 아니라 Android API 버전으로 설정된다. 매핑을 찾으려면 Android 버전 히스토리를 참조한다.

iOS 버전 감지

iOS에서는 Platform.Version 을 통해 현재 기기의 운영 체제 버전을 문자열 형태로 가져올 수 있다. 이 값은 내부적으로 UIDevicesystemVersion 속성을 사용하여 가져온다.

예를 들어 Platform.Version 값이 "10.3"이라면, iOS 10.3 버전에서 앱이 실행되고 있다는 것을 의미한다. 이 정보를 활용하여 특정 iOS 버전에서의 동작을 제어할 수 있다.

만약 iOS 10 이하에서는 다르게 처리해야 하는 로직이 있다면, 아래와 같이 Platform.Version 에서 주 버전(major version) 번호를 추출하여 비교할 수 있다.

import { Platform } from 'react-native';

const majorVersionIOS = parseInt(Platform.Version, 10);

if (majorVersionIOS <= 9) {
  console.log('Work around a change in behavior');
}

플랫폼별 확장자

플랫폼별 코드가 복잡할 때는 코드를 별도 파일로 분리하는 것을 고려해야 한다. React Native는 파일의 .ios. 또는 .android. 확장자를 감지하고 다른 컴포넌트에서 필요할 때 관련 플랫폼 파일을 로드한다.

예를 들어 프로젝트에 다음 파일들이 있다고 가정해 보자:

BigButton.ios.js
BigButton.android.js

그러면 다음과 같이 컴포넌트를 가져올 수 있다:

import BigButton from './BigButton';

React Native는 실행 중인 플랫폼에 따라 자동으로 올바른 파일을 선택한다.

Native 전용 확장자(즉, NodeJS 및 웹과 코드 공유)

모듈이 NodeJS/Web과 React Native 간에 공유되어야 하지만 Android/iOS 간에는 차이가 없는 경우 .native.js 확장자를 사용할 수 있다. 이는 React Native와 ReactJS 간에 공통 코드를 공유하는 프로젝트에 특히 유용하다.

예를 들어 프로젝트에 다음과 같은 파일이 있다고 가정해 보자:

Container.js # webpack, Rollup 또는 기타 웹 번들러에서 선택
Container.native.js # Android와 iOS 모두에 대해 React Native 번들러(Metro)에서 선택

물론 다음과 같이 .native 확장자 없이 import할 수 있다:

import Container from './Container';

Tip

프로덕션 번들에서 사용되지 않는 코드를 제거하여 최종 번들 크기를 줄이기 위해 웹 번들러가 .native.js 확장자를 무시하도록 설정하는 것이 좋다.