태그
목차

컬러 테마

앱에서 라이트 모드와 다크 모드를 지원하는 방법을 알아본다.

생성일: 2024-04-12

수정일: 2024-04-12

앱에서 라이트 모드와 다크 모드를 모두 지원하는 것은 흔한 일이다. 다음은 Expo 프로젝트에서 두 모드를 모두 지원하는 방법의 예시다.

설정

Android와 iOS에서 라이트 모드와 다크 모드 전환을 지원하려면 프로젝트에 추가 설정이 필요하다. (웹에서는 추가 설정이 필요하지 않다)

app.jsonuserInterfaceStyle 프로퍼티를 사용하여 사용 가능한 컬러 모드를 설정할 수 있다. 또한 android.userInterfaceStyle 또는 ios.userInterfaceStyle 을 원하는 값으로 설정하여 특정 플랫폼이 다른 컬러 모드를 지원하도록 구성할 수도 있다.

사용 가능한 옵션은 다음과 같다:

이 프로퍼티가 없으면 앱은 기본적으로 라이트 모드가 된다. 다음은 설정 예시다:

// app.json
{
  "expo": {
    "userInterfaceStyle": "automatic"
  }
}

개발 빌드에서는 네이티브 패키지 expo-system-ui 를 설치해야 한다. 그렇지 않으면 userInterfaceStyle 프로퍼티는 무시된다. 다음 명령어를 사용하여 프로젝트가 잘못 설정되었는지 확인할 수도 있다:

npx expo config --type introspect

프로젝트가 잘못 설정된 경우 다음과 같은 경고가 표시된다:

» android: userInterfaceStyle: Install expo-system-ui in your project to enable this feature.

순수 React Native 앱을 사용하는 경우

Android

AndroidManifest.xmlMainActivity(및 이 동작이 필요한 다른 모든 액티비티)에 uiMode 플래그가 있는지 확인한다:

<activity android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode">

MainActivity.java 에서 onConfigurationChanged 메서드를 구현한다:

import android.content.Intent; // <--- import
import android.content.res.Configuration; // <--- import
public class MainActivity extends ReactActivity {
  // ...

  @Override
  public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    Intent intent = new Intent("onConfigurationChanged");
    intent.putExtra("newConfig", newConfig);
    sendBroadcast(intent);
  }
  // ...
}

iOS

Info.plist 에서 UIUserInterfaceStyle 키를 사용하여 지원되는 스타일을 구성할 수 있다. 라이트 모드와 다크 모드를 모두 지원하려면 Automatic 을 사용한다.

테마 감지

프로젝트에서 테마를 감지하려면 react-nativeAppearance 또는 useColorScheme을 사용한다:

import { Appearance, useColorScheme } from 'react-native';

그런 다음 아래와 같이 useColorScheme() 훅을 사용한다:

function MyComponent() {
  let colorScheme = useColorScheme();

  if (colorScheme === 'dark') {
    // 다크 모드 렌더링
  } else {
    // 라이트 모드 렌더링
  }
}

경우에 따라 Appearance.getColorScheme() 으로 현재 테마를 명령적으로 가져오거나 Appearance.addChangeListener 로 변경 사항을 수신하는 것이 도움될 수 있다.

기본 예제

import { Text, StyleSheet, View, useColorScheme } from 'react-native';
import { StatusBar } from 'expo-status-bar'; // 테마에 따라 자동으로 바 스타일 전환

export default function App() {
  const colorScheme = useColorScheme();

  const themeTextStyle =
    colorScheme === 'light' ? styles.lightThemeText : styles.darkThemeText;
  const themeContainerStyle =
    colorScheme === 'light' ? styles.lightContainer : styles.darkContainer;

  return (
    <View style={[styles.container, themeContainerStyle]}>
      <Text style={[styles.text, themeTextStyle]}>
        Color scheme: {colorScheme}
      </Text>
      <StatusBar />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  text: {
    fontSize: 20,
  },
  lightContainer: {
    backgroundColor: '#d0d0c0',
  },
  darkContainer: {
    backgroundColor: '#242c40',
  },
  lightThemeText: {
    color: '#242c40',
  },
  darkThemeText: {
    color: '#d0d0c0',
  },
});

프로젝트를 개발하는 동안 다음 단축키를 사용하여 시뮬레이터 또는 기기의 테마를 변경할 수 있다:

이렇게 Expo 프로젝트에서 라이트 모드와 다크 모드를 모두 지원하려면 약간의 설정이 필요하지만, useColorScheme 훅을 사용하면 현재 테마에 따라 동적으로 스타일을 적용할 수 있다. 이를 통해 사용자의 선호도에 맞는 적응형 UI를 제공할 수 있다.