Django 구조 완전 정복 — URL·View·Template 3파일 흐름을 3단계로 이해하는 법

Django를 처음 배울 때 가장 먼저 만나는 벽이 있다. 파일은 세 개인데, 어디서 무슨 일이 벌어지는지 감이 안 잡히는 것. urls.py를 건드렸는데 왜 화면이 안 바뀌지? views.py에 코드를 썼는데 왜 오류가 나지? 이 혼란은 Django 구조에서 세 파일이 각각 무슨 역할을 하는지를 구분하지 못해서 생긴다.

이 글에서는 Django 구조의 핵심인 URL → View → Template 흐름을 엔지니어 관점에서 단계별로 정리한다. 개념을 잡고 나면 새 페이지를 만들 때마다 어느 파일을 건드려야 하는지 자동으로 판단할 수 있게 된다.

Django 구조 — URL·View·Template 각 파일의 역할부터 구분하자

Django 구조에서 세 파일은 각자 딱 하나의 질문에만 답한다.

파일담당하는 질문역할 한 줄 요약
urls.py어떤 주소로 들어왔는지주소 보고 담당자 지정
views.py그 요청을 어떻게 처리할지판단하고 처리하는 두뇌
templates/어떤 HTML을 보여줄지결과를 화면으로 출력

이 경계가 무너지면 코드가 뒤섞인다. Django가 이 구조를 강제하는 이유는 유지보수 때문이다. 나중에 화면만 바꾸고 싶을 때 Template만, 로직만 바꾸고 싶을 때 View만 건드리면 된다. Django 구조를 이해한다는 건 이 경계를 몸에 익히는 것이다.

urls.py — “어떤 주소로 들어왔는지” 판단하는 안내데스크

urls.py는 판단하지 않는다. 주소를 보고 넘겨주는 것이 전부다.

# main/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('', views.home, name='home'),
    # main/ 뒤에 아무것도 없으면 → views.home 실행
]

Django 구조에서 URL은 실제로 두 단계로 나뉜다. 프로젝트 전체 관문인 config/urls.py가 먼저 받아서, 앱별 urls.py로 위임한다.

# config/urls.py (프로젝트 관문)
from django.urls import path, include

urlpatterns = [
    path('main/', include('main.urls')),
    # main/ 으로 시작하는 요청은 전부 main앱 urls.py로 넘겨
]

urls.py에서 기억할 핵심은 하나다. 주소와 함수를 연결하는 것만 한다. 처리 로직은 없다.

views.py — “요청을 어떻게 처리할지” 결정하는 두뇌

Django 구조에서 views.py가 핵심이다. URL한테 요청을 넘겨받아 처리하고, 어떤 Template을 보여줄지 결정한다.

# main/views.py
from django.shortcuts import render

def home(request):
    # 여기서 필요한 처리를 다 한다
    # DB 조회, 조건 판단, 계산 등

    return render(request, 'main/home.html')
    # 처리 완료 → main/home.html을 화면에 보여줘라

render() 함수의 두 번째 인자가 Template 경로다. templates/ 폴더를 기준점으로 잡기 때문에 그 이후 경로만 적어주면 된다. 이게 가능한 이유는 settings.py에 아래 설정이 등록되어 있기 때문이다.

# settings.py
TEMPLATES = [
    {
        'DIRS': [BASE_DIR / 'templates'],  # 여기서부터 찾아라
    },
]

Template — “어떤 HTML을 보여줄지” 출력하는 결과물

Template은 판단하지 않는다. View가 넘겨준 것을 화면에 그리는 것이 전부다.

templates/
└── main/
    └── home.html   ← views.py에서 'main/home.html'로 지정한 파일
<!-- templates/main/home.html -->
{% extends 'base.html' %}

{% block content %}
  <h1>메인 홈 화면</h1>
{% endblock %}

{% extends 'base.html' %}은 템플릿 상속이다. 공통 레이아웃(헤더, 네비게이션, 푸터)을 base.html 하나에 모아두고, 각 페이지는 바뀌는 부분만 작성하는 방식이다. base.html 하나를 수정하면 모든 페이지에 반영된다. Django 구조에서 중복 코드를 없애는 핵심 패턴이다.

Django 구조 — URL·View·Template 3파일 흐름 3단계 설명

Django 구조 전체 흐름 — 3단계로 한번에 보기

브라우저: http://127.0.0.1:8000/main/ 접속
                    │
                    ▼
            config/urls.py
            "main/ 왔네 → main앱 urls.py로 넘겨"
                    │
                    ▼
            main/urls.py
            "뒤에 아무것도 없네 → views.home 실행"
                    │
                    ▼
            main/views.py  (home 함수)
            "처리 완료 → main/home.html 보여줘"
                    │
                    ▼
            templates/main/home.html
            화면 렌더링 → 사용자에게 표시

새 페이지를 만들 때마다 이 Django 구조의 3단계를 순서대로 밟으면 된다.

단계파일할 일
urls.py이 주소로 오면 어떤 함수 실행할지 등록
views.py그 함수에서 처리하고 어떤 HTML 보낼지 작성
templates실제 HTML 파일 생성

핵심 요약

  • Django 구조의 핵심은 역할 분리다 — urls.py는 주소만, views.py는 처리만, Template은 출력만 담당한다
  • 이 경계를 머릿속에 고정해두면 문제가 생겼을 때 어느 파일을 봐야 하는지 바로 판단할 수 있다
  • 새 페이지 추가는 항상 urls.py → views.py → templates 순서로 진행한다
  • 템플릿 상속(extends)으로 공통 레이아웃을 한 곳에서 관리한다
  • Django 구조를 초반에 몸에 익혀두면 DB 연동·폼 처리 등 더 복잡한 기능을 배울 때 흔들리지 않는 기반이 된다

[링크 제안]

Django 구조에서 데이터를 담당하는 모델이 어떻게 동작하는지 함께 이해해두면 전체 그림이 완성된다.

Django를 시작하기 전 개발환경 세팅이 아직 낯설다면 이 글이 먼저다.

아이언맨으로 Agentic Engineering을 이해하다

FAQ

앱이 여러 개일 때 URL을 앱별로 분산 관리하기 위해서다. 프로젝트 전체 urls.py가 모든 URL을 들고 있으면 관리가 어려워진다. include()를 써서 각 앱의 urls.py로 위임하는 구조가 Django 구조의 기본 패턴이다.

현재 폴더(앱 폴더)를 가리킨다. from main import views라고 써도 같은 의미지만, 앱 이름이 바뀌어도 코드 수정이 필요 없는 상대 경로 방식이 더 권장된다.

있다. 이 구조는 MVC 패턴(Model-View-Controller)의 변형으로, Django에서는 MTV(Model-Template-View)라고 부른다. Flask, Spring, Rails 등 대부분의 웹 프레임워크가 비슷한 역할 분리 구조를 가지고 있다.

settings.py의 DIRS에 templates/ 폴더를 등록해뒀기 때문에 Django가 그 폴더를 기준점으로 탐색한다. templates/ 이후 경로만 적어주면 된다.

공통 레이아웃(헤더, 네비, 푸터)을 페이지마다 복사-붙여넣기 하지 않기 위해서다. base.html 하나를 수정하면 모든 페이지에 반영된다. Django 구조 학습 초반에 템플릿 상속을 잡아두면 이후 유지보수가 훨씬 편해진다.

관련 글 보기