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







