AWS Mobile Hub을 이용한 react-native 애플리케이션 개발(Cloud API REST 호출)

AWS 모바일-허브가 대응react-native했기 때문에 매뉴얼(Developer Guide)을 기반으로 샘플 적용을 제작·시도했다.
이번에는 다이나모db로 표를 만들고 샘플을 따라 크루 앱을 만들었다.

개시하다


이전 글에서 로그인하고 다이나모db를 참조하는 간단한 샘플 프로그램을 실행해 보았습니다.

Backend 설정(Mobile Hub)


테이블 작성


명령에서 다음 조작을 실행하다
awsmobile database enable --prompt
설명서에 따라 Notes 표 작성
Welcome to NoSQL database wizard
You will be asked a series of questions to help determine how to best construct your NoSQL database table.

? Should the data of this table be open or restricted by user? Open
? Table name Notes

You can now add columns to the table.

? What would you like to name this column NoteId
? Choose the data type string
? Would you like to add another column Yes
? What would you like to name this column NoteTitle
? Choose the data type string
? Would you like to add another column Yes
? What would you like to name this column NoteContent
? Choose the data type string
? Would you like to add another column No


Before you create the database, you must specify how items in your table are uniquely organized. This is done by specifying a Primary key. The primary key uniquely identifies each item in the table, so that no two items can have the same key.
This could be and individual column or a combination that has "primary key" and a "sort key".
To learn more about primary key:
http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.CoreComponents.html#HowItWorks.CoreComponents.PrimaryKey


? Select primary key NoteId
? Select sort key (No Sort Key)

You can optionally add global secondary indexes for this table. These are useful when running queries defined by a different column than the primary key.
To learn more about indexes:
http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.CoreComponents.html#HowItWorks.CoreComponents.SecondaryIndexes

? Add index No
Table Notes saved

CRUD API 생성하기


다음 명령을 사용하여cloud-api를 만듭니다
awsmobile cloud-api enable --prompt
방금 작성한 Notes 표에서 생성을 선택합니다.로그인해야 함을 선택했습니다.
This feature will create an API using Amazon API Gateway and AWS Lambda. You can optionally have the lambda function perform CRUD operations against your Amazon DynamoDB table.


? Select from one of the choices below. Create CRUD API for an existing Amazon DynamoDB table
? Select Amazon DynamoDB table to connect to a CRUD API Notes
? Restrict API access to signed-in users Yes
Adding lambda function code on: 
/Users/masanao/dev/awsmobile/awsmobilejs/backend/cloud-api/Notes/
...
Path to be used on API for get and remove an object should be like:
/Notes/object/:NoteId

Path to be used on API for list objects on get method should be like:
/Notes/:NoteId

JSON to be used as data on put request should be like:
{
  "NoteTitle": "INSERT VALUE HERE",
  "NoteContent": "INSERT VALUE HERE",
  "NoteId": "INSERT VALUE HERE"
}
To test the api from the command line (after awsmobile push) use this commands
awsmobile cloud-api invoke NotesCRUD <method> <path> [init]
Api NotesCRUD saved

설정 반영하기


다음 명령을 사용하여 AWS 모듈 만들기
awsmobile push
제작에 시간이 좀 걸리니 완성되기를 기다리세요.
building backend
   building cloud-api
      zipping Notes
   generating backend project content
   backend project content generation successful
done, build artifacts are saved at: 
/Users/masanao/dev/awsmobile/awsmobilejs/.awsmobile/backend-build

preparing for backend project update: awsmobile
   uploading Notes-20180108140947.zip
   upload Successful  Notes-20180108140947.zip
done

updating backend project: awsmobile
awsmobile update api call returned with no error
waiting for the formation of cloud-api to complete
cloud-api update finished with status code: CREATE_COMPLETE

Successfully updated the backend awsmobile project: awsmobile

retrieving the latest backend awsmobile project information
awsmobile project's details logged at: awsmobilejs/#current-backend-info/backend-details.json
awsmobile project's access information logged at: awsmobilejs/#current-backend-info/aws-exports.js
awsmobile project's access information copied to: aws-exports.js
awsmobile project's specifications logged at: awsmobilejs/#current-backend-info/mobile-hub-project.yml
contents in #current-backend-info/ is synchronized with the latest in the aws cloud

프런트엔드 구축


App.js를 편집하고 CRUD의 코드를 씁니다.

모듈 import

import { API } from 'aws-amplify-react-native';

CRUD 코드에 대한 설명


샘플 코드를 직접 붙여넣기로 했습니다.
state 추가
state = {
  apiResponse: null,
  noteId: ''
     };

  handleChangeNoteId = (event) => {
        this.setState({noteId: event});
}
saveNote 함수 추가
  // Create a new Note according to the columns we defined earlier
    async saveNote() {
      let newNote = {
        body: {
          "NoteTitle": "My first note!",
          "NoteContent": "This is so cool!",
          "NoteId": this.state.noteId
        }
      }
      const path = "/Notes";

      // Use the API module to save the note to the database
      try {
        const apiResponse = await API.put("NotesCRUD", path, newNote)
        console.log("response from saving note: " + apiResponse);
        this.setState({apiResponse});
      } catch (e) {
        console.log(e);
      }
    }
getNote 함수 추가
  // noteId is the primary key of the particular record you want to fetch
      async getNote() {
        const path = "/Notes/object/" + this.state.noteId;
        try {
          const apiResponse = await API.get("NotesCRUD", path);
          console.log("response from getting note: " + apiResponse);
          this.setState({apiResponse});
        } catch (e) {
          console.log(e);
        }
      }
deleteNote 함수 추가
  // noteId is the NoteId of the particular record you want to delete
      async deleteNote() {
        const path = "/Notes/object/" + this.state.noteId;
        try {
          const apiResponse = await API.del("NotesCRUD", path);
          console.log("response from deleteing note: " + apiResponse);
          this.setState({apiResponse});
        } catch (e) {
          console.log(e);
        }
      }
render 함수 변경(View 변경)
<View style={styles.container}>
        <Text>Response: {this.state.apiResponse && JSON.stringify(this.state.apiResponse)}</Text>
        <Button title="Save Note" onPress={this.saveNote.bind(this)} />
        <Button title="Get Note" onPress={this.getNote.bind(this)} />
        <Button title="Delete Note" onPress={this.deleteNote.bind(this)} />
        <TextInput style={styles.textInput} autoCapitalize='none' onChangeText={this.handleChangeNoteId}/>
</View>

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
  textInput: {
      margin: 15,
      height: 30,
      width: 200,
      borderWidth: 1,
      color: 'green',
      fontSize: 20,
      backgroundColor: 'black'
   }
});
제작된 앱.출처
react-native의 샘플 원본을 바탕으로 하기 때문에 일부 필요하지 않은 원본 코드가 있지만 그대로 유지됩니다.
/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import Amplify from 'aws-amplify-react-native';
import { API } from 'aws-amplify-react-native';
import { withAuthenticator } from 'aws-amplify-react-native';
import aws_exports from './aws-exports';

Amplify.configure(aws_exports);

import React, { Component } from 'react';
import {
  Platform,
  StyleSheet,
  Text,
  Button,
  TextInput,
  View
} from 'react-native';

const instructions = Platform.select({
  ios: 'Press Cmd+R to reload,\n' +
    'Cmd+D or shake for dev menu',
  android: 'Double tap R on your keyboard to reload,\n' +
    'Shake or press menu button for dev menu',
});

class App extends Component<{}> {
  constructor(props) {
        super(props);
    this.state = {
      apiResponse: null,
      noteId: ''
    };
  }

  handleChangeNoteId = (event) => {
        this.setState({noteId: event});
  }

  // Create a new Note according to the columns we defined earlier
    async saveNote() {
      let newNote = {
        body: {
          "NoteTitle": "My first note!",
          "NoteContent": "This is so cool!",
          "NoteId": this.state.noteId
        }
      }
      const path = "/Notes";

      // Use the API module to save the note to the database
      try {
        const apiResponse = await API.put("NotesCRUD", path, newNote)
        console.log("response from saving note: " + apiResponse);
        this.setState({apiResponse});
      } catch (e) {
        console.log(e);
      }
    }
     // noteId is the primary key of the particular record you want to fetch
      async getNote() {
        const path = "/Notes/object/" + this.state.noteId;
        try {
          const apiResponse = await API.get("NotesCRUD", path);
          console.log("response from getting note: " + apiResponse);
          this.setState({apiResponse});
        } catch (e) {
          console.log(e);
        }
      }

     // noteId is the NoteId of the particular record you want to delete
      async deleteNote() {
        const path = "/Notes/object/" + this.state.noteId;
        try {
          const apiResponse = await API.del("NotesCRUD", path);
          console.log("response from deleteing note: " + apiResponse);
          this.setState({apiResponse});
        } catch (e) {
          console.log(e);
        }
      }

  render() {
    return (
<View style={styles.container}>
        <Text>Response: {this.state.apiResponse && JSON.stringify(this.state.apiResponse)}</Text>
        <Button title="Save Note" onPress={this.saveNote.bind(this)} />
        <Button title="Get Note" onPress={this.getNote.bind(this)} />
        <Button title="Delete Note" onPress={this.deleteNote.bind(this)} />
        <TextInput style={styles.textInput} autoCapitalize='none' onChangeText={this.handleChangeNoteId}/>
</View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
  textInput: {
      margin: 15,
      height: 30,
      width: 200,
      borderWidth: 1,
      color: 'green',
      fontSize: 20,
      backgroundColor: 'black'
   }
});
export default withAuthenticator(App);

실행

react-native run-ios

텍스트 상자에 NoteID를 입력하고 "Save Note"를 누르면 저장됩니다.
내용은 원본 코드에 적힌 것처럼 고정 문자를 등록합니다.
결국 샘플 소스일 뿐이라고.

AWS 확인

Mobile Hub 의 Cloud Logic 에 다음과 같이 등록합니다.

람바다도 확인했는데 노트스크루드-xxx라는 이름으로 등록된 것으로 확인됐다.

다이나모DB도 마찬가지로 표를 만들었고 데이터도 등록했다는 것을 알았다.

일반적인 CRUD라면 기본적으로 비프로그래밍을 통해 백엔드 논리를 생성할 수 있다.

좋은 웹페이지 즐겨찾기