본문으로 건너뛰기
Previous
Next
Django 기초 | Python 풀스택 웹 프레임워크 시작하기

Django 기초 | Python 풀스택 웹 프레임워크 시작하기

Django 기초 | Python 풀스택 웹 프레임워크 시작하기

이 글의 핵심

Django 기초: Python 풀스택 웹 프레임워크 시작하기. Django 시작하기·모델 (Model).

들어가며

Django는 “배터리 포함(Batteries Included)” 철학의 Python 웹 프레임워크입니다. 인증, ORM, Admin, 폼 검증, 보안(CSRF, XSS, SQL Injection 방어) 등 웹 애플리케이션에 필요한 거의 모든 기능이 기본 제공됩니다.

이 글에서 다루는 내용

  • Django의 역사와 설계 철학: 왜 “신문사를 위한 프레임워크”인가?
  • MVT 아키텍처: Model-View-Template 패턴의 동작 원리
  • ORM의 내부 구조: 쿼리셋의 지연 평가와 N+1 문제
  • 마이그레이션 시스템: 데이터베이스 스키마 변경의 자동화
  • Admin 사이트: 왜 Django Admin은 특별한가?
  • 실무 패턴: 쿼리 최적화, 캐싱, 보안, 배포

0. Django의 역사와 설계 철학

신문사에서 탄생한 프레임워크

Django는 2003년 미국 캔자스주 로렌스의 Lawrence Journal-World 신문사에서 탄생했습니다. 웹 개발자 Adrian HolovatySimon Willison이 신문 기사, 사진, 비디오를 빠르게 웹에 게시하는 시스템을 만들다가 공통 패턴을 프레임워크로 분리한 것이 Django의 시작입니다.

2005년 오픈소스로 공개된 Django는 다음 철학을 표방했습니다:

  1. Don’t Repeat Yourself (DRY): 중복을 제거하고 재사용 가능하게
  2. Loose coupling, tight cohesion: 각 컴포넌트는 독립적이되, 함께 잘 동작
  3. Explicit is better than implicit: 마법 같은 동작보다 명시적 선언
  4. Batteries included: 인증, Admin, ORM 등 풀스택 기능 제공

왜 “신문사” 배경이 중요할까? 신문사는 빠른 마감, 대량의 콘텐츠, 복잡한 워크플로를 다루는 곳입니다. Django는 처음부터 “빠르게 기능을 만들고, 안전하게 운영하고, 쉽게 확장할 수 있어야 한다”는 현실적 요구에 최적화되었습니다.

MTV vs MVC: Django만의 용어

웹 프레임워크는 보통 MVC(Model-View-Controller) 패턴을 따릅니다. Django도 유사하지만, 용어가 다릅니다:

전통적 MVCDjango MVT역할
ModelModel데이터베이스 스키마, 비즈니스 로직
ViewTemplate사용자에게 보여지는 HTML
ControllerViewHTTP 요청을 처리하는 함수/클래스

왜 헷갈리게 만들었을까? Django 개발자들은 “Controller”라는 용어가 프레임워크 내부(URL 라우팅)에 더 가깝고, View는 “사용자가 보는 것”이 아니라 “로직”이라고 생각했습니다. Template이 진짜 “사용자가 보는 View”에 가깝다는 주장입니다.

ORM의 철학: “SQL을 숨기되, 우회로는 열어두기”

Django ORM은 데이터베이스 독립성을 제공합니다. PostgreSQL, MySQL, SQLite, Oracle 등을 같은 Python 코드로 다룰 수 있습니다:

# Python ORM 코드
Post.objects.filter(published=True).order_by('-created_at')[:10]

# PostgreSQL SQL
SELECT * FROM blog_post WHERE published = TRUE ORDER BY created_at DESC LIMIT 10;

# MySQL SQL (동일)
SELECT * FROM blog_post WHERE published = 1 ORDER BY created_at DESC LIMIT 10;

하지만 성능이 중요한 경우, raw SQL을 직접 쓸 수 있는 “탈출구”도 제공합니다:

Post.objects.raw('SELECT * FROM blog_post WHERE ...')

이는 “추상화는 좋지만, 현실에서는 최적화가 필요할 때가 있다”는 실용주의를 반영합니다.

”Admin은 사이트 관리자용, 사용자용 UI가 아니다”

Django Admin은 내부 관리자를 위한 CRUD 인터페이스입니다. 많은 초보자가 “Admin을 커스터마이징해서 일반 사용자에게 제공”하려 하지만, Django 공식 문서는 이를 권장하지 않습니다:

Admin은 사이트 관리자가 데이터를 빠르게 수정하기 위한 도구입니다. 일반 사용자용 UI는 별도로 만들어야 합니다.

왜? Admin은 권한 체크가 느슨하고, 모든 모델을 노출하며, 성능 최적화가 안 되어 있습니다. “신문사 편집자가 급하게 기사를 수정하는” 용도로는 완벽하지만, 일반 사용자용으로는 부적합합니다.

마이그레이션의 역사: South → Django 1.7

초기 Django(~1.6)에는 마이그레이션 시스템이 없었습니다. 모델을 변경하면 직접 SQL을 작성해서 ALTER TABLE을 실행해야 했습니다. 이를 해결하기 위해 South라는 서드파티 라이브러리가 등장했습니다(2008).

Django 1.7(2014)에서 South의 핵심 개발자가 Django 코어 팀에 합류하며 공식 마이그레이션 시스템이 내장되었습니다. 이제 makemigrationsmigrate 명령으로 스키마 변경을 자동화할 수 있습니다.


1. Django 시작하기

설치 및 프로젝트 생성

startproject웹 사이트 전체를 감쌀 큰 상자를 만들고, startapp은 그 안에 기능 단위(예: 블로그, 결제) 모듈을 하나씩 추가하는 과정입니다. 이후 models.py는 DB 테이블 모양을, views.py는 요청 처리 순서를, templates는 화면 HTML을 담당합니다.

# Django 설치
pip install django
# 프로젝트 생성
django-admin startproject myproject
cd myproject
# 앱 생성
python manage.py startapp blog
# 개발 서버 실행
python manage.py runserver

프로젝트 구조

myproject/
├── myproject/
│   ├── __init__.py
│   ├── settings.py  # 설정
│   ├── urls.py      # URL 라우팅
│   └── wsgi.py
├── blog/
│   ├── models.py    # 모델 (데이터)
│   ├── views.py     # 뷰 (로직)
│   ├── urls.py
│   └── templates/   # 템플릿 (화면)
└── manage.py

2. 모델 (Model)

모델 정의

# blog/models.py
from django.db import models
class Post(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    author = models.CharField(max_length=100)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    def __str__(self):
        return self.title
    
    class Meta:
        ordering = ['-created_at']

마이그레이션

# 마이그레이션 파일 생성
python manage.py makemigrations
# 데이터베이스에 적용
python manage.py migrate

3. 뷰 (View)

함수 기반 뷰

# blog/views.py
from django.shortcuts import render, get_object_or_404
from .models import Post
def post_list(request):
    posts = Post.objects.all()
    return render(request, 'blog/post_list.html', {'posts': posts})
def post_detail(request, pk):
    post = get_object_or_404(Post, pk=pk)
    return render(request, 'blog/post_detail.html', {'post': post})

클래스 기반 뷰

from django.views.generic import ListView, DetailView
from .models import Post
class PostListView(ListView):
    model = Post
    template_name = 'blog/post_list.html'
    context_object_name = 'posts'
    paginate_by = 10
class PostDetailView(DetailView):
    model = Post
    template_name = 'blog/post_detail.html'

4. URL 라우팅

URL 패턴

# blog/urls.py
from django.urls import path
from . import views
app_name = 'blog'
urlpatterns = [
    path(', views.post_list, name='post_list'),
    path('post/<int:pk>/', views.post_detail, name='post_detail'),
]
# myproject/urls.py
# 필요한 모듈 import
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
    path('admin/', admin.site.urls),
    path('blog/', include('blog.urls')),
]

5. 템플릿

템플릿 작성

<!-- templates/blog/post_list.html -->
<!DOCTYPE html>
<html>
<head>
    <title>블로그</title>
</head>
<body>
    <h1>블로그 포스트</h1>
    
    {% for post in posts %}
        <article>
            <h2>
                <a href="{% url 'blog:post_detail' post.pk %}">
                    {{ post.title }}
                </a>
            </h2>
            <p>{{ post.content|truncatewords:30 }}</p>
            <small>{{ post.created_at|date:"Y-m-d H:i" }}</small>
        </article>
    {% empty %}
        <p>포스트가 없습니다.</p>
    {% endfor %}
</body>
</html>

6. Admin 사이트

Admin 등록

# blog/admin.py
from django.contrib import admin
from .models import Post
@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    list_display = ['title', 'author', 'created_at']
    list_filter = ['created_at', 'author']
    search_fields = ['title', 'content']
    date_hierarchy = 'created_at'

슈퍼유저 생성

python manage.py createsuperuser
# Username: admin
# Email: [email protected]
# Password: ****
# http://localhost:8000/admin/ 접속

7. 실전 예제

간단한 블로그

# blog/views.py
from django.shortcuts import render, redirect
from django.contrib import messages
from .models import Post
def create_post(request):
    if request.method == 'POST':
        title = request.POST.get('title')
        content = request.POST.get('content')
        author = request.POST.get('author')
        
        Post.objects.create(
            title=title,
            content=content,
            author=author
        )
        
        messages.success(request, '포스트가 생성되었습니다!')
        return redirect('blog:post_list')
    
    return render(request, 'blog/create_post.html')

내부 동작과 핵심 메커니즘

이 글의 주제는 「Django 기초 | Python 풀스택 웹 프레임워크 시작하기」입니다. 여기서는 앞선 설명을 구현·런타임 관점에서 한 번 더 압축합니다. 데이터 흐름과 실패 모드를 기준으로 생각하면, “입력이 어디서 검증되고, 핵심 연산이 어디서 일어나며, 부작용(I/O·네트워크·디스크)이 어디서 터지는가”가 한눈에 드러납니다.

처리 파이프라인(개념도)

flowchart TD
  A[입력·요청·이벤트] --> B[파싱·검증·디코딩]
  B --> C[핵심 연산·상태 전이]
  C --> D[부작용: I/O·네트워크·동시성]
  D --> E[결과·관측·저장]

알고리즘·프로토콜 관점에서의 체크포인트

  • 불변 조건(Invariant): 각 단계가 만족해야 하는 조건(예: 버퍼 경계, 프로토콜 상태, 트랜잭션 격리)을 문장으로 적어 두면 디버깅 비용이 줄어듭니다.
  • 결정성: 동일 입력에 동일 출력이 보장되는 순수한 층과, 시간·네트워크에 의해 달라질 수 있는 층을 분리해야 테스트와 장애 분석이 쉬워집니다.
  • 경계 비용: 직렬화/역직렬화, 문자 인코딩, syscall 횟수, 락 경합처럼 “한 번의 호출이 아니라 누적되는 비용”을 의심 목록에 넣습니다.

프로덕션 운영 패턴

실서비스에서는 기능 구현과 함께 관측·배포·보안·비용이 동시에 요구됩니다. 아래는 팀에서 자주 쓰는 최소 체크리스트입니다.

영역운영 관점에서의 질문
관측성요청 단위 상관 ID, 에러율/지연 분위수, 주요 의존성 타임아웃이 보이는가
안전성입력 검증·권한·비밀 관리가 코드 경로마다 일관적인가
신뢰성재시도는 멱등한 연산에만 적용되는가, 서킷 브레이커·백오프가 있는가
성능캐시 계층·배치 크기·풀링·백프레셔가 데이터 규모에 맞는가
배포롤백 룬북, 카나리, 마이그레이션 호환성이 문서화되어 있는가

운영 환경에서는 “개발자 PC에서는 재현되지 않던 문제”가 시간·부하·데이터 크기 때문에 드러납니다. 따라서 스테이징의 데이터 양·네트워크 지연을 가능한 한 현실에 가깝게 맞추는 것이 중요합니다.


문제 해결(Troubleshooting)

증상가능 원인조치
간헐적 실패레이스 컨디션, 타임아웃, 외부 의존성 불안정최소 재현 스크립트 작성, 분산 트레이스·로그 상관관계 확인
성능 저하N+1 쿼리, 동기 I/O, 잠금 경합, 과도한 직렬화프로파일러·APM으로 핫스팟 확인 후 한 가지씩 제거
메모리 증가캐시 무제한, 클로저/이벤트 구독 누수, 대용량 객체의 불필요한 복사상한·TTL·스냅샷 비교(힙 덤프/트레이스)
빌드·배포만 실패환경 변수·권한·플랫폼 차이CI 로그와 로컬 diff, 컨테이너/런타임 버전 핀(pin)

권장 디버깅 순서: (1) 최소 재현 만들기 (2) 최근 변경 범위 좁히기 (3) 의존성·환경 변수 차이 확인 (4) 관측 데이터로 가설 검증 (5) 수정 후 회귀·부하 테스트.

정리

핵심 요약

  1. Django: 풀스택 웹 프레임워크
  2. MVT: Model, View, Template
  3. ORM: Python 코드로 DB 조작
  4. Admin: 자동 관리자 페이지
  5. 마이그레이션: 데이터베이스 스키마 관리

다음 단계


관련 글


자주 묻는 질문 (FAQ)

Q. 이 내용을 실무에서 언제 쓰나요?

A. Django 기초: Python 풀스택 웹 프레임워크 시작하기. Django 시작하기·모델 (Model)로 흐름을 잡고 원리·코드·실무 적용을 한글로 정리합니다. Python·Django·웹개발 중심으로 설명합니다.… 실무에서는 위 본문의 예제와 선택 가이드를 참고해 적용하면 됩니다.

Q. 선행으로 읽으면 좋은 글은?

A. 각 글 하단의 이전 글 또는 관련 글 링크를 따라가면 순서대로 배울 수 있습니다. Python 시리즈 목차에서 전체 흐름을 확인할 수 있습니다.

Q. 더 깊이 공부하려면?

A. cppreference와 해당 라이브러리 공식 문서를 참고하세요. 글 말미의 참고 자료 링크도 활용하면 좋습니다.


같이 보면 좋은 글 (내부 링크)

이 주제와 연결되는 다른 글입니다.


이 글에서 다루는 키워드 (관련 검색어)

Python, Django, 웹개발, 백엔드, ORM, MVT, 프레임워크 등으로 검색하시면 이 글이 도움이 됩니다.