본문 바로가기
IT

리액트 네이티브 앱 개발 #4-3 ChatGPT 따라하는 Expo 프로젝트

by SOGNOD 2024. 11. 12.
반응형

Expo 와 React Native 버전 동기화 이슈로

새로운 WebView 프로젝트를 만들어 보기로 함

요구조건:
React Native 하이브리드 앱 생성
앱 인트로, 메인화면, 로그인, footer 는 네이티브 영역
Footer 에 있는 MyPage  버튼을 누르면 웹(WebView) 영역이 나오도록
Android TargetSDK 34 를 지원
React Native Expo 및 JavaScript(TypeScript 아님)로 소스코드 생성

 

1. Expo CLI 설치

> npm install -g expo-cli

 

2. Expo 프로젝트 생성

> npx create-expo-app --template
> project-name?
> blank vs TypeScript 선택 
(expo init project-name 은 앞으로 지원하지 않음)

$ cd project-name
$ npx expo install react-native-webview

 

3. 프로젝트 실행

> npx expo start

안내 메세지:

Starting Metro Bundler
The following packages should be updated for best compatibility with the installed expo version:
  expo@51.0.38 - expected version: ~51.0.39
Your project may not work correctly until you install the expected versions of the packages.

실행은 되지만 ... 잡고 진행 하기로

 

3-1. Expo 패키지 버전이 CLI 와 충돌

expo@51.0.38이 설치되어 있지만, Expo CLI가 ~51.0.39 버전을 요구하고 있습니다.
프로젝트의 package.json 파일에 정의된 Expo 관련 패키지 버전이 CLI와 동기화되지 않은 상태입니다.

 

3-2. Expo 패키지 업그레이드 실행

> npx expo install expo

> npx expo-doctor (이것도 변경됨, 전에는 expo-cli doctor 입니다)

 

3-3. 기타 명령어

$ npx expo start (실행)
$ npx expo-doctor (local CLI 용)
$ npx expo install expo (Expo 패키지 동기화 업그레이드)
$ npx expo upgrade (권장 버전으로 설치)
$ npm outdated (설치 완료 후 종속성 확인)
$ npm cache clean --force (npm 캐시 정리)
$ npx expo start -c (Expo 캐시 정리)

 

3-4. 또 다른 경고 메세지

 React Native의 일부 패키지가 @babel/preset-env라는 패키지를 의존하고 있지만, 현재 프로젝트에 설치되어 있지 않다

warning "react-native > @react-native/codegen@0.74.87" has unmet peer dependency "@babel/preset-env@^7.1.6".
warning "react-native > @react-native/codegen > jscodeshift@0.14.0" has unmet peer dependency "@babel/preset-env@^7.1.6".

 

3-5. @babel/preset-env 설치

> npm install @babel/preset-env --save-dev

이후 메세지 사라짐 확인!! 두둥

 

4. App.js 파일 예제

import React, { useState } from 'react';
import { View, Text, Button, StyleSheet, SafeAreaView } from 'react-native';
import { WebView } from 'react-native-webview';

const IntroScreen = ({ onNext }) => (
  <View style={styles.centered}>
    <Text style={styles.title}>Welcome to Hybrid App</Text>
    <Button title="Start" onPress={onNext} />
  </View>
);

const LoginScreen = ({ onLogin }) => (
  <View style={styles.centered}>
    <Text style={styles.title}>Login</Text>
    <Button title="Login" onPress={onLogin} />
  </View>
);

const MainScreen = () => (
  <View style={styles.centered}>
    <Text style={styles.title}>Main Screen</Text>
  </View>
);

const MyPageScreen = () => (
  <WebView source={{ uri: 'https://goggle.com' }} style={{ flex: 1 }} />
);

const Footer = ({ onNavigate }) => (
  <View style={styles.footer}>
    <Button title="Home" onPress={() => onNavigate('main')} />
    <Button title="MyPage" onPress={() => onNavigate('mypage')} />
  </View>
);

const App = () => {
  const [currentScreen, setCurrentScreen] = useState('intro');

  const renderScreen = () => {
    switch (currentScreen) {
      case 'intro':
        return <IntroScreen onNext={() => setCurrentScreen('login')} />;
      case 'login':
        return <LoginScreen onLogin={() => setCurrentScreen('main')} />;
      case 'main':
        return <MainScreen />;
      case 'mypage':
        return <MyPageScreen />;
      default:
        return null;
    }
  };

  return (
    <SafeAreaView style={styles.container}>
      {renderScreen()}
      {currentScreen !== 'intro' && currentScreen !== 'login' && (
        <Footer onNavigate={setCurrentScreen} />
      )}
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
  },
  centered: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 20,
  },
  footer: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    padding: 10,
    backgroundColor: '#f8f8f8',
    borderTopWidth: 1,
    borderColor: '#ddd',
  },
});

export default App;

 

> npx expo start

반응형