All Articles

Django에서 AWS S3로 이미지 바로 업로드 하기

사용자 프로필 사진을 S3로 바로 업로드하는 기능을 DRF로 구현해봤다.

우선 models.py다. 장고 User 모델을 상속하기에는 쓰는 필드보다 안 쓰는 필드가 더 많아서 AbstractBaseUser를 상속했다. 그런데 자꾸 is_staff attribute가 없다는 에러가 나서 필드 마지막에 억지로 추가해줬다. 난 is_admin만 있으면 된다고!

유저 닉네임은 어떻게 할까 고민하다가 ‘user12345’ 이런 식으로 ‘user’ + 랜덤 숫자로 지정해줬다. 장고였으면 저걸 views.py에서 구현해줬겠지만 아직 DRF 햇햇햇햇병아리라 어떻게 해야할지 몰라서 일단 모델에 때려넣었다. 더 공부하면서 적당한 것으로 수정할 예정. 일단 이미지 업로드에 관한 포스팅이므로 유저 모델에 대해서는 나중에 다루겠다.

이미지 필드에서 upload_to=upload_image로 지정했는데, upload_image는 utils.py에 작성한 함수다.

class User(AbstractBaseUser, PermissionsMixin):
  email          = models.EmailField(_('email_address'),
                                     unique=True, null=True)
  date_joined    = models.DateTimeField(_('date joined'), auto_now_add=True)
  nickname       = models.CharField(_('nickname'), max_length=20,
                                    default='user'+str(randint(100,99999)),
                                    unique=True, null=True)
  profile_image  = models.ImageField(upload_to=upload_image,
                                     editable=True, null=True)
  is_active      = models.BooleanField(_('active'), default=1)
  is_social_user = models.BooleanField(default=0)
  is_staff       = models.BooleanField(default=0)

  objects = UserManager()

  USERNAME_FIELD  = 'email'
  REQUIRED_FIELDS = []

utils.py에 저장한 이미지 업로드 함수다.

파일 이름이랑 저장 경로를 어디로 할까 고민하다가 그냥 버킷 최상위 디렉토리에 바로 저장하는 것으로 결정했다. 어차피 이번 프로젝트용 버킷인데다 유저(인스턴스) id 값으로 디렉토리를 만들어버리면 왠지 개인정보(?)를 카테고라이징 해둔 것 같아서 일단 주석처리 해뒀다.

파일 이름은 ‘업로드 날짜_랜덤숫자’ 형태로 지정했다.

def upload_image(instance, filename):
  import os
  from random import randint
  from django.utils.timezone import now
  filename_base, filename_ext = os.path.splitext(filename)

  return '%s' % (
      #instance.id,
      now().strftime('%Y%m%d')+'_'+str(randint(10000000,99999999))
  )

그리고 settings.py

우선 커스텀 유저 모델을 등록해줬다.

AUTH_USER_MODEL = 'account.User'

그리고 기본 파일 스토리지를 S3로 지정해줬다. 액세스 키나 시크릿 키같은 민감정보는 전부 my_settings.py에 따로 저장했다.

DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
AWS_S3_SECURE_URLS = False
AWS_QUERYSTRING_AUTH = False

AWS_S3_ACCESS_KEY_ID = my_settings.S3['aws_access_key_id']
AWS_S3_SECRET_ACCESS_KEY = my_settings.S3['aws_secret_access_key']
AWS_STORAGE_BUCKET_NAME = my_settings.S3['aws_bucket']

어드민 화면에서 업로드 테스트를 해봤다.

s3 image upload

사진을 선택하고 SAVE 하면,

s3 image upload

지정한 파일 이름 형식대로 파일이 저장된다. S3와 CloudFront를 연동했기 때문에 이미지는 CloudFront를 통해 확인해보자.

s3 image upload

업로드가 잘 되었다 짝짝짝