웹 프로그래밍 또는 웹 서비스 프로그래밍이란 용어를 조금 더 정확하게 표현하면 웹 애플리케이션 프로그래밍이라고 할 수 있습니다. 그러면 애플리케이션이란 무엇일까요?

웹 사이트를 설계할 때 가장 먼저 해야 할 일은 프로그램이 해야 할 일을 적당한 크기로 나누어서 모듈화하는 것입니다. 이때 웹 사이트의 전체 프로그램 또는 모듈화된 단위 프로그램을 애플리케이션이라고 합니다. 즉, 프로그램으로 코딩할 대상을 애플리케이션이라고 부르는 것입니다.

그런데 장고(Django)에서는 애플리케이션의 개념을 웹 서버 프로그래밍 측면에서 조금 더 구체화하여 웹 사이트에 대한 전체 프로그램을 프로젝트Project라 하고, 모듈화된 단위 프로그램을 애플리케이션 Application이라 부릅니다. 즉, 애플리케이션 프로그램들이 모여서 프로젝트를 이루는 개념입니다. 장고는 기본적으로 MVT 패턴에 따라 애플리케이션을 개발하도록 유도하는데 먼저 MVT 패턴을 살펴보겠습니다.

 

 


✅MVT 패턴

웹 프로그래밍 시 일반적으로 언급되는 MVCModel-View-Controller 패턴이란 데이터(Model), 사용자 인터페이스(View), 데이터를 처리하는 로직(Controller)을 구분해서 한 요소가 다른 요소들에 영향을 주지 않도록 설계하는 방식을 의미합니다. 이런 방식으로 개발을 진행하면 UI 디자이너는 데이터 관리나 애플리케이션 로직에 신경 쓰지 않고도 화면 UI를 설계할 수 있고 로직이나 데이터를 설계하는 개발자도 화면 디자인은 디자이너에게 맡기고 자신의 설계 및 개발 업무에만 집중할 수 있습니다. 파이썬도 이러한 MVC 패턴의 개념을 그대로 받아들였는데 용어는 다르게 사용합니다.

장고 프레임워크에서는 View를 Template, Controller는 View라고 표현하며 MVC 대신 MVT Model-View-Template 패턴이라고 합니다. 모델 Model은 데이터베이스에 저장되는 데이터를, 템플릿Template은 사용자에게 보이는 UI 부분을 의미하며, 뷰 View는 실질적으로 프로그램 로직이 동작하여 데이터를 가져오고 적절하게 처리한 결과를 템플릿에 전달하는 역할을 수행합니다.

예를 들면 모델은 블로그의 내용을 데이터베이스로부터 가져오거나 저장/수정하는 역할을, 뷰는 버튼을 눌렀을 때 어떤 함수를 호출하며 데이터를 어떻게 가공할 것인지 결정하는 역할을, 템플릿은 화면 출력을 위해 디자인과 테마를 적용해서 보이는 페이지를 만드는 역할을 담당합니다. 다음 그림은 사용자 요청에 반응하는 MVT 패턴의 각 요소가 서로 어떻게 연결되는지를 보여 줍니다.

장고의 MVT 패턴

 

웹 클라이언트의 요청을 받아 장고에서 MVT 패턴에 맞게 처리하는 과정을 요약하면 다음과 같습니다.

  • 클라이언트로부터 요청을 받으면 URLconf를 이용하여 URL을 분석합니다.
  • URL 분석 결과를 바탕으로 해당 URL 처리를 담당할 를 결정합니다.
  • 뷰는 자신의 로직을 실행하면서 만일 데이터베이스 처리가 필요하면 모델을 통해 처리하고 그 결과를 반환받습니다.
  • 뷰는 자신의 로직 처리가 끝나면 템플릿을 사용하여 클라이언트에 전송할 HTML 파일을 생성합니다.
  • 뷰는 최종 결과로 HTML 파일을 클라이언트에게 보내 응답합니다.

 

 

 


✅Model – 데이터베이스 정의

 

앞에서 모델, 뷰, 템플릿에 관해 간략하게 살폈는데요, 이제부터는 조금 더 세부적인 내용을 보도록 하겠습니다. 모델이란 사용될 데이터에 대한 정의를 담고 있는 장고의 클래스입니다. 장고에서는 ORM 기법을 바탕으로 애플리케이션에서 사용할 데이터베이스를 클래스로 매핑하여 코딩할 수 있습니다. 즉, 하나의 모델 클래스는 하나의 테이블에 매핑되고, 모델 클래스의 속성은 테이블의 컬럼에 매핑됩니다.

이렇게 ORM 기법을 사용하여 테이블을 클래스로 매핑하면 애플리케이션에서는 데이터베이스로의 액세스를 SQL 없이도 클래스를 다루는 것처럼 할 수 있어서 편리합니다. 또한 SQLite3, MySQL, PostgreSQL 등 데이터베이스 엔진을 변경하더라도 ORM 기법이 적용된 API는 변경할 필요가 없으므로 필요에 따라 데이터베이스 엔진을 쉽게 변경할 수 있습니다.

 

🤔잠깐 ORM이 뭐였더라?

ORM(Object-Relational Mapping)은 쉽게 표현하면 객체와 관계형 데이터베이스를 연결하는 역할을 합니다. 기존의 웹 프로그래밍에서 데이터베이스에 접근하려면 직접 SQL 언어를 사용하여 데이터를 요청해야 했고, 개발자는 SQL 및 데이터베이스에 접근하기 위한 드라이버 API 등에 관해 잘 알고 있어야 했습니다. 하지만 ORM에서는 데이터베이스 대신 객체(클래스)를 사용하여 데이터를 처리할 수 있습니다. 객체를 대상으로 필요한 작업을 실행하면 ORM이 자동으로 적절한 SQL 구문이나 데이터베이스 API를 호출하여 처리하기 때문입니다. 물론 직접 SQL을 사용하여 데이터베이스의 데이터를 가져올 수도 있습니다.

장고의 ORM 기법에 대한 이해를 돕기 위해 Person이라는 테이블, 즉 장고의 Person 모델 클래스를 정의해 보겠습니다. 이러한 모델 클래스는 models.py 파일에 정의합니다.

from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length= 30)
last_name = models.CharField(max_length=30)

 

앞서 정의한 Person 모델은 장고 내부의 SQL 명령을 사용하여 다음과 같은 데이터베이스 테이블을 자동으로 생성합니다.

CREATE TABLE myapp_person (
"id" serial NOT NULL PRIMARY KEY,
"first_name" varchar(30) NOT NULL,
"last_name" varchar(30) NOT NULL
);

 

장고에는 테이블 및 컬럼을 자동으로 생성하기 위해 지켜야 하는 규칙이 많습니다. 위의 예제는 그중에서 다음과 같은 규칙이 적용되었습니다.

  • 테이블명은 애플리케이션명과 모델 클래스명을 밑줄(_)로 연결한 문자열로 정하고 모두 소문자로 표시합니다. 원한다면 다른 이름으로 직접 지정할 수도 있습니다.
  • Primary Key는 Person 클래스에서 정의하지 않아도 장고에서 알아서 부여합니다. 개발자가 직접 지정할 수도 있습니다.

장고는 테이블을 모델 클래스로 정의하고 이를 실제 데이터베이스에 반영한 후에도 테이블에 데이터를 입력하고 입력된 데이터를 확인 및 변경할 수 있는 여러 가지 기능을 제공하고 있습니다.

 

 

 


✅View – 로직 정의

 

장고는 웹 요청에 있는 URL을 분석하고 그 결과로 해당 URL에 매핑된 뷰를 호출합니다.

일반적으로 뷰는 웹 요청을 받아서 데이터베이스 접속 등 해당 애플리케이션의 로직에 맞는 처리를 하고 그 결과 데이터를 HTML로 변환하기 위해 템플릿 처리를 한 후 최종 HTML로 된 응답 데이터를 웹 클라이언트로 반환합니다. 장고에서 뷰는 함수 또는 클래스의 메소드로 작성되며 웹 요청을 받고 응답을 반환합니다.

여기서 응답은 HTML 데이터일 수도 있고, 리다이렉션 명령일 수도 있고, 404 에러 메시지일 수도 있습니다. 다양한 형태의 응답 데이터를 만드는 로직을 뷰에 작성하는 것입니다. 이러한 뷰는 보통 views.py 파일에 작성하지만, 원한다면 다른 파일에 작성해도 무방합니다. 다만 파이썬 경로에 있는 파일이어야 장고가 찾을 수 있습니다.

간단한 예시로 현재 날짜와 시간을 HTML로 반환하는 뷰를 작성해 보겠습니다.

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)

 

이 예시에서는 클래스가 아니라 함수로 뷰를 작성했습니다. 뷰 함수는 첫 번째 인자로 Http Request 객체(이 예시에서는 request)를 받습니다. 그리고 필요한 처리를 한 후에 최종적으로 HttpResponse 객체를 반환합니다.

만일 에러를 반환하고 싶다면 다음처럼 HttpResponseNotFound와 같은 에러 응답 객체를 반환하면 됩니다. 에러 응답 클래스는 모두 HttpResponse 클래스의 하위 클래스로 정의되어 있습니다.

return HttpResponseNotFound('<h1>Page not found</h1>')

 

앞의 예시에서는 HTML 코드를 뷰 함수 내에 직접 사용하였지만, 보통은 별도의 템플릿 파일에 HTML 코드를 작성합니다. 즉, 뷰는 별도로 작성된 템플릿 파일을 해석해서 HTML 코드를 생성하고 이를 HttpResponse 객체에 담아서 클라이언트에게 응답합니다. MVT 방식의 마지막 요소인 템플릿(또는 템플릿 파일)에 관해서는 다음 부분에서 설명합니다.

 

 

 


✅Template – 화면 UI 정의

 

장고가 클라이언트에게 반환하는 최종 응답은 HTML 텍스트입니다. 개발자가 응답에 사용할 *.html 파일을 작성하면 장고는 이를 해석해서 최종 HTML 텍스트 응답을 생성하고 이를 클라이언트에게 보냅니다. 클라이언트(보통 웹 브라우저)는 응답으로 받은 HTML 텍스트를 해석해서 우리가 보는 웹 브라우저 화면에 UI를 표시합니다.

이러한 과정에서 개발자가 작성하는 *.html 파일을 템플릿이라 부르며 이 파일에 화면에 표시되는 UI를 템플릿 문법에 맞게 작성합니다.

장고는 자체 템플릿 엔진을 가지고 있기 때문에 디자이너도 쉽게 이해할 수 있는 문법을 제공합니다. 화면 디자인을 변경할 일이 생기면 디자이너는 프로그램 로직에 상관없이 문법에 맞게 템플릿만 수정하면 되므로 디자이너와 개발자 간의 협업이 편리합니다. 또한 장고에서 제공하는 템플릿은 템플릿 태그/필터 기능을 사용하여 파이썬 코드를 직접 사용할 수 있어 더욱 강력하고 확장하기 쉬운 구조로 되어 있습니다.

템플릿 파일은 *.html 확장자를 가지며 장고의 템플릿 시스템 문법에 맞게 템플릿 파일을 작성합니다. 유의할 점은 템플릿 파일을 적절한 디렉터리에 위치시켜야 한다는 것입니다. 즉, 장고에서 템플릿 파일을 찾는 방식을 이해하고 있어야 하며 그에 맞는 위치에 템플릿 파일을 위치시켜야 장고가 그 템플릿 파일을 찾을 수 있습니다.

장고에서 템플릿 파일을 찾을 때는 TEMPLATES 및 INSTALLED_APPS에 지정된 애플리케이션의 디렉터리를 검색합니다. 이 항목들은 프로젝트 설정 파일인 settings.py에 정의되어 있습니다.여러 개의 디렉터리를 지정할 수 있는데 지정된 순서대로 디렉터리를 검색하여 템플릿 파일을 찾습니다.

만일 settings.py 파일에 다음과 같이 정의되어 있다면

INSTALLED_APPS = [
    'polls.apps.PollsConfig’,
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

TEMPLATES = [
    {
        . . .
        'DIRS': [BASE_DIR / 'templates'],
        . . .
    }
]

 

다음과 같은 순서대로 템플릿 디렉터리를 검색하여 템플릿 파일을 찾습니다. BASE_DIR이 \PRIVATE\Programmer\RedBook\ch99인 점을 유의해 주세요.

\PRIVATE\Programmer\RedBook\ch99\templates
\PRIVATE\Programmer\RedBook\ch99\polls\templates
\DevelopPgm\Python36\Lib\site-packages\django\contrib\admin\templates
\DevelopPgm\Python36\Lib\site-packages\django\contrib\auth\templates
\DevelopPgm\Python36\Lib\site-packages\django\contrib\contenttypes\templates
\DevelopPgm\Python36\Lib\site-packages\django\contrib\sessions\templates
\DevelopPgm\Python36\Lib\site-packages\django\contrib\messages\templates
\DevelopPgm\Python36\Lib\site-packages\django\contrib\staticfiles\templates

 

TEMPLATES 항목에 정의된 디렉터리를 먼저 찾은 다음 INSTALLED_APPS 항목에 등록된 각 앱의 templates 디렉터리를 찾는다는 사실을 기억해 주시면 됩니다.

 

 

 


✅MVT 코딩 순서

 

모델, 뷰, 템플릿 셋 중에서 무엇을 먼저 코딩해야 하는지에 관해 정해진 순서는 없습니다. MVT 방식에 따르면 화면 설계는 뷰와 템플릿 코딩으로 연결되고 테이블 설계는 모델 코딩에 반영됩니다. 뷰와 템플릿은 서로 영향을 미치므로 독립적으로 개발할 수 있는 모델을 먼저 코딩하고 그 후 뷰와 템플릿을 같이 코딩하는 것이 일반적입니다.

뷰와 템플릿의 코딩 순서도 굳이 정할 필요는 없지만, UI 화면을 생각하면서 로직을 풀어 나가는 것이 쉽기 때문에 보통은 템플릿을 먼저 코딩합니다. 다만 클래스형 뷰CBV, Class-Based View처럼 뷰의 코딩이 매우 간단한 경우에는 뷰를 먼저 코딩한 다음 템플릿을 코딩합니다.

 

함수형 뷰를 사용하는 경우 모델, 템플릿, 뷰 순서로 코딩을 진행합니다(클래스형 뷰를 사용하는 경우에는 모델, 뷰, 템플릿 순서로 코딩을 진행합니다.). 프로젝트 설정 파일 및 URLConf 파일까지 포함한 코딩 순서를 정리하면 다음과 같습니다.

  • 프로젝트 뼈대 만들기 : 프로젝트 및 애플리케이션 프로그래밍에 필요한 디렉터리와 파일 생성
  • 모델 코딩하기 : 테이블 관련 사항을 프로그래밍(models.py, admin.py 파일)
  • URLconf 코딩하기 : URL 및 뷰 매핑 관계를 정의(urls.py 파일)
  • 템플릿 코딩하기 : 화면 UI 프로그래밍(templates/ 디렉터리 하위의 *.html 파일들)
  • 뷰 코딩하기 : 애플리케이션 로직 프로그래밍(views.py 파일)

 

이처럼 자기만의 코딩 순서를 정하면 에러를 해결하거나 로직을 풀어나가는 데 일관성을 유지할 수 있고 웹 개발 노하우도 빨리 습득할 수 있습니다. 방금 말씀드린 코딩 순서와 상관없이 편한 순서대로 코딩해 주세요.

 

 

 


혼자 공부하는 파이썬(개정판)파이썬 웹 프로그래밍 기초편

 

위 내용은 『파이썬 웹 프로그래밍, 기초편(3판)』과 장고 공식 문서를 참고하여 작성되었습니다. 프로그래밍이 처음이거나 파이썬을 아직 배우지 못한 분들은 『혼자 공부하는 파이썬(개정판) 』으로 기본기를 다진 후에 파이썬 웹 개발에 도전하시는 것을 추천합니다.

파이썬 웹 프로그래밍, 기초편(3판)
장고 공식 문서 바로가기
혼자 공부하는 파이썬(개정판)