장고의 File storage API는 기본적으로 로컬 파일 시스템 만을 지원합니다. 클라우드에서는 AWS S3, Azure Storage, Google Cloud Storage 등을 스토리지 시스템을 많이 사용하는 데요. 장고에서는 django-storages 라이브러리를 통해 settings 설정 변경 만으로 손쉽게 스토리지 시스템을 활용할 수 있습니다.
AWS Lightsail은 AWS에서 제공하는 간편한 웹 어플리케이션 호스팅 서비스입니다. 기존 서비스들이 자유도/설정의 폭이 넓은 만큼 서비스가 많이 복잡했었는데요. Lightsail은 저렴하고 간결한 설정으로 이용할 수 있는 VM/컨테이너/데이터베이스/스토리지/도메인 종합선물세트 서비스입니다.
Lightsail에 대한 전반적인 내용은 (유튜브) Amazon Lightsail로 워드프레스 웹 사이트 이전하기 | AWS Builders 온라인 시리즈 7월, 2022 영상을 참고해주세요.
AWS Lightsail에서 지원하는 서비스 중에 스토리지와 장고를 연동하는 방법에 대해서 살펴보려 합니다.
장고와 연동하게 된다면, 다음 2가지가 가능해집니다.
이를 가능케하기 위해 뷰/모델/폼 코드를 수정할 필요는 없습니다. 장고의 파일 시스템 API는 완벽히 추상화되어있기에, 몇 개의 settings 설정 만으로 완벽히 동작합니다.
가상머신에서 서비스를 운영하더라도 스토리지 서비스와 데이터베이스 서비스를 활용하게 되면, 가상머신은 컴퓨팅 계산 만을 담당하게 되고 가상머신 내에서는 저장/관리하는 파일들이 없으므로, 향후 Scale Out 처리에 유리합니다.
django-storages 라이브러리는 다음의 스토리지 백엔드를 지원합니다.
Amazon Lightsail bucket은 Amazon S3 기반의 서비스이므로 설정하는 방법은 동일합니다. 장고 settings
에 다음 3가지 설정이 필요합니다.
AWS_S3_ACCESS_KEY_ID
와 AWS_S3_SECRET_ACCESS_KEY
AWS_STORAGE_BUCKET_NAME
: 생성한 버킷의 이름입니다. 버킷 생성 페이지에서는 "버킷 식별"로 안내되고 있습니다.AWS_S3_REGION_NAME
: 생성된 "버킷 위치" 리전을 지정합니다. 서울은 ap-northeast-2 입니다."스토리지" > "버킷 생성" 메뉴를 통해 "새 버킷 생성" 페이지로 들어갑니다. 다음 3가지 옵션을 선택해줍니다.
AWS_S3_REGION_NAME
AWS_STORAGE_BUCKET_NAME
위 항목을 기입하시고, 버킷을 생성해주세요. 생성에 성공하시면 아래와 같은 화면을 만나시게 됩니다.
객체 페이지에서 "새 폴더 생성" 메뉴를 통해 static
, media
폴더를 생성해줍니다.
권한 페이지에서 버킷 액세스 권한을 "개별 객체를 퍼블릭 및 읽기 전용으로 설정 가능" 으로 변경해주세요. 버킷 자체의 액세스 권한이 private
이라면, 버킷 내 파일들의 권한을 public-read
로 설정하더라도 모두 private이 됩니다.
AWS에는 디폴트 액세스 정책이 있습니다. static/media 파일은 권한이 없어도 URL 만으로 읽기가 가능해야 하므로, 아래 ACL 설정에서 public-read
로 지정할 것입니다. 디폴트는 private
이며, public-read-write
등의 다양한 옵션을 지원합니다.
관련 설정 : AWS_S3_ACCESS_KEY_ID
와 AWS_S3_SECRET_ACCESS_KEY
권한 페이지에서 "액세스 키 생성" 메뉴를 통해 키를 생성해주세요.
클릭 몇 단계를 거쳐, 아래 화면에서 2개의 키를 메모장에 복사해주세요.
Lightsail 포털에서 할 일은 이제 끝났습니다.
django-storages
: 버전 1.13.2에서 테스트되었습니다.boto3
: 버전 1.26.77에서 테스트되었습니다.장고 settings에 설정할 정보들을 정리해봅시다.
AWS_STORAGE_BUCKET_NAME
: 버킷 식별자AWS_S3_ACCESS_KEY_ID
와 AWS_S3_SECRET_ACCESS_KEY
: 키 2개AWS_S3_REGION_NAME
: 버킷을 서울 리전으로 생성하셨다면, ap-northeast-2
값으로 지정해주셔야 합니다. 버킷 생성 시에 지정한 리전으로 지정해주셔야 합니다.각 정보들을 잘 가지고 계시겠죠? 이제 장고 settings
에 적용해봅시다. 이때 주의하실 점은 절대 소스코드에 직접 기입하지 마세요. 환경변수를 통해 설정값을 주입하는 것이 안전합니다. 각자 사용하시는 환경에 맞춰 환경변수가 로딩될 수 있도록 설정해주세요.
장고 개발환경에서의 환경변수 적용은 django-environ
라이브러리를 활용하시면 .env
파일 로딩도 지원하고, 환경변수 문자열들을 손쉽게 파싱할 수 있어서 편리합니다.
import os
AWS_STORAGE_BUCKET_NAME = os.environ.get("AWS_STORAGE_BUCKET_NAME", "")
AWS_S3_ACCESS_KEY_ID = os.environ.get("AWS_S3_ACCESS_KEY_ID", "")
AWS_S3_SECRET_ACCESS_KEY = os.environ.get("AWS_S3_SECRET_ACCESS_KEY", "")
AWS_S3_REGION_NAME = os.environ.get("AWS_S3_REGION_NAME", "ap-northeast-2")
# django-environ 라이브러리를 쓰신 경우, 환경변수 참조하는 예시
AWS_STORAGE_BUCKET_NAME = env.str("AWS_STORAGE_BUCKET_NAME", default="")
AWS_S3_ACCESS_KEY_ID = env.str("AWS_S3_ACCESS_KEY_ID", default="")
AWS_S3_SECRET_ACCESS_KEY = env.str("AWS_S3_SECRET_ACCESS_KEY", default="")
AWS_S3_REGION_NAME = env.str("AWS_S3_REGION_NAME", default="ap-northeast-2")
임의의 경로에 아래 스토리지 코드를 저장해줍니다. 저는 core/storages/aws.py
경로에 저장한 것으로 가정하겠습니다.
# core/storages/aws.py
from storages.backends.s3boto3 import S3Boto3Storage
from storages.backends.s3boto3 import S3StaticStorage
# 장고 MEDIA 파일을 다루는 각종 설정을 커스텀할 수 있습니다.
# - "media" 폴더에 저장되도록 location 설정을 해줍니다.
# - "public-read" 권한으로 업로드되도록 default_acl 설정을 해줍니다.
class AwsMediaStorage(S3Boto3Storage):
location = "media"
default_acl = "public-read"
# 장고 STATIC 파일을 다루는 각종 설정을 커스텀할 수 있습니다.
# - "static" 폴더에 저장되도록 location 설정을 해줍니다.
# - "public-read" 권한으로 업로드되도록 default_acl 설정을 해줍니다.
class AwsStaticStorage(S3StaticStorage):
location = "static"
default_acl = "public-read"
액세스/시크릿키 및 버킷명이 로딩된 상황에서만 파일/스태틱 스토리지를 변경해주도록 하겠습니다. 아래의 코드를 적용한다면, 3가지 설정 중에 하나라도 누락이 된다면 스토리지 변경은 되지 않고, 로컬 파일시스템에 media/static을 저장하고 관리하게 됩니다.
# settings
import django
if AWS_S3_ACCESS_KEY_ID and AWS_S3_SECRET_ACCESS_KEY and AWS_STORAGE_BUCKET_NAME:
# 장고 4.2부터 스토리지 클래스 지정방법이 변경되었습니다.
if django.VERSION < (4, 2):
DEFAULT_FILE_STORAGE = "core.storages.aws.AwsMediaStorage"
STATICFILES_STORAGE = "core.storages.aws.AwsStaticStorage"
else:
STORAGES = {
"default": {
"BACKEND": "core.storages.aws.AwsMediaStorage",
},
"staticfiles": {
"BACKEND": "core.storages.aws.AwsStaticStorage",
},
}
이제 collectstatic
명령을 내리면, Lightsail 버킷으로 프로젝트내 static 파일들이 자동으로 복사됩니다. 명령을 여러 번 수행하면, 변경된 파일들만 복사됩니다.
Lightsail 버킷 static 폴더 내에 파일들이 복사된 것을 확인하실 수 있습니다.
장고 서버를 띄우시고, 웹페이지 소스보기를 해보시면 각 static
파일들의 주소가 AWS S3
주소로 변경되어있음을 확인하실 수 있습니다. 웹페이지에서도 static
파일들이 잘 로딩될 것입니다.
모델에 models.FileField
, models.ImageField
타입의 필드가 있다면, 이 필드를 통해 파일을 저장해보세요. Lightsail 버킷 media
폴더에 저장이 됨을 확인하실 수 있습니다.
testdriven.io의 Storing Django Static and Media Files on Amazon S3 포스팅을 참고해보세요. ;-)
장고와 Amazon Lightsail 스토리지 연동에 대해서 살펴봤습니다. Amazon S3와의 연동도 환경변수 값만 변경하면 동일하게 동작합니다.
이 외에도 애저/구글/FTP/드랍박스 등의 스토리지도 비슷한 방식으로 구현이 되니 응용하여 구현해보세요.
여러분의 해피 장고 라이프를 응원합니다. ;-)
댓글
사이드 프로젝트에서 서버 고민이 있었는데, lightsail도 선택지로 생각해봐야겠군요!!
좋습니다. AWS EC2를 고려하고 계신다면, 사이드 프로젝트라면 Lightsail을 먼저 고려해보세요. EC2의 맛보기 버전인데, 가격도 저렴하고 무료지원 폭도 넓습니다. ;-)
Lightsail의 컴퓨팅/데이터베이스/버킷을 모두 쓰셔도 좋구요. 1년 동안 무료로 지원되는 서버도 있죠.
무료 지원 이후에 media 스토리지가 따로 필요없으시다면, fly.io를 고려해보시는 것도 좋습니다. 도커 배포를 지원하고 PostgreSQL 데이터베이스도 지원해줍니다. 무료 범위도 크고 $5/월까지는 과금하지 않습니다. 단 스토리지 서비스가 없습니다.
저도 따로 운영해보는 서비스에서 $3.5 나왔는 데, 아래 메일을 보내주더라구요.
혹은 fly.io + lightsail 버킷 조합도 괜찮구요.
와우 자세한 답변 감사합니다..!! fly.io라는 서비스는 처음 들어봤는데, 알아봐야겠네요! 항상 좋은 지식 공유해주셔서 감사합니다 ㅎㅎ