[Django] 개요와 프로젝트 구조
정의
Django는 2003년 시작된 Python 풀스택 웹 프레임워크. “Web framework for perfectionists with deadlines”라는 모토대로 batteries-included(ORM, 관리자, 인증, 폼, 마이그레이션, 캐싱 등 기본 내장). MTV(Model-Template-View) 아키텍처. Instagram, Pinterest, Mozilla 등 대규모 운영 사례.
MTV 패턴
전통적인 MVC와 약간 다른 명명.
| Django | 전통 MVC | 역할 |
|---|---|---|
| Model | Model | DB 스키마와 비즈니스 로직 |
| Template | View | HTML 렌더링 |
| View | Controller | HTTP 요청 처리 |
| URL Dispatcher | Router | URL → View 매핑 |
요청 흐름: URL → View → (Model 조회/변경) → Template 렌더링 → Response
요청 처리 흐름
flowchart LR
Client["클라이언트"] -->|"HTTP 요청"| MW1["Request Middleware"]
MW1 --> URLConf["URL Dispatcher"]
URLConf --> View["View"]
View --> Model["Model / ORM"]
Model --> View
View --> Template["Template Engine"]
Template --> MW2["Response Middleware"]
MW2 -->|"HTTP 응답"| Client
미들웨어는 요청/응답 양방향을 모두 가로챌 수 있다. 인증, 세션, CSRF, 캐싱 등이 여기 위치한다.
프로젝트 구조
django-admin startproject myproject
cd myproject
python manage.py startapp blog
myproject/
├── manage.py # CLI 진입점
├── myproject/ # 프로젝트 설정 패키지
│ ├── __init__.py
│ ├── settings.py # 설정
│ ├── urls.py # 루트 URL conf
│ ├── asgi.py # ASGI 진입점
│ └── wsgi.py # WSGI 진입점
├── blog/ # 앱
│ ├── __init__.py
│ ├── admin.py # 관리자 등록
│ ├── apps.py # 앱 설정
│ ├── models.py # 데이터 모델
│ ├── views.py # 뷰
│ ├── urls.py # 앱별 URL (관례)
│ ├── tests.py
│ └── migrations/ # DB 마이그레이션
└── templates/ # 템플릿 (관례)
프로젝트 = 사이트, 앱 = 기능 단위. 한 프로젝트에 여러 앱. 앱은 독립적이고 재사용 가능하도록 작성.
첫 모델
# blog/models.py
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=200)
body = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
마이그레이션 생성과 적용:
python manage.py makemigrations
python manage.py migrate
첫 뷰와 URL
# blog/views.py
from django.shortcuts import render
from .models import Post
def post_list(request):
posts = Post.objects.all()
return render(request, "blog/post_list.html", {"posts": posts})
# blog/urls.py
from django.urls import path
from . import views
urlpatterns = [
path("", views.post_list, name="post-list"),
]
# myproject/urls.py
from django.urls import include, path
urlpatterns = [
path("blog/", include("blog.urls")),
]
템플릿
{# templates/blog/post_list.html #}
{% for post in posts %}
<h2>{{ post.title }}</h2>
<p>{{ post.body|truncatewords:30 }}</p>
{% empty %}
<p>No posts.</p>
{% endfor %}
개발 서버
python manage.py runserver # localhost:8000
python manage.py runserver 8080
python manage.py runserver 0.0.0.0:8000 # 외부 접속
프로덕션엔 절대 사용 X. Gunicorn/Uvicorn + nginx.
settings.py 핵심
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"blog", # 우리 앱
]
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": "mydb",
"USER": "myuser",
"PASSWORD": "...",
"HOST": "localhost",
"PORT": "5432",
}
}
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
DEBUG = True # 프로덕션에선 반드시 False
SECRET_KEY = "..." # 절대 커밋 X
ALLOWED_HOSTS = ["example.com"]
manage.py 자주 쓰는 명령
python manage.py startapp blog # 앱 생성
python manage.py makemigrations # 마이그레이션 파일 생성
python manage.py migrate # DB에 적용
python manage.py createsuperuser # 관리자 계정
python manage.py shell # IPython/REPL
python manage.py dbshell # DB CLI
python manage.py collectstatic # 정적 파일 수집
python manage.py test # 테스트
python manage.py runserver
Django vs Flask vs FastAPI
| Django | Flask | FastAPI | |
|---|---|---|---|
| 스타일 | 배터리 포함 | 마이크로 | API 우선 |
| ORM | 내장 | SQLAlchemy 등 | 외부 |
| 관리자 | 내장 | X | X |
| 비동기 | 부분 (3.1+) | 부분 | 네이티브 |
| 학습 곡선 | 중 | 낮 | 중 |
| 적합 | 일반 웹앱, CMS | 작은 API/앱 | API, 마이크로서비스 |
버전과 LTS
| 버전 | 출시 | 지원 종료 | 비고 |
|---|---|---|---|
| 4.2 LTS | 2023-04 | 2026-04 | 이전 LTS |
| 5.0 | 2023-12 | 2025-04 | |
| 5.1 | 2024-08 | 2025-12 | |
| 5.2 LTS | 2025-04 | 2028-04 | 현재 LTS |
LTS는 3년 지원. 프로덕션은 LTS 권장.
함정
1. DEBUG = True 를 프로덕션에 두면 안 된다
에러 발생 시 스택 트레이스, 로컬 변수, settings 값까지 브라우저에 노출된다. SECRET_KEY 도 유출 위험이 있다. 프로덕션에서는 반드시 DEBUG = False 와 ALLOWED_HOSTS 설정.
2. N+1 쿼리
# ✗ 루프마다 쿼리 발생 (FK 마다 SELECT)
for post in Post.objects.all():
print(post.author.name)
# ✓ select_related 로 JOIN 한 번에
for post in Post.objects.select_related("author"):
print(post.author.name)
ORM 이 편리하지만 쿼리 수를 놓치기 쉽다. django-debug-toolbar 나 ORM 고급 를 통해 쿼리 수를 확인해야 한다.
3. 마이그레이션 충돌
팀 개발 시 두 브랜치가 동시에 makemigrations 를 실행하면 번호가 충돌한다. squashmigrations 또는 충돌 파일 수동 정리로 해소. 자세히는 Django Migrations 참조.
4. SECRET_KEY 노출
.env 또는 환경 변수로 관리해야 한다. 실수로 git commit 에 포함되면 레포가 public 이 되는 순간 키 탈취 가능. django-environ / python-decouple 로 환경 변수 분리를 권장.
5. ALLOWED_HOSTS 미설정
DEBUG = False 일 때 ALLOWED_HOSTS = [] 면 모든 요청이 400 응답. 도메인/IP 를 정확히 나열해야 한다.
관련 위키
이 글의 용어 (12개)
- [Django] 마이그레이션: makemigrations, migrate, 데이터 마이그레이션django
- 정의 Django 마이그레이션은 모델 변경을 DB 스키마 변경으로 변환·기록하는 시스템. 는 모델과 현재 마이그레이션 상태를 비교해 새 마이그레이션 파일 생성. 는 DB에 적용.…
- [Django] 배포: Gunicorn, Uvicorn, whitenoise, Dockerdjango
- 정의 Django 프로덕션 배포는 WSGI/ASGI 서버 + 리버스 프록시 + 정적 파일 + DB + 캐시 + 큐 조합. runserver는 개발 전용. nginx + gunic…
- [Django] 인증: User, login, permissionsdjango
- 정의 Django는 User 모델, 인증·세션, 권한·그룹을 기본 제공한다. 앱이 핵심. 비밀번호 해싱(PBKDF2, scrypt, Argon2), 세션, 권한, 그룹, 비밀번호…
- [Django] 테스트: TestCase, Client, factory_boydjango
- 정의 Django는 표준 라이브러리 기반 TestCase를 제공한다. 트랜잭션 격리, fixtures, test client, DB 셋업 자동화. 실무는 + 가 사실상 표준. 기…
- [Django] Admin: 자동 생성 관리자 페이지django
- 정의 Django Admin은 모델 등록만으로 CRUD UI 자동 생성하는 내장 백오피스. 내부 운영 도구, 콘텐츠 관리(CMS) 등에 강력. 권한 시스템 통합. Rails에는 …
- [Django] DRF 개요: Serializer, ViewSet, Routerdjango
- 학습 로드맵 이 페이지는 개요. 처음 접하는 사람은 아래 순서로 읽으면 자연스럽다: DRF 는 파이프라인이 핵심. 한번 그림으로 보면 이해가 쉽다: 정의 Django REST F…
- [Django] Model과 Field 타입django
- 정의 Django 모델은 DB 테이블의 Python 표현이다. 상속, 클래스 속성 = 컬럼, 메타 클래스 = 테이블 설정. 모델 정의 후 + 로 DB 스키마 자동 생성. 기본 정…
- [Django] ORM 심화: N+1, prefetch, Subquery, Windowdjango
- 정의 Django ORM은 SQL을 잘 모르는 개발자에게도 안전하지만 비효율을 숨기기 쉽다. N+1, 비효율 JOIN, 큰 결과셋 메모리 폭발이 흔한 함정. selectrelat…
- [Django] settings 관리: 환경 분리, secrets, 12-factordjango
- 정의 Django settings는 단일 Python 파일에 모든 설정을 두는 게 기본이지만, 환경별 분리·비밀 정보 분리·12-factor 원칙 적용이 실무 표준. 개발/스테이…
- [Django] Template 언어: 태그, 필터, 상속django
- 정의 Django Template Language (DTL)는 HTML과 Python 사이의 안전한 표현 언어. 임의 Python 실행 차단(보안), 로 변수, 로 태그, 로 필…
- [Django] URL 디스패치: path, re_path, includedjango
- 정의 Django는 URL 패턴 리스트로 요청을 view에 라우팅한다. 1.01.x는 (regex만), 2.0+ (간결한 converter 문법)와 (regex) 두 방식. 기본…
- [Django] View: 함수 기반 vs 클래스 기반django
- 정의 Django View는 HTTP 요청을 받아 응답을 반환하는 callable. 두 스타일이 공존. - FBV (Function-Based View): 일반 함수. 간단하고 …
💬 댓글