Django를 처음 배울 때 이런 설명을 본 적이 있을 것이다. “config/urls.py는 프로젝트 최상위 URL 라우팅 파일입니다.” 솔직히 처음엔 무슨 말인지 잘 모르겠었다. “URL 라우팅”이라는 단어 자체가 낯설었고, “최상위”가 뭘 의미하는지도 직관적으로 와닿지 않았다.
그런데 어느 순간 회사 대표 전화번호에 비유하니까 한 번에 이해됐다. Django의 URL 라우팅 구조는 생각보다 단순하다. 오늘은 코드보다 개념 중심으로, 이 구조를 완전히 소화해보자.
URL 요청이란 무엇인가 — 브라우저가 서버에 보내는 신호
URL 라우팅을 이해하려면 먼저 “URL 요청”이 뭔지 알아야 한다. 브라우저 주소창에 이걸 입력하는 순간을 떠올려보자.
https://deepcarpenter.com/django-url-view-template-structure-guide/
이 순간 브라우저는 서버에 이런 신호를 보낸다. “deepcarpenter.com 서버야, /django-url-view-template-structure-guide/ 페이지 줘봐.” 이게 URL 요청이다. 사용자가 주소를 입력하거나, 링크를 클릭하거나, 버튼을 누를 때마다 이 신호가 발생한다.
URL 요청은 목적에 따라 종류가 나뉜다.
| 종류 | 언제 발생? | 예시 |
|---|---|---|
| GET | 페이지 조회 | 블로그 글 읽기 |
| POST | 데이터 전송 | 로그인, 댓글 작성 |
| PUT | 데이터 수정 | 글 수정 |
| DELETE | 데이터 삭제 | 글 삭제 |
가장 자주 접하는 건 GET이다. 브라우저 주소창에 URL을 입력하는 행위 자체가 GET 요청이다.
urls.py가 하는 일 — 회사 대표 전화번호의 비유
이제 핵심이다. Django에서 urls.py는 정확히 무슨 역할을 할까.
회사 대표 전화번호를 떠올려보자.
고객이 대표번호로 전화
↓
교환원: "영업 문의세요? → 영업부 연결해드릴게요"
교환원: "AS 문의세요? → 고객센터 연결해드릴게요"
교환원: "결제 문의세요? → 회계팀 연결해드릴게요"
여기서 대표 전화번호 = urls.py다. 모든 외부 연락은 반드시 이 번호를 거친다. 대표 전화를 건너뛰고 특정 부서로 바로 연결되는 일은 없다. urls.py도 마찬가지다. 사용자의 모든 URL 요청은 반드시 이 파일을 먼저 통과한다.
그래서 이 파일을 “전체 URL 진입점”이라고 부른다. “전체”의 의미는 도메인(deepcarpenter.com 같은 주소)을 가리키는 게 아니다. 프로젝트 안에 있는 모든 URL 라우팅을 이 파일이 총괄한다는 뜻이다.
URL 라우팅이란 — 교환원이 부서를 연결하는 행위
**URL 라우팅(Routing)**은 “요청을 올바른 목적지로 길 안내하는 것”이다.
대표 전화 비유로 다시 보면, 교환원이 고객의 용건을 듣고 해당 부서로 연결하는 행위 자체가 URL 라우팅이다. Django 흐름으로 옮겨보면 이렇다.
사용자 요청: /blog/post/1/
↓
config/urls.py (진입점에서 URL 라우팅 판단)
"blog/로 시작하면 blog 앱 urls.py로 넘겨"
↓
blog/urls.py → PostDetailView 실행
↓
해당 페이지 응답 반환
여기서 두 개념이 명확히 구분된다.
| 용어 | 의미 | 대표전화 비유 |
|---|---|---|
| 진입점 | 요청이 처음 도착하는 곳 | 대표 전화번호 |
| URL 라우팅 | 어디로 보낼지 결정하는 행위 | 교환원이 부서 연결 |
| config/urls.py | 진입점 + 라우팅을 모두 담당 | 대표 전화 + 교환원 |
config/urls.py가 “최상위”인 이유
Django 프로젝트에는 urls.py가 여러 개 존재할 수 있다.
myproject/
├── config/
│ └── urls.py ← 최상위 (프로젝트 레벨)
├── blog/
│ └── urls.py ← 앱 레벨
└── shop/
└── urls.py ← 앱 레벨
최상위란 계층 구조에서 가장 위에 있다는 뜻이다. 대표 전화를 거쳐야 각 부서로 연결되듯이, config/urls.py를 거쳐야 각 앱의 urls.py로 도달할 수 있다. Django는 settings.py에서 이 파일을 공식 진입점으로 지정한다.
# settings.py
ROOT_URLCONF = 'config.urls' # 이 파일이 진입점이야
이 한 줄 덕분에 Django는 요청이 들어오면 무조건 config/urls.py부터 확인한다. URL 라우팅의 시작점이 여기서 고정되는 것이다.
전체 흐름을 한 번에 정리하면
URL 라우팅의 전체 흐름을 단계별로 보면 이렇다.
| 단계 | 내용 |
|---|---|
| ① | 사용자가 URL 입력 |
| ② | 브라우저가 서버로 URL 요청 전송 |
| ③ | Django가 요청 수신 |
| ④ | config/urls.py (진입점)에서 URL 라우팅 판단 |
| ⑤ | 해당 앱의 urls.py로 전달 |
| ⑥ | 뷰(View) 실행 → 페이지 응답 반환 |
어렵게 느껴졌던 “전체 URL 진입점”과 “URL 라우팅”이 사실은 이 흐름 안에서 각자의 역할을 하고 있을 뿐이다.
핵심 요약
- URL 요청 = 브라우저가 서버에 “이 페이지 줘봐”라고 보내는 신호
- urls.py = 모든 URL 요청이 처음 도착하는 전체 진입점 (대표 전화번호)
- URL라우팅 = 도착한 요청을 올바른 앱으로 연결하는 행위 (교환원의 역할)
- config/urls.py = 진입점 + URL 라우팅을 동시에 담당하는 프로젝트 최상위 파일
- Django를 처음 배울 때 이 구조를 확실히 잡아두면 View·Template 흐름도 수월하게 이어진다
[링크 제안]
URL라우팅 개념이 잡혔다면, 요청이 View와 Template으로 이어지는 전체 Django 구조를 함께 확인해두자.
include()로 앱별 URL을 연결하는 실제 설정 방법은 이 글에서 바로 이어진다.
엔지니어라면 한 번쯤 — 영화 F1이 주는 Inspiration







