콘텐츠로 이동

Django 전통적인 라우팅#

2024 iThome 철인 대회

이 글은 Django Ninja 입문 가이드의 7번째 글이에요. 우리는 시리즈의 3장에 도달했어요.

3장은 이번 시리즈의 하이라이트예요. 왜냐하면 Django Ninja의 핵심인 API를 소개할 것이기 때문이죠.

저는 이 장을 세 개의 작은 섹션으로 나누었어요:

  1. 1절: 라우터(Router)
  2. 2절: 요청(Request)
  3. 3절: 응답(Response)

3장은 전체 시리즈에서 유일하게 섹션이 나뉘어 있는 장이기도 해요.

이제 첫 번째 섹션인 라우터로 들어가 볼게요. 먼저 이 섹션의 학습 핵심을 알아볼까요.

GitHub 예제 프로젝트#

👉 Django-Ninja-Tutorial


본 절의 핵심#

본 절은 총 두 편으로 구성되어 있어요:

  • 7편: 라우팅 (상) 기존 Django 라우팅 방식
  • 8편: 라우팅 (하) Django Ninja 라우팅 설정

왜 이렇게 구성했을까요? 그 이유는 엔드포인트와 라우팅이 API 요청의 출발점이기 때문이에요.

이들이 없다면 뷰(view) 함수가 요청을 받을 수 없고, 당연히 응답도 할 수 없어요. 따라서 라우팅 설정은 API 개발 학습의 진입점으로서 가장 먼저 다루어야 해요.

'엔드포인트(endpoints)'는 API가 위치한 URL이라고 간단히 생각하시면 돼요.

본문의 요지#

두 번째로, Django Ninja의 라우팅 설정은 기존 Django나 Django REST framework(이하 DRF)의 라우팅 설정과 매우 달라서, 오히려 FastAPI나 Flask 스타일에 가까워요.

이것은 제가 Django Ninja를 배울 때 부딪힌 첫 번째 문턱이었어요 (결국 DRF를 2년이나 썼으니까요😅). 그래서 기초를 다지고 혼란을 줄일 수 있도록 상, 하 두 편의 글로 자세히 설명하기로 했어요.

본문의 핵심은 Django의 전통적인 라우팅 설정 방식을 소개하는 거예요. 시작해 볼까요!


라우터(Routers)란 무엇인가#

라우터(Router)는 웹 서비스의 중요한 구성 요소 중 하나로, 클라이언트(보통 브라우저)가 보낸 HTTP 요청을 올바른 처리 로직에 매핑하는 역할을 해요.

Django에서 라우팅은 '어떤 요청이 어떤 뷰(View)에 의해 처리되어야 하는지'를 결정하는 메커니즘이에요.

클라이언트가 특정 URL(우리가 '엔드포인트'라고 부르는 것)에 접근하면, Django 서버는 이 URL을 기반으로 해당하는 처리 함수를 찾아 특정 로직을 실행해요.

이 '매핑(mapping)' 과정이 바로 라우팅의 핵심 역할이에요.


Django 라우팅 소개#

Django의 라우팅 메커니즘은 주로 urls.py의 설정을 통해 서로 다른 레벨의 라우팅 구조를 관리하며, 1차 라우팅과 2차 라우팅을 통해 모든 엔드포인트를 통합하고 조직화해요.

지금까지 우리는 Django 라우팅의 세 가지 핵심 요소를 언급했어요:

  • 1차 라우팅
  • 2차 라우팅
  • urls.py

이에 대한 소개는 다음과 같아요.

1차 라우팅#

1차 라우팅은 '프로젝트 레벨'의 라우팅으로, 보통 Django 프로젝트 디렉토리 하위(예제 프로젝트의 NinjaForum 디렉토리)에 있는 urls.py에 위치해요.

1차 라우팅은 주로 각 Django 앱에 앱 전체에 통일된 '라우팅 접두사'를 추가하고, 모든 앱에서 오는 라우팅을 통합하는 데 사용돼요.

우리 프로젝트를 예로 들면, 다음과 같이 보일 수 있어요:

# NinjaForum/urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('posts/', include('post.urls')),  # post 앱의 라우팅 처리
    path('users/', include('user.urls')),  # user 앱의 라우팅 처리
]

여기서 urlpatterns는 Django의 1차 라우팅이에요. /posts//users/ 경로를 각각 post와 user 앱의 2차 라우팅으로 연결하여, 각 앱 2차 라우팅의 통일된 접두사로 사용해요.

2차 라우팅#

2차 라우팅은 각 Django 앱이 자체적으로 관리하는 라우팅이에요. 앱 자체의 뷰(view) 함수에 직접 매핑돼요:

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

urlpatterns = [
    path('', views.get_posts)
    path('<int:post_id>/', views.post_detail),
]

1차 라우팅과 2차 라우팅의 로직을 재조합하면, 위 두 앱 레벨 라우팅의 실제 엔드포인트는 다음과 같아요:

  1. /posts/ : 모든 게시글 가져오기.
  2. /posts/<int:post_id>/ : 특정 게시글 세부 정보 가져오기.

이러한 계층적인 라우팅 구조는 URL을 더 체계적으로 만들 뿐만 아니라, 다양한 앱의 기능을 더욱 모듈화하게 해줘요.

예를 들어 user 앱에 '사용자 정보 가져오기' API를 추가하고 싶다면, user 앱의 urls.py에 해당하는 라우팅만 추가하면 되며 프로젝트 레벨의 라우팅 설정은 수정할 필요가 없어요.


프로젝트 아키텍처 다이어그램#

조감도 시점으로 보면 더 명확할 수 있어요.

Django의 전통적인 라우팅 부분에서, 전체 예제 프로젝트의 디렉토리와 파일 구조는 다음과 같아요 (무관한 부분은 생략됨):

├── NinjaForum
   ├── urls.py  # 프로젝트 1차 라우팅
   ├── ...
├── post
   ├── urls.py  # 앱 2차 라우팅
   ├── ...
├── user
   ├── urls.py  # 앱 2차 라우팅
   ├── ...
├── ...

이러한 구조는 Django 프로젝트에서 매우 흔하게 볼 수 있으며, DRF의 표준 방식이기도 해요.

프로젝트 1차 라우팅은 전역적인 진입점을 담당하고, 2차 라우팅은 앱 내의 뷰 함수 매핑을 담당해요. 이러한 설계는 프로젝트 아키텍처를 더 모듈화되고 확장 가능하게 만들어줘요.


Django 전통적인 라우팅의 장점과 단점#

Django의 전통적인 라우팅 메커니즘은 프로젝트와 앱 레벨의 urls.py를 통해 완전한 URL 경로(엔드포인트)를 조직하고 정의해요. 이러한 설계에는 장단점이 모두 있는데, 그 득실을 살펴볼까요.

장점: 명확한 엔드포인트 목록#

Django 전통적인 라우팅의 큰 장점 중 하나는 모든 엔드포인트와 라우팅이 urls.py에 집중되어 있다는 거예요. 이는 개발자가 현재의 모든 API 엔드포인트를 한눈에 알아볼 수 있다는 것을 의미해요(앱 부분에서). 예를 들면:

# 앱 레벨 urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('home/', views.home, name='home'),
    path('about/', views.about, name='about'),
    path('contact/', views.contact, name='contact'),
]

urls.py는 마치 라우팅 디렉토리처럼 한눈에 들어와요.

단점: 엔드포인트와 뷰 함수를 대조하려면 왔다 갔다 해야 함#

앞서 언급했듯이, 라우팅은 엔드포인트와 뷰 함수를 연결하는 역할을 해요.

각 엔드포인트는 하나의 뷰 함수에 대응해야 하며, 대응하는 뷰 함수는 보통 views.py에 위치해요.

대응 구조도(참고용)

이로 인해 한 가지 문제가 발생해요. 개발자는 하나의 엔드포인트와 그 이면의 구현 로직을 완전히 이해하기 위해 urls.pyviews.py 사이를 왔다 갔다 해야만 해요.

이러한 '직관적이지 않음'은 개발 시의 인지적 부담을 증가시킬 뿐만 아니라, API를 수정할 때 오류를 발생시키기 쉬워요.

또한 프로젝트 규모가 커짐에 따라 urls.py 안의 엔드포인트 목록은 점점 길어지고—해당하는 뷰 함수를 찾는 데 시간이 걸리고 번거로워져, 오류 발생 가능성이 더 커지게 돼요.


소결#

이 글에서는 기존 Django의 라우팅 설계를 깊이 살펴보고 그 장단점을 논의했어요.

이러한 구조화된 설계는 라우팅 관리를 더욱 모듈화하게 하지만, 대규모 프로젝트에서는 유지보수와 가독성을 떨어뜨리는 문제를 야기하기도 해요.

다음으로 우리는 Django Ninja가 어떻게 더 간결한 라우팅 메커니즘을 제공하는지 탐구하고, 전통적인 Django 라우팅과 비교해 볼 거예요.

The Django Ninja Way#

Django Ninja는 라우팅과 뷰 함수를 처리하는 데 있어 더욱 현대적인 방식을 채택했어요. 이 둘을 밀접하게 결합하여 API 엔드포인트를 정의하는 더 직관적인 수단을 제공하죠. (사실 모두가 Flask를 배웠죠☺️)

이는 서로 다른 파일 사이를 전환해야 하는 필요성을 크게 줄였을 뿐만 아니라, 코드의 가독성과 유지보수성도 높였어요.

다음 글에서는 Django Ninja의 라우팅 메커니즘에 대해 알아보고, 그것이 이러한 문제들을 어떻게 개선하는지 살펴보도록 할게요.