2018년 4월 24일 화요일

[AWS] 프론트엔드 개발자가 혼자 웹어플리케이션 만들기. #3. AWS Amplify와 S3를 이용한 이미지 저장

[AWS] 프론트엔드 개발자가 혼자 웹어플리케이션 만들기. #3. AWS Amplify와 S3를 이용한 이미지 저장


시리즈 포스팅 순서
#1. 시리즈 포스팅 소개
#2. AWS Amplify와 Cognito를 이용한 회원가입, 로그인 기능 구현
#3. AWS Amplify와 S3를 이용한 이미지 저장
#4. AWS API Gateway, Lambda, DynamoDB를 이용한 REST API 구현
      (Amplify를 이용한 API 호출 방법 포함)
#5. AWS Lambda에 Express.js 기반의 웹어플리케이션 배포하기
      (AWS ACM, API Gateway를 이용한 Custom Domain 적용 방법 포함)
#6. AWS S3에 Static Web Hosting으로 SPA(Single Page Application) 웹어플리케이션 배포하기
      (AWS CloudFront, Route53을 이용한 HTTPS 지원방법 포함)


  이번 포스팅에서는 웹어플리케이션에서 AWS Amplify를 이용하여 AWS S3에 이미지를 업로드 하는 방법을 정리해보려합니다. 사실 이미지가 아닌 모든 파일이 가능하지만, 이번 시리즈에서 예시로 사용하는 웹어플리케이션인 NameSite에 필요한 기능이 이미지 업로드이기 때문에 이미지 파일을 업로드 하는 방법을 정리해봅시다.


> 1. AWS S3 준비

  가장먼저 준비되야할 것은 이미지 파일이 저장될 S3 버킷입니다. 버킷 생성은 매우 간단한 작업입니다.

  S3 대시보드에서 '버킷 만들기'를 클릭합니다.
(그림) '버킷 만들기' 클릭


  그렇게 하면, 아래와 같이 버킷 생성을 위한 정보를 입력하는 창이 뜨는데, 여기서 '버킷 이름'과 '리전'만 선택한 다음에 '생성'을 클릭합니다. 이름은 모든 AWS 유저의 S3 버킷 이름과 중복될 수 없습니다. 혹시 중복된 이름이라서 사용할 수 없다고 오류가 난다면, 조금 더 자신만의 식별자가 될 수 있는 이름을 사용하시길 권장합니다.

(그림) 버킷 생성을 위한 정보 입력


  이렇게 버킷 생성이 간단히 끝나면, 아래와 같이 생성한 버킷이 S3 대시보드의 버킷 리스트에 나타납니다.

(그림) 버킷 생성 후, 리스트에 버킷이 추가 됨


  지금부터는 방금 생성한 버킷을 웹어플리케이션의 리소스 저장소로 사용하기 위하여, 버킷을 Public으로 설정하고 CORS 설정을 하겠습니다.

  버킷을 Public으로 설정한다는 것은, 버킷에 업로드 된 파일들이 인터넷에 공개적으로 노출 된다는 것을 의미합니다. S3 버킷에 업로드 된 파일에는 각각이 고유한 URL이 생성되는데, 버킷이 Public이라면 익명의 사용자가 파일의 URL로 접근했을 때 파일을 다운로드 받을 수 있습니다. 그래서 AWS에서도 버킷을 Public으로 설정하는 작업은 조심하라고 주의를 주고 있습니다. 하지만, 웹사이트에 노출되야하는 이미지들은 Public이여야 하기 때문에 이번 포스팅에서는 S3 버킷을 Public으로 설정하겠습니다.

  버킷을 Public으로 설정하기 위해서는 아래와 같이 해당 버킷의 '권한' 탭으로 이동합니다. 그리고 하위 버튼 중에 '버킷 정책'을 선택합니다.

(그림) S3 버킷의 Public 설정을 위한 이동


  '버킷 정책'을 선택하면 하단에 정책을 입력할 수 있는 입력칸이 나타납니다. 그곳에 아래 정책을 복사하고, '{버킷 이름}' 부분만 본인의 버킷 이름으로 수정합니다. 아래 정책은 지정한 버킷의 모든 파일을 누구나 접근할 수 있게 허용하는 정책입니다.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AddPerm",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::{버킷 이름}/*"
        }
    ]
}



  그리고 CORS 설정도 해줍니다. '버킷 정책'과 동일한 '권한' 탭에서 'CORS 구성'을 선택합니다.(권한탭에 '퍼블릿'이라는 이름이 붙었는데, 이는 버킷 정책에서 모든 사용자가 접근할 수 있게 정책을 설정해서 그런것입니다.)

(그림) 'CORS 구성' 선택


  CORS 구성을 선택하면 나타나는 입력칸에 아래 내용을 그대로 복사해서 붙여넣습니다.

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>HEAD</AllowedMethod>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <AllowedMethod>DELETE</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <ExposeHeader>x-amz-server-side-encryption</ExposeHeader>
    <ExposeHeader>x-amz-request-id</ExposeHeader>
    <ExposeHeader>x-amz-id-2</ExposeHeader>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>


  이로써, 이미지 파일이 저장될 S3 버킷 준비는 끝났습니다.


> 2. AWS Amplify 설정

  위에서 이미지 파일을 저장할 S3 버킷을 생성했으니, Javascript에서 이미지 파일을 올려야합니다. 이때, AWS Amplify 라이브러리를 이용하려 합니다.

Amplify 라이브러리에 대한 소개와 Amplify 설정 위치는 이전 포스팅을 참고해주시기 바랍니다.

  AWS S3는 Amplify의 Storage 모듈을 이용해서 사용할 수 있습니다. 그러기 위해서 Amplify에서 Storage 모듈을 이용하기 위한 설정을 해주어야합니다. 그 방법은 아래와 같습니다.

  이전 포스팅에서는 Amplify의 Auth 모듈에 대한 설정을 했는데, 거기에 추가로 Storage 모듈에 대한 설정을 아래와 같이 추가합니다. Storage 모듈을 사용하려면 S3 버킷에 파일을 업로드 할 수 있는 권한을 가진 자격증명이 있어야하기 때문에 반드시 Auth 모듈과 함께 설정되어야합니다.
  그리고 로그인하지 않은 익명의 사용자도 파일을 업로드할 수 있게 하기 위해서는, 'identityPoolId'에 입력하는 자격증명풀은 생성하실 때 또는 수정에서 '인증되지 않은 자격 증명에 대한 액세스 활성화'를 체크하시고 IAM Role(역할)에서 해당 자격증명풀(Identity Pool)의 인증되지 않은 사용자를 위한 역할에 S3에 접근할수 있는 정책(Policy)을 추가시켜주셔야합니다.

  아래의 코드는 Storage 모듈을 사용하기 위한 최소한의 Auth 모듈 설정을 작성했습니다.

Amplify.configure({
  Auth: {
    identityPoolId: 'ap-northeast-0:00000000-0000-0000-0000-000000000000',
    region: '{리전 코드}', // 서울리전: ap-northeast-2
  },
  Storage: {
    bucket: '{버킷 이름}', // S3 버킷 이름
    region: '{리전 코드}', // 버킷을 생성한 리전 코드
  }
})



> 3. AWS Amplify.Stoarge API를 이용해서 S3에 이미지 파일 업로드하기

  Amplify의 Storage 모듈 설정이 끝났으면 Storage API를 이용해서 S3 버킷에 파일을 업로드할 수 있습니다.

  예시로 사용되는 코드는 Vue.js 기반의 코드입니다. 하지만 간단한 코드이기 때문에 다른 프론트엔드 프레임워크를 사용하시는 분들도 쉽게 응용가능하시리라 생각합니다.

  우선 html 코드에서 input태그로 파일을 입력받습니다. 그리고 저는 파일이 선택되었을때, handleOnChangeFileS3() 라는 메소드가 실행되도록 하였습니다.

<input type="file" @change="handleOnChangeFileS3($event)">


  handleOnChangeFileS3() 메소드의 코드는 아래와 같습니다. 단지 javascript에서 file 객체를 획득하고, 업로드할 파일 이름을 정한뒤에 Amplify Storage API로 업로드합니다.

handleOnChangeFileS3 (e) {
  e.preventDefault()

  let inputFile = e.target.files[0]
  let date = new Date()

  this.$s3.put(`test-${date.getTime()}-${inputFile.name}`, inputFile)
  .then(resp => {
    console.log(resp.key)
    // resp.key에 업로드한 파일의 이름이 응답으로 옴.
    //이때, 객체의 URL 주소가 아니라 그냥 파일 이름만 key에 담겨서 옴.
  }).catch(err => {
    console.log(err)
  })
}

  Amplify.Storage.put() 메소드를 이용해서 파일을 업로드하고 나면, 응답 객체에 업로드한 파일의 이름이 응답으로 전달됩니다. 그런데, 이 파일의 이름이 S3 객체의 URL이 아니라 그냥 파일 이름뿐이기 때문에, S3에 업로드된 파일의 URL을 javascript에서 쓰고 싶다면 수동으로 붙여줘야합니다.



  이로써, AWS Amplify를 이용해서 AWS S3에 이미지 파일을 업로드 하는 방법을 정리해보았습니다. 혹여 설명이 부족하다면 댓글로 질문해주시면 빠른 시일내에 답변드리겠습니다.
  또한, 잘못된 부분이 있거나 건의해주실 내용도 댓글로 달아주시면 추가 반영하도록 하겠습니다.

  감사합니다.




댓글 없음:

댓글 쓰기