Django 소개

Django 소개

장고는 2005년 부터 시작된 파이썬의 오픈 소스 웹 프레임워크이자 풀-스택 프레임워크이다. 많은 사람들이 애용하는 파이썬으로 만들어진 프레임워크로, 웹 개발을 처음 시작하는 사람들도 많이 접근하는 프레임워크이다.

나에게 장고는 대학교 3학년 시절 시작한 스타트업 팀에서 메인 서버 개발에 활용한 프레임워크이다. 처음으로 맡아본 중책이자, 처음 맡아본 총괄 업무였던 지라 개발하며 겪었던 그때의 문제들이 지금까지도 기억에 깊이 남아있다.

스타트업에서 첫 메인 서버 개발을 위한 프레임워크로 장고를 선택한 이유는 아래에 서술된 장고의 특징과 장점들이 크게 작용하였다.

  • 검증된 안정성: 현존하는 다양한 서비스들이 장고를 활용하여 지금도 서비스 하고 있다. (ex, 인스타그램, 나사 공식 홈페이지, BitBucket, Disqus 등등)
  • 다양한 확장성: 광대한 파이썬 패키지 환경과 손쉬운 서비스 확장 방법 (django-app 방식)
  • 친절한 커뮤니티: 개발중에 마주한 이슈 해결을 위해서나 새로운 업데이트등을 손쉽게 접할 수 있는 잘 정리되고 친절한 장고-커뮤니티

위 3가지 특징 뿐 아니라 다양한 특징과 장점도 있지만, 당시 스타트업 시작 초기에 내가 고려했던 핵심 사항들은 저것들이 대부분 이였다. 나에게 유용했던 장고가 다른 사람에게도 유용한 도구가 되길 바라며, 장고의 사용법들을 정리해보고자 한다. 본격적인 장고의 소개에 앞서 장고가 추구하는 소프트웨어-아키텍처, MVT 패턴부터 살펴보자.

MVT Pattern

MVT Pattern은 소프트웨어 설계 패턴 중 하나로, M (Model) - V (View) - T (Template)의 약자를 따서 만든 줄임말이다. 상호 연결된 3가지 요소로 프로그램의 로직을 구분하여 개발하는 MVC Pattern을 응용한 구조이다. MVC Pattern 과의 정확한 차이점으로는, 기존의 MVC Pattern의 URL 라우팅은 Controller 단에서 처리하지만, 장고 프레임워크의 MVT Pattern은 프레임워크 자체에서 처리(URL Conf 기능 활용)한다.

파이썬으로 코딩한 모델을 관계형 데이터베이스로 구축해주는 모델(Model), URL의 라우팅을 통해 들어온 Request를 연결하는 뷰(View), HTTP 요청을 처리하는 웹 템플릿 시스템인 템플릿 (Template)으로 구성된 MVT 디자인 패턴을 따른다.

서버에서의 전체적인 흐름을 Model, View, Template 요소를 활용해 플로우 차트로 그려본다면 다음과 같다.

architecture

위 플로우 차트는 가장 왼편의 Client의 Request 부터 시작한다. 서버 안에서의 프레임워크 작업을 처음부터 순서대로 설명하자면,

  1. Client의 Request가 서버로 들어온다.
  2. Request를 접수한 서버는 Django의 URL Conf를 이용하여 URL을 해석한다.
  3. URL 해석 결과에 맞춰 처리를 담당할 View를 선택한다.
  4. View는 자신의 로직을 수행하고, 만일 DB 처리가 필요한 작업일 경우 Model을 통해 작업을 처리하고, 결과를 반환 받는다.
  5. View의 로직 처리가 끝나면, Template을 활용하여 Client에게 전송할 Response(대개, HTML or JSON) 파일을 생성한다.
  6. View는 최종결과를 Client에게 Response 한다.

장고 프레임워크의 전체적인 흐름은 이렇게 돌아가지만, 각 요소의 세부적인 동작방식을 플로우차트 만으로 이해하기는 쉽지 않다. Client의 Request를 수신하는 URL Conf 부터 장고 프레임워크의 요소들을 흐름대로 하나씩 살펴보자.

URL Conf

장고는 앞서 설명했듯 자체적으로 URL을 매핑 처리해주는 기능이 내장되어 있다. 장고 프레임워크의 설정을 다루는 setting.py 파일에서 ROOT_URLCONF의 설정값이 URLconf를 담당하는 파일이다. 주로 메인 프로젝트 설정 폴더 아래 urls.py 파일로 자동 정의되어 있다. urls.py 파일의 모습을 살펴보자면 대략 다음과 같다.

from django.urls import path
 
from . import views

urlpatterns = [
    path('articles/2003/', views.special_case_2003),
    path('articles/<int:year>', views.year_archive),
    path('articles/<int:year>/<int:month>/', views.month_archive),
    path('articles/<int:year>/<int:month>/<slug:slug>', views.article_detail),
]

urls.py 파일 속 urlpatterns라는 변수명의 list에 미리 설정해둔 url들이 views 파일에 있는 메서드들과 바인드 되어있다. url은 <TYPE:NAME> 형식으로 설정하여 URL 패턴의 일부 문자열을 추출할 수 있다.

Web Client가 우리들의 장고-서버에 Request를 보낼 때, 장고에서 URL을 분석하는 순서를 요약하면 다음과 같다

  • setting.py 파일의 ROOT_URLCONF 항목을 읽어 최상위 URLconf(urls.py)의 위치를 알아냄
  • URLconf를 로딩하여 urlpatterns 변수에 지정되어 있는 URL list를 검사
  • 위에서부터 순서대로 URL list의 내용을 검사하면서 URL pattern이 매치되면 검사를 종료함
  • 매치된 URL의 View를 호출함
  • 호출 시 HttpRequest 객체매칭할 때 추출된 단어들을 View에 인자로 넘겨줌
  • URL 리스트 끝까지 검사했는데도 매칭에 실패하면 Error-Handling-View를 호출

URL Conf에 대한 더욱 자세한 내용은 다른 게시글에서 다룰 예정이다.

View

View는 앞에서 살펴본 URL Conf에서의 설정에 따라 Web Request을 로직에 맞춰 처리한다. 처리한 결과 데이터를 HTML로 변환하기 위하여 Template 처리(Template Rendering)를 한 후에 최종 HTML로 된 Response 데이터를 Web Client로 다시 반환하는 역할을 한다.

장고에서 View는 함수 또는 클래스의 메소드로 작성되며, Web Request를 파라미터로 받고 Response를 반환(리턴)해준다. 사용자의 목적에 맞게 알맞은 Response 데이터를 만들어 내기 위한 로직을 View에 작성하는 것인데, 이러한 View는 보통 views.py 파일에 작성하지만 원한다면 다른 파일에 작성하고 urls.py에서 바인딩해도 무방하다.

간단한 예시로, 현재 날짜와 시간을 HTML로 반환해주는 View코드를 보자.

from django.http import HttpResponse
import datetime

def current_datetime(request):
  now = datetime.datetime.now();
  html = "<html><body>It is now %s</body></html>" % now
  return HttpResponse(html)

이 경우 클래스가 아니라 함수로 View를 작성한 예시이다. View 함수는 첫번째 인자로 HttpRequest 객체를 받는다. 그리고 필요한 처리를 한 후에 최종적으로 HttpResponse 객체를 반환해준다.

위의 예시에서는 HTML태그를 View 함수 내에 직접 작성하였지만, 보통은 별도의 Template 파일에 HTML태그를 작성한다. 즉, View는 별도로 작성된 Template 파일을 해석해서 HTML 태그를 생성하고 이를 HttpResponse 객체에 담아서 Client에게 응답한다.

더욱 자세한 View설정은 다른 게시글에서 샆펴보고, View 단에서 해석할 Template에 대해 알아보자.

Template

서버가 client에 반환하는 최종 response는 기본적으로 HTML이다. 최근에는 프론트 영역이 발달해서 JSON으로도 Response를 전달하지만, 프론트 개발이 활발해지기 이전 서버들은 HTML 문서를 반환했다. 응답에 사용할 *.html 파일을 작성하면, 장고는 이를 해석해서 최종 HTML 문서를 생성하고, 이를 client에게 보내준다.

Template 파일은 *.html 확장자를 가지며, 장고의 독자적인 Template 시스템 문법에 맞게 작성한다. 유의할 점은 Template 파일을 적절한 디렉터리에 위치시켜야 한다는 점이다. 장고에서 Template 파일을 찾을 때 참고하는 적절한 디렉터리란 settings.py에 설정된 TEMPLATE_DIRSINSTALLED_APPS에서 지정된 앱의 디렉터리를 검색한다. Template 파일은 앞에 명세된 곳에 위치해야 Template 파일을 찾을 수 있다. Template 파일을 탐색할 여러 개의 디렉터리를 지정할 수 있는데, settings.py의 변수들에 지정된 순서대로 디렉터리를 검색하여 Template 파일을 찾는다.

아래는 장고의 Template 시스템 문법을 활용하여 만든 html 예시 파일이다.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Home page</title>
</head>
<body>
  {% if youngest_teams %}
    <ul>
      {% for team in youngest_teams %}
        <li>{{ team.team_name }}</li>
      {% endfor %}
    </ul>
  {% else %}
    <p>No teams are available.</p>
  {% endif %}
</body>
</html>

위 코드에서 보듯이 {% %}를 활용하여 Template 외부 변수를 주입할 수 있다. 자세한 내용은 다음의 개별 포스트에서 다루도록 하겠다.

다음으로 장고 MVT 모델의 마지막 남은 Model에 대해 알아보자

Model

Model은 장고 프레임워크에서 데이터베이스에 저장되는 데이터를 의미한다. 장고 공식 문서에서 설명하는 Model에 대한 설명을 조금 더 해석해 보면 다음과 같이 기술한다. Model은 장고 프레임워크의 추가적인 메타데이터가 포함된 기본적인 데이터베이스 레이아웃으로서, 내 데이터에 대한 확실한 단일 정보원(정보의 근원)이라고 한다. 즉, 다른 데이터들과 구분되는 하나의 데이터에 대한 형식을 정의한 것을 장고의 Model 이라고 한다.

Model에 대한 대략적인 코드는 다음과 같다.

from django.db import models


class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField("date published")

    def __str__(self):
        return self.question_text


class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

장고 내부에 미리 정의된 django.db.models 객체를 상속받아 개인이 원하는 자신의 Model을 만들어 낼 수 있다. Model 객체 내부에는 위 코드에서도 보듯 CharField(), DateTimeField(), IntegerField()등 Model 객체에 미리 정의된 필드들을 활용하여 데이터의 타입을 정의한다.

뿐만 아니라, 파이썬의 객체의 특성을 활용하여 내부 메서드를 정의, 장고 프레임워크 내부에서 편리하게 Model을 호출, 처리할 수 있다.

Summary

지금까지 MVT 패턴과 URL Conf를 활용하여 장고 프레임워크의 기초적인 코드 흐름을 나름의 방식으로 분석해보았다. 지금 사용중인 장고 서버는 다양한 확장 패키지들을 추가로 설치하여 사용중이라 순수 장고의 모양은 많이 사라졌지만, 그러나 대부분의 패키지의 동작방식은 장고의 기본 원리와 같다. 우리 모두 개발 생산성을 높이기 위해 다양한 시도를 하지만, 앞선 개발자들의 다양한 시도로 프레임워크의 기본적인 방식이 적립되어 있다는 걸 잊지말자.

틀린 점 지적해주시면 감사히 다시 공부하겠습니다. 읽어주셔서 감사합니다.