React Native를 위한 Create React App와 같다.
Create React App을 쓰는 이유는 webpack 등 별도의 설정 없이 쉽게 React JS를 사용하기 위한 것이다.
Expo나 React Native CLI도 마찬가지다. CLI와 차이는 시작하는 법과 약간 타협을 해야하는 것이다.
⇒ 앱의 요구사항들을 먼저 파악해서 Expo로만 가능할지를 판단하는 것이 중요하다.
Expo로부터 설정 파일을 모두 꺼내올 수 있다. Xcode와 Android studio와 모든 파일을 노출시킨다. 그러면, 프로젝트는 React Native와 Expo SDK로 이루어진 네이티브 프로젝트가 된다. 양쪽의 좋은 점을 모두 쓸 수 있게 되는 것이다. ( Expo SDK를 쓰면서 필요없는 API를 지워 용량을 줄이는 등..)
⇒ Managed Workflow (Expo)로 시작해서 나중에 한계가 생기면 eject로 Bare Workflow(Native 프로젝트)로 변환해라
Expo CLI 전역 설치
// 콘솔에서 커맨드를 실행하려면, 커맨드가 앱과 터미널 전역으로 설치되어야 함
npm install --global expo-cli
프로젝트 생성
expo init [프로젝트 이름]
/*
템플릿 선택
-- Managed workflow--
> blank - 빈 캔버스에서 시작
> blank (TypesScript)
> tabs (TypeScript) => 탭 네비게이션
--Bare workflow--
=> Android Studio와 Xcode 파일 접근 가능 (네이티브 모듈이 필요하면 선택)
> minimal
> minimal (TypeScript)
*/
이제 3가지 플랫폼을 기반으로한 (Web, iOS, Android)앱을 만들 수 있다. app.json
에서 앱을 열때 보이는 스크린 (splash), 앱의 아이콘, 타블렛 모드 등 설정 가능하다.
시뮬레이터를 이용하여 핸드폰 화면을 컴퓨터로 확인할 수 있다. Mac에 React Native 개발환경 구축하는 법이 잘 정리되어 있는 포스트를 참고하면서 iOS 에뮬레이터를 맥북에서 실행시킬 수 있었다.
맥(Mac)에 react native 개발 환경 구축하기
Xcode의 경우, 내가 사용하고 있는 Mac OS 버전이 낮아 애플 개발자 페이지에서 다운받을 수 있었다.
npm start
로 로컬에서 앱을 실행하면 Expo Go로 앱을 확인할 수 있는 QR코드가 나오는데, 핸드폰으로 앱의 모습을 확인할 수 있다. 컴퓨터에서 코드를 수정하면, 핸드폰 화면에 즉각적으로 반영되는 것을 확인할 수 있다.
Ctrl + Command + Z
커맨드로 개발자 Expo 메뉴를 에뮬레이터에서 열 수 있다.
메뉴에 있는 항목은 다음과 같은 기능을 한다.
// AppLoading 설치
expo install expo-app-loading
// 폰트 설치
expo install expo-font
// preload를 하기 위한 Asset 패키지
expo install expo-asset
유저가 앱을 보기 전에, 앱은 항상 준비되어 있어야한다. 예를 들면, 네비게이션 바에 보여질 로고나 폰트 등이 먼저 로딩이 되어있어야 한다.
그러기 위해서, AppLoading
이라는 컴포넌트를 사용한다. 로딩 상태일동안, 실행되어야할 작업을 마치고 로딩 상태가 끝나면 본격적으로 앱 화면이 렌더링된다.
AppLoading
에 사용되는 props가 있는데 다음과 같다.
loadAsync
라는 메서드를 사용)// App.tsx
...
export default function App() {
const [loading, setLoading] = useState(true);
const onFinish = () => setLoading(false);
const preload = async () => {
// 폰트
const fontToLoad = [Ionicons.font];
// loadAsync : font를 불러와서 Promise 배열로 만듦
const fontPromises = fontToLoad.map((font) => Font.loadAsync(font));
// 이미지
const imagesToLoad = [
require("./assets/logo.png"),
"https://upload.wikimedia.org/wikipedia/commons/thumb/2/2a/Instagram_logo.svg/2880px-Instagram_logo.svg.png",
]; // 로컬 이미지, url
// 로컬 이미지가 많으면, 앱이 무거워지니 다른 서버 url 사용 (이미지가 적으면, 로컬로 빌드)
const imagePromises = imagesToLoad.map((image) => Asset.loadAsync(image));
await Promise.all<Promise<void> | Promise<Asset[]>>([
...fontPromises,
...imagePromises,
]);
};
if (loading) { // 로딩이 끝나기 전까지, 스플래쉬 스크린만 계속 보임
return (
<AppLoading
startAsync={preload}
onError={console.warn}
onFinish={onFinish}
/>
);
}
return (
<View style={styles.container}>
<Text>Open up App.tsx to start working on your app!</Text>
<StatusBar style="auto" />
</View>
);
}