Django-Deploy_EC2(Storage)

본 문서는 패스트캠퍼스 ‘Web-Programming School’ 수업 자료를 바탕으로 작성되었습니다.


summary

FileField(경로) -> FieldFile(파일에 접근할 수 있는 중간 경로) ->  Storage -> 실제 저장되는 파일

* FielSystemStorage
Django가 실행되는 환경의 '파일 시스템'을 기반으로 파일을 관리

- Custom Storage
* S3Strorage
AWS S3 서비스의 저장공간을 기반으로 파일을 관리
Storage 호스트 요청을 서버에 보냄 혹은 서버에서 받은 다음에 이걸 인스턴스로 넘겨줌

fileField내용이 '/photo/pby89.jpg'
FileSystem에서 찾을 때는 settings.MEDIA_ROOT기준으로 검색
S3Storage에서 찾을 때는 특정 저장소를 기준으로 위 경로에 해당하는 파일을 다운로드 받아서 사용 할 수 있다.

Storage

Django_FileField


summary

  • IAM : AWS 에서 제공하는 기능에 대한 인증/인가를 위한 유저 관리 시스템 특정 권한을 가진 유저를 생성하고, 자격증명 생성
  • Boto3 : Python과 aws api를 연결시켜주는 라이브러리 (AWS CLI보다 LOW레벨)
  • AWS CLI : Boto3를 기반으로 AWS의 서비스를 쉽게 사용할 수 있도록 도와주는 라이브러리
File -> FileField.save() -> FIeldfile
-> Storage.save()
->경로(upload_to 기준)을 FileField 내용에 저장
-> Storage 와 연결된 저장공간에 파일데이터 저장

s3   RDS
Django
uWSGI
Nginx
EC2

IAM

boto3를 사용하기 전에 IAM 사용자를 만들어주자.

  1. 사용자 추가 버튼을 누르고 사용자 세부 정보 설정에 사용자 이름을 설정하고 액세스 유형은 콘솔화면에서 사용하기 때문에 프로그래밍 방식 액세스를 선택하자.
  2. 기존 정책 직접 연결 - S3 검색 - AmazonS3FullAccess 선택하기
  3. .csv 다운로드 를 통해 액세스 키와 패스워드를 저장하자 - 이 페이지를 넘어가면 다시 볼 수 없으므로 꼭 저장 할것

boto3

boto3

Boto는 HTTP API 호출을 숨기는 편한 추상화 모델을 가지고 있고, Amazon EC2 인스턴스 및 S3 버켓과 같은 AWS 리소스와 동작하는 파이선 클래스를 제공한다.

>> pip install boto3

AWS CLI

AWS CLI는 AWS 서비스와 상호 작용하는 명령을 제공하는 AWS SDK for Python (Boto)을 기반으로 구축된 오픈 소스 도구이다. 최소한의 구성으로, 원하는 터미널 프로그램에서 AWS Management 콘솔이 제공한 모든 기능을 사용 가능하다.

AWS CLI 설치

<!-- global 환경에 설치  -->
>> pip install awscli
<!-- 제대로 설치 된 경우  -->
>> aws
usage: aws [options] <command> <subcommand> [<subcommand> ...] [parameters]
To see help text, you can run:

aws help
aws <command> help
aws <command> <subcommand> help
aws: error: the following arguments are required: command

AWS CLI 설정

  • 명시적으로 프로필명을 지정하여 AWS CLI을 실행하기 위해 설정
>> aws configure
AWS Access Key ID [None]:
AWS Secret Access Key [None]:
Default region name [None]: ap-northeast-2
Default output format [None]: json

>> ~/.aws
>> vi credentials
[s3]
aws_access_key_id =
aws_secret_access_key =

버킷 생성하기

boto3_Amazon S3

  • 버킷 이름의 경우, 기존에 있는 버킷이름들과 중복되면 안된다. 버킷 생성후, aws S3에 커맨드로 생성된 버킷이 만들어진 것을 볼 수 있다.
<!-- 해당 프로젝트에서 ipython 실행 -->
>> ipython

>> import boto3
>> session = boto3.Session(profile_name='s3')
>> client = session.client('s3')
>> client.create_bucket(Bucket='oh-team-ec2', CreateBucketConfiguration={'LocationConstraint':'ap-northeast-2'})

Out[10]:
{'Location': 'http://oh-team-ec2.s3.amazonaws.com/',
'ResponseMetadata': {'HTTPHeaders': {'content-length': '0',
'date': 'Tue, 27 Mar 2018 08:57:19 GMT',
'location': 'http://oh-team-ec2.s3.amazonaws.com/',
'server': 'AmazonS3',
'x-amz-id-2': '24kUqZgANWB3Tc2uuis6Nxcj6PfCsbXJPArlqBE5A8TO1HSdvrQEGxBBFHyXjBbCUmsIJGE9BZo=',
'x-amz-request-id': 'C31262B4F71101ED'},
'HTTPStatusCode': 200,
'HostId': '24kUqZgANWB3Tc2uuis6Nxcj6PfCsbXJPArlqBE5A8TO1HSdvrQEGxBBFHyXjBbCUmsIJGE9BZo=',
'RequestId': 'C31262B4F71101ED',
'RetryAttempts': 0}}

secrets 파일 설정 하기

/* .secrets/base.json /
{

  "AWS_ACCESS_KEY_ID": "",
  "AWS_SECRET_ACCESS_KEY": "",
  "AWS_STORAGE_BUCKET_NAME": ""
}

Django Storage

django_storages

  • Storage를 직접 구현할 수도 있지만 이미 필요한 함수들이 구현되어있는 django-storages 를 이용해보자!!
  • Django 에서 유저가 업로드한 파일과 정적 파일 외 다른 파일을 관리하는 Django_default_storage가 있다. 그리고 정적 파일을 관리하는 Django_staitcfiles_storage가 있는데, 어떤 스토리지를 사용할 것인가에 대해 설정해줘야 한다.

설치

>> pip install django-storages

설정

  • S3 storage를 사용하기 위해 설정
# app/config/settings/base.py
INSTALLED_APPS = (
...
'storages',
...
)
AWS_ACCESS_KEY_ID = secrets['AWS_ACCESS_KEY_ID']
AWS_SECRET_ACCESS_KEY = secrets['AWS_SECRET_ACCESS_KEY']
AWS_STORAGE_BUCKET_NAME = secrets['AWS_STORAGE_BUCKET_NAME']
# app/config/settings/dev.py

# Media(User-uploaded files)를 위한 스토리지
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
# Static file(collectstatic)을 위한 스토리지
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'

S3 Storage

변경한 설정들을 통해 S3 Storage가 잘 작동되는지 확인해보자. 아래 명령어를 실행한 뒤, AWS Bucket에 접속하면 프로젝트의 static 파일들이 존재하는 것을 볼 수 있다.

>> export DJANGO_SETTINGS_MODULE=config.settings.dev
>> ./manage.py collectstatic

별도의 경로 저장하기

현재 미디어 파일들과 정적 파일들이 S3 Bucket 저장소에 잘 저장되는 것을 확인했다. 그러나 두 파일이 구분없이 모두 한 곳이 저장되는 것이 문제이다. 이는 파일이 많아지만 관리가 어려워질 수 있기 때문에, 미디어 파일은 미디어 폴더에 정적 파일들은 정적 폴더에 구분해서 저장해보자

# app/config/storage.py 생성
from storages.backends.s3boto3 import S3Boto3Storage


class StaticFileStorage(S3Boto3Storage):
    location = 'static'
    default_acl = "public-read"


class DefaultFileStorage(S3Boto3Storage):
    location = 'media'

각 스토리지는 S3Boto3Storage 를 상속 받으며, settings.py 에서 지정해놓은 .._LOCATION 변수의 값으로 저장 경로를 지정하는 location메소드를 오버라이드 한다. default_acl는 해당 사이트에서만 파일을 볼 수 있고 나중에는 볼 수 없는 그런 설정(좀더 알아보자..)-> 이 경우 dev에서는 보이는데 production에서는 그림을 볼 수 없다.


# Media(user-uploaded file)을 위한 스토리지
DEFAULT_FILE_STORAGE = 'config.storage.DefaultFileStorage'
# Static files(collectstatic) 을 위한 스토리지
STATICFILES_STORAGE = 'config.storage.StaticFileStorage'

변경된 스토리지 저장 경로를 settings/dev.py에도 적용하자. 그리고 기존 S3 bucket에 있던 파일들을 삭제한 뒤, 다시 한번 ./manage.py collectsatic을 실행하면 이번엔 미디어와 정적 디렉토리에 분리되어 저장되는 것을 확인 할 수 있다.