Django 하이라이트: 정적 자산 및 미디어 파일 랭글링(4부)

게시 됨: 2022-03-10
빠른 요약 ↬ 프론트 엔드 개발자와 디자이너는 웹 애플리케이션을 위한 놀라운 정적 자산을 만듭니다. 오늘 우리는 스타일 핫픽스나 방금 완성한 아름다운 그래픽이 마스터로 푸시된 후 어떤 일이 일어나는지에 초점을 맞추고 있습니다. 또한 미디어 파일이라고 하는 사용자가 업로드하는 파일을 처리하는 방법도 조사할 것입니다. 함께 우리는 Django 개발자가 이러한 파일을 안전하고 성능이 뛰어나며 비용 효율적인 방식으로 전 세계 사용자에게 제공하기 위해 사용할 수 있는 전략에 대한 직관력을 개발할 것입니다.

Django 웹사이트에는 많은 파일이 포함됩니다. 구성, 모델, 보기 및 템플릿에 대한 소스 코드뿐만 아니라 CSS 및 JavaScript, 이미지, 아이콘과 같은 정적 자산도 있습니다. 이미 충분하지 않은 것처럼 때때로 사용자가 와서 웹 사이트에 자신의 파일을 업로드하려고 합니다. 모든 개발자를 믿을 수 없게 만들기에 충분합니다. 어디에나 있는 파일!

여기 내가 (주의 사항 없이) 말하고 싶은 곳이 있습니다. 그러나 불행하게도 정적 자산과 미디어 파일을 다룰 때 처리해야 할 많은 주의 사항이 있습니다.

오늘 우리는 압축, 캐싱 및 가용성과 같은 요소를 고려하면서 단일 서버 및 확장 가능한 배포 모두를 위한 파일 저장 및 제공을 다룰 것입니다. 또한 CDN 및 전용 파일 스토리지 솔루션의 비용과 이점에 대해서도 논의합니다.

참고 : 이것은 Django 사이트를 특정 플랫폼에 배포하는 방법에 대한 자습서가 아닙니다. 대신 Django Highlights 시리즈의 다른 기사(아래 참조)와 마찬가지로 프론트엔드 개발자와 디자이너가 웹 애플리케이션을 만드는 프로세스의 다른 부분을 이해하는 데 도움이 됩니다. 오늘 우리는 스타일 핫픽스나 방금 완성한 아름다운 그래픽이 마스터로 푸시된 후 어떤 일이 일어나는지에 초점을 맞추고 있습니다. 함께 우리는 Django 개발자가 이러한 파일을 안전하고 성능이 뛰어나며 비용 효율적인 방식으로 전 세계 사용자에게 제공하기 위해 사용할 수 있는 전략에 대한 직관력을 개발할 것입니다.

시리즈의 이전 부품 :

  • 1부: 사용자 모델 및 인증
  • 파트 2: 템플릿을 사용하면 라인 절약
  • 3부: 모델, 관리 및 관계형 데이터베이스 활용
점프 후 더! 아래에서 계속 읽기 ↓

정의

이러한 용어의 대부분은 매우 간단하지만 이 토론을 위한 공유 어휘를 설정하는 데 시간을 할애할 가치가 있습니다.

라이브 Django 애플리케이션의 세 가지 유형의 파일은 다음과 같습니다.

  1. 소스 코드
    Django 프레임워크로 생성된 Python 및 HTML 파일입니다. 이 파일은 응용 프로그램의 핵심입니다. 소스 코드 파일은 일반적으로 킬로바이트 단위로 매우 작습니다.
  2. 정적 파일
    "정적 자산"이라고도 하는 이러한 파일에는 응용 프로그램 개발자 및 타사 라이브러리가 작성한 CSS 및 JavaScript는 물론 PDF, 소프트웨어 설치 프로그램, 이미지, 음악, 비디오 및 아이콘이 포함됩니다. 이러한 파일은 클라이언트 측에서만 사용됩니다. 정적 파일은 몇 킬로바이트의 CSS에서 몇 기가바이트의 비디오에 이르기까지 다양합니다.
  3. 미디어 파일
    프로필 사진부터 개인 문서까지 사용자가 업로드한 모든 파일을 미디어 파일이라고 합니다. 이러한 파일은 사용자를 위해 안전하고 안정적으로 저장 및 검색되어야 합니다. 미디어 파일의 크기는 제한되지 않으며 사용자는 몇 킬로바이트의 일반 텍스트를 몇 기가바이트의 비디오에 업로드할 수 있습니다. 당신이 이 규모의 끝자락에 있다면 아마도 이 기사에서 제공할 준비가 된 것보다 더 전문적인 조언이 필요할 것입니다.

두 가지 유형의 Django 배포는 다음과 같습니다.

  1. 단일 서버
    단일 서버 Django 배포는 말 그대로 모든 것이 단일 서버에 있습니다. 이 전략은 매우 간단하고 개발 환경과 매우 유사하지만 크거나 일정하지 않은 트래픽을 효과적으로 처리할 수 없습니다. 단일 서버 접근 방식은 안정적인 가동 시간이 필요한 실제 응용 프로그램이 아닌 학습 또는 데모 프로젝트에만 적용할 수 있습니다.
  2. 확장 가능
    사용자 요구에 맞게 확장할 수 있는 Django 프로젝트를 배포하는 다양한 방법이 있습니다. 이러한 전략에는 종종 수많은 서버를 가동 및 축소하고 로드 밸런서 및 관리되는 데이터베이스와 같은 도구를 사용하는 것이 포함됩니다. 다행히 이 기사의 목적을 위해 단일 서버 배포보다 더 복잡한 모든 것을 이 범주로 효과적으로 묶을 수 있습니다.

옵션 1: 기본 Django

소규모 프로젝트는 단순한 아키텍처의 이점을 얻습니다. Django의 정적 자산 및 미디어 파일의 기본 처리는 간단합니다. 각각에 대해 파일을 저장하는 루트 폴더가 있고 서버의 소스 코드 바로 옆에 있습니다. 단순한. 이러한 루트 폴더는 대부분 yourproject/settings.py 구성을 통해 생성 및 관리됩니다.

정적 자산

Django에서 정적 파일로 작업할 때 이해해야 하는 가장 중요한 것은 python manage.py collectstatic 명령입니다. 이 명령은 Django 프로젝트에 있는 각 앱의 정적 폴더를 통해 모든 정적 자산을 루트 폴더에 복사합니다. 이 명령을 실행하는 것은 Django 프로젝트 배포의 중요한 부분입니다. 다음 디렉토리 구조를 고려하십시오.

 - project - project - settings.py - urls.py - ... - app1 - static/ - app1 - style.css - script.js - img.jpg - templates/ - views.py - ... - app2 - static/ - app2 - style.css - image.png - templates/ - views.py - ...

또한 project/settings.py 에서 다음 설정을 가정합니다.

 STATIC_URL = "/static/" STATIC_ROOT = "/path/on/server/to/djangoproject/static"

python manage.py collectstatic 명령을 실행하면 서버에 다음 폴더가 생성됩니다.

 - /path/on/server/to/djangoproject/static - app1 - style.css - script.js - img.jpg - app2 - style.css - image.png

각 정적 폴더에는 앱 이름이 있는 다른 폴더가 있습니다. 이는 정적 파일이 수집된 후 네임스페이스 충돌을 방지하기 위한 것입니다. 위의 파일 구조에서 볼 수 있듯이 이것은 app1/style.cssapp2/style.css 를 구별되게 유지합니다. 여기에서 애플리케이션은 프로덕션 동안 STATIC_ROOT 에서 이 구조의 정적 파일을 찾습니다. 따라서 app1/templates/ 의 템플릿에서 다음과 같이 정적 파일을 참조하십시오.

 {% load static %} <link rel="stylesheet" type="text/css" href="{% static "app1/style.css" %}">

Django는 이 동작을 모델링하기 위해 개발 중 정적 파일을 가져올 위치를 자동으로 파악하므로 개발 중에 collectstatic 을 실행할 필요가 없습니다.

자세한 내용은 Django 설명서를 참조하세요.

미디어 파일

사용자 데이터베이스가 있는 전문 네트워킹 사이트를 상상해 보십시오. 이러한 각 사용자는 무엇보다도 아바타 이미지와 이력서 문서를 포함할 수 있는 연결된 프로필을 갖게 됩니다. 다음은 해당 정보의 간단한 예시 모델입니다.

 from django.db import models from django.contrib.auth.models import User def avatar_path(instance, filename): return "avatar_{}_{}".format(instance.user.id, filename) class Profile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) resume = models.FileField(upload_to="path/string") avatar = models.ImageField(upload_to=avatar_path)

이것이 작동하려면 정적 자산과 같이 project/settings.py 에 다음 옵션이 필요합니다.

 MEDIA_URL = "/media/" MEDIA_ROOT = "/path/on/server/to/media"

ImageFieldFileField 에서 상속되므로 동일한 매개변수와 기능을 공유합니다. 두 필드 모두 선택적 upload_to 인수가 있습니다. 이 인수는 경로인 문자열을 MEDIA_ROOT 에 추가하여 파일을 저장한 다음 MEDIA_URL 상단의 동일한 경로에서 액세스할 수 있습니다. upload_to 인수는 avatar_path 함수에서 설명한 것처럼 문자열을 반환하는 함수를 사용할 수도 있습니다.

버전 관리에서 미디어 파일 디렉토리와 그 내용을 생략해야 합니다. 두 개발자가 다른 시스템에서 동일한 애플리케이션을 테스트할 때 그 내용이 충돌할 수 있으며, 이는 정적 자산과 달리 배포 가능한 Django 애플리케이션의 일부가 아닙니다.

옵션 2: 서비스가 포함된 Django

제 지도 철학은 도구가 가장 잘하는 것을 위해 도구를 사용하는 것입니다. Django는 놀라운 프레임워크이며 사용자 인증, 서버 측 렌더링, 모델 및 양식 작업, 관리 기능, 기타 수십 가지 웹 애플리케이션 구축 필수 측면을 위한 뛰어난 도구를 즉시 제공합니다. 그러나 정적 자산 및 미디어 파일을 처리하기 위한 도구는 내 생각에 확장 가능한 사이트의 프로덕션에 적합하지 않습니다. Django 핵심 개발자는 많은 사람들이 프로덕션에서 이러한 파일을 처리하는 대체 접근 방식을 선택한다는 것을 알고 있습니다. 프레임워크는 당신이 할 때 방해가 되지 않도록 아주 잘합니다. 일반적으로 사용되는 대부분의 Django 사이트는 정적 자산을 통합하고 이러한 비 Django 관련 접근 방식을 사용하여 미디어 파일을 처리하기를 원할 것입니다.

CDN의 정적 자산

중소 프로젝트는 하나가 없어도 무방하지만 CDN(콘텐츠 전달 네트워크)은 사용하기 쉽고 모든 규모의 응용 프로그램 성능을 향상시킵니다. CDN은 일반적으로 전 세계적으로 웹 콘텐츠(대부분 정적 자산)를 배포하고 제공하는 서버 네트워크입니다. 인기 있는 CDN에는 Cloudflare CDN, Amazon CloudFront 및 Fastly가 있습니다. CDN을 사용하려면 정적 파일을 업로드한 후 애플리케이션에서 다음과 같이 참조하십시오.

 <link rel="stylesheet" type="text/css" href="https://cdn.example.com/path/to/your/files/app1/style.css">

이 프로세스는 Django 배포 스크립트와 쉽게 통합됩니다. python manage.py collectstatic 명령을 실행한 후 생성된 디렉토리를 CDN(사용 중인 서비스에 따라 크게 달라지는 프로세스)에 복사한 다음 Django 배포 패키지에서 정적 자산을 제거합니다.

개발 중에는 프로덕션에서와 다른 정적 자산 사본에 액세스하려고 할 것입니다. 이렇게 하면 프로덕션 사이트에 영향을 주지 않고 로컬에서 변경할 수 있습니다. 로컬 자산을 사용하거나 CDN의 두 번째 인스턴스를 실행하여 파일을 전달할 수 있습니다. CDN_URL 과 같은 일부 사용자 정의 변수로 yourproject/settings.py 를 구성하고 템플릿에서 해당 값을 사용하여 개발 및 프로덕션에서 올바른 버전의 자산을 사용하고 있는지 확인하십시오.

마지막으로 많은 CSS 및 JavaScript용 라이브러리에는 대부분의 웹사이트에서 사용할 수 있는 무료 CDN이 있습니다. 예를 들어 Bootstrap 4 또는 underscore.js를 로드하는 경우 이러한 공개 CDN을 사용하여 개발 단계에서 자체 사본을 사용하는 번거로움과 프로덕션에서 자체 사본을 제공하는 비용을 건너뛸 수 있습니다.

전용 파일 저장소가 있는 미디어 파일

프로덕션 Django 사이트는 사이트를 실행하는 서버의 어딘가에 있는 간단한 /media/ 폴더에 사용자 파일을 저장해서는 안 됩니다. 다음은 하지 말아야 할 많은 이유 중 세 가지입니다.

  1. 여러 서버를 추가하여 사이트를 확장해야 하는 경우 해당 서버 간에 업로드된 파일을 복사하고 동기화하는 방법이 필요합니다.
  2. 서버가 충돌하면 소스 코드가 버전 제어 시스템에 백업되지만 서버를 구성하지 않는 한 미디어 파일은 기본적으로 백업되지 않습니다. 파일 저장소.
  3. 악의적인 활동의 경우 사용자가 업로드한 파일을 응용 프로그램을 실행하는 서버와 별도의 서버에 보관하는 것이 다소 낫습니다.

사용자가 업로드한 파일을 저장하기 위해 타사를 통합하는 것은 정말 쉽습니다. 모델에서 FileFieldupload_to 값을 제거하거나 수정하고 몇 가지 설정을 구성하는 것을 제외하고 코드에서 아무 것도 변경할 필요가 없습니다. 예를 들어 파일을 AWS S3에 저장하려는 경우 다음을 수행하고 싶을 것입니다. 이는 Google Cloud, Azure, Backblaze 또는 유사한 경쟁 서비스를 사용하여 파일을 저장하는 프로세스와 매우 유사합니다.

먼저 boto3django-storages 라이브러리를 설치해야 합니다. 그런 다음 AWS에서 버킷 및 IAM 역할을 설정해야 합니다. 이는 이 문서의 범위를 벗어나지만 여기에서 지침을 볼 수 있습니다. 모든 것이 구성되면 project/settings.py 에 세 개의 변수를 추가해야 합니다.

 DEFAULT_FILE_STORAGE = "storages.backends.s3boto3.S3Boto3Storage" AWS_STORAGE_BUCKET_NAME = "BUCKET_NAME" AWS_S3_REGION_NAME = "us-east-2"

또한 AWS 버킷에 대한 자격 증명 액세스를 설정해야 합니다. 일부 자습서에서는 ID와 비밀 키를 설정 파일에 추가하거나 환경 변수로 추가하는 방법을 보여주지만 이는 안전하지 않은 방법입니다. 대신 여기에 설명된 대로 AWS CLI와 함께 django-storages 를 사용하여 키를 구성하십시오. django-storages 문서에 관심이 있을 수도 있습니다.

개발 또는 테스트 미디어 파일이 실제 사용자의 업로드와 혼동되는 것을 원하지 않습니다. 이를 피하는 것은 매우 간단합니다. 하나는 개발용(또는 각 개발자용), 하나는 테스트용, 하나는 프로덕션용으로 여러 버킷을 설정합니다. 그런 다음 환경별로 AWS_STORAGE_BUCKET_NAME 설정만 변경하면 됩니다.

성능 및 가용성

웹사이트의 성능과 안정성에 영향을 미치는 많은 요소가 있습니다. 다음은 관리에 어떤 접근 방식을 사용하든 상관없이 중요한 정적 및 미디어 파일을 고려할 때 몇 가지 중요한 사항입니다.

비용

사용자에게 파일을 제공하는 데는 스토리지와 대역폭이라는 두 가지 이유로 비용이 듭니다. 파일을 저장하려면 호스팅 제공업체에 비용을 지불해야 하지만 파일을 제공하려면 비용을 지불해야 합니다. 대역폭은 스토리지보다 훨씬 더 비쌉니다(예를 들어, AWS S3는 스토리지에 대해 기가바이트당 2.3센트를 청구하지만 작성 당시 인터넷으로 데이터를 전송하는 데는 기가바이트당 9센트를 청구함). S3 또는 CDN과 같은 파일 저장소의 경제성은 Digital Ocean droplet과 같은 일반화된 호스트의 경제성과 다릅니다. 값비싼 파일을 해당 파일에 맞게 설계된 서비스로 이동하여 전문화 및 규모의 경제를 활용하십시오. 또한 많은 파일 저장소와 CDN은 무료 계획을 제공하므로 사용하지 않고 빠져나갈 수 있을 만큼 충분히 작은 사이트가 대신 그렇게 하고 추가 인프라 비용 없이 이점을 얻을 수 있습니다.

압축 및 트랜스코딩

사진 및 동영상과 같은 정적 자산으로 인해 발생하는 대부분의 문제는 대용량 파일이기 때문입니다. 당연히 개발자는 이러한 파일을 더 작게 만들기 위해 이 문제를 해결합니다. 무손실 및 손실이라는 두 가지 일반적인 범주에서 압축과 트랜스코딩을 혼합하여 이를 수행하는 여러 가지 방법이 있습니다. 무손실 압축은 자산의 원래 품질을 유지하지만 파일 크기는 비교적 완만하게 감소합니다. 손실 압축 또는 손실 형식으로의 코드 변환은 원본 아티팩트의 품질을 일부 손실하는 대신 훨씬 작은 파일 크기를 허용합니다. 이에 대한 예는 비디오를 더 낮은 비트 전송률로 트랜스코딩하는 것입니다. 자세한 내용은 비디오 전송 최적화에 대한 이 문서를 확인하십시오. 웹을 통해 대용량 파일을 제공할 때 대역폭 속도는 종종 손실 압축이 필요한 고도로 압축된 아티팩트를 제공해야 합니다.

YouTube가 아닌 한 압축 및 트랜스코딩은 즉석에서 발생하지 않습니다. 정적 자산은 배포 전에 적절한 형식을 지정해야 하며 사용자 업로드에 대한 기본 파일 유형 및 파일 크기 제한을 적용하여 사용자의 미디어 파일에서 충분한 압축과 적절한 형식을 보장할 수 있습니다.

축소

JavaScript 및 CSS 파일은 일반적으로 이미지만큼 크지 않지만 종종 압축하여 더 적은 바이트로 압축할 수 있습니다. 이 과정을 축소라고 합니다. 축소는 파일의 인코딩을 변경하지 않으며 여전히 텍스트이며 축소된 파일은 여전히 ​​원래 언어에 대한 유효한 코드여야 합니다. 축소된 파일은 원래 확장자를 유지합니다.

축소된 파일에서 가장 중요한 것은 불필요한 공백이며, 컴퓨터의 관점에서 CSS와 JavaScript의 거의 모든 공백은 불필요합니다. 축소 체계는 또한 변수 이름을 줄이고 주석을 제거합니다.

기본적으로 축소는 코드를 난독화합니다. 개발자는 축소되지 않은 파일로만 작업해야 합니다. 배포 프로세스 중 일부 자동 단계는 파일을 저장 및 제공하기 전에 축소해야 합니다. 타사 CDN에서 제공하는 라이브러리를 사용하는 경우 가능한 경우 해당 라이브러리의 축소 버전을 사용하고 있는지 확인하세요. HTML 파일은 축소할 수 있지만 Django는 서버 측 렌더링을 사용하기 때문에 즉석에서 수행하는 처리 비용이 페이지 크기의 작은 감소보다 클 가능성이 큽니다.

글로벌 가용성

이웃에게 편지를 보내는 것이 전국으로 보내는 것보다 시간이 덜 걸리는 것처럼, 가까운 곳에서 데이터를 보내는 것도 전 세계에서보다 시간이 덜 걸립니다. CDN이 페이지 성능을 향상시키는 방법 중 하나는 자산을 전 세계의 서버에 복사하는 것입니다. 그런 다음 클라이언트가 요청을 하면 가장 가까운 서버(종종 에지 노드라고 함)에서 정적 자산을 수신하여 로드 시간을 줄입니다. Django 사이트에서 CDN을 사용하는 것의 장점 중 하나는 코드의 전역 배포에서 정적 자산의 전역 배포를 분리하는 것입니다.

클라이언트 측 캐싱

사용자와 가까운 서버에 정적 파일을 두는 것보다 나은 점은 무엇입니까? 정적 파일이 이미 사용자의 장치에 저장되어 있습니다! 캐싱은 더 빠르게 반복적으로 액세스할 수 있도록 계산 또는 요청 결과를 저장하는 프로세스입니다. CSS 스타일시트가 CDN에서 전 세계적으로 캐시될 수 있는 것처럼, 클라이언트가 귀하의 사이트에서 페이지를 처음 로드할 때 클라이언트의 브라우저에 캐시될 수 있습니다. 그런 다음 후속 요청에서 스타일시트를 기기 자체에서 사용할 수 있으므로 클라이언트는 요청을 더 적게 만들고 페이지 로드 시간을 개선하며 대역폭 사용을 줄입니다.

브라우저는 자체 캐싱 작업을 수행하지만 사이트에 상당한 트래픽이 있는 경우 Django의 캐시 프레임워크를 사용하여 클라이언트 측 캐싱 동작을 최적화할 수 있습니다.

결론적으로

다시 말하지만, 제 지도 철학은 도구가 가장 잘하는 것을 위해 도구를 사용하는 것입니다. 경량의 정적 자산만 있는 단일 서버 프로젝트 및 소규모 확장 가능한 배포는 Django의 기본 제공 정적 자산 관리를 사용할 수 있지만 대부분의 애플리케이션은 CDN을 통해 제공될 자산을 분리해야 합니다.

프로젝트가 실제 사용을 위한 것이라면 Django의 기본 방법으로 미디어 파일을 저장하지 말고 대신 서비스를 사용하세요. "충분한 트래픽"이 인터넷 규모에서 상대적으로 적은 수인 충분한 트래픽이 있으면 아키텍처, 개발 프로세스 및 배포에 대한 추가적인 복잡성이 정적 및 미디어 파일에 대한 별도의 CDN 및 파일 스토리지 솔루션.

권장 읽을거리

  • 1부: 사용자 모델 및 인증
  • 파트 2: 템플릿을 사용하면 라인 절약
  • 3부: 모델, 관리 및 관계형 데이터베이스 활용