출시·고도화 중
React Native 안내서 · 3/6
React Native는 React 컴포넌트로 화면을 설명하면 그것을 각 플랫폼의 진짜 네이티브 뷰로 그립니다. 웹 페이지를 앱 안에 띄우는 방식이 아닙니다. 이 장에서는 코어 컴포넌트, 스타일과 Flexbox, 플랫폼 차이, 내비게이션, 네이티브 모듈과 New Architecture를 차례로 살펴봅니다.
HTML의 div나 p 대신 React Native가 제공하는 컴포넌트를 씁니다.
| 컴포넌트 | 하는 일 | Android / iOS 대응 |
|---|---|---|
View | 레이아웃 상자 | ViewGroup / UIView |
Text | 글자 표시 | TextView / UITextView |
Image | 이미지 표시 | ImageView / UIImageView |
TextInput | 글자 입력 | EditText / UITextField |
ScrollView | 스크롤 영역 | ScrollView / UIScrollView |
FlatList | 긴 목록(보이는 것만 그림) | 가상화 목록 |
Pressable | 누름 처리 | 터치 이벤트 |
모든 글자는 반드시 Text 안에 있어야 합니다. View 안에 글자를 바로 넣으면 오류가 납니다.
import { Image, Pressable, Text, View } from "react-native";
export function Profile({ onFollow }: { onFollow: () => void }) {
return (
<View style={{ padding: 16, gap: 8 }}>
<Image source={{ uri: "https://reactnative.dev/img/tiny_logo.png" }} style={{ width: 64, height: 64 }} />
<Text style={{ fontSize: 18, fontWeight: "600" }}>React Native</Text>
<Pressable onPress={onFollow}>
<Text>팔로우</Text>
</Pressable>
</View>
);
}네트워크 이미지는 크기를 알 수 없으므로 width·height를 직접 지정해야 합니다. 로컬 이미지는 require("./assets/icon.png")로 불러옵니다.
ScrollView는 자식을 한꺼번에 모두 그리므로 항목이 많으면 느려집니다. 길이가 정해지지 않은 목록에는 화면에 보이는 항목만 그리는 FlatList를 씁니다.
import { FlatList, Text } from "react-native";
type Todo = { id: string; title: string };
export function TodoList({ items }: { items: Todo[] }) {
return (
<FlatList
data={items}
keyExtractor={(item) => item.id}
renderItem={({ item }) => <Text style={{ padding: 12 }}>{item.title}</Text>}
ListEmptyComponent={<Text>할 일이 없습니다.</Text>}
/>
);
}스타일은 CSS와 비슷한 이름을 camelCase로 쓴 JavaScript 객체입니다. 단위 없는 숫자는 기기 독립 픽셀(dp)이고, 스타일은 부모에서 자식으로 상속되지 않습니다(중첩된 Text 사이에서만 일부 상속됩니다). 레이아웃은 Flexbox로 하며 웹과 달리 기본 방향 flexDirection이 column입니다.
import { StyleSheet, Text, View } from "react-native";
export function Row() {
return (
<View style={styles.row}>
<Text style={styles.label}>이름</Text>
<Text style={[styles.label, styles.value]}>홍길동</Text>
</View>
);
}
const styles = StyleSheet.create({
row: { flexDirection: "row", justifyContent: "space-between", padding: 16 },
label: { fontSize: 16 },
value: { fontWeight: "bold" },
});style에 배열을 넘기면 뒤의 스타일이 앞의 것을 덮어씁니다. 조건부 스타일을 만들 때 유용합니다.
같은 코드가 Android와 iOS에서 돌지만 플랫폼마다 다르게 처리해야 할 때가 있습니다. Platform API나 플랫폼별 파일 확장자를 씁니다.
import { Platform, StyleSheet } from "react-native";
const styles = StyleSheet.create({
card: {
padding: 16,
...Platform.select({
ios: { shadowColor: "#000", shadowOpacity: 0.1, shadowRadius: 8 },
android: { elevation: 3 },
}),
},
});
export const isIOS = Platform.OS === "ios";Button.ios.tsx와 Button.android.tsx를 만들고 ./Button으로 불러오면 번들러가 플랫폼에 맞는 파일을 고릅니다. 노치나 상태 표시줄을 피하려면 react-native-safe-area-context의 SafeAreaView를, 화면 크기에는 useWindowDimensions 훅을 씁니다.
React Native 자체에는 화면 이동 기능이 없습니다. Expo 프로젝트는 Expo Router를, CLI 프로젝트는 주로 React Navigation을 씁니다. Expo Router는 React Navigation 위에 만들어졌습니다.
import { Link, router, useLocalSearchParams } from "expo-router";
import { Button, Text, View } from "react-native";
// app/posts/[id].tsx
export default function Post() {
const { id } = useLocalSearchParams<{ id: string }>();
return (
<View>
<Text>글 번호 {id}</Text>
<Link href="/">홈으로</Link>
<Button title="다음 글" onPress={() => router.push(`/posts/${Number(id) + 1}`)} />
</View>
);
}JavaScript만으로 할 수 없는 기기 기능은 Kotlin·Java·Swift·Objective-C로 작성한 네이티브 모듈로 씁니다. 대부분은 이미 라이브러리로 나와 있으니 React Native Directory에서 먼저 찾아봅니다.
현재 React Native는 New Architecture를 기본으로 씁니다. 예전에는 JavaScript와 네이티브가 비동기 직렬화 메시지(브리지)로 통신했지만, New Architecture는 JSI로 JavaScript가 네이티브 객체를 직접 참조하고 필요하면 동기 호출도 할 수 있습니다. 네이티브 모듈은 필요할 때 불러오는 Turbo Native Module, 화면 렌더러는 Fabric이며, Codegen이 TypeScript 명세로부터 타입이 맞는 연결 코드를 생성합니다. 기본 JavaScript 엔진은 Hermes입니다.
import type { TurboModule } from "react-native";
import { TurboModuleRegistry } from "react-native";
export interface Spec extends TurboModule {
setItem(value: string, key: string): void;
getItem(key: string): string | null;
}
export default TurboModuleRegistry.getEnforcing<Spec>("NativeLocalStorage");Expo 프로젝트에서는 Swift·Kotlin으로 더 간단히 모듈을 쓸 수 있는 Expo Modules API도 쓸 수 있습니다(npx create-expo-module@latest --local).
View, Text, Image, FlatList 같은 코어 컴포넌트로 만들고, 실제 네이티브 뷰로 그려집니다.StyleSheet와 Flexbox(기본 방향 column)로 지정합니다.Platform과 .ios·.android 파일로 처리합니다.
댓글 0개
로그인 · 로그인하면 댓글을 남길 수 있습니다.
첫 댓글을 남겨 보세요.