AWS - S3를 통해 DB에 이미지 넣기

KDG·2020년 7월 25일
2

AWS S3를 통해 프론트에서 업로드 한 이미지url을 내 MySQL에 넣기

1. AWS IAM 설정

AWS IAM(Identity and Access Management) AWS resource 보안 서비스. AWS 서비스와 리소스에 대한 액세스를 안전하게 관리할 수 있다.

  1. IAM 서비스 선택
  2. IAM 액세스 관리에서 정책 선택
  3. 정책 생성
  4. 정책 생성에서 JSON선택하고 아래의 JSON입력
{
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "VisualEditor0",
                "Effect": "Allow",
                "Action": [
                    "s3:PutObject",
                    "s3:GetObjectAcl",
                    "s3:GetObject",
                    "s3:ListBucket",
                    "s3:DeleteObject",
                    "s3:PutObjectAcl"
                ],
                "Resource": [
                    "arn:aws:s3:::example-bucket-name/*",  # example-bucket-name/* 에 S3 bucket 이름 적어주기
                    "arn:aws:s3:::example-bucket-name"  # example-bucket-name 에 S3 bucket 이름 적어주기
                ]
            }
        ]
    }
  1. 입력하고 정책검토 -> 정책 이름과 설명 써넣기 -> 정책 생성
  2. IAM 액세스 관리에서 사용자 선택
  3. 사용자 추가 -> 사용자 이름 적고, AWS 액세스 유형 선택에서 프로그래밍 방식 액세스 선택하고 다음으로
  4. 기존 정책 직접 연결 누르고, 전에 만들었던 정책이름 검색해서 선택하고 다음
  5. 태그 추가 건너뛰고 검토하고 사용자 만들기
  6. 성공하면 액세스 키 ID와 비밀 액세스 키가 나오는데 이 부분은 나중에 꼭 필요하므로 .csv 다운로드를 통해 다운받아 보관해놓기(다시 다운 불가능)

2. AWS S3 Bucket

Amazon S3에 데이터(사진, 동영상, 문서 등)를 업로드하려면 우선 하나의 AWS 리전에 S3 버킷을 만들어야 한다.(file folder 같은 역할을 한다.)
1. S3 서비스 선택
2. 버킷 만들기 선택
3. 버킷 이름과 리전 설정하고 다음
4. 속성설정은 패스
5. 퍼블릭 액세스 차단(버킷 설정) 부분에서 모든 퍼블릭 액세스 차단 해제하고 경고 창이 뜨는데 경고창에 체크하고 다음
6. 버킷 만들기
7. 버킷 생성이 완료되면 생성한 버킷을 클릭하고 권한 탭에서 버킷 정책 선택
8. 버킷 정책 편집기에 아래 JSON 입력

{
   "Version": "2012-10-17",
   "Statement": [
       {
           "Sid": "Stmt1507637373230",
           "Effect": "Allow",
           "Principal": {
               "AWS": "{user_arn}"  # {user_arn} 부분에 IAM user의 ARN 입력
           },
           "Action": [
               "s3:GetObject",
               "s3:PutObject",
               "s3:DeleteObject"
           ],
           "Resource": "arn:aws:s3:::{bucket_name}/*"  # {bucket_name}/* 부분에 버킷이름 입력
       },
       {
           "Sid": "Stmt1507637391106",
           "Effect": "Allow",
           "Principal": "*",
           "Action": "s3:GetObject",
           "Resource": "arn:aws:s3:::{bucket_name}/*"  # {bucket_name}/* 부분에 버킷이름 입력
       }]
}

IAM user의 ARN은 IAM -> 사용자 -> 사용자 선택하면 사용자 ARN이라고 나오는데 그 부분 복사해서 넣어주면 된다.
9. 저장버튼을 누르면 Public access warning이 뜬다. 원칙적으로 S3는 public access를 주지않는것이 보안 상으로는 좋다. 일단 지금은 무시한다. 저장은 잘 되었을 것이다.
10. 버킷 정책을 끝내고 CORS 구성으로 가서 CORS 구성 편집기에 아래 내용 입력하고 저장

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<ExposeHeader>ETag</ExposeHeader>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>

이걸로 S3 준비는 끝났다.

3. 이미지 저장 엔드포인트 구현

프론트에서 이미지를 formdata로 보내면 url로 DB에 넣는 엔드포인트를 구현
우선 터미널에 pip install boto3 입력

views.py

import import boto3
from datetime import datetime
from 프로젝트 폴더이름.settings import AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY
# AWS_ACCESS_KEY는 공유되면 안되기 때문에 mysettings.py에 적어 공유되지 않게 한다.

def post(self, request):
    user_id = request.user.id
        
    # image
    s3_client = boto3.client(
        's3',
        aws_access_key_id     = AWS_ACCESS_KEY_ID,
        aws_secret_access_key = AWS_SECRET_ACCESS_KEY
    )

    image = request.FILES['filename']  # formdata 키 : filename으로 이미지를 받는다.
    image_time = (str(datetime.now())).replace(" ","") # 이미지이름을 시간으로 설정하기 위해 datetime를 사용했다.
    image_type = (image.content_type).split("/")[1]
    s3_client.upload_fileobj(
        image,
        "dkinterest", # 버킷이름
        image_time+"."+image_type,
        ExtraArgs = {
            "ContentType" : image.content_type
        }
    )
    image_url = "http://dkinterest.s3.ap-northeast-2.amazonaws.com/"+image_time+"."+image_type  # 업로드된 이미지의 url이 설정값으로 저장됨
    image_url = image_url.replace(" ","/")

    Pin.objects.create(image_url = image_url)
    return HttpResponse(status=200)

위와같이 작성하면 AWS S3에 이미지가 업로드되고 다음 MySQL DB에 이미지 url이 저장될것이다.

** 참고
https://velog.io/@devzunky/TIL-no.83-AWS-Django-S3-multiple-file-Upload

1개의 댓글

comment-user-thumbnail
2023년 9월 15일

안녕하세요 선생님 혹시 MongoDB를 사용해도 위와 같이 하면 될까요?

답글 달기