React Native 에서 Styled Component로 Dark 테마 추가하기, OS와 맞추기

햄스터아저씨·2021년 9월 2일
4

App 내에서 DarkMode, LightMode를 설정할 수 있게 하는 방법을 공유합니다

사용기술

  • React-Native
  • Expo
  • styled-components/native
  • styled-components의 ThemeProvider : 테마를 적용합니다
  • Appearance in React-Native : 테마를 변경할 수 있게 해줍니다

1. 테마 분리하기 - ThemeProvider

light 모드와 dark 모드에 사용할 테마를 분리해서 만듭니다.
styled-components는 이 theme 객체를 통째로 바꿔 테마를 변경합니다.

1.1 테마를 만듭니다. (src/Theme/index.ts)

export const light = {
  color: {
    mainBg: "#ffffff",
  },
};

export const dark = {
  color: {
    mainBg: "#000000",
  },
};

1.2 ThemeProvider를 사용합니다. (App.tsx)


import { ThemeProvider } from "styled-components";
import { light, dark } from "@src/Theme";
...

const App = () => {
  return (
    //...
    //일단 Theme를 light로 잠시 고정해둡니다. 변경하는 방법은 뒤쪽에서 설명합니다.
          <ThemeProvider theme={light}> 
    	 
            <NavigationContainer>
              <HomeStack />
            </NavigationContainer>
          </ThemeProvider>
    //...
  );
};

1.3 원하는 위치에서 설정한 Theme을 사용합니다.

ThemeProvider에서 설정한 Theme은 별다른 설정없이 StyledComponent에서 인자로 사용할 수 있습니다.

import styled from "styled-components/native";

...

// 첫번째 방법: props로 가져오기
const MyComp = styled.View`
  background: ${(props) => props.theme.color.mainBg};
  width: 100%;
  height: 100%;
`;

// 두번째 방법: 비구조화 할당으로 가져오기
const MyComp2 = styled.View`
  background: ${({ theme }) => theme.color.mainBg};
  width: 100%;
  height: 100%;
`;

여기까지 하면 light 테마가 적용된 것을 확인할 수 있습니다.
하지만 아직 테마 변경이 불가능하죠. 그래서 테마를 변경하는 기능을 추가하려고 합니다.

2. OS 테마값 읽기 - Apperarance

2.1 Apperarance 이해

이 객체는 오직 테마 변경만을 위해 존재합니다.

ReactNative 최신버전에서는 react-native-appearance 라이브러리는 deprecated 되었고 대신 Appearance가 통째로 react-native 내부에 포함되었습니다.
expo는 SDK 43부터 react-native-appearance를 지원하지 않습니다.

2.2 expo 설정 변경

expo를 사용하는 경우, app.json에 다음 내용이 추가되어야 합니다.
추가하지 않을 경우, 항상 light 만 사용하게 됩니다.

{
  "expo": {
    "userInterfaceStyle": "automatic",
    "ios": {
      "userInterfaceStyle": "automatic"
    },
    "android": {
      "userInterfaceStyle": "automatic"
    }
  }
}

//참고: https://github.com/facebook/react-native/issues/31806

2.3 OS 테마값 읽기

사용할 수 있는 방법이 2개가 있습니다.

  • 1. useColorScheme() - APP이 켜질때 OS 테마값 사용하기
    • 사용이 간단합니다.
    • 아래와 같이 App.tsxThemeProvider에서 사용하면 끝입니다.
    • 단점: 유저의 Theme가 변경되는 경우, 앱을 종료했다가 켜야 변경사항이 적용됩니다.
      대부분의 경우 이것으로도 충분하지만, 오전 오후마다 Theme이 자동으로 변경되는 유저의 경우 불편을 느낄 수 있습니다.
import { useColorScheme } from "react-native";
import { light, dark } from "@src/Theme";

const App = () => {
  return (
    //...
          <ThemeProvider theme={useColorScheme() === "light" ? light : dark}> 
            <NavigationContainer>
              <HomeStack />
            </NavigationContainer>
          </ThemeProvider>
    //...
  );
};
  • 2. Apperarance.getColorScheme() - 유저의 테마를 실시간으로 적용하기
    • 설정을 한번 더 읽습니다
    • 유저가 OS 테마를 변경하는 경우, 앱도 즉시 테마를 변경합니다.
import { Appearance } from "react-native";

const App = () => {
  const [appTheme, setAppTheme] = useState(light);

  useEffect(() => {
    Appearance.addChangeListener(({ colorScheme }) => {
      setAppTheme(Appearance.getColorScheme() === "dark" ? dark : light);
    });
    return () => {};
  }, []);

  return (
    //...
          <ThemeProvider theme={appTheme}>
            <NavigationContainer>
              <HomeStack />
            </NavigationContainer>
          </ThemeProvider>
    //...
  );
};
profile
서버도 하고 웹도 하고 시스템이나 인프라나 네트워크나 그냥 다 함.

1개의 댓글

comment-user-thumbnail
2024년 4월 1일

좋은 자료 감사합니다.

답글 달기