모바일 관련하여 개발을 진행하다보니, App DataBase로 Realm을 선정하게 되었고, 이에 대해서 좀더 자세하게 알아보고자 한다. 

 

Realm : SQLite와 Core Data의 대안으로 ORM이나 SQLite보다 더 빠른 성능을 제공한다.

 

지원 가능 언어 ( 2019년 11월 20일 현재 ) 

  • 자바 , Java
  • 스위프트 , Swift
  • 오브젝티브-C , Objective-C
  • 자바스크립트 , Javascript
  • 닷넷 : .NET

이번 블로그는 자바스크립트와 React Native를 기준을 설명하겠다. 


Realm에 대한 상세한 가이드는  https://realm.io/docs/javascript/latest/ 를 참고한다면 더욱 도움이 될 것 같다. 

 

참고로 Expo에서는 Realm를 지원하지 않는다. 따라서 

v0.60을 기준으로 ( 나는 MacBook을 이용해서 실행하였다. )

 

$ npx react-native init <project_name>

 

그후, 해당 <project_name> 폴더로 가서 

 

$ cd <project_name>

$ npm install --save realm

 

이후 ios 폴더에서 

 

$ cd ios

$ pod install 

 

위와 같이 진행하면 realm을 XCode에서 돌리기 위한 기본적인 절차는 끝이 났다.

 

위의 내용과 관련하여 이해가 안될 경우 아래의 링크를 참고하면 도움이 될 것이다.

npx, cocoapod, react-native 설치, XCode 호출에 대해서 알아보기

 

Realm의 공식 API 문서 

https://realm.io/docs/javascript/latest/api/

'알아보기' 카테고리의 다른 글

0004 Reactive Programming 2  (0) 2019.12.05
0004 Reactive Programming 1  (0) 2019.12.04
0002 Realm 활용하기 2  (0) 2019.11.22
0002 Realm 활용하기 3  (0) 2019.11.22
0003 자바를 이용한 병렬 프로그래밍 1  (0) 2019.11.20

React Native와 Realm 

 

로그인 정보를 App Data로 저장하기


로그인 정보를 App내에서 사용하기 위해서 모바일 App Database로 활용할 수 있는 다양한 App을 찾아 본 결과 

 

  • SQLite
  • Realm

크게는 SQLite 와 Realm을 주로 많이 사용하는 것으로 보이며, 이전에 SQLite로 개발했을 때 마치 RDB를 설계하는 듯한 느낌이 들어서

별로였었는데, Realm의 심플함에 반해서 Realm으로 넘어왔다. Mobile Database로 Realm을 추천하는 사례들도 많아졌기에 이번 App을 개발시에 적용해 보려한다. 

 

Realm 설치 


$ cd {React Native 프로젝트 경로}

 

$ npm insall --save realm

Realm 설치

 

$ react-native link realm

realm 연동

$ cd ios 

$ pod install

pod install 실행

 

이후 XCode를 실행시켜  Realm을 사용하는 방법을 알아보겠다.

 

 

 

Realm 사용하기 


Realm을 사용하기위한 DataBase Component 작성 

var Realm = require('realm');

const DataBase = ( props ) => {
    
    const LoginSchema = {
        name : 'Login',
        properties : {
            userId : 'string'
        }
    }

    const CategorySchema = {
        name: 'Category',
        properties: {
            categorySeqNo : 'int',
            categoryName  : 'string',
        }
    };

    const CategoryListSchema = {
        name: 'CategoryList',
        properties : {
            categoryList : { type : 'list' , objectType : 'Category' }
        }
    }

    let realm = new Realm({ schema : [LoginSchema, CategoryListSchema, CategorySchema]});

    return realm;
}

export default DataBase;

로그인의 일부 코드 

  saveUserId 함수를 보면, Realm을 이용해서 데이터를 저장하고, 가져오는 방식을 간단하게 작성해봤다.

  좀더 상세한 활용 방법 및 사용법은 https://realm.io/docs/javascript/latest/ 링크를 접속해서 확인할 수 있다. 

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

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

      this.realm = DataBase();

      console.log(this.realm)
    }
      
    static navigationOptions = {
        header: null,
    }

    saveUserId = async userIdValue => {
      try {
        let login = this.realm.objects('Login');

        if(!login["0"].userId){
          this.realm.write(() =>{
            this.realm.create('Login', { userId :  userIdValue })
          });
        }
        
        console.log(login);
        console.log(login["0"].userId);

      } catch (error) {
        // Error retrieving data
        console.log(error.message);
      }
    }

로그인 화면에서 id를 입력하고 값을 가져오는 방법 위와 같이 작성하면, 아래와 같은 결과를 얻을 수 있었다. 

shj@lines.com을 4번을 입력하고 그 중 첫번째 userId만 가져오도록 한 결과이다. 

 

Realm에 대해서는 추후에 별도로 정리할 예정이다. 

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

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 개발기 2  (0) 2019.11.15
0001 React Native App 개발기 1  (0) 2019.11.15

작성일 : 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