설계 철학¶
이 문서는 Django의 개발자들이 프레임워크를 창조하는 데 사용한 기초 철학을 설명합니다. 이 문서의 목적은 과거를 설명하고 미래를 안내하는 것입니다.
일반¶
느슨한 결합¶
Django 스택의 근본적인 목표는 느슨한 결합, 탄탄한 응집입니다. 프레임워크의 각 계층은 정말로 필요하기 전에는 서로 《알지 못해야》 합니다.
예를 들어, 템플릿 시스템은 웹 요청에 대해 알지 못하고, 데이터베이스 계층은 데이터 표출에 대해 알지 못하며, 뷰 시스템은 프로그래머가 어떤 템플릿 시스템을 사용하는지와 무관합니다.
Django는 편의성을 위해 풀 스택으로 제공되지만, 스택의 각 부분은 가능한 한 독립성을 띱니다.
적은 코드¶
Django는 가능한 한 최소한의 코드를 사용하며, 틀에 박힌 코드를 배제합니다. Django는 인트로스펙션과 같은 Python의 동적인 기능을 최대한 활용합니다.
신속한 개발¶
21세기의 웹 프레임워크의 주안점은 웹 개발의 속도를 높이는 것입니다. Django는 놀라우리만큼 빠른 웹 개발을 가능케 해야 합니다.
반복하지 말 것(DRY)¶
고유한 개념 및 데이터는 단 한 번, 단 한 곳에 존재하는 것으로 족합니다. 중복성은 나쁜 것이고, 정규화는 좋은 것입니다.
그러한 이유로, 본 프레임워크는 최소한의 것들을 가지고 최대한의 것을 만들어내도록 합니다.
명시적인 것이 묵시적인 것보다 낫다¶
이것은 PEP 20에 기술된 Python 핵심 원칙이며, Django가 《마법》을 많이 부리지 말아야 한다는 것입니다. 정당한 이유 없이 마법이 일어나서는 안 됩니다. 마법은 매우 큰 편익이 있을 때만 허용되며, 기능의 사용법을 배우고자 하는 개발자에게 혼란을 일으키는 방식으로 구현되어서는 안 됩니다.
일관성¶
본 프레임워크는 모든 수준에서 일관적이어야 합니다. 일관성은 저수준(Python 코딩 스타일)에서 고수준(Django 사용 《경험》)이 이르기까지 적용됩니다.
모델¶
명시적인 것이 묵시적인 것보다 낫다¶
어떤 필드가 그 이름에 전적으로 의존하여 특정한 성질을 가질 것으로 가정해서는 안 됩니다. 이는 시스템에 대한 지식을 너무 많이 필요로 하며 오류를 양산합니다. 필드의 성질은 키워드 인자에 근거해야 하며, 경우에 따라서는 필드의 유형에 근거해야 합니다.
모든 관련 도메인 로직을 포함하라¶
모델은 마틴 파울러의 활성 레코드(Active Record) 디자인 패턴을 따라 《객체》의 모든 관점(aspect)을 캡슐화해야 합니다.
데이터를 모델로 표현하고 그에 대한 정보(사람이 읽을 수 있는 이름, 기본 순서 같은 선택 사항 등)를 모델 클래스에 정의하는 이유는 그 때문입니다. 모델을 이해하는 데 요구되는 모든 정보가 모델 내에 있어야 합니다.
데이터베이스 API¶
데이터베이스 API의 핵심 목표는 다음과 같습니다.
SQL 효율성¶
SQL 문을 가능한 한 적은 횟수로 실행해야 하며 내부적으로 최적화해야 합니다.
저장을 프레임워크에서 조용히 처리해주는 대신, 개발자가 save()
를 명시적으로 호출하도록 한 이유입니다.
select_related()
QuerySet
메서드가 존재하는 것도 이 때문입니다. 이것은 《관련된 모든 객체》를 선택하는 공통적인 경우에 성능을 향상시키는 선택사항입니다.
간결하고 강력한 구문¶
데이터베이스 API는 가능한 한 적은 구문을 가지고 풍부하고 표현력이 뛰어난 문장을 생성할 수 있어야 합니다. 다른 모듈이나 도움 객체를 임포트하는 것에 의존해서는 안 됩니다.
조인(join)이 요구될 때에는 겉으로 드러나지 않게 자동으로 수행되어야 합니다.
모든 객체는 시스템의 모든 관련 객체에 접근할 수 있어야 합니다. 이러한 접근은 양방향이어야 합니다.
필요할 경우 SQL 문을 직접 작성하기 쉬워야 함¶
데이터베이스 API는 개발의 편의를 위한 것이며, 반드시 사용해야 하는 것은 아닙니다. 프레임워크는 맞춤 SQL(전체 문장 또는 API 호출 시 맞춤 파라미터로서의 맞춤 WHERE
절)도 쉽게 작성할 수 있어야 합니다.
URL 설계¶
느슨한 결합¶
Django 앱의 URL은 하부 Python 코드와 결합되어서는 안 됩니다. Python 함수 이름과 URL을 엮는 것은 좋지 않습니다.
Django URL 시스템은 같은 앱을 다른 맥락에서 사용할 수 있도록 합니다. 예를 들어, 한 사이트에서는 /stories/
에, 또 다른 사이트에서는 /news/
에 넣을 수 있습니다.
무한한 유연성¶
URL은 가능한 한 유연해야 합니다. 생각할 수 있는 모든 URL 설계가 가능합니다.
모범 사례를 장려¶
본 프레임워크는 개발자로 하여금 지저분한 URL보다는 예쁜 URL을 더 쉽게 설계할 수 있도록 해야 합니다.
웹페이지 URL에 파일 확장자가 들어가지 않도록 해야 합니다.
URL에 Vignette 스타일의 콤마는 큰 벌을 받아 마땅합니다.
명확한 URL¶
기술적인 측면에서, foo.com/bar
와 foo.com/bar/
는 서로 다른 URL이며, 검색 엔진 로봇이나 몇몇 웹 트래픽 분석 도구에서는 그 둘을 서로 다른 페이지로 봅니다. Django는 URL을 정규화하여 검색 엔진 로봇이 혼동하지 않게 해야 합니다.
이것이 바로 APPEND_SLASH
설정이 있는 이유입니다.
템플릿 시스템¶
표현과 로직을 분리¶
우리는 템플릿 시스템이 표현을 제어하는 도구이자 표현에 관련된 로직일 뿐이라고 봅니다. 템플릿 시스템은 이러한 기본 목표를 넘어서는 기능을 지원하지 말아야 합니다.
중복을 배제¶
대다수의 동적 웹사이트는 공통 헤더, 푸터, 네이게이션 바 같은 사이트 공통 디자인을 갖습니다. Django 템플릿 시스템은 이러한 요소를 한 곳에 저장하기 쉽게 하여 중복 코드를 없애야 합니다.
이것이 템플릿 상속의 기초가 되는 철학입니다.
HTML과의 분리¶
템플릿 시스템은 HTML만을 출력하도록 설계하지 말아야 합니다. 텍스트 기반 포맷 또는 일반 텍스트도 마찬가지로 잘 생성할 수 있어야 합니다.
XML을 템플릿 언어로 사용하지 말 것¶
템플릿 해석을 위해 XML 엔진을 사용하게 되면 템플릿 편집에 있어서 실수가 발생할 가능성이 매우 커질 뿐 아니라, 템플릿 처리에 너무 큰 과부하가 걸립니다.
디자이너가 코딩 능력이 있는 것으로 가정¶
템플릿 시스템은 템플릿이 반드시 드림위버(Dreamweaver) 같은 위지윅(WYSIWYG) 편집기에서 제대로 보이도록 설계하지는 않습니다. 그렇게 하려면 너무 제약이 많아지며 지금과 같이 훌륭한 구문을 유지하기 힘들기 때문입니다. Django는 템플릿 작성자가 HTML을 직접 편집하는 것을 어려워 하지 않을 것을 전제로 합니다.
공백에 특별한 의미를 부여하지 말 것¶
템플릿 시스템은 공백을 가지고 특수한 동작을 일으켜서는 안 됩니다. 템플릿에 공백이 포함되어 있으면 그것을 그저 텍스트의 공백으로서 표출(display)해야 합니다. 템플릿 태그 내에 있지 않은 모든 공백은 표출해야 합니다.
프로그래밍 언어를 발명하지 말 것¶
프로그래밍 언어의 발명을 목적으로 하는 것이 아닙니다. 분기와 반복 같이 표현 계층에 꼭 필요한 프로그래밍 기능을 제공하는 것이 목표입니다. Django 템플릿 언어(DTL)는 고급 로직을 제공하지 않습니다.
Django 템플릿 시스템은 템플릿이 프로그래머가 아닌 디자이너에 의해 작성되는 것을 전제로 하므로, 그들이 Python 지식을 갖고 있을 것으로 간주해서는 안 됩니다.
안전과 보안¶
템플릿 시스템은 데이테베이스의 레코드를 삭제하는 명령과 같은 악의적 코드를 포함할 수 없게 되어 있어야 합니다.
이것은 템플릿 시스템이 임의의 Python 코드를 실행할 수 없는 또다른 이유이기도 합니다.
뷰¶
단순성¶
뷰를 작성하는 것은 Python 함수를 작성하는 것만큼 단순해야 합니다. 개발자는 함수로 처리할 수 있는 일을 하기 위해 클래스의 인스턴스를 굳이 생성하지 않아도 됩니다.
요청 객체의 사용¶
뷰는 요청 객체(현재 요청에 대한 메타데이터를 갖는 객체)에 접근할 수 있어야 합니다. 뷰 함수가 글로벌 변수의 요청 데이터에 접근하도록 하지 말고, 요청 객체를 뷰 함수에 직접 전달합니다. 《가짜》 요청 객체를 전달함으로써 가볍고 깔끔하며 쉬운 테스트 뷰를 만들 수 있습니다.
느슨한 결합¶
뷰는 개발자가 어느 템플릿 시스템을 사용하는지, 혹은 템플릿 시스템을 사용하는지에 무관해야 합니다.
GET과 POST를 구분¶
GET과 POST는 고유한 것이므로, 개발자는 명시적으로 둘 중 하나를 사용해야 합니다. 본 프레임워크는 GET과 POST 데이터를 쉽게 구분할 수 있도록 해야 합니다.