AWS 시작하기

풀 스택 React 애플리케이션 구축

AWS Amplify를 사용하여 간단한 웹 애플리케이션 생성

모듈 5: 스토리지 추가

이 모듈에서는 앱에서 이미지를 메모에 연결하는 기능과 스토리지를 추가합니다.

개요

이제 메모 앱이 작동하므로 각 메모에 이미지를 연결하는 기능을 추가해보겠습니다. 이 모듈에서는 Amplify CLI와 라이브러리를 사용하여 Amazon S3 기반의 스토리지 서비스를 생성합니다. 그런 다음 이전 모듈에서 생성한 GraphQL 스키마를 업데이트하여 각 메모에 이미지를 연결합니다. 마지막으로, 이미지 업로드, 가져오기 및 렌더링을 지원하도록 React 앱을 업데이트합니다.

학습 목표

이 모듈에서는 다음을 수행합니다.
  • 스토리지 서비스 생성
  • GraphQL 스키마 업데이트
  • React 앱 업데이트

주요 개념

스토리지 서비스 - 이미지, 동영상 등의 파일을 저장하고 쿼리하는 기능은 대부분의 애플리케이션에서 기본적으로 요구됩니다. 이 기능을 구현하는 방법 중 하나는 파일을 Base64로 인코딩하고 문자열로 전송해 데이터베이스에 저장하는 것입니다. 이 방법은 인코딩된 파일의 크기가 원본 바이너리보다 커지고, 작업을 수행하는 데 컴퓨팅 리소스가 많이 소요되며, 적절하게 인코딩하고 디코딩하는 데 따른 복잡성이 가중된다는 단점이 있습니다. 다른 방법으로, 파일 저장용으로 특별히 구축되고 최적화된 스토리지 서비스를 이용할 수 있습니다. Amazon S3와 같은 스토리지 서비스는 이 기능을 최대한 높은 성능으로 쉽고 저렴하게 구현하기 위해 제공됩니다.

 소요 시간

10분

 사용 서비스

구현

  • 이미지 스토리지 기능을 추가하려면 Amplify 스토리지 카테고리를 사용합니다. 아래의 옵션은 대부분 기본값이 선택된 채로 두어도 되지만, 프롬프트를 계속 진행하려면 Enter 키를 누르기 전에 각 옵션에서 스페이스바를 눌러 생성/업데이트, 읽기삭제 옵션을 개별적으로 선택해야 합니다.

    amplify add storage
    
    ? Select from one of the below mentioned services: Content (Images, audio, video, etc.)
    ? Provide a friendly name for your resource that will be used to label this category in the project: imagestorage
    ? Provide bucket name: <your-unique-bucket-name>
    ? Who should have access: Auth users only
    ? What kind of access do you want for Authenticated users? create/update, read, delete
    ? Do you want to add a Lambda Trigger for your S3 Bucket? (y/N) no
  • 다음으로, amplify/backend/api/notesapp/schema.graphql을 열고 다음 스키마로 업데이트합니다.

    type Note @model @auth(rules: [ { allow: public } ] ){
      id: ID!
      name: String!
      description: String
      image: String
    }

    파일을 저장합니다.

  • 스토리지 서비스를 로컬로 구성하고 GraphQL 스키마를 업데이트했으므로 이제 Amplify 푸시 명령을 실행하여 업데이트를 배포할 수 있습니다.

    amplify push --y
  • 백엔드가 업데이트되었으므로, React 앱을 업데이트하여 메모에 사용할 이미지를 업로드하고 표시하는 기능을 추가해보겠습니다. src/App.js를 열고 다음과 같이 변경합니다.

    a. 먼저 Amplify 가져오기에 스토리지 클래스와 이미지 구성 요소를 추가합니다.

    import { API, Storage } from 'aws-amplify';
    import {
      Button,
      Flex,
      Heading,
      Image,
      Text,
      TextField,
      View,
      withAuthenticator,
    } from '@aws-amplify/ui-react';

    b. 메모에 연결된 이미지가 있는 경우 이미지를 가져오도록 fetchNotes 함수를 업데이트합니다.

    async function fetchNotes() {
      const apiData = await API.graphql({ query: listNotes });
      const notesFromAPI = apiData.data.listNotes.items;
      await Promise.all(
        notesFromAPI.map(async (note) => {
          if (note.image) {
            const url = await Storage.get(note.name);
            note.image = url;
          }
          return note;
        })
      );
      setNotes(notesFromAPI);
    }

    c. 메모에 이미지가 연결되어 있는 경우 로컬 이미지 어레이에 이미지를 추가하도록 createNote 함수를 업데이트합니다.

    async function createNote(event) {
      event.preventDefault();
      const form = new FormData(event.target);
      const image = form.get("image");
      const data = {
        name: form.get("name"),
        description: form.get("description"),
        image: image.name,
      };
      if (!!data.image) await Storage.put(data.name, image);
      await API.graphql({
        query: createNoteMutation,
        variables: { input: data },
      });
      fetchNotes();
      event.target.reset();
    }
    

    d. 메모가 삭제될 때 스토리지에서 파일을 삭제하도록 deleteNote 함수를 업데이트합니다.

    async function deleteNote({ id, name }) {
      const newNotes = notes.filter((note) => note.id !== id);
      setNotes(newNotes);
      await Storage.remove(name);
      await API.graphql({
        query: deleteNoteMutation,
        variables: { input: { id } },
      });
    }

    e. 반환 블록의 양식에 새 입력을 추가합니다.

    <View
      name="image"
      as="input"
      type="file"
      style={{ alignSelf: "end" }}
    />

    f. 메모 어레이로 매핑할 때 이미지를 렌더링합니다(있는 경우).

    {notes.map((note) => (
      <Flex
        key={note.id || note.name}
        direction="row"
        justifyContent="center"
        alignItems="center"
      >
        <Text as="strong" fontWeight={700}>
          {note.name}
        </Text>
        <Text as="span">{note.description}</Text>
        {note.image && (
          <Image
            src={note.image}
            alt={`visual aid for ${notes.name}`}
            style={{ width: 400 }}
          />
        )}
        <Button variation="link" onClick={() => deleteNote(note)}>
          Delete note
        </Button>
      </Flex>
    ))}

    g. 변경 사항을 적용하고 GitHub에 푸시합니다. 그런 다음 빌드가 완료될 때까지 기다렸다가 전체 앱을 라이브로 확인합니다.

    git add .
    git commit -m "Added graphql and storage"
    git push origin main
  • 앱을 테스트하려면 시작 명령을 실행합니다.

    npm start

    이제 각 메모마다 이미지를 선택적으로 업로드할 수 있습니다.

  • 개별 서비스 제거

    개별 서비스를 제거하려면 Amplify 제거 명령을 사용하면 됩니다.

    amplify remove auth
    
    ? Choose the resource you would want to remove: <your-service-name>

    그런 다음 Amplify 푸시 명령을 실행합니다.

    amplify push

    전체 프로젝트 삭제

    프로젝트, 그리고 연결된 리소스를 삭제하려면 Amplify 삭제 명령을 실행하면 됩니다.

    amplify delete

결론

AWS Amplify를 사용하여 웹 애플리케이션을 배포했습니다! 사용자가 가입하고 로그인하고 계정을 관리할 수 있도록 앱에 인증을 추가했습니다. 이 앱에는 Amazon DynamoDB를 사용하여 구성된 확장형 GraphQL API도 추가되어 사용자가 메모를 생성하고 삭제할 수 있습니다. 또한 Amazon S3를 사용한 파일 스토리지도 추가하여 사용자가 이미지를 업로드하고 앱에서 볼 수 있게 했습니다.

이 페이지의 내용이 도움이 되었나요?

축하합니다!

AWS에서 웹 애플리케이션을 구축했습니다. 다음 단계로, 특정 AWS 기술을 자세히 살펴보고 애플리케이션의 수준을 한 차원 높여보겠습니다.