Django 15. Django & S3(AWS) 연결

jiffydev·2020년 11월 11일
1


AWS의 S3를 사용해서 업로드한 이미지를 저장하고자 한다.
크게 3가지 스텝으로 나눌 수 있다.
1. AWS IAM 사용자 생성
2. AWS S3 버킷 생성
3. 장고에서 세팅

구글링을 해 보면 django-storages 모듈을 설치한다고 나오는 곳도 있다. 이 모듈은 다양한 저장소를 이용할 수 있도록 하는 모듈인데, 그냥 한 곳에 업로드만 돼도 상관 없다면 설치하지 않아도 상관 없다. 이 글에서도 django-storages는 없이 진행할 것이다.

이번 글은 정말 단순한 업로드 기능만 다룰 예정이므로 더 복잡한 설정이 필요한 분들은 다른 글을 찾아보는 것을 추천드린다.

1. AWS IAM 사용자 생성

  1. 사용자 이름을 설정하고 액세스 유형은 프로그래밍 방식 액세스로 설정한다.
  2. 기존 정책 직접 연결을 선택하여 정책생성 버튼을 누른다.
  3. 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/*",
                "arn:aws:s3:::example-bucket-name"
            ]
        }
    ]
}

"Resource"의 example-bucket-name은 나중에 버킷을 생성하면 버킷 이름으로 반드시 바꿔 줘야 한다.

  1. 정책이 생성되었으면 이전 화면으로 돌아가 정책 필터에서 내가 설정한 정책 이름을 검색하여 선택한다.

  2. 이것으로 생성이 완료되었다. 유저의 Access Key ID, Secret Access Key가 주어지는데, 이 때 반드시 csv를 저장해 놓아야 한다.

2. AWS S3 버킷 생성

  1. s3에 접속하여 버킷 만들기를 클릭한다.

  2. 버킷 이름과 리전을 선택한다.(리전은 사용하는 곳과 가까운 곳을 추천)

  3. 퍼블릭 액세스 차단 항목에서는 모든 퍼블릭 액세스 차단을 체크 해제한다.

    원칙상 퍼블릭 액세스를 주는 것은 위험하므로 일반적으로는 s3는 퍼블릭 액세스를 차단하고 s3 앞에 AmazonCloudFront를 붙여 CDN 기능을 구현하지만, 이 글은 연습용이므로 위와 같이 한다.

  4. 나머지 항목은 그대로 두고 버킷 만들기를 눌러 버킷을 생성하고, 권한 탭에 들어간다.

  5. 버킷 정책에 들어가 정책을 편집하는데, 아래와 같이 입력하고 저장한다.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1507637373230",
            "Effect": "Allow",
            "Principal": {
                "AWS": "{user_arn}"
            },
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:DeleteObject"
            ],
            "Resource": "arn:aws:s3:::{bucket_name}/*"
        },
        {
            "Sid": "Stmt1507637391106",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::{bucket_name}/*"
        }
    ]
}

user_arn은 IAM에서 생성한 사용자의 ARN을 뜻하며, 버킷 이름은 방금 생성한 버킷의 이름을 넣으면 된다.(중괄호는 삭제)

  1. 권한 탭에서 밑으로 내려가 CORS(Cross-origin 리소스 공유)를 편집한다.
  2. 보통 조금 옛날 블로그에 보면 xml로 다음과 같이 입력하라는 글이 있는데
<?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에서 정책으로 json으로만 입력하도록 만들었다. 그래서 이제는 위의 내용은 아래와 같이 입력 후 저장한다.

[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "GET"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": [
            "ETag"
        ],
        "MaxAgeSeconds": 3000
    }
]

이 부분의 내용은 필요에 따라 달라질 수 있으니 검색해서 필요한 내용을 찾는 것을 추천한다.

3. Django 설정 및 view

이제 프론트엔드에서 파일을 보내면 이를 s3에 업로드하고 url을 돌려주는 view를 만들 것이다.

우선 s3에 업로드 해 주는 모듈을 설치한다.
pip install boto3

이제 view를 작성하면 되는데, 아래 예제를 적당히 수정해서 사용하면 될 것이다.

import uuid

class CommentView(View):
    # s3 계정에 대한 세팅
    s3_client = boto3.client(
        's3',
        aws_access_key_id=AWS_ACCESS_KEY_ID,
        aws_secret_access_key=AWS_SECRET_ACCESS_KEY
    )
    def post(self, request, product_id, post_id):
        try:
            # 파일뿐만 아니라 key:value 형식도 받을 수 있다
            content=request.POST['content']
            # 파일은 MultiValueDict 형식으로 오므로 getlist를 사용하여 value를 리스트로 저장한다
            file=request.FILES['file']
            if file:
                # 파일명만으로 업로드하면 파일명이 동일할 때 덮어쓰기 될 수 있으므로 uuid를 사용해 이름을 지정한다
                filename=str(uuid.uuid1()).replace('-','')
                # 파일을 s3에 업로드
                self.s3_client.upload_fileobj(
                    file,
                    {bucket-name},
                    filename,
                    ExtraArgs={
                        "ContentType": file.content_type
                    }
                )
                file_url=f"https://s3.ap-northeast-2.amazonaws.com/{bucket-name}/{filename}"

aws_access_key_id, aws_secret_access_key는 IAM에서 유저를 생성했을 때 받은 csv에 있다.
postman을 사용해서 테스트할 때는 Body에서 form-data 형식으로 보내야 한다.

profile
잘 & 열심히 살고싶은 개발자

0개의 댓글