๐ŸŒ™ 42. React Native ๋‹คํฌ ๋ชจ๋“œ ์™„์ „ ์ •๋ฆฌ โ€” Appearance, ThemeProvider, Zustand๊นŒ์ง€

JM_Devยท2025๋…„ 5์›” 20์ผ
0
post-thumbnail

์š”์ฆ˜ ์ถœ์‹œ๋˜๋Š” ์•ฑ๋“ค์„ ๋ณด๋ฉด
๊ฑฐ์˜ ๋Œ€๋ถ€๋ถ„ ๋‹คํฌ ๋ชจ๋“œ(Dark Mode)๋ฅผ ์ง€์›ํ•œ๋‹ค.
๋ˆˆ์˜ ํ”ผ๋กœ๋ฅผ ์ค„์ด๊ณ , ๋ฐฐํ„ฐ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰๋„ ์ค„์ด๋ฉฐ, ์‚ฌ์šฉ์ž์˜ ์„ ํ˜ธ๋„์— ๋”ฐ๋ผ UI๋ฅผ ๋ฐ”๊พธ๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.

React Native์—์„œ๋„ ๋‹คํฌ ๋ชจ๋“œ๋ฅผ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์—ฌ๋Ÿฌ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.
์ด๋ฒˆ ๊ธ€์€ ์‹œ์Šคํ…œ ํ…Œ๋งˆ ๊ฐ์ง€๋ถ€ํ„ฐ ์ปค์Šคํ…€ ํ…Œ๋งˆ ์‹œ์Šคํ…œ ๊ตฌ์ถ•๊นŒ์ง€ ์ •๋ฆฌํ•œ ๊ธ€์ด๋‹ค.


โœ… 1. Appearance๋กœ ์‹œ์Šคํ…œ ๋‹คํฌ๋ชจ๋“œ ๊ฐ์ง€ํ•˜๊ธฐ

import { useColorScheme } from 'react-native';

const scheme = useColorScheme(); // 'light' | 'dark'
  • iOS, Android ๋ชจ๋‘ ์‚ฌ์šฉ์ž์˜ ์‹œ์Šคํ…œ ํ…Œ๋งˆ๋ฅผ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ์Œ
  • useEffect ์—†์ด ์ฆ‰์‹œ ํ™•์ธ ๊ฐ€๋Šฅ

๐ŸŽจ 2. ๋‹คํฌ ๋ชจ๋“œ ํ…Œ๋งˆ ๊ฐ์ฒด ๋งŒ๋“ค๊ธฐ

export const LightTheme = {
  background: '#ffffff',
  text: '#000000',
};

export const DarkTheme = {
  background: '#000000',
  text: '#ffffff',
};

๐Ÿ’… 3. ThemeProvider๋กœ ์ „์ฒด ์•ฑ์— ์ ์šฉ

styled-components ์‚ฌ์šฉ ์˜ˆ์‹œ

import { ThemeProvider } from 'styled-components/native';

const scheme = useColorScheme();
const theme = scheme === 'dark' ? DarkTheme : LightTheme;

return (
  <ThemeProvider theme={theme}>
    <App />
  </ThemeProvider>
);
const Title = styled.Text`
  color: ${(props) => props.theme.text};
`;

๐Ÿ” 4. ์ƒํƒœ ๊ธฐ๋ฐ˜ ํ…Œ๋งˆ ์ „ํ™˜ (Zustand or Context)

์‚ฌ์šฉ์ž๊ฐ€ ์ˆ˜๋™์œผ๋กœ ๋ผ์ดํŠธ/๋‹คํฌ ๋ชจ๋“œ๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋ ค๋ฉด ์ƒํƒœ ์ €์žฅ์ด ํ•„์š”ํ•˜๋‹ค.

Zustand ์˜ˆ์‹œ

const useThemeStore = create((set) => ({
  isDark: false,
  toggleTheme: () => set((state) => ({ isDark: !state.isDark })),
}));
const theme = isDark ? DarkTheme : LightTheme;
  • ์ž๋™ + ์ˆ˜๋™ ํ† ๊ธ€ ๋ชจ๋‘ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ
  • ์•ฑ ์„ค์ • ํ™”๋ฉด์—์„œ ํ…Œ๋งˆ ๋ณ€๊ฒฝ ๊ธฐ๋Šฅ ๋งŒ๋“ค๊ธฐ์—๋„ ์œ ๋ฆฌ

๐Ÿงช ํ…Œ์ŠคํŠธ ํŒ

ํ™˜๊ฒฝ๋‹คํฌ๋ชจ๋“œ ํ…Œ์ŠคํŠธ ๋ฐฉ๋ฒ•
iOS ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ์„ค์ • > Developer > Appearance
Android ์—๋ฎฌ๋ ˆ์ดํ„ฐ์„ค์ • > ๋””์Šคํ”Œ๋ ˆ์ด > ๋‹คํฌ ํ…Œ๋งˆ
ExpoExpo ์•ฑ > ์žฅ์น˜ ํ…Œ๋งˆ ๊ฐ์ง€ ๊ฐ€๋Šฅ

๐Ÿ“ ๋‚ด๊ฐ€ ๋А๋‚€ ์ 

์ฒ˜์Œ์—” ๋‹คํฌ๋ชจ๋“œ๋Š” UI์— ์ƒ‰์ƒ๋งŒ ๋ฐ”๊พธ๋Š” ๊ฑฐ๋ผ๊ณ  ์ƒ๊ฐํ–ˆ๋Š”๋ฐ,
์‚ฌ์šฉ์ž๊ฐ€ ์•ฑ์„ ์–ด๋–ป๊ฒŒ ๋А๋ผ๋Š”์ง€์— ์˜ํ–ฅ์„ ์ฃผ๋Š” ์ค‘์š”ํ•œ UX ํฌ์ธํŠธ๋ผ๋Š” ๊ฑธ ์•Œ๊ฒŒ ๋๋‹ค.

์ง€๊ธˆ์€ ๋ฌด์กฐ๊ฑด ๋‹คํฌ ๋ชจ๋“œ๋ฅผ ๊ธฐ๋ณธ์œผ๋กœ ๊ณ ๋ คํ•ด์„œ ๋””์ž์ธ ์‹œ์Šคํ…œ๋ถ€ํ„ฐ ์„ค๊ณ„ํ•˜๊ณ ,
Zustand๋ฅผ ์จ์„œ ์ˆ˜๋™ ํ† ๊ธ€๋„ ํ•จ๊ป˜ ์ง€์›ํ•˜๊ณ  ์žˆ๋‹ค.


๐ŸŒ— โ€œ์ข‹์€ ์•ฑ์€ ๋น›์—์„œ๋„ ์–ด๋‘ ์—์„œ๋„ ๋˜‘๊ฐ™์ด ๋ฉ‹์ ธ์•ผ ํ•œ๋‹ค.โ€


profile
๊ฐœ๋ฐœ์ž๋กœ ์ทจ์—…์„ ์ค€๋น„ ์ค‘ ์ด๋ฉฐ, ์—ด์‹ฌํžˆ ๊ณต๋ถ€ ์ค‘ ์ž…๋‹ˆ๋‹ค!

0๊ฐœ์˜ ๋Œ“๊ธ€