AWS 데이터 스토리지

안녕히 계세요, 레도크스, 마피아, 아폴로!


Source post
백엔드와 프런트엔드 사이의 선이 끊어졌습니다!국가 관리자 발전의 혁신 절차.

웹과 모바일 응용 프로그램을 개발하는 데 가장 어려운 임무 중 하나는 장치 간에 데이터를 동기화하고 오프라인 작업을 실행하는 것이다.이상적인 상황에서 장치가 오프라인 상태일 때 고객은 응용 프로그램을 계속 사용할 수 있어야 합니다. 데이터에 접근할 수 있을 뿐만 아니라 데이터를 만들고 수정할 수 있습니다.디바이스가 온라인으로 복구되면 애플리케이션이 백엔드에 다시 연결되어 데이터를 동기화하고 충돌을 해결해야 합니다(있는 경우).모든 극단적인 상황을 정확하게 처리하려면 대량의 미분화 코드가 필요합니다. 자주적인 돌연변이와 증량 동기화를 가진 장치에서 AWS AppSync SDK 캐시를 사용할 때도 마찬가지입니다.
인터넷이나 오프라인에 연결하면 Amplify data Store는 장치에 지속적인 저장을 제공하여 데이터 변경을 기록, 읽기, 감시하고 클라우드와 장치 간에 쉽게 데이터를 동기화할 수 있습니다.
Amplify DataStore는 개발자가 오프라인 또는 온라인 스크립트를 위해 추가 코드를 작성하지 않고 분산 데이터를 사용하여 응용 프로그램을 작성할 수 있도록 합니다.
Amplify 데이터 저장소를 사용하여 AWS 계정이 필요 없거나 AWS AppSync와 Amazon DynamoDB를 사용하여 전체 백엔드를 오프라인으로 사용할 수 있습니다.
데이터 스토리지에는 GraphQL 백엔드의 변동분 동기화 및 여러 가지 충돌 해결 정책이 포함됩니다.

AWS의 장점은 Redux, MobX, Apollo 및 Relay에 비해 데이터 스토리지를 확장하는 것입니다.


AWS Amplify와 Redux를 비교할 때 MobX는 정확하지 않습니다. AWS Amplify는 상태 관리자일 뿐만 아니라 클라이언트 서버이기 때문에 클라이언트 서버 클래스에서 우리는 이를 Apollo와 Relay와 비교합니다.

1. 즉시 상자를 열면 바로 사용할 수 있다.


만약 한 기업의 모바일 응용 프로그램이 웹 플러그인 기술로 이루어진 구독 사건의 영향을 받지 않는다면 이 기업은 심각하지 않다고 생각한다.
현재 몇 개의 응용 프로그램이 웹 플러그인에서 일합니까?
나는 그렇게 생각하지 않는다. 왜냐하면 실시간으로 개발자가 백엔드와 백엔드에서 추가로 일하기 때문이다.
우리에 대해 말하자면 fullStack serverless AWS의 개발자들은 실시간성을 확대했다. 전단이든 후단이든 우리는 모든 모델의 웹 플러그인을 통합하기 위해 실현 코드를 작성할 필요가 없다. 왜냐하면 이것은 자동으로 생성된 것이기 때문에 우리는 모든 생성된 코드를 위해 문서를 작성해야 한다. 이런 코드는 우리의 프로젝트에서 GraphQL 모델 지령을 바탕으로 실현된다.큰 단어에 놀라지 않도록 AWS Amplify에 저장된 정의를 설명하는 예제 the last lesson 를 보여 드리겠습니다.
type Job
  @model
  @auth(
    rules: [
      {allow: owner, ownerField: "owner", operations: [create, update, delete]},
    ])
{
  id: ID!
  position: String!
  rate: String!
  description: String!
  owner: String
}
이것은 상점의 모델을 결정하는데 앞부분뿐만 아니라 뒷부분에도 적용된다.프런트엔드와 백엔드의 실제 출처그래, 그래, 나는 내 일생 동안 한 번이 아니라는 것을 안다. 왜냐하면 이것은 킬러급의 기능과 묘어와 Redux, MobX, Apollo, Relay이기 때문이다.
바로 이런 구조는 Redux, MobX, Apollo와 다르다. 이것은 백엔드와 백엔드 사이의 경계를 없앴다.모든 사람에게 AWS 확대 데이터 저장
백엔드에서 온 경우 분석 프로그램을 데이터베이스에 쓰고 구독을 모든 데이터 모델로 드래그할 필요가 없습니다.
서버 없음 - 백엔드 개발자들이 백엔드를 배우기 시작했을 때입니다. 왜냐하면 그들의 서비스는 시대를 따라가지 못하는 프로젝트에만 사용되고 실시간이 아니기 때문입니다.

2. 코드 생성.


위키백과에서 코드 생성의 의미를 모르면 나 없이 코드 생성을 읽을 수 있다. 이것은 우리 자신을 떠올리게 한다.
fetch나axios를 사용하시겠습니까?
deep forest API에 요청을 보내면 Redux, MobX, Apollo, Relay와 함께 이 API를 작성합니다.
이것은 오늘의 또 다른 뉴스다!
이 API 호출을 작성할 필요가 없습니다. 호출만 하면 됩니다.
이것은 서버 요청 코드로 이 상당히 큰 데이터베이스를 만들 필요가 없다는 것을 의미합니다. 왜냐하면 AWS Amplify 데이터 저장소에서, 그것들도 당신의 프로젝트에서 당신의 저장소를 바탕으로 생성되며, 그것들의 첫 번째 항목의 같은 GraphQL 그림에 의해 정의되기 때문입니다.이것은 명령입니다.
npm run amplify-modelgen
결과적으로 우리는 생성 코드를 포함하는 모델스 폴더를 얻었다.

그리고 서버로 전송된 graphql 폴더는 모든 요청이 Flow, TS 또는 vanilla JavaScript 형식으로 나타납니다.

3. 오프라인 데이터와 클라우드 동기화


응용 프로그램이 온라인으로 연결되면 서버에 추가 코드를 작성하여 요청할 필요가 없습니다.
때때로 당신은 자신이 믿을 수 없는 상황에 처해 있다는 것을 발견하지만, 뚜렷한 실패가 아닌 더 긴 시간을 기다리는 것이 가장 좋다.
Apollo에는 Apollo 링크 재시도 기능이 있으며 기본 시도 간에 지수 롤백과 서버 요청을 제공할 수 있습니다.확실히 그는 응답에서 GraphQL 오류의 재시도를 처리하지 않고 네트워크 오류만 처리합니다.
물론 Redux, MobX는 이 해결 방안이 없습니다. 클라이언트가 아니기 때문에 제3자 중간부품을 사용해야 합니다. 왜냐하면 REST는 퇴직한 할아버지처럼 손자와 손녀의 지원이 있기 때문입니다.GraphQL vs REST의 상세한 분석.
AWS Amplify 데이터 저장소는 아폴로 체인 재시험의 시뮬레이션 기능을 가지고 있을 뿐만 아니라 내장된 맞춤형 익숙한 프로그래밍 모델을 가지고 있으며 자동 버전 제어, 충돌 검측과 구름 속에서 해결된다.
AWS Amplify의 단점 중에서 Apollo 연결과 불러오기, 상자를 열면 오류로 전단에서 작성한 코드의 양을 줄일 수 있다는 것을 언급하고 싶습니다.
Official documentation
이 강의가 끝나면 Amplify 데이터 저장소를 사용하여 모바일 애플리케이션을 수집합니다.

가다


AWS Amplify 지원 채팅Discord
이 부분의 최종 코드는 Github 에서 찾을 수 있습니다.

클론 저장소


수업을 계속하면 5단계로 바로 넘어갈 수 있다.
git clone https://github.com/fullstackserverless/startup.git
프로젝트 폴더로 이동
cd startup
종속 항목 설치
yarn
또는
npm install

AWS 계정 등록


AWS를 등록하지 않으려면
우리는 this 설명에 따라 등록한다📃 비디오 강좌를 통해 우리는 모든 5단계를 검사했다.
은행카드 한 장 필요해요.💳, 여기서 1$보다 커야 합니다.💵
여기서 CLI(확대 명령줄 인터페이스)를 보고 배치합니다.

React 로컬 프로젝트에서 AWS Amplify 초기화


React 네이티브 프로젝트의 루트 디렉토리에서 AWS Amplify 프로젝트를 초기화합니다.
amplify init
우리는 다음과 같은 질문에 대답했다.

항목 초기화🚀

인증 플러그인 연결


현재 응용 프로그램은 이미 구름 속에 있습니다. 예를 들어 사용자가 우리의 응용 프로그램을 등록하고 로그인할 수 있도록 하는 기능을 추가할 수 있습니다.
우리는 인증 기능을 연결한다.
amplify add auth

클라우드에 변경 내용 제출💭
amplify push
✔ 모든 자원이 구름 속에서 갱신된다
우리는 항목을 수집하고 신분 검증의 조작을 검사한다.


어플리케이션 확대


데이터 저장을 시작하는 가장 빠른 방법은 npx 스크립트를 사용하여 프로그램을 확대하는 것입니다.
npx amplify-app@latest

종속 항목 설치


세부 설치here
React Native CLI가 있는 경우
yarn add @aws-amplify/datastore @aws-amplify/core @react-native-community/netinfo @react-native-community/async-storage
React Native>0.60을 사용하는 경우 iOS에서 다음 명령을 실행합니다.
cd ios && pod install && cd ..

API 플러그인 연결(App Sync)


the last lesson에 연결할 경우 이 단계를 건너뜁니다.
없는 경우 API 플러그인을 연결하십시오.
amplify add api

선택 항목이 선택되면 GraphQL 모드가 amplify/backend/api/<datasourcename>/schema.graphql 에서 열리고 여기에 모델을 삽입합니다.
type Job
  @model
  @auth(
    rules: [
      {allow: owner, ownerField: "owner", operations: [create, update, delete]},
    ])
{
  id: ID!
  position: String!
  rate: String!
  description: String!
  owner: String
}
추가 정보here

모델 생성


데이터를 모델링하고 데이터 저장에 사용되는 모델을 만드는 것이 첫 번째 단계입니다.GraphQL은 JavaScript, iOS, Android의 공통 언어로 사용되며 클라우드와 동기화할 때 네트워크 프로토콜로도 사용된다.GraphQL은 AppSync의 자동 병합과 같은 기능도 지원합니다.NPX 스크립트를 사용하거나 AMPLYPE CLI를 사용하여 명령줄에서 모델을 생성할 수 있습니다.

You do not need an AWS account to run it and use DataStore locally, however, if you want to synchronize with the cloud, it is recommended to install and configure Amplify CLI as in the last lesson


기왕 우리가 지난 수업에서 회로를 묘사한 이상, 지금은 명령을 실행할 수 있다
npm run amplify-modelgen
src/models 폴더에서 생성된 모델 가져오기

API 업데이트


우리는 모든 API의 데이터 저장소를 포함한다
amplify update api

클라우드에 변경 내용 제출💭
amplify push
✔ 모든 자원이 구름 속에서 갱신된다

읽다


JobsMain src/screens/Jobs/JobsMain을 만듭니다.js 화면

이 화면에서, 우리는 페이지 나누기 옵션을 사용하여 조회할 것입니다. 그 중 숫자는useQuery를 통해 연결됩니다. 숫자는 우리에게 그룹으로 되돌아오고, 우리는 그것을 Flatlist로 보냅니다.
import React, { useEffect, useState } from 'react'
import { FlatList } from 'react-native'
import { Auth } from 'aws-amplify'
import { AppContainer, CardVacancies, Space, Header } from 'react-native-unicorn-uikit'
import { DataStore } from '@aws-amplify/datastore'
import { Job } from '../../models'
import { goBack, onScreen } from '../../constants'

const JobsMain = ({ navigation }) => {
  const [data, updateJobs] = useState([])

  const fetchJobs = async () => {
    const mess = await DataStore.query(Job)
    updateJobs(mess)
  }

  useEffect(() => {
    fetchJobs()
    const subscription = DataStore.observe(Job).subscribe(() => fetchJobs())
    return () => {
      subscription.unsubscribe()
    }
  }, [data])

  const _renderItem = ({ item }) => {
    const owner = Auth.user.attributes.sub
    const check = owner === item.owner
    return (
      <>
        <CardVacancies obj={item} onPress={onScreen(check ? 'JOB_ADD' : 'JOB_DETAIL', navigation, item)} />
        <Space height={20} />
      </>
    )
  }

  const _keyExtractor = (obj) => obj.id.toString()

  return (
    <AppContainer onPress={goBack(navigation)} flatlist>
      <FlatList
        scrollEventThrottle={16}
        data={data}
        renderItem={_renderItem}
        keyExtractor={_keyExtractor}
        onEndReachedThreshold={0.5}
        ListHeaderComponent={
          <Header
            onPress={goBack(navigation)}
            onPressRight={onScreen('JOB_ADD', navigation)}
            iconLeft="angle-dobule-left"
            iconRight="plus-a"
          />
        }
        stickyHeaderIndices={[0]}
      />
    </AppContainer>
  )
}

export { JobsMain }
공백에 대한 자세한 내용을 보려면 screen JobDetail src/screens/Jobs/JobDetail을 만듭니다.회사 명

import React from 'react'
import { Platform } from 'react-native'
import { AppContainer, CardVacancies, Space, Header } from 'react-native-unicorn-uikit'
import { goBack } from '../../constants'

const JobDetail = ({ route, navigation }) => {
  return (
    <AppContainer>
      <Header onPress={goBack(navigation)} iconLeft="angle-dobule-left" />
      <CardVacancies obj={route.params} detail />
      <Space height={Platform.OS === 'ios' ? 100 : 30} />
    </AppContainer>
  )
}

export { JobDetail }

업데이트 삭제 만들기


화면 JobAdd src/screens/Jobs/JobAdd를 만듭니다.js, 여기서 함수 CREATE UPDATE DELETE를 실행합니다.

import React, { useState, useEffect, useRef } from 'react'
import { AppContainer, Input, Space, Button, Header, ButtonLink } from 'react-native-unicorn-uikit'
import { DataStore } from '@aws-amplify/datastore'
import { Formik } from 'formik'
import * as Yup from 'yup'
import { Job } from '../../models'
import { goBack } from '../../constants'

const JobAdd = ({ route, navigation }) => {
  const [loading, setLoading] = useState(false)
  const [check, setOwner] = useState(false)
  const [error, setError] = useState('')

  const [input, setJob] = useState({
    id: '',
    position: '',
    rate: '',
    description: ''
  })

  const formikRef = useRef()

  useEffect(() => {
    const obj = route.params
    if (typeof obj !== 'undefined') {
      setOwner(true)
      setJob(obj)
      const { setFieldValue } = formikRef.current
      const { position, rate, description } = obj
      setFieldValue('position', position)
      setFieldValue('rate', rate)
      setFieldValue('description', description)
    }
  }, [route.params])

  const createJob = async (values) => (await DataStore.save(new Job({ ...values }))) && goBack(navigation)()

  const updateJob = async ({ position, rate, description }) => {
    try {
      setLoading(true)
      const original = await DataStore.query(Job, input.id)
      const update = await DataStore.save(
        Job.copyOf(original, (updated) => {
          updated.position = position
          updated.rate = rate
          updated.description = description
        })
      )
      update && goBack(navigation)()
      setLoading(false)
    } catch (err) {
      setError(err)
    }
  }

  const deleteJob = async () => {
    try {
      setLoading(true)
      const job = await DataStore.query(Job, input.id)
      const del = await DataStore.delete(job)
      del && goBack(navigation)()
      setLoading(false)
    } catch (err) {
      setError(err)
    }
  }

  return (
    <AppContainer onPress={goBack(navigation)} loading={loading} error={error}>
      <Header onPress={goBack(navigation)} iconLeft="angle-dobule-left" />
      <Space height={20} />
      <Formik
        innerRef={formikRef}
        initialValues={input}
        onSubmit={(values) => (check ? updateJob(values) : createJob(values))}
        validationSchema={Yup.object().shape({
          position: Yup.string().min(3).required(),
          rate: Yup.string().min(3).required(),
          description: Yup.string().min(3).required()
        })}
      >
        {({ values, handleChange, errors, setFieldTouched, touched, isValid, handleSubmit }) => (
          <>
            <Input
              name="position"
              value={values.position}
              onChangeText={handleChange('position')}
              onBlur={() => setFieldTouched('position')}
              placeholder="Position"
              touched={touched}
              errors={errors}
            />
            <Input
              name="rate"
              keyboardType="numeric"
              value={`${values.rate}`}
              onChangeText={handleChange('rate')}
              onBlur={() => setFieldTouched('rate')}
              placeholder="Rate"
              touched={touched}
              errors={errors}
            />
            <Input
              name="description"
              value={values.description}
              onChangeText={handleChange('description')}
              onBlur={() => setFieldTouched('description')}
              placeholder="Description"
              touched={touched}
              errors={errors}
              multiline
              numberOfLines={5}
            />
            <Space height={40} />
            <Button title={check ? 'Update' : 'Create'} disabled={!isValid} onPress={handleSubmit} formik />
            {check && (
              <>
                <Space height={10} />
                <ButtonLink title="or" textStyle={{ alignSelf: 'center' }} />
                <Space height={15} />
                <Button title="DELETE" onPress={deleteJob} cancel />
              </>
            )}
          </>
        )}
      </Formik>
      <Space height={100} />
    </AppContainer>
  )
}

export { JobAdd }
스크린/작업/색인에서.js 화면 내보내기
export * from './JobsMain'
export * from './JobDetail'
export * from './JobAdd'

항행


작업 가져오기 화면을 추가하고 StackNavigator에 연결
import * as React from 'react'
import { createStackNavigator } from '@react-navigation/stack'
import { enableScreens } from 'react-native-screens' // eslint-disable-line
import { Hello, SignUp, SignIn, ConfirmSignUp, User, Forgot, ForgotPassSubmit } from './screens/Authenticator'
import { JobsMain, JobDetail, JobAdd } from './screens/Jobs'

enableScreens()

const Stack = createStackNavigator()

const AppNavigator = () => {
  return (
    <Stack.Navigator
      screenOptions={{
        headerShown: false
      }}
      initialRouteName="HELLO"
    >
      <Stack.Screen name="HELLO" component={Hello} />
      <Stack.Screen name="SIGN_UP" component={SignUp} />
      <Stack.Screen name="SIGN_IN" component={SignIn} />
      <Stack.Screen name="FORGOT" component={Forgot} />
      <Stack.Screen name="FORGOT_PASSWORD_SUBMIT" component={ForgotPassSubmit} />
      <Stack.Screen name="CONFIRM_SIGN_UP" component={ConfirmSignUp} />
      <Stack.Screen name="USER" component={User} />
      <Stack.Screen name="JOBS_MAIN" component={JobsMain} />
      <Stack.Screen name="JOB_DETAIL" component={JobDetail} />
      <Stack.Screen name="JOB_ADD" component={JobAdd} />
    </Stack.Navigator>
  )
}

export default AppNavigator

작업 단추


스크린/Authenticator/User/index에서 사용자 화면을 편집합니다.회사 명
import React, { useState, useEffect } from 'react'
import { Auth } from 'aws-amplify'
import * as Keychain from 'react-native-keychain'
import { AppContainer, Button } from 'react-native-unicorn-uikit'
import { goHome, onScreen } from '../../../constants'

const User = ({ navigation }) => {
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState('')

  useEffect(() => {
    const checkUser = async () => {
      await Auth.currentAuthenticatedUser()
    }
    checkUser()
  })

  const _onPress = async () => {
    setLoading(true)
    try {
      await Auth.signOut()
      await Keychain.resetInternetCredentials('auth')
      goHome(navigation)()
    } catch (err) {
      setError(err.message)
    }
  }

  const _onPressJob = () => onScreen('JOBS_MAIN', navigation)() // переход на экран JOBS_MAIN

  return (
    <AppContainer message={error} loading={loading}>
      <Button title="Sign Out" onPress={_onPress} />
      <Button title="Jobs" onPress={_onPressJob} />
    </AppContainer>
  )
}

export { User }
애플리케이션 구축 및 테스트

Source post

도은✅


참고 문헌:


https://aws-amplify.github.io
https://learning.oreilly.com/library/view/full-stack-serverless/9781492059882/
https://www.altexsoft.com/blog/engineering/graphql-core-features-architecture-pros-and-cons/
https://engineering.fb.com/core-data/graphql-a-data-query-language/
https://graphql.org/learn

좋은 웹페이지 즐겨찾기