[Django] 첫 프로젝트 튜토리얼: 순차 학습
정의
Django 를 처음 접하는 사람 을 위한 순차 학습 페이지. 투표 앱 (polls) 을 만들며 Django 의 핵심 개념을 익힌다.
먼저 django-overview 로 MTV 패턴과 프로젝트 구조를 파악한 후 이 페이지로.
학습 순서 (전체 지도)
flowchart TB
S["1. 설치 + startproject"] --> T["2. runserver 확인"]
T --> A["3. app 생성 (startapp)"]
A --> M["4. 모델 (Model)"]
M --> Adm["5. Admin 사이트"]
Adm --> V["6. View + URL"]
V --> Tpl["7. Template"]
Tpl --> F["8. Form"]
F --> Test["9. Test"]
Test --> D["10. Deploy"]
이 순서로 페이지를 따라가면 Django 의 90% 를 이해.
사전 준비
# Python 3.12+ 권장 (Django 6.0 최소 3.12)
python --version
# 가상환경
python -m venv .venv
source .venv/bin/activate # macOS/Linux
# .venv\Scripts\activate # Windows
# Django 6.0 설치
pip install django
python -m django --version
Step 1. 프로젝트 시작
django-admin startproject mysite
cd mysite
mysite/
├── manage.py # CLI 진입점
└── mysite/
├── __init__.py
├── settings.py # 설정 파일
├── urls.py # 루트 URL 설정
├── asgi.py # ASGI 서버
└── wsgi.py # WSGI 서버
python manage.py runserver
# → http://127.0.0.1:8000/ 접속
TIP
manage.py 는 프로젝트 마다 하나. django-admin 은 전역 명령. 실제로 프로젝트 안에서는 manage.py 를 쓴다.
Step 2. App 생성
Django 의 app = 재사용 가능한 모듈. 프로젝트는 여러 app 의 조립.
python manage.py startapp polls
polls/
├── __init__.py
├── admin.py # Admin 등록
├── apps.py # App 설정
├── models.py # 모델
├── views.py # 뷰
├── tests.py # 테스트
└── migrations/ # 마이그레이션 파일
mysite/settings.py 에 app 등록:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'polls.apps.PollsConfig', # ← 추가
]
Step 3. 모델 정의
polls/models.py:
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, related_name='choices')
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
def __str__(self):
return self.choice_text
Migration 생성 + DB 반영:
python manage.py makemigrations polls
python manage.py migrate
자세한 필드 종류는 django-models-fields, migrations 는 django-migrations.
Step 4. Admin 사이트
python manage.py createsuperuser
# 이름, 이메일, 비밀번호 입력
polls/admin.py:
from django.contrib import admin
from .models import Question, Choice
@admin.register(Question)
class QuestionAdmin(admin.ModelAdmin):
list_display = ('question_text', 'pub_date')
list_filter = ('pub_date',)
search_fields = ('question_text',)
@admin.register(Choice)
class ChoiceAdmin(admin.ModelAdmin):
list_display = ('choice_text', 'question', 'votes')
python manage.py runserver
# http://127.0.0.1:8000/admin/ 접속 → 위 계정으로 로그인
자세한 건 django-admin.
Step 5. View + URL
polls/views.py:
from django.http import HttpResponse
from django.shortcuts import render, get_object_or_404
from .models import Question
def index(request):
latest_questions = Question.objects.order_by('-pub_date')[:5]
return render(request, 'polls/index.html', {
'latest_questions': latest_questions,
})
def detail(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/detail.html', {'question': question})
polls/urls.py:
from django.urls import path
from . import views
app_name = 'polls'
urlpatterns = [
path('', views.index, name='index'),
path('<int:question_id>/', views.detail, name='detail'),
]
mysite/urls.py:
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('polls/', include('polls.urls')),
]
자세한 건 django-urls, django-views, django-shortcuts-decorators.
Step 6. Template
polls/templates/polls/index.html:
{% extends "base.html" %}
{% block content %}
<h1>최근 질문</h1>
{% if latest_questions %}
<ul>
{% for q in latest_questions %}
<li>
<a href="{% url 'polls:detail' q.id %}">{{ q.question_text }}</a>
</li>
{% endfor %}
</ul>
{% else %}
<p>질문이 없습니다.</p>
{% endif %}
{% endblock %}
자세한 건 django-templates.
Step 7. Form
polls/forms.py:
from django import forms
from .models import Question
class QuestionForm(forms.ModelForm):
class Meta:
model = Question
fields = ['question_text', 'pub_date']
widgets = {
'pub_date': forms.DateTimeInput(attrs={'type': 'datetime-local'}),
}
자세한 건 django-forms, django-modelforms, django-formsets.
Step 8. Test
# polls/tests.py
from django.test import TestCase
from django.utils import timezone
from .models import Question
class QuestionModelTests(TestCase):
def test_str(self):
q = Question.objects.create(question_text='Test?', pub_date=timezone.now())
self.assertEqual(str(q), 'Test?')
def test_recent_questions(self):
Question.objects.create(question_text='Old', pub_date=timezone.now() - timezone.timedelta(days=10))
Question.objects.create(question_text='New', pub_date=timezone.now())
recent = Question.objects.order_by('-pub_date').first()
self.assertEqual(recent.question_text, 'New')
python manage.py test polls
자세한 건 django-testing.
Step 9. Deploy
# 1. 정적 파일 collect
python manage.py collectstatic
# 2. WSGI 서버 (gunicorn)
pip install gunicorn
gunicorn mysite.wsgi:application
# 3. 환경변수
export DJANGO_SETTINGS_MODULE=mysite.settings.production
export DATABASE_URL=postgres://...
# 4. 필수 체크
python manage.py check --deploy
자세한 건 django-deployment, django-settings.
Django vs 다른 프레임워크
| Feature | Django | Rails | Spring Boot | FastAPI | Express |
|---|---|---|---|---|---|
| 언어 | Python | Ruby | Java | Python | Node.js |
| Batteries | 포함 | 포함 | starter | 최소 | 최소 |
| ORM | ORM 내장 | ActiveRecord | JPA/Hibernate | SQLAlchemy | 없음 (선택) |
| Admin UI | 내장 | 없음 (gem) | 없음 | 없음 | 없음 |
| Migrations | 내장 | Active Record | Flyway | Alembic | 별도 |
| Template | DTL | ERB | Thymeleaf | Jinja2 | EJS/Pug |
| Forms | 내장 | Form helpers | Spring MVC | Pydantic | 없음 |
| 학습 곡선 | 완만 | 완만 | 가파름 | 매우 완만 | 매우 완만 |
| 규모 | 대형 | 대형 | 대형 | 소-중 | 자유 |
Django 는 “완벽주의자를 위한 프레임워크” - 컨벤션이 많아 처음에는 답답할 수 있지만 대규모 프로젝트에서는 일관성 + 안전 이 큰 장점.
다음 단계
이 튜토리얼 후 학습 순서 권장:
- django-models-fields - 필드 종류
- django-queryset - ORM 쿼리
- django-urls - URL routing
- django-views - View 상세
- django-templates - 템플릿 문법
- django-forms - 폼 처리
- django-admin - 관리자 커스터마이즈
- django-auth - 인증
- django-cache - 캐싱
- django-testing - 테스트
관련 위키
- django-overview (전체 개요)
- django-settings (설정 관리)
- django-management-commands (manage.py)
- python-asyncio (async views 이해)
이 글의 용어 (19개)
- [Django] 개요와 프로젝트 구조django
- 정의 Django는 2003년 시작된 Python 풀스택 웹 프레임워크. "Web framework for perfectionists with deadlines"라는 모토대로 b…
- [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] Caching: per-site, per-view, low-leveldjango
- 정의 Django 캐싱은 데이터/페이지 재생성 비용 회피의 핵심. 4단계 그래뉴얼리티 제공: site-wide → per-view → template fragment → low-…
- [Django] Form과 ModelFormdjango
- 정의 Django Form은 사용자 입력 정의·검증·렌더링·바인딩을 통합. 일반 은 임의 필드, 은 모델 자동 매핑. 검증과 보안(CSRF, SQL 인젝션 방지) 내장. Form…
- [Django] Formsets: 여러 폼 동시 처리django
- 정의 Formset = 여러 폼을 한 페이지에서 동시 처리. "상품 3개 한 번에 등록", "주문 상세 여러 줄 편집" 같은 시나리오. 3가지 종류 1. 기본 FormSet Te…
- [Django] Management Commandsdjango
- 정의 Django 커스텀 명령은 형태로 실행되는 CLI 도구. 정기 작업(cron + management command), 데이터 마이그레이션, import/export, 디버깅…
- [Django] Model과 Field 타입django
- 정의 Django 모델은 DB 테이블의 Python 표현이다. 상속, 클래스 속성 = 컬럼, 메타 클래스 = 테이블 설정. 모델 정의 후 + 로 DB 스키마 자동 생성. 기본 정…
- [Django] ModelForm: 모델 기반 폼 자동 생성django
- 정의 ModelForm = Model 로부터 Form 자동 생성. 필드 반복 정의 없이 CRUD 폼 완성. 일반 Form 은 참고. 왜 ModelForm? 기본 사용 vs [!W…
- [Django] QuerySet과 Managerdjango
- 정의 QuerySet은 DB 쿼리를 lazy하게 빌드하는 객체. , 같은 메서드를 체이닝해도 실제 SQL 실행은 평가 시점( , , , slice 등)에 한 번 발생. Manag…
- [Django] settings 관리: 환경 분리, secrets, 12-factordjango
- 정의 Django settings는 단일 Python 파일에 모든 설정을 두는 게 기본이지만, 환경별 분리·비밀 정보 분리·12-factor 원칙 적용이 실무 표준. 개발/스테이…
- [Django] Shortcuts + Decorators: render, redirect, get_object_or_404django
- 정의 Django 의 View 작성을 간결하게 하는 shortcut 함수들 + view 에 공통 기능을 붙이는 decorator 들. Shortcuts (django.shortc…
- [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): 일반 함수. 간단하고 …
- [Python] asyncio: 비동기 프로그래밍python
- 정의 asyncio 는 Python 의 표준 비동기 I/O 라이브러리 (3.4+). event loop 위에서 coroutine 을 스케줄링. 기본 병렬 실행 gather 세 요…
💬 댓글