작성일 : 2019년 11월 16일 

 

React-Native 기반하에 운동 Timer를 개발해보고자 한다. 

 


개발에 필요한 것

  • XCode ( Version 11.2 ) 
  • Terminal
  • Visual Studio Code 

개발 시 사용할 Modules

  • realm : App 데이터 저장소 
  • react-native-clean-form 
  • react-native-countdown-component 
  • react-navigation, react-navigation-statck, react-navigation-tabs

이외에도 다양한 모듈이 사용되었지만 메인이되었던 항목들을 나열하였다. 

 

App.js 구성 


React Native App이 진입점은 index.js 파일이고, index.js 파일을 보면 아래와 같이 구성되어 있다. 

/**
 * @format
 */

import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';

AppRegistry.registerComponent(appName, () => App);

AppRegistry

 

Index.js 파일에서 로딩되는 App 파일을 기점으로 하여 간단하게 Timer App을 만들어보겠다.

 


import에 대해서 알고 싶으면 [더보기]를 클릭하세요.

더보기

import 와 export는 ES6(EcmaScript2015)에서 도입되었다. 현재 (2019년 11월 15일 현재) 브라우저에서 기본으로 제공되고 있지 

않습니다. 따라서 별도의 트랜스파일러(Transpiler)에 의해서 동작할 수 있습니다. 

 

아래는 Import와 Export를 사용하는 간단한 예시이며, 이외에도 다양한 방법으로 사용할 수 있다. 

// import 를 사용하는 간단한 예제 
import example from "example-module";
import example as ex from "example-module";
import { example1 } from "example-modules";
import { example1, example2 } from "example-modules";

// export 를 사용하는 간단한 예제 
export { example1 };
export example1;
export default example1; // 각각의 모듈 당 단하나의 default만 가질 수 있습니다. 
export let example1 = ..., example2 = ...;
export { example1, example2 } from ...;
 

 

개발을 위한 Module 설치


react-navigation은 V4를 사용한다.

 

npm을 통해 아래의 명령어를 실행하고, 

$ npm install --save react-navigation react-navigation-tabs react-navigation-stack

 

pod install 실행 

$ pod install 

 

하지만 제대로 실행되지 않고... 아래와같은 메세지가 뜬다.

pod install 시 발생한 에러 

그래서 아래의 모듈을 다시한번 설치해주고,

 

$ npm install --save @react-native-community/cli-platform-ios

 

이래도 pod install 시에 정상적으로 설치가 되지 않는다. 

pod install 시 에러

그래서 다시 한번 react-native app 폴더에서 npm install 을 진행하였다. 그랬더니 그제서야 정상적으로 pod install 이 동작했다. 

pod install 이 정상적으로 설치

 

 

pod install이 정상적으로 진행되고 난 뒤 xcworkspace 프로젝트를 열어 App을 실행했더니...

기동 이후 화면 로딩 시 에러 발생

 

흠... 알고 봤더니 @react-native-community/cli-platform-ios 이걸 설치하던 부분 부터 다시정리해보면,

react-navivation을 사용하기 위해 필요한 Package.json을 다시 아래와 같이 정의하고,

 

[package.json] 파일의 일부 , 

"react-native-gesture-handler": "^1.5.0",

"react-native-reanimated": "^1.4.0",

"react-navigation": "^4.0.10",

"react-navigation-stack": "^1.10.3",

"react-navigation-tabs": "^2.5.6"

 

package.json 파일 

아래와 같은 작업을 다시 실시하였다. 


  1. $ rm -rf node_modules
  2. package.json 재확인하여 정리 
  3. $ npm install 
  4. $ cd ios
  5. $ pod install 진행 
  6. xcworkspace 재오픈 처리 

최종 컴파일 화면


아래의 소스 코드는 로그인화면의 소스 코드이다. 로그인 화면은 구글링을 통해 제공되던 샘플을 공유한다. 

import React, {Component} from 'react';
import { View, Text, TextInput, StyleSheet, TouchableHighlight } from 'react-native';
import { widthPercentageToDP as wp } from 'react-native-responsive-screen';

export default class LoginScreen extends Component {
    
    constructor(props) {
      super(props);
      this.state = {
        email   : '',
        password: '',
      }
    }
      
    static navigationOptions = {
        header: null,
    }

    saveUserId = async userId => {
      try {
        await AsyncStorage.setItem('userId', userId);
      } catch (error) {
        // Error retrieving data
        console.log(error.message);
      }
    }

    onClickListener = (viewId) => {
      this.getMoviesFromApiAsync(() => { this.props.navigation.replace('TabNavigator') })      
    }

    getMoviesFromApiAsync = (executeFunc) => {

      if(this.state.email == '' || this.state.password  == '' ){
        alert("로그인을 위해서 값을 입력해주세요.")
        return;
      }

      const formData = new FormData();
      formData.append('email', this.state.email);
      formData.append('password', this.state.password);

      this.saveUserId(this.state.email);

      return fetch('http://localhost:9090/v1/accounts/login',
        {
          method: 'POST',
          body: formData
        })
        .then((response) => response.json())
        .then((responseJson) => {
          if(responseJson.userStatus.code == "2000"){
            executeFunc()
          }else{
            alert(responseJson.userStatus.message);
          }

          return responseJson.movies;
        })
        .catch((error) => {
          console.error(error);
        })
    }

    serializeJSON = (data) => {
      return Object.keys(data).map(function (keyName) {
        return encodeURIComponent(keyName) + '=' + encodeURIComponent(data[keyName])
      }).join('&');
    }


    render(){
        return (
        <View style={styles.container}>
            <View style={styles.titleArea}>
                <Text style={styles.title}>Excercise Timer</Text>
            </View>
            <View style={styles.inputContainer}>
              <TextInput style={styles.inputs}
                  placeholder="Email"
                  keyboardType="email-address"
                  autoCapitalize = 'none'
                  underlineColorAndroid='transparent'
                  onChangeText={(email) => this.setState({email})}/>
            </View>
            
            <View style={styles.inputContainer}>
              <TextInput style={styles.inputs}
                  placeholder="Password"
                  secureTextEntry={true}
                  underlineColorAndroid='transparent'
                  onChangeText={(password) => this.setState({password})}/>
            </View>
    
            <TouchableHighlight style={[styles.buttonContainer, styles.loginButton]} onPress={() => this.onClickListener('login')}>
              <Text style={styles.loginText}>Login</Text>
            </TouchableHighlight>


            <TouchableHighlight style={styles.buttonContainer} onPress={() => this.onClickListener('restore_password')}>
                <Text>Forgot your password?</Text>
            </TouchableHighlight>
          </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
      flex: 1,
      justifyContent: 'center',
      alignItems: 'center',
      backgroundColor: '#616155',
    },
    titleArea: {
        width: '100%',
        padding: wp('10%'),
        alignItems: 'center',
    },
    title: {
        fontSize: wp('10%'),
    },
    inputContainer: {
        borderBottomColor: '#F5FCFF',
        backgroundColor: '#FFFFFF',
        borderRadius:30,
        borderBottomWidth: 1,
        width:250,
        height:45,
        marginBottom:20,
        flexDirection: 'row',
        alignItems:'center'
    },
    inputs:{
        height:45,
        marginLeft:16,
        borderBottomColor: '#FFFFFF',
        flex:1,
    },
    inputIcon:{
      width:30,
      height:30,
      marginLeft:15,
      justifyContent: 'center'
    },
    buttonContainer: {
      height:45,
      flexDirection: 'row',
      justifyContent: 'center',
      alignItems: 'center',
      marginBottom:20,
      width:250,
      borderRadius:30,
    },
    loginButton: {
      backgroundColor: "#00b5ec",
    },
    loginText: {
      color: 'white',
    }
  });
  

'따라해보기' 카테고리의 다른 글

0001 React Native App 개발기 6-1  (0) 2019.12.12
0001 React Native App 개발기 5  (0) 2019.12.08
0001 React Native App 개발기 4  (0) 2019.11.22
0001 React Native App 개발기 3  (1) 2019.11.17
0001 React Native App 개발기 1  (0) 2019.11.15

+ Recent posts