Django | 클래스 101 클론 - AWS S3를 이용한 이미지 업로더

김민철·2021년 2월 12일
2

팀프로젝트

목록 보기
6/8
post-thumbnail

1. 흐름

마이 페이지에서 프로필 사진을 바꾸는 기능을 구현했습니다. 구현한 기능의 흐름은 이렇습니다.

유저가 프로필 사진을 바꾸면, 바꾼 사진의 데이터가 서버로 넘어오게 됩니다. 그러면 서버는 파일 이름을 생성하고 aws s3에 파일을 업로드 합니다. 마지막으로 사진 파일의 url 을 기존의 DB 에 업데이트 시켜주면 모든 과정이 끝납니다.

이 흐름을 바탕으로 로직을 구현해 보았습니다.

2. import

먼저 boto3 와 uuid 를 import 해줍니다.

boto 는 파이썬용 AWS SDK 이고 uuid 는 universally unique identifier(범용 고유 식별자) 를 의미합니다.
만약 업로드한 사진들의 url 중 일부가 겹치게 되면, 다른 파일이 덮어써지는 일이 발생합니다. 이를 막기위해서 uuid 를 사용해 url 을 만들어줍니다.

3. 이미지 업로더에 필요한 설정

이제 클래스를 작성하겠습니다.
boto3의 client 메소드를 이용해, 어떠한 서비스 클라이언트를 생성해줄지 설정합니다.
's3' 를 지정하고, 제 계정의 access_key_id 와 secret_access_key 를 넣어줍니다.

s3_client = boto3.client(
        's3',
        aws_access_key_id     = AWS_ACCESS_KEY_ID,
        aws_secret_access_key = AWS_SECRET_ACCESS_KEY
    )

클라이언트에서 받은 정보들도 지정해줍니다.

user = request.user
file  = request.FILES['file']

사진 파일이 들어왔는지 if문으로 체크를 하고 이미지 업로드를 시작합니다.

먼저 올라갈 파일의 url을 지정해주기 위해, uuid를 사용해 문자열을 생성합니다. uuid는 버전이 1,3,4,5 가 있는데 저는 uuid1을 사용했습니다. uuid1 을 이용하면 host ID, 현재 시간등의 정보를 이용해 문자열을 만들어줍니다.

filename = str(uuid.uuid1()).replace('-','')

4. 이미지 업로더

boto3의 client.upload_fileobj() 메소드를 살펴 보겠습니다.

self.s3_client.upload_fileobj(
                file,
                'ac101',
                filename,
                ExtraArgs = {
                    'ContentType': 'image/jpeg'
                }
            )

file 은 올려줄 파일, 'ac101' 은 s3 의 버킷 이름, filename 은 업로드할 key 의 이름입니다.

ExtraArgs 에는 파일의 메타 정보를 추가 인자로 보내줍니다. 여기서 'contentType' : 'image/jpeg' 로 인자를 보내면, 사진 파일 url에 접속시 이미지가 다운되거나 하지 않고, 사진만 볼 수 있습니다.
이렇게 설정함으로써 이미지업로더를 구현했습니다.

5. DB 업데이트

file_url = f"https://s3.ap-northeast-2.amazonaws.com/ac101/{filename}"

User.objects.filter(id = user.id).update(
                profile_image = file_url
            )

마지막으로, 사진 파일 url 을 DB 에 업데이트 시키면 업로드 과정이 끝나게 됩니다.


참고

https://docs.python.org/3.9/library/uuid.html#uuid.uuid1

https://boto3.amazonaws.com/v1/documentation/api/latest/reference/core/session.html#boto3.session.Session.client

0개의 댓글