[Django] Assets(Static) Google Cloud Storage로 서비스하기

2021. 6. 10. 00:56Develop/Python

728x90

 

 

2021년 오늘날 Django에서는 기본적으로 runserver는 개발용으로 사용한다는 것은 많은 사람들이 인지하고 있습니다. runserver에서는 개발 용도이므로 static 파일도 local에서 serving 하게 되는데, 배포할때는 기본적으로 static을 제공하지 않고 Web Server에게 위임합니다.

 

하지만 static을 url로 주고 staticfiles를 불러오게해서 함께 serving하거나 whitenoise를 통해 서비스 할 수 있지만, 기본적으로 캐싱관리 효율이 매우떨어지고 트래픽 비용이 발생하다보니, 그렇게는 잘 사용안하고 보통은 Web Server 주로 Nginx에서 static을 처리하게 해서 캐싱타임을 줍니다.

 

하지만 이런 방법보다는 Django 공식문서에서도 언급하는 CDN 방식인 Cloud를 통한 serving이 향후 유지보수 관리측면에서도 편리하기 때문에 CDN을 통한 제공이 무적권 좋다고는 못하겠으나 저는 좋다고 생각합니다.

 

S3보다는 Google 제품군이 개인적으로 깔끔하고 관리 및 비용계산 및 관리가 편해서  Google Cloud Storage를 연결하는 방법을 기술해보고자 합니다.

 

 

 

 

Google Cloud Storage의 키를 발급받고 하는 내용은 생략합니다.

 

 

 

의존성 설치

pip install google-auth-httplib2 google-auth-oauthlib django-storages[google]

 

django-storages[google]

google-auth-oauthlib

 

 

 

Django Settings.py 설정

 

# project/project/settings.py

from google.oauth2 import service_account

GS_PROJECT_ID = os.getenv('GS_PROJECT_ID', '')
GS_BUCKET_NAME = os.getenv('GS_BUCKET_NAME', '')

GS_CREDENTIALS = service_account.Credentials.from_service_account_info({
    'type': 'service_account',
    'project_id': GS_PROJECT_ID,
    'private_key_id': os.getenv('GS_PRIVATE_KEY_ID', ''),
    'private_key': os.getenv('GS_PRIVATE_KEY', '').replace('\\n', '\n'),
    'client_email': os.getenv('GS_CLIENT_EMAIL', ''),
    'client_id': os.getenv('GS_CLIENT_ID', ''),
    'auth_uri': 'https://accounts.google.com/o/oauth2/auth',
    'token_uri': 'https://oauth2.googleapis.com/token',
    'auth_provider_x509_cert_url': 'https://www.googleapis.com/oauth2/v1/certs',
    'client_x509_cert_url': os.getenv('GS_CLIENT_x509_CERT_URL', '')
})

STATICFILES_STORAGE = 'project.project.backends.GoogleCloudStaticStorage'
STATIC_URL = f'https://storage.googleapis.com/{GS_BUCKET_NAME}/static/'

json 파일로 관리하는 방법이 더 깔끔하긴한데, 환경변수로 설정하는게 조금 더 유동적이게 하고 안정적인 측면을 가져갈 수 있습니다.

환경변수의 GS_들은 Google Cloud 에서 사용자 인증 정보를 통해 JSON 파일로 받으면 나오는 값들입니다.

 

STATICFILES_STORAGE 는 밑에서 작성하는 backend 파일의 경로입니다.

이를 통해 나중에 collectstatic을 사용할 경우 자동으로 Google Cloud Storage에 업로드됩니다.

 

 

Backend Storage 작성

 

# project/project/backends.py

from abc import ABC

from django.conf import settings
from storages.backends.gcloud import GoogleCloudStorage
from storages.utils import setting
from urllib.parse import urljoin


class GoogleCloudMediaStorage(GoogleCloudStorage, ABC):
    """GoogleCloudStorage suitable for Django's Media files."""

    def __init__(self, *args, **kwargs):
        if not settings.MEDIA_URL:
            raise Exception('MEDIA_URL has not been configured')
        kwargs['bucket_name'] = setting('GS_BUCKET_NAME')
        super(GoogleCloudMediaStorage, self).__init__(*args, **kwargs)

    def url(self, name):
        """.url that doesn't call Google."""
        return urljoin(settings.MEDIA_URL, name)


class GoogleCloudStaticStorage(GoogleCloudStorage, ABC):
    """GoogleCloudStorage suitable for Django's Static files"""

    def __init__(self, *args, **kwargs):
        if not settings.STATIC_URL:
            raise Exception('STATIC_URL has not been configured')
        kwargs['bucket_name'] = setting('GS_BUCKET_NAME')
        super(GoogleCloudStaticStorage, self).__init__(*args, **kwargs)

    def url(self, name):
        """.url that doesn't call Google."""
        return urljoin(settings.STATIC_URL, name)

 

만약 media를 다른 버킷에 생성하였다면 변경해주시면 됩니다. 저는 같은 버킷내에 하위 경로로 구분하였습니다.

 

 

Google에서 키 발급하는거 빼면 코드측면만 바라봤을때 생각보다 짧습니다...

 

 

728x90