Django 정적 파일

Django는 실 서비스 환경에서 사용할 정적 파일을 제공하는 기능을 제공하지 않습니다. 서버에 저장된 정적 파일을 읽어들여서 그대로 웹 클라이언트에 보내기만 하면 그만인 단순한 기능인데도 Django는 그런 기능을 제공하지 않습니다. 왜냐하면 그럴 필요가 없기 때문인데, 앞서 설명한 바와 같이 그런 작업에 대해서는 웹 서버가 전문가이기 때문입니다.


게다가 웹 애플리케이션은 웹 서버와 연결하는 중간 인터페이스를 거치므로 효율이 더 떨어집니다. 하지만, 개발 상황인 경우는 효율보다는 기능(역할)이 중요한 경우가 많습니다. 정적 파일이 제대로 제공되는지 확인하려고 항상 웹 서버를 구동할 필요는 없습니다. Django는 개발 단계에서 쓸 정적 파일 제공 기능을 제공합니다. 성능은 웹 서버가 직접 정적 파일을 제공하는 것 보다 떨어지지만 정적 파일 제공에 필요한 기능은 대부분 지원합니다.

Django은 정적 파일을 크게 Static file과 Media file 두 종류로 구분합니다.

Static file은 Javascript, CSS, Image 파일처럼 웹 서비스에서 사용하려고 미리 준비해 놓은 정적 파일입니다. 파일 자체가 고정되어 있고, 서비스 중에도 수시로 추가되거나 변경되지 않고 고정되어 있습니다.

Media file은 이용자가 웹에서 올리는(upload) 파일입니다. 파일 자체는 고정되어 이지만, 언제 어떤 파일이 정적 파일로 제공되고 준비되는지 예측할 수 없습니다.

Static file과 Media file은 정적 파일이라는 점에서는 같지만, 정적 파일을 제공하는 상황을 예측할 수 있는지 여부는 다릅니다. Static file은 서비스에 필요한 정적 파일을 미리 준비해놓기 때문에 manage.py 도구에 findstatic과 collectstatic이라는 기능으로 정적 파일을 모으고 찾는 관리 기능을 제공합니다. manage.py은 Django 프로젝트를 관리하는 일에 필요한 기능을 명령줄 쉘(shell)에서 수행하는 도구입니다. 그에 반해 Media file은 이용자가 웹에서 올리는 파일이므로 미리 예측해서 준비할 수 없습니다. 그래서 Static file 관련된 관리 기능인 findstatic과 collectstatic 기능을 사용하지 못합니다.

Static file

Static file은 웹 서비스에 사용할 정적 파일을 미리 준비하여 제공하는 데 사용합니다. Django로 운영되는 프로젝트의 설정을 관리하는 settings.py에 Static file와 관련된 항목이 다섯 가지 존재하며, 보통은 다음 세 가지를 사용합니다.

  • STATICFILES_DIRS
  • STATIC_URL
  • STATIC_ROOT

STATICFILES_DIRS

STATICFILES_DIRS은 개발 단계에서 사용하는 정적 파일이 위치한 경로들을 지정하는 설정 항목입니다. 특정 Django App(Django로 생성한 프로젝트를 Django 프로젝트라 하고, Django 프로젝트는 뭔가를 수행하는 기능 단위인 Django App을 모아놓은 좀 더 큰 단위입니다.) 에만 사용하는 정적 파일이 있거나 혹은 정적 파일을 관리하기 용이하게 하기 위해 여러 경로(path)에 정적 파일을 배치하였다면, 이 경로들을 Python의 list나 tuple로 담으면 됩니다.

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
)

대개는 static이라는 디렉터리에 정적 파일을 담습니다. 주의할 점은 정적 디렉터리 경로가 하나이더라도 반드시 list나 tuple로 담아야 한다는 점입니다. manage.py에서 제공하는 명령어 중 findstatic은 STATICFILES_DIRS에 설정한 경로에서 지정한 정적 파일을 찾습니다.

STATIC_URL

STATIC_URL은 웹 페이지에서 사용할 정적 파일의 최상위 URL 경로입니다. 이 최상위 경로 자체는 실제 파일이나 디렉터리가 아니며, URL로만 존재하는 단위입니다. 그래서 이용자 마음대로 정해도 상관없습니다.

STATIC_URL = '/assets/'

문자열은 반드시 /로 끝나야 합니다. findstatic 명령어로 탐색되는 정적 파일 경로에 STATIC_URL 경로를 합치면 실제 웹에서 접근 가능한 URL이 됩니다. STATIC_URL은 정적 파일이 실제 위치한 경로를 참조하며, 이 실제 경로는 STATICFILES_DIRS 설정 항목에 지정된 경로가 아닌 STATIC_ROOT 설정 항목에 지정된 경로입니다. 

STATIC_ROOT

STATIC_ROOT는 Django 프로젝트에서 사용하는 모든 정적 파일을 한 곳에 모아넣는 경로입니다. 한 곳에 모으는 기능은 manage.py 파일의 collectstatic 명령어로 수행합니다. Django가 모든 파일을 검사하여 정적 파일로 사용하는지 여부를 확인한 뒤 모으는 건 아니고, 각 Django 앱 디렉터리에 있는 static 디렉터리와 STATICFILES_DIRS에 지정된 경로에 있는 모든 파일을 모읍니다. 

개발 과정에선, 정확히는 settings.py의 DEBUG가 True로 설정되어 있으면 STATIC_ROOT 설정은 작용하지 않으며, STATIC_ROOT는 실 서비스 환경을 위한 설정 항목입니다. 그래서 개발 과정에선 STATIC_ROOT에 지정한 경로가 실제로 존재하지 않거나 아예 STATIC_ROOT 설정 항목 자체가 없어도 문제없이 동작합니다. 실 서비스 환경에서 STATIC_ROOT이 필요한 이유는 이 경로에 있는 모든 파일을 웹 서버가 직접 제공(serving)하기 위함입니다.  아래 예제를 통해 확인해 보겠습니다.

settings.py에 다음과 같이 STATIC_ROOT 설정 항목을 추가합니다.

STATIC_ROOT = os.path.join(BASE_DIR, 'collected_statics')

 


list나 tuple형인 STATICFILES_DIRS와는 달리 문자열 경로를 할당합니다. 이제 collectstatic 명령어로 현 프로젝트가 사용하는 모든 정적 파일을 모읍니다. 

$ python manage.py collectstatic

지정한 경로에 있는 기존 파일을 전부 덮어 쓰는데 정말로 모을 거냐고 묻습니다. 원본 파일을 덮어 쓰는 게 아니니 yes라고 입력합니다. 정적 파일을 모을 경로를 manage.py 파일이 있는 경로에 collected_statics 디렉터리로 지정했으므로 이 디렉터리가 만들어지고, 이 안에 사용하는 모든 정적 파일이 복사됩니다. 

 이렇게 정적 파일을 모아놓은 STATIC_ROOT는 Django가 직접 접근하진 않습니다. Django가 접근하여 다루는 설정은 STATICFILES_DIRS이며, STATIC_ROOT는 정적 파일을 직접 제공(serving)할 웹 서버가 접근합니다. collectstatic 명령어를 수행하면 STATICFILES_DIRS나 앱 디렉토리에 있는 static 디렉토리 안에 있는 파일을 STATIC_ROOT에 모으는데, STATICFILES_DIRS에 지정된 경로인 경우 따로 명시한 접두사으로 디렉토리를 만들어 그 안에 파일을 복사하고, 앱 디렉토리에 있는 static 디렉토리인 경우는 앱 이름으로 디렉토리를 만들어 그 안에 static 디렉터리 안에 있는 파일을 복사합니다. 즉, 개발 단계(DEBUG = True)에서는 정적 파일 URL 경로가 논리 개념이고, 서비스 환경(DEBUG = False)에서는 실제 물리 개념인 정적 파일 URL 경로가 되는 것입니다.

 주의할 점은 STATIC_ROOT 경로는 STATICFILES_DIRS 등록된 경로와 같은 경로가 있어서는 안 됩니다. 남들이 잘 안 쓸만한 이상한 이름(collected_statics?)을 쓰는 것을 추천합니다.

 

Media file

Media file은 이용자가 웹에서 업로드한 정적 파일입니다. 미리 준비해놓고 제공하는 Static file과는 달리 언제 어떤 파일이 추가될 지 모르므로 findstatic과 collectstatic같은 명령어는 Media file에 대해서는 무의미합니다.

 

settings.py에 Media file와 관련된 항목이 두 가지 존재합니다.

  • MEDIA_ROOT
  • MEDIA_URL

파일 업로드와 관련하여 세부 조정하는 설정이 몇 가지 더 있지만, 대개는 기본 설정(global_settings)대로 써도 무방합니다. MEDIA_ROOT는 이름이 STATIC_ROOT과 비슷한데, 업로드가 끝난 파일을 배치할 최상위 경로를 지정하는 설정 항목입니다. STATIC_ROOT보다는 STATICFILES_DIRS이 더 비슷한 역할을 합니다. 또한 MEDIA_ROOT는 STATIC_ROOT와 다른 경로를 지정해야 합니다. MEDIA_URL은 STATIC_URL과 이름도 비슷하고 역할도 비슷합니다. /로 끝나는 URL 경로 문자열로 설정해야 한다는 점도 같습니다. MEDIA_URL도 MEDIA_ROOT와 마찬가지로 STATIC_URL과 URL 경로가 달라야 합니다. 아래 예제를 통해 더 자세히 설명하겠습니다.

먼저 settings.py에서 MEDIA_ROOT 부분을 작성한 예제입니다.

MEDIA_URL = '/uploads/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'uploaded_files')


+ Random Posts