리액트 네이티브(React Native),
엑스포(Expo)를 활용한 앱 만들기
들어가면서..
앱 기초지식인 컴포넌트, 속성(Props), 상태(useState)와 useEffect을 이해한다.
VSCode, React, React-native와 Expo를 활용하여
'나만의 꿀팁'이라는 컨셉의 앱 페이지를 제작하고, 페이지 이동을 위한 스택 네비게이션을 활용해본다.
1. 리액트 기본 개념 (컴포넌트, 상태, 속성, Hook)
본 앱을 제작하면서 리액트 네이티브(React-native)를 사용하지만, 이는 곧 리액트(React.js) 기반으로
만들어진 앱 개발 기술이기 때문에 아래 개념들을 잘 이해해야 페이지를 구성할 수 있다.
- 컴포넌트(Component) : UI를 구성하는 요소, 함수형, 클래스형이 있다.
ex) 상위) App → 하위), SafeAreaView, View, Text, ...
앱 개발시 컴포넌트화는 기능별 구성요소화를 통해 재사용이 용이해진다.
- 상태(State, useState) :
(1) state : 컴포넌트의 (상태값을) 변경 가능한 데이터 저장소. 출력을 위해서 render 필요.
뷰의 렌더링이 갱신될 때 동적 정보를 출력하기 위해 사용
setState(메서드)를 통해 상태값 변경
(2) useState : 컴포넌트의 상태값을 관리하는 함수
* 리액트에서 use로 시작하는 다양한 함수가 내장되어 있는데 이들을 Hook이라고 부른다.
Hook은 상태 관리, 최적화, 컴포넌트 작동 흐름 관리 등의 기능을 수행가능하다.
const App = () => {
const [A, setA] = useState(true);
return(
<SafeAreaView>
<Box rounded={true} size="large" color="red" />
</SafeAreaView>
);
};
export default App;
위 식은 useState의 활용 예시이다.
여기서 A는 상태값, setA는 상태값을 변경(업데이트)하는 함수이다.
SetA를 호출하면, A값이 true로 변경되며, useState 함수에 넣어준 파라미터는 상태값의 초깃값이다.
- 속성(Props, properties) : 상위 컴포넌트로부터 전달받는 속성(데이터)을 지닌 객체
ex) numberOfLines, resizeMode, ...
아래 코드를 보면 content라는 이름으로 MainPage.js에서 Card.js로 속성(데이터)를 전달하고 있는 모습이다.
- 컴포넌트에 속성(데이터)을 부여하여 전달할 땐, 키와 벨류(content={content})형태로 전달할 것
- 컴포넌트를 반복문 돌릴 땐, 컴포넌트마다 고유하다는 것을 표현하기 위해, map에서 나오는 인덱스(i)를
key={i} 속성 전달형태로 꼭 넣을 것
비구조 할당 방식(딕셔너리에서 키값을 바로 취해서 변수로 함수내에서 즉시 사용하는 방식)
MainPage.js에서 넘겨준 속성은 실제 받게되는 컴포넌트엥서 딕셔너리 데이터를 받았다고 생각하면 쉽다.
- useEffect : 화면이 그려진 다음 가장 먼저 실행되는 함수, 주로 데이터를 준비할 때 사용
화면 생성 → useEffect가 데이터 준비 → 상태 데이터 업데이트 후 화면 재생성
useEffect(()=>{
...화면이 그려진 다음 가장 먼저 실행되야 할 코드 작성 공간
},[])
※ 로딩 화면
import React from 'react';
import {View,Text,StyleSheet} from 'react-native';
export default function Loading(){
return(<View style={styles.container}><Text style={styles.title}>준비중입니다...</Text></View>)
}
const styles = StyleSheet.create({
container: {
//앱의 배경 색
flex:1,
justifyContent:'center',
alignItems:'center',
backgroundColor: '#fdc453',
},
title: {
fontSize:20,
fontWeight:'700'
}
})
※ MainPage.js 컴포넌트
useEffect(()=>{
navigation.setOptions({
title:'My Tips'
})
setTimeout(()=>{
setState(data.tip)
setCateState(data.tip)
setReady(false)
},1000)
}, [])
※ 적용 모습
2. 앱 상태 바(Status Bar) 사용
// 사전 설치
expo install expo-status-bar
- Status Bar는 컴포넌트마다 다르게 적용할 수도 있고, 앱 전체에 공통적으로 적용할 수도 있다.
특히 Style을 "auto", "light", "black"에 따라 색상이 다르니 배경색에 맞게 지정하도록 유의해야 한다.
import { StatusBar } from 'expo-status-bar';
export default function MainPage({navigation, route}) {
...
<StatusBar style='auto' />
...
}
3. 스택 네비게이션(Stack Navigation)
- 앱의 기능들을 페이지화 시켜주고, 페이지간 이동을 가능하게 해주는 라이브러리
// 사전 설치
yarn add @react-navigation/native
expo install react-native-screens react-native-safe-area-context react-native-gesture-handler
yarn add @react-navigation/stack
- Stack.Screen(페이지), Stack.Navigator(책갈피)
- ../navigation/StackNavigator.js 코드 내용
import React from 'react';
//스택 네비게이션 라이브러리 호출
import { createStackNavigator } from '@react-navigation/stack';
//페이지로 만들 컴포넌트 불러오기
import DetailPage from '../pages/DetailPage';
import MainPage from '../pages/MainPage';
import AboutPage from '../pages/AboutPage';
import LikePage from '../pages/LikePage';
//항상 상단에 선언하고 시작하는 것이 규칙!
const Stack = createStackNavigator();
const StackNavigator = () =>{ // 컴포넌트를 페이지처럼 여기게하는 기능인 네비게이터 태그 선언
return (
//위에서 선언한 const Stack = createStackNavigator(); Stack 변수에 들어있는 태그를 꺼내 사용합니다.
//Stack.Navigator 태그 내부(화면)를 스타일링하는 옵션↓
<Stack.Navigator
screenOptions={{
headerStyle: {
backgroundColor: "black",
borderBottomColor: "black",
shadowColor: "black",
height:100
},
headerTitleAlign:'left',
headerTintColor: "#fff",
headerBackTitleVisible: false
}}
>
{/* 컴포넌트를 페이지로 만들어주는 엘리먼트에 할당 */}
<Stack.Screen name="MainPage" component={MainPage}/>
<Stack.Screen name="DetailPage" component={DetailPage}/>
<Stack.Screen name="AboutPage" component={AboutPage}/>
<Stack.Screen name="LikePage" component={LikePage}/>
</Stack.Navigator>
)
}
export default StackNavigator;
- Navigation을 적용한 App.js 코드 내용
import React from 'react';
import { StatusBar } from 'expo-status-bar';
import {NavigationContainer} from '@react-navigation/native';
import StackNavigator from './navigation/StackNavigator'
export default function App() {
console.disableYellowBox = true;
return (
<NavigationContainer>
<StatusBar style="light" />
<StackNavigator/>
</NavigationContainer>);
}
- MainPage.js 적용 모습
export default function MainPage({navigation, route}) {
const [state,setState] = useState([])
const [cateState,setCateState] = useState([])
const [ready,setReady] = useState(true)
useEffect(()=>{
navigation.setOptions({
title:'My Tips'
})
setTimeout(()=>{
setState(data.tip)
setCateState(data.tip)
setReady(false)
},1000)
}, [])
const category = (cate) => {
if(cate=="전체보기"){
setCateState(state)
}else{
setCateState(state.filter((d)=>{
return d.category == cate
}))
}
}
return ready ? <Loading/> : (
<SafeAreaView style={styles.SafeArea}>
<ScrollView style={styles.container}>
...
<ScrollView style={styles.middleContainer} horizontal indicatorStyle='white'>
<TouchableOpacity style={styles.middleButtonAll} onPress={()=>{category('전체보기')}}><Text style={styles.middleButtonText}>전체보기</Text></TouchableOpacity>
<TouchableOpacity style={styles.middleButton01} onPress={()=>{category('생활')}}><Text style={styles.middleButtonText}>생활</Text></TouchableOpacity>
<TouchableOpacity style={styles.middleButton02} onPress={()=>{category('재테크')}}><Text style={styles.middleButtonText}>재테크</Text></TouchableOpacity>
<TouchableOpacity style={styles.middleButton03} onPress={()=>{category('반려견')}}><Text style={styles.middleButtonText}>반려견</Text></TouchableOpacity>
<TouchableOpacity style={styles.middleButton04} onPress={()=>{navigation.navigate('LikePage')}}><Text style={styles.middleButtonText}>꿀팁 찜</Text></TouchableOpacity>
</ScrollView>
<View style={styles.cardContainer}>
{/*하나의 카드 영역을 나타내는 View */}
{
cateState.map((content,i)=>{
return (<Card content={content} key={i} navigation={navigation}/>)
})
}
</View>
<StatusBar style='auto' />
</ScrollView>
</SafeAreaView>
);
}
4. 외부 공유하기(Share)
- Share를 통해 페이지를 외부로 공유할 수 있다.
import { Share } from "react-native";
...
export default function DetailPage({navigation,route}) {
...
const share = () => {
Share.share({
message:`${tip.title} \n\n ${tip.desc} \n\n ${tip.image}`,
});
}
5. Link 이동하기
- 사전 설치
expo install expo-linking
- 사용하기
import React,{useState,useEffect} from 'react';
import { StyleSheet, Text, View, Image, ScrollView,TouchableOpacity,Alert,Share } from 'react-native';
import * as Linking from 'expo-linking';
export default function DetailPage({navigation,route}) {
...
const link = () => {
Linking.openURL("https://ggommappooh.tistory.com/") //이동시킬 url 삽입
}
6. 생각하기
- 이번 개발일지를 작성하면서 짧은 기간 내에 정말 많은 개념들을 활용해서 개발했던 것 같다.
기초 이론이 되는 React, 그리고 React-native의 각 컴포넌트, 속성, 상태에 대한 개념을 계속해서 개발하면서 상기하고
별도의 도서 등을 통해 계속 익혀나가야 할 것 같다.
'DEV > App 개발' 카테고리의 다른 글
React Native 앱 만들기 :: 구글 파이어베이스(Firebase)를 활용한 서버 구성 (0) | 2022.08.11 |
---|---|
React Native 앱 만들기 :: React Native, Expo 앱 화면 만들기 (0) | 2022.07.22 |
React Native 앱 만들기 :: 자바스크립트 기본 개념 및 문법 (0) | 2022.07.12 |
댓글