웹에서 Tailwind에 익숙해진 다음 React Native로 넘어오면 StyleSheet.create가 답답하게 느껴진다. 색 하나 바꾸려고 컴포넌트 아래까지 스크롤해서 스타일 객체를 찾고, 이름 짓고, style={styles.xxx}로 연결하고. 간단한 레이아웃 하나에도 손이 많이 간다.
NativeWind는 그 Tailwind 문법을 React Native에서 그대로 쓰게 해준다. className에 유틸리티 클래스를 적으면 빌드 타임에 네이티브 스타일로 변환된다. 웹이랑 앱을 같이 만드는 프로젝트라면 스타일 언어를 통일할 수 있어서 더 좋다.
설치
npx expo install nativewind tailwindcss react-native-reanimated react-native-safe-area-context
tailwind.config.js를 만들고 content 경로를 잡아준다.
// tailwind.config.js
module.exports = {
content: ['./app/**/*.{js,jsx,ts,tsx}', './components/**/*.{js,jsx,ts,tsx}'],
presets: [require('nativewind/preset')],
theme: { extend: {} },
plugins: [],
}
babel.config.js에 preset도 추가한다. 이걸 빠뜨리면 className이 무시되고 스타일이 아예 안 먹힌다.
// babel.config.js
module.exports = function (api) {
api.cache(true)
return {
presets: [
['babel-preset-expo', { jsxImportSource: 'nativewind' }],
'nativewind/babel',
],
}
}
마지막으로 글로벌 CSS 파일을 만들어 앱 진입점에서 import 한다.
/* global.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
컴포넌트에서 쓰기
이제 style 대신 className을 쓰면 된다.
import { View, Text, Pressable } from 'react-native'
export default function Card({ title, onPress }: Props) {
return (
<View className="m-4 rounded-2xl bg-white p-5 shadow-md">
<Text className="text-lg font-bold text-gray-900">{title}</Text>
<Pressable
className="mt-3 rounded-lg bg-blue-500 px-4 py-2 active:bg-blue-600"
onPress={onPress}
>
<Text className="text-center font-semibold text-white">열기</Text>
</Pressable>
</View>
)
}
웹 Tailwind와 거의 똑같다. active: 같은 상태 변형도 그대로 동작한다. 다만 hover:처럼 터치 기기에 의미 없는 변형은 빠져 있고, 모든 CSS 속성이 다 되는 건 아니다. flex, spacing, color, border, 폰트 정도는 대부분 커버된다.
다크 모드와 반응형
dark: 접두사로 다크 모드를, sm: 같은 브레이크포인트로 화면 크기 대응을 할 수 있다.
<View className="bg-white dark:bg-gray-900">
<Text className="text-base text-gray-900 dark:text-gray-100 sm:text-lg">
안녕하세요
</Text>
</View>
다크 모드는 기본적으로 기기 설정을 따라간다. 직접 토글하고 싶으면 useColorScheme 훅으로 제어하면 된다.
StyleSheet가 나쁜 건 아니지만, 마크업 옆에 스타일이 바로 보이니까 컴포넌트를 읽고 고치는 속도가 확실히 빨라진다. 웹과 앱을 함께 굴리는 팀이라면 스타일 사고방식을 하나로 맞출 수 있다는 게 가장 큰 장점이다. 세팅에서 babel preset만 빼먹지 않으면 30분이면 붙는다.