본문 바로가기

문돌이 존버/Django 스터디

장고(Django), static 파일 다루는 방법 및 extends html

반응형
본 글은 Holix의 "리액트와 함께 장고 시작하기 Complete" 강의를 듣고 작성한 일지입니다.

Static & Media 파일

Static 파일은 개발 리소스로서의 정적인 파일(js, css, image 등)을 말합니다. 앱 혹은 프로젝트 단위로 저장하고 서빙합니다. 반면, Media 파일은 FileField/ImageField를 통해 저장한 모든 파일을 가리킵니다. DB 필드에는 저장경로를 저장하며, 파일은 파일 스토리지에 저장합니다. 앱이 아닌 프로젝트 단위로 저장하고 서빙합니다.

장고 Static 파일 경로

아시다시피 장고는 One project, Multi app 구조입니다. 일반적으로 한 app을 위한 static 파일을 app/static/app 경로에 둡니다. 프로젝트 전반적으로 사용되는 static 파일은 settings.STATICFILES_DIRS 에 지정된 경로에 둡니다. 그리고 다수 디렉토리에 저장된 static 파일은 collectstatic 명령을 통해 settings.STATIC_ROOT 에 지정한 경로로 모아 (복사)해서 서비스에 사용합니다.

관련 settings 예시는 아래와 같습니다.

STATIC_URL = None
- 각 static 파일에 대한 URL Prefix
  (탬플릿 태그 {% static "경로" %}에 의해서 참조되는 설정
- 항상 /로 끝나도록 설정

STATICFILES_DIRS = []
- File System Loader에 의해 참조되는 설정

STATIC_ROOT = None
- python manage.py collectstatic 명령이 참조되는 설정
- 여러 디렉토리로 나눠진 static 파일들을 해당 경로의 디렉토리로 복사(서빙 배포에서만 의미가 있는 설정) 

Static Files Finders

Template Loader와 유사하며, 설정된 Finders를 통해 static 템플릿이 있을 디렉토리 목록을 구성합니다(장고 서버 초기 시작 시에만 1회 작성). 디렉토리 목록에서 지정 상대경로를 가지는 static 파일을 찾습니다.

대표적인 2가지 Static Files Finders로는 아래가 있습니다.

1. App Directories Finder
- "장고앱/static/" 경로를 "디렉토리 목록"에 추가

2. File System Finder
- settings.STATICFILES_DIRS 설정값을 "디렉토리 목록"에 추가

참고로 기존의 settings.py 에는 아래 코드가 명시되어 있었지만 현재는 내부에만 구현하고 표시하지 않는다고 합니다.

# settings.py
STATICFILES_FINDERS = [
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
]​

템플리에서 static URL을 처리할 때는 하드코딩(모든 주소 입력) 대신 Template Tag를 통한 유연한 처리가 가능합니다.

<!-- html 예시 -->
{% load static %}
<img src="{% static 'blog/title.png' %} />

개발환경에선 개발서버를 쓰고 settings.DEBUG=True 일 때만 static 파일 서빙을 지원합니다. 프로젝트/urls.py에 Rule이 명시되어 있지 않아도 자동으로 추가하며 이는 순수 개발목적으로만 제공됩니다. 따라서 개발서버를 쓰지 않거나 settings.DEBUG=False 일 경우는 별도로 static 서빙 설정을 해주어야 합니다.

myproj/static/main.css => http://localhost:8000/static/main.css 경로로 접근 가능
blog/static/blog/style.css => http://localhost:8000/static/blog/style.css 경로로 접근 가능

위의 예시를 보면 URL을 통해 파일에 접근하는 것처럼 보이지만, 그것이 아니라 지정 이름의 STATIC 파일을 장고의 Static Files Finder에서 대신 찾아 그 내용을 읽어서 응답하는 것입니다.


매 화면마다 html 파일을 만들어서 웹 페이지에 보여주게 되는데, 전반적인 css, js 파일 적용은 동일하게 할 수 있습니다. 즉 각 html 파일마다 반복되는 css, js 파일을 적용하는 것이 아니라 전체적인 틀(구조)을 맞추는 파일(예: lay_out.html)을 두고 특징적인 것만 각 html 파일에 명시하는 것입니다.

이때 사용하는 것은 {% block %} {% endblock %} 구조입니다. 그리고 각 html 파일에는 반드시 {% extends "기본 구조.html" %}를 입력해야 합니다.

<!-- lay_out.html -->
{% load static %}

<!doctype html>
<html lang="ko">
<head>
    <meta charset="utf-8" />
    <title>{% block title %}{% endblock title %}</title>
    <!-- CSS only -->
    <!-- <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" crossorigin="anonymous"> -->
    <link rel="stylesheet" href="{% static 'bootstrap-4.3.1-dist/css/bootstrap.css' %}" />
    <script src="{% static 'jquery-3.6.0.min.js' %}"></script>
    <script src="{% static 'bootstrap-4.3.1-dist/js/bootstrap.js' %}"></script>

    <style>
        @media (max-width: 600px) {
            body {
                background-color: green;
            }
        }
    </style>
</head>
<body>
    {% block content %}
    {% endblock content %}
</body>
</html>
<!-- post_list.html -->
{% extends "blog1/lay_out.html" %} <!-- 상속받는다는 의미 -->
{% load django_bootstrap5 %}

{% block title %}
    Instagram / Post List
{% endblock title %}

{% block content %}
...
{% endblock content %}
728x90
반응형