반응형

장고(Django)로 쉽고 빠르게 Todo 리스트 앱 만들기 🚀

장고 초보자라면 이 글 하나만으로 Todo 앱 구현의 모든 것을 마스터할 수 있어요.
같이 만들어볼까요?
반응형

 

안녕하세요, 여러분!

오늘도 함께 성장하는 블로그, First Step입니다. 이번 포스트에서는 Django로 직접 Todo 리스트 웹 애플리케이션을 만드는 과정을 차근차근 알아볼 거예요.

저도 처음 Django를 접했을 때, 모델을 만들고 데이터베이스에 저장하는 과정이 헷갈렸던 기억이 나네요.

여러분은 그런 고민 없이 바로 이해하고 따라 할 수 있도록 쉬운 설명과 실습을 준비했습니다.

함께 손을 움직이며 직접 경험해 보면 어느새 CRUD 기능이 익숙해질 거예요!

 

1. TodoItem 모델 생성과 마이그레이션 🔧

모든 웹 애플리케이션에서 가장 중요한 부분 중 하나는 바로 데이터를 어떻게 다루는지, 즉 데이터 모델을 설정하는 방법이에요. Django에서는 이 모델을 데이터베이스와 자동으로 연동시켜주는 아주 편리한 ORM(Object-Relational Mapping) 기능이 있어서 여러분이 데이터베이스를 잘 몰라도 쉽게 데이터를 관리할 수 있어요.

📌 TodoItem 모델 정의하기

먼저 프로젝트 폴더 내의 앱 폴더로 들어가서 models.py 파일을 열고 다음과 같이 모델을 정의해볼게요.

from django.db import models

class TodoItem(models.Model):
    title = models.CharField(max_length=200)  # Todo 항목 제목
    content = models.TextField()              # Todo 항목 내용
    created_at = models.DateTimeField(auto_now_add=True)  # 생성된 날짜 및 시간 자동 기록

    def __str__(self):
        return self.title
  • title: 할 일의 제목을 입력하는 필드로 최대 200자까지 입력 가능해요.
  • content: Todo에 대한 상세 내용을 입력할 수 있는 텍스트 필드에요.
  • created_at: Todo 항목이 언제 만들어졌는지 자동으로 날짜와 시간이 저장되는 필드에요.

📌 모델 마이그레이션 실행하기

이제 이 모델을 데이터베이스에 실제로 반영해 볼 거예요. Django는 간단한 명령어 몇 줄만으로 이 작업을 자동으로 해줘서 참 편리해요. 터미널을 열고 프로젝트 폴더 내에서 다음 명령어를 차례대로 입력해 보세요.

python manage.py makemigrations
python manage.py migrate

위의 명령어를 실행하면, makemigrations는 모델에서의 변경 사항을 감지하고, 이를 기록하는 파일을 생성해요. 이후 migrate 명령어는 이 기록을 실제 데이터베이스에 적용하는 과정이랍니다.

✔️ 마이그레이션 확인하기

마이그레이션이 정상적으로 완료되었는지 확인하려면, Django Admin 페이지에 접속하거나 Django 쉘을 사용해서 모델 객체를 만들어보는 방법이 있어요. Admin 페이지에 접속하는 방법은 다음 단계에서 더 자세히 알아볼게요!

 

여기까지 따라 하셨다면 축하드려요! 🎉 이제 실제 데이터를 다룰 수 있는 모델이 준비됐습니다. 다음 단계에서는 이 데이터를 화면에 어떻게 출력할 수 있는지 알아볼게요!

 

 

2. Todo 항목 목록 조회 📋

모델이 준비됐으니, 이제 실제로 데이터베이스에 저장된 Todo 항목들을 화면에 출력해 볼까요? 목록 조회는 데이터베이스에 저장된 데이터를 불러와서 웹 페이지에 표시하는 기본적이면서도 꼭 필요한 작업이에요. Django에서는 이 과정을 아주 깔끔하게 처리할 수 있어요. 제가 처음 Django를 접했을 때 데이터가 화면에 출력되는 걸 보고 신기했던 기억이 나네요.

📌 목록 뷰(List View) 함수 만들기

먼저 앱 폴더 안에 있는 views.py 파일을 열고 아래 코드를 입력해서 데이터베이스에서 Todo 항목들을 불러오는 함수를 작성해볼게요.

from django.shortcuts import render
from .models import TodoItem

def todo_list(request):
    todos = TodoItem.objects.all().order_by('-created_at')  # 생성일 기준 최신 순으로 정렬
    context = {
        'todos': todos
    }
    return render(request, 'todo/todo_list.html', context)
  • TodoItem.objects.all(): 데이터베이스에 저장된 모든 Todo 항목을 불러오는 Django ORM 메서드예요.
  • order_by('-created_at'): 가장 최근에 추가된 Todo 항목이 맨 위에 오도록 생성일을 기준으로 정렬해요.

📌 URL 설정하기

다음으로는 이 뷰 함수를 웹에서 접근할 수 있도록 URL을 설정할 차례예요. urls.py 파일을 앱 폴더에 만들어서 다음 코드를 작성해주세요.

from django.urls import path
from . import views

urlpatterns = [
    path('', views.todo_list, name='todo_list'),
]

📌 템플릿 파일 만들기(todo_list.html)

이제 실제 화면에 Todo 항목을 출력하는 템플릿을 만들 거예요. 프로젝트 폴더 내 템플릿 폴더(templates/todo/)를 만들고 todo_list.html 파일을 추가해 아래와 같이 작성해 볼게요.

<!-- todo_list.html -->
<h1>Todo 목록</h1>
<ul>
    {% for todo in todos %}
        <li>{{ todo.title }} - {{ todo.created_at }}</li>
    {% empty %}
        <li>할 일이 없어요!</li>
    {% endfor %}
</ul>

이렇게 준비가 끝나면 브라우저에서 Django 서버를 실행하고 웹 페이지를 접속해 보세요. 이제 실제로 데이터베이스에 저장된 Todo 항목들이 화면에 예쁘게 나타나는 것을 확인할 수 있을 거예요. 🎉

 

다음 단계에서는 각 Todo 항목의 상세 정보를 볼 수 있는 뷰를 만드는 방법을 알아볼게요. 기대해 주세요!

 

 

3. 개별 Todo 항목 상세 보기 🔍

목록을 통해 Todo 항목들이 잘 보이는 것까지 성공했어요! 하지만 실제 앱에서는 각각의 항목을 클릭하면 더 자세한 내용을 볼 수 있어야겠죠? 이번 단계에서는 개별 Todo 항목을 클릭했을 때, 제목과 내용을 상세하게 보여주는 상세 보기(Detail View)를 만들어볼 거예요.

📌 상세 뷰(Detail View) 함수 만들기

먼저 views.py 파일에 다음과 같이 상세 뷰 함수를 추가해볼게요.

from django.shortcuts import render, get_object_or_404
from .models import TodoItem

def todo_detail(request, pk):
    todo = get_object_or_404(TodoItem, pk=pk)
    context = {
        'todo': todo
    }
    return render(request, 'todo/todo_detail.html', context)
  • get_object_or_404: 요청한 항목이 없을 경우 자동으로 404 에러를 표시하는 아주 편리한 Django 내장 함수예요.

📌 상세보기 URL 설정하기

이제 방금 만든 상세보기 뷰를 연결해 주기 위해 앱의 urls.py 파일에 다음 코드를 추가해 주세요.

from django.urls import path
from . import views

urlpatterns = [
    path('', views.todo_list, name='todo_list'),
    path('todo/<int:pk>/', views.todo_detail, name='todo_detail'),
]
  • URL에서 <int:pk> 부분은 각 Todo 항목의 고유한 ID(primary key)를 전달받는 부분이에요.

📌 상세보기 템플릿 파일(todo_detail.html) 작성하기

마지막으로 템플릿 폴더 내에 todo_detail.html을 만들어 다음과 같이 작성해주세요.

<!-- todo_detail.html -->
<h1>{{ todo.title }}</h1>
<p>{{ todo.content }}</p>
<p>생성일: {{ todo.created_at }}</p>
<a href="{% url 'todo_list' %}">목록으로 돌아가기</a>

이제 목록 페이지에서 각 Todo 항목을 클릭하면, 해당 Todo의 상세 정보 페이지로 이동하는 기능이 잘 동작할 거예요! 🎯

 

다음 단계는 Todo를 생성하는 방법을 알아보는 단계예요. 계속해서 함께 달려볼까요? 🏃‍♂️💨

 

 

4. ModelForm으로 새로운 Todo 추가하기 📝

지금까지 Todo 목록을 조회하고 개별 항목의 상세 정보까지 확인했어요. 이제는 웹 페이지에서 직접 새로운 Todo 항목을 추가하는 기능을 만들어볼 거예요. 이때 Django의 ModelForm을 사용하면 정말 쉽게 입력 폼을 만들 수 있답니다.

📌 ModelForm 정의하기

앱 디렉토리 안에 forms.py 파일을 만들고 아래처럼 작성해볼게요.

from django import forms
from .models import TodoItem

class TodoForm(forms.ModelForm):
    class Meta:
        model = TodoItem
        fields = ['title', 'content']
  • fields: 폼에서 입력 받을 필드를 지정해요. 여기서는 제목과 내용만 입력받아요.

📌 생성(Create) 뷰 만들기

이제 실제 폼을 보여주고 입력값을 처리할 뷰를 만들어볼까요? views.py에 추가합니다.

from django.shortcuts import render, redirect
from .forms import TodoForm

def todo_create(request):
    if request.method == 'POST':
        form = TodoForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('todo_list')
    else:
        form = TodoForm()
    return render(request, 'todo/todo_form.html', {'form': form})

📌 URL 설정하기

URL 패턴도 추가해줘야겠죠? 앱의 urls.py에 아래 코드를 추가해주세요.

path('todo/new/', views.todo_create, name='todo_create'),

📌 입력 폼 템플릿(todo_form.html) 작성하기

폼 화면을 구성하는 템플릿을 만들어 볼게요. 아래와 같이 templates/todo/todo_form.html을 작성하세요.

<!-- todo_form.html -->
<h1>새로운 Todo 추가하기</h1>

<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">추가하기</button>
</form>

<a href="{% url 'todo_list' %}">목록으로 돌아가기</a>

✔️ 폼 데이터 확인 및 테스트하기

이제 서버를 실행하고 브라우저에서 /todo/new/ 주소로 접속해보세요. 간단한 입력 폼이 잘 나오고, 내용을 입력한 후 추가 버튼을 클릭하면 Todo 항목이 성공적으로 추가되는 것을 볼 수 있어요. 🎉

 

다음 단계에서는 Todo 항목의 수정 및 삭제 기능을 함께 만들어 볼게요. 계속 함께 가요! 🚀

 

 

5. Todo 수정 및 삭제 기능 구현 ✏️🗑️

이제 Todo 앱에서 꼭 필요한 기능인 항목 수정과 삭제 기능을 구현할 차례입니다. 저는 처음 Django를 공부할 때, 이 기능들을 구현하고 나니 정말 뿌듯했던 기억이 있어요. 여러분도 이 단계만 따라 하면 손쉽게 구현할 수 있을 거예요!

📌 수정(Update) 기능 구현하기

views.py 파일에 다음과 같이 수정 뷰를 추가합니다.

from django.shortcuts import render, get_object_or_404, redirect
from .models import TodoItem
from .forms import TodoForm

def todo_update(request, pk):
    todo = get_object_or_404(TodoItem, pk=pk)
    if request.method == 'POST':
        form = TodoForm(request.POST, instance=todo)
        if form.is_valid():
            form.save()
            return redirect('todo_detail', pk=pk)
    else:
        form = TodoForm(instance=todo)
    return render(request, 'todo/todo_form.html', {'form': form})

📌 삭제(Delete) 기능 구현하기

이번에는 삭제 기능을 구현해 볼까요? 간단한 삭제 확인 화면을 추가해 사용자가 실수로 항목을 삭제하지 않도록 해줄게요.

def todo_delete(request, pk):
    todo = get_object_or_404(TodoItem, pk=pk)
    if request.method == 'POST':
        todo.delete()
        return redirect('todo_list')
    return render(request, 'todo/todo_confirm_delete.html', {'todo': todo})

📌 URL 추가하기

수정과 삭제를 위한 URL을 앱의 urls.py에 추가하세요.

path('todo/<int:pk>/edit/', views.todo_update, name='todo_update'),
path('todo/<int:pk>/delete/', views.todo_delete, name='todo_delete'),

📌 삭제 확인 템플릿 작성하기

삭제 확인을 위한 템플릿 todo_confirm_delete.html을 작성하세요.

<!-- todo_confirm_delete.html -->
<h1>정말 삭제할까요?</h1>
<p>삭제할 Todo: {{ todo.title }}</p>

<form method="post">
    {% csrf_token %}
    <button type="submit">네, 삭제할게요</button>
    <a href="{% url 'todo_detail' todo.pk %}">취소</a>
</form>

이제 Todo 항목 상세 페이지에서 수정 및 삭제 링크를 추가해 테스트해보세요. 모든 기능이 정상적으로 작동하면 드디어 기본적인 CRUD 기능이 완성된 거예요! 🎉

 

다음 마지막 단계에서는 개발한 전체 기능을 종합적으로 테스트하고 마무리할게요. 거의 다 왔습니다! 🥳

 

 

6. 개발한 Todo 앱의 CRUD 동작 테스트 ✅

자, 여러분! 우리가 지금까지 차근차근 만든 Todo 앱의 모든 CRUD(Create, Read, Update, Delete) 기능이 제대로 동작하는지 마지막 테스트를 해볼 시간이에요. 솔직히 제가 Django를 배우면서 이 순간이 가장 설렜던 것 같아요. 직접 만든 기능들이 제대로 동작하는 걸 볼 때의 성취감, 다들 느껴보셨죠? 😄

📌 1단계: Todo 추가 기능 테스트

  • 브라우저에서 /todo/new/ 주소에 접속해 새로운 Todo 항목을 추가해보세요.
  • 입력한 항목이 목록 페이지에서 정상적으로 표시되는지 확인해보세요.

📌 2단계: 목록 및 상세 조회 기능 테스트

  • 메인 페이지(/)에서 목록이 잘 나타나는지 확인하세요.
  • 목록에서 항목을 클릭해 상세보기 페이지가 잘 열리는지 확인해보세요.

📌 3단계: Todo 수정 기능 테스트

  • 상세보기 페이지에서 "수정하기" 버튼 또는 URL(/todo/{pk}/edit/)을 통해 Todo 항목을 수정해보세요.
  • 수정한 내용이 정확히 반영되었는지 확인하세요.

📌 4단계: Todo 삭제 기능 테스트

  • 상세보기 페이지에서 "삭제하기" 버튼 또는 URL(/todo/{pk}/delete/)로 항목 삭제를 시도하세요.
  • 삭제 후 메인 페이지에서 항목이 사라졌는지 확인하세요.

 

이 모든 기능이 잘 작동했다면 정말 훌륭합니다! 👏

여러분은 Django를 활용해 간단하면서도 강력한 CRUD 웹 애플리케이션을 성공적으로 완성했어요. 스스로를 칭찬해 주세요! 😄

 

 

마무리하며 🎯

지금까지 저와 함께 Django를 사용해서 Todo 리스트 애플리케이션의 모델 정의부터 CRUD 기능 구현까지 차근차근 살펴보았어요. 처음 Django를 접했을 때 복잡하고 어렵게 느껴졌던 부분들이, 이렇게 하나씩 실습하면서 익숙해지셨다면 정말 기쁠 것 같아요. 여러분이 이번 실습을 통해 배운 내용을 응용하면 더 다양한 웹 애플리케이션도 손쉽게 개발할 수 있을 거예요.

 

그럼 다음에도 더 유익하고 재미있는 내용으로 찾아올게요. 끝까지 함께 해주셔서 정말 감사합니다! 😍

📌 이번 실습을 통해 배운 것 요약

  • Django 모델 생성과 마이그레이션 방법
  • Django 뷰 함수 및 템플릿을 활용한 목록, 상세 조회 방법
  • ModelForm을 이용한 데이터 입력 및 유효성 검사 방법
  • Django ORM을 사용한 데이터 수정 및 삭제 기능 구현
반응형
반응형

CRUD 구현과 Todo 앱 개발

여러분, 나만의 Todo 앱, 어렵다고만 느껴졌나요?
오늘은 Django로 누구나 쉽게 만들 수 있도록 친절하게 알려드릴게요!
반응형

 

안녕하세요, 여러분! 😊

오늘은 웹 개발에서 가장 기본이면서도 실습으로 정말 많이 등장하는 CRUD 기능 구현과 Todo 앱 개발을 함께 진행해볼 거예요.

특히 Django 프레임워크를 활용해서 폼(Form) 처리부터 CRUD 사이클을 자연스럽게 익힐 수 있도록 구성했어요.

"Create-Read-Update-Delete"라는 말을 들어본 적은 있지만 실제로 프로젝트에 적용하는 과정이 막막했던 분들,

지금부터 하나씩 차근차근, 꼭 필요한 부분만 쏙쏙 집어서 설명드릴 테니 끝까지 따라와 주세요! 🙌

 

1. CRUD 개념 이해하기 ✨

여러분, CRUD라는 단어, 개발 입문하면서 한 번쯤은 들어보셨죠? 😊

하지만 정확히 어떤 의미인지 헷갈리는 분들도 많더라고요.

그래서 오늘은 아주 쉽게, 그리고 확실하게 정리해드릴게요!

CRUD란 무엇인가요?

  • Create (생성): 새로운 데이터를 만들어요.
  • Read (조회): 저장된 데이터를 읽어와요.
  • Update (수정): 기존 데이터를 수정해요.
  • Delete (삭제): 더 이상 필요 없는 데이터를 지워요.

이 네 가지 행동이 바로 CRUD예요.

거의 모든 웹 애플리케이션은 이 CRUD 사이클을 기반으로 동작한다고 해도 과언이 아니에요!

블로그 글 작성, 댓글 남기기, 쇼핑몰 상품 수정하기, 회원 탈퇴하기... 다 CRUD입니다.

CRUD를 자유자재로 다룰 수 있으면 웹 개발의 70%는 이미 마스터했다고 봐도 무방할 정도예요. 😎

CRUD 흐름, 어떻게 돌아가는 걸까?

  1. 사용자가 폼에 데이터를 입력하고 생성(Create) 요청을 보낸다.
  2. 서버가 데이터베이스에 데이터를 저장한다.
  3. 사용자가 목록을 보거나 검색해서 조회(Read)를 요청한다.
  4. 특정 항목을 수정하고 싶으면 수정(Update) 요청을 보낸다.
  5. 필요 없는 데이터는 삭제(Delete) 요청을 통해 삭제한다.

이렇게 보면 CRUD는 그냥 "데이터를 만들고, 읽고, 고치고, 없애는 것"이죠.

그리고 이 모든 과정을 Django에서는 아주 쉽게 처리할 수 있도록 도와줘요.

(진짜 너무 편해요, 감동할걸요? 😭)

 

즉, CRUD는 웹 서비스의 '심장'이라고 할 수 있습니다.

이 개념을 제대로 이해하고 구현할 수 있어야 제대로 된 웹 애플리케이션을 만들 수 있어요!

 

 

2. Django 폼(Form)과 ModelForm 활용법 📝

CRUD를 제대로 구현하려면 사용자로부터 데이터를 입력받을 수 있어야 해요.

그걸 담당하는 게 바로 폼(Form)입니다.

Django에서는 폼을 정말 쉽게 만들 수 있도록 Form 클래스와 ModelForm 클래스를 제공해줘요.

Form 클래스란?

Form 클래스는 말 그대로 입력 폼을 정의하는 클래스입니다.

입력받을 필드를 직접 하나하나 지정해줘야 해요.

from django import forms

class TodoForm(forms.Form):
    title = forms.CharField(max_length=100)
    content = forms.CharField(widget=forms.Textarea)

이렇게 하면 titlecontent를 입력할 수 있는 폼이 완성돼요!

폼 유효성 검증도 자동으로 해주기 때문에 "빈칸이면 오류" 같은 기본적인 체크도 따로 코딩할 필요가 없어요.

진짜 편하죠? 😆

ModelForm 클래스란?

ModelForm은 Form을 더 쉽게 만들기 위한 강력한 무기예요!

특정 모델(Model)과 연결해서 폼을 자동 생성해주는 클래스거든요.

from django import forms
from .models import Todo

class TodoModelForm(forms.ModelForm):
    class Meta:
        model = Todo
        fields = ['title', 'content']

ModelForm을 쓰면 모델에 정의된 필드 정보로 폼을 알아서 만들어줘요.

그리고 save() 메서드 하나만 호출하면 바로 데이터베이스에 저장까지 끝!

노가다 코딩은 이제 안녕입니다. 👋

Form vs ModelForm 요약

구분 Form ModelForm
특징 필드를 직접 지정 모델을 기반으로 자동 생성
작성 난이도 조금 번거로움 매우 간편
추천 상황 비표준 폼 필요시 모델 기반 CRUD 작업

Tip: CRUD 구현할 때는 대부분 ModelForm을 사용하는 게 훨씬 편하고 효율적입니다! 😎

 

 

3. GET과 POST 요청 흐름 파헤치기 🔄

Django로 폼을 만들었으면 이제 중요한 게 하나 남았어요.

바로 요청(Request) 처리 흐름입니다. 특히 GETPOST 요청을 제대로 이해해야 CRUD 기능을 완성할 수 있어요!

GET 요청: 페이지를 보여주는 요청

GET은 사용자가 페이지를 보러 올 때 보내는 요청이에요.

예를 들어, 글쓰기 폼을 보여줄 때 GET 요청을 사용합니다.

def todo_create(request):
    if request.method == 'GET':
        form = TodoModelForm()
        return render(request, 'todo_form.html', {'form': form})

위 코드를 보면 알겠지만, GET 요청이면 빈 폼을 만들어서 보여줘요.

"폼 열어줘!" 하는 느낌이라고 생각하면 쉽습니다. 😉

POST 요청: 데이터를 제출하는 요청

POST는 사용자가 폼에 입력한 데이터를 제출할 때 보내는 요청이에요.

예를 들어, 글쓰기 버튼을 눌렀을 때 POST 요청이 발생합니다.

def todo_create(request):
    if request.method == 'POST':
        form = TodoModelForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('todo_list')

POST 요청이면, 폼에 입력된 데이터를 form 객체에 담고, 검증(is_valid())한 뒤, 이상 없으면 save() 메서드로 저장해요!

그리고 저장이 완료되면 redirect()를 사용해 목록 페이지로 이동시켜줍니다.

요약: GET vs POST

요청 종류 역할
GET 폼을 보여준다 (읽기용)
POST 폼 데이터를 제출하고 처리한다 (쓰기용)

이 흐름을 확실히 이해하면, 폼 처리와 CRUD 기능 구현이 정말 쉬워져요!

"GET이면 보여주고, POST면 처리한다" 이 공식만 기억하세요! 😎

 

 

4. 기능별 URL 설계 방법 🛤️

이제 폼도 만들었고, 요청 흐름(GET/POST)도 알게 되었어요.

그럼 다음으로 중요한 건 바로 URL 패턴 설계입니다! 🚀

CRUD 각각의 기능에 맞게 알기 쉬운 URL을 짜야 해요.

사용자가 길을 잃지 않게 해주는 일종의 "표지판" 같은 거죠.

기능별 URL 기본 패턴 ✨

  • 목록 보기(Read) : /todos/
  • 상세 보기(Read) : /todos/<id>/
  • 새로 만들기(Create) : /todos/new/
  • 수정하기(Update) : /todos/<id>/edit/
  • 삭제하기(Delete) : /todos/<id>/delete/

기능별 URL을 이렇게 직관적으로 설계하면, 개발자도 헷갈리지 않고 사용자도 편리하게 이용할 수 있어요.

특히 id를 경로에 포함시키는 부분은 아주 중요합니다!

(어떤 Todo 항목을 수정하거나 삭제할지 구분해야 하니까요.)

Django URL 설정 예시 🛠️

from django.urls import path
from . import views

urlpatterns = [
    path('todos/', views.todo_list, name='todo_list'),
    path('todos/new/', views.todo_create, name='todo_create'),
    path('todos//', views.todo_detail, name='todo_detail'),
    path('todos//edit/', views.todo_update, name='todo_update'),
    path('todos//delete/', views.todo_delete, name='todo_delete'),
]

URL 패턴을 이렇게 깔끔하게 맞춰주면 뷰 함수도 훨씬 체계적으로 관리할 수 있어요.

게다가 name을 지정해주면 나중에 {% url 'todo_list' %} 이런 식으로 템플릿에서 바로 사용 가능!

진짜 효율적입니다. 😎

정리!

  • 기능별로 URL을 명확하게 구분하자.
  • id를 경로에 포함해서 특정 항목을 다루자.
  • name 속성으로 URL 이름을 정해서 템플릿에서도 활용하자.

 

 

5. 클래스 기반 뷰(Generic Views) 살펴보기 🏗️

자, 여기까지 온 여러분! CRUD를 함수 기반 뷰로 처리하는 법은 잘 이해하셨죠? 👏

그런데 Django는 여기서 더 친절하게도 클래스 기반 뷰(Class-Based Views, CBV)라는 걸 제공해요.

특히 Generic Views를 사용하면 CRUD 작업을 훨씬 더 빠르고 깔끔하게 만들 수 있답니다!

Generic Views란 무엇인가요?

Generic View는 Django가 CRUD 작업을 위해 미리 만들어놓은 뷰 클래스를 말해요.

우리는 상속만 받아서 살짝 설정만 해주면, 복잡한 코드를 직접 작성할 필요 없이 CRUD 기능을 자동으로 사용할 수 있어요.

진짜 개발자의 삶의 질이 달라집니다... ✨

대표적인 CRUD Generic View 종류

  • ListView - 객체 목록을 보여줄 때 사용
  • DetailView - 하나의 객체 상세 정보를 보여줄 때 사용
  • CreateView - 새로운 객체를 생성할 때 사용
  • UpdateView - 기존 객체를 수정할 때 사용
  • DeleteView - 객체를 삭제할 때 사용

Generic View 코드 예시 ✍️

from django.views.generic import ListView, CreateView
from .models import Todo

class TodoListView(ListView):
    model = Todo
    template_name = 'todo_list.html'

class TodoCreateView(CreateView):
    model = Todo
    fields = ['title', 'content']
    template_name = 'todo_form.html'
    success_url = '/todos/'

봐요, 진짜 깔끔하죠?

이런 식으로 기본적인 목록보기, 생성하기 기능이 몇 줄 코드만으로 뚝딱 완성됩니다!

정리!

  • 클래스 기반 뷰는 CRUD 작업을 빠르고 쉽게 만든다!
  • ListView, CreateView, UpdateView 등을 잘 활용해보자!

 

6. 미니 Todo 앱 만들기 🗒️

여러분, 드디어 실습 시간이에요! 🎉

지금까지 배운 걸 바탕으로 간단한 미니 Todo 앱을 만들어볼 거예요.

처음엔 복잡해 보여도 걱정 마세요. 하나하나 따라 하면 금방 멋진 결과물이 나옵니다!

1. 모델 생성하기

from django.db import models

class Todo(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title

제목(title), 내용(content), 생성일(created_at)을 갖는 아주 심플한 모델이에요.

makemigrationsmigrate 명령어로 데이터베이스 반영도 잊지 말기!

2. URL 설정하기

아까 배운 CRUD URL 패턴을 토대로 urls.py를 작성해요!

from django.urls import path
from .views import TodoListView, TodoCreateView, TodoDetailView, TodoUpdateView, TodoDeleteView

urlpatterns = [
    path('todos/', TodoListView.as_view(), name='todo_list'),
    path('todos/new/', TodoCreateView.as_view(), name='todo_create'),
    path('todos//', TodoDetailView.as_view(), name='todo_detail'),
    path('todos//edit/', TodoUpdateView.as_view(), name='todo_update'),
    path('todos//delete/', TodoDeleteView.as_view(), name='todo_delete'),
]

3. 뷰(Views) 작성하기

from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from .models import Todo
from django.urls import reverse_lazy

class TodoListView(ListView):
    model = Todo
    template_name = 'todo_list.html'

class TodoDetailView(DetailView):
    model = Todo
    template_name = 'todo_detail.html'

class TodoCreateView(CreateView):
    model = Todo
    fields = ['title', 'content']
    template_name = 'todo_form.html'
    success_url = reverse_lazy('todo_list')

class TodoUpdateView(UpdateView):
    model = Todo
    fields = ['title', 'content']
    template_name = 'todo_form.html'
    success_url = reverse_lazy('todo_list')

class TodoDeleteView(DeleteView):
    model = Todo
    template_name = 'todo_confirm_delete.html'
    success_url = reverse_lazy('todo_list')

4. 템플릿 만들기

각 페이지를 위한 HTML 파일을 작성해야겠죠?

  • todo_list.html (목록 페이지)
  • todo_form.html (작성 및 수정 폼)
  • todo_detail.html (상세보기)
  • todo_confirm_delete.html (삭제 확인)

템플릿은 Django 템플릿 언어(DTL)를 써서 {{ todo.title }} 같은 식으로 데이터를 출력할 수 있어요. 초반에는 간단하게, 차차 예쁘게 꾸며나가면 됩니다. ✨

정리!

  • 모델 → URL → 뷰 → 템플릿 순서대로 개발 진행
  • Generic View를 적극 활용하면 빠르게 개발 가능
  • 완성 후 서버를 돌려 테스트하기!

 

마무리 ✨

자, 여기까지 함께 따라오신 여러분 정말 고생 많으셨습니다! 👏

오늘은 CRUD 개념부터 시작해서 Django의 Form 처리, GET과 POST 요청 흐름, 기능별 URL 설계, 그리고 클래스 기반 뷰(Generic Views)까지 배운 다음, 직접 미니 Todo 앱을 만들어봤어요.

처음에는 막막하게 느껴질 수 있지만, 작은 프로젝트를 하나씩 완성하다 보면 어느 순간 "아, CRUD는 이렇게 돌아가는구나!" 하고 자연스럽게 체득할 수 있습니다. 실전 프로젝트를 만들 때도 오늘 배운 이 흐름을 그대로 활용할 수 있어요.

 

Tip! 👉 오늘 만든 Todo 앱을 조금 더 발전시키고 싶다면?

  • 완료 여부(체크박스)를 추가해보세요 ✅
  • 마감일(deadline) 필드를 추가해 날짜순 정렬을 해보세요 📅
  • 사용자 인증(로그인 기능)을 붙여서 개인별 Todo 관리로 발전시켜보세요 🔐

 

이렇게 한 걸음 한 걸음 업그레이드해 나가면서 실전 웹 개발자로 성장할 수 있습니다! 🚀

오늘도 함께 성장하는 하루였길 바라요. 감사합니다! 🙏

반응형
반응형

리액트에서 리스트 데이터를 화면에 출력하는 모든 방법

리스트를 효과적으로 출력하는 방법을 몰라 고생하고 계신가요?
map 함수부터 조건부 렌더링까지,
초보자를 위한 실전 예제로 모두 설명해드립니다!
반응형


https://inf.run/mg1G5

 

Next.js 15: Full-Stack Development| 구멍가게코딩단 - 인프런 강의

전통적인 React 개발 방식과 Next.js를 이용해서 개발하는 방식은 전혀 다릅니다. 이 강의는 최신 Next.js 15의 핵심을 꿰뚫고, '진짜' Next.js다운 개발 방식을 알려드립니다. 취업 포트폴리오부터 실무

www.inflearn.com

 

안녕하세요, 여러분! 🙋‍♂️

이번 시간에는 리액트(React)로 화면에 리스트 데이터를 출력하는 방법을 알아보려고 해요.

특히 초보 개발자 분들이 자주 실수하는 포인트와 자주 쓰이는 패턴들을 중심으로, 최대한 쉽게 설명드릴게요.

단순한 텍스트 배열부터 객체 배열까지 다양한 데이터 출력 방법을 예제로 직접 보여드릴 테니, 끝까지 읽어보시면 실력이 한층 업그레이드될 거예요!

 

1. map() 함수를 사용한 배열 출력 방법 🧩

리액트에서 리스트 데이터를 출력할 때 가장 많이 사용하는 방법 중 하나가 바로 map() 함수입니다.

배열의 각 요소를 순회하면서 JSX 요소를 리턴해 주는 방식인데요.

간단하지만 강력한 이 방법부터 함께 알아볼게요!

✅ 기본 배열을 출력하는 예제

예를 들어 ['사과', '바나나', '포도']라는 문자열 배열이 있다고 가정해봅시다.

이 데이터를 화면에 출력하려면 다음과 같이 작성할 수 있어요.

{['사과', '바나나', '포도'].map((item, index) => (
  <li key={index}>{item}</li>
))}

위 코드는 배열의 각 요소를 <li> 태그로 감싸서 출력해 주고 있어요.

key 속성은 리액트가 리스트를 효율적으로 렌더링하기 위해 꼭 필요한 부분이니, 잠시 후 자세히 설명드릴게요.

📋 리스트 출력 시 유용한 팁

  • JSX 안에서 직접 map()을 사용할 수 있어요.
  • 출력할 HTML 요소에 key 속성을 꼭 넣어주세요.
  • 너무 복잡한 로직은 별도의 함수로 분리하면 더 깔끔해져요.

📊 비교를 위한 표

구분 사용 여부 설명
map() 배열을 순회하며 JSX 반환
forEach() JSX를 반환하지 않아 화면에 출력 불가

자, 여기까지가 리액트에서 리스트 데이터를 가장 기본적으로 출력하는 방법이었습니다.

다음 섹션에서는 객체 배열을 출력할 때의 유용한 팁과 예제를 알아볼게요!

 

 

2. 객체 배열을 활용한 리스트 렌더링 📚

단순한 문자열 배열뿐 아니라 객체 배열을 화면에 출력하는 경우도 정말 많죠.

예를 들어

게시판의 글 목록, 사용자 리스트, 상품 정보 등 대부분의 실무 데이터는 객체 배열로 이루어져 있어요.

그럼 실제 예제로 살펴볼까요?

💡 사용자 목록 출력 예제

const users = [
  { id: 1, name: '홍길동', age: 28 },
  { id: 2, name: '김철수', age: 34 },
  { id: 3, name: '이영희', age: 22 },
];

{users.map(user => (
  <div key={user.id}>
    <p>이름: {user.name}</p>
    <p>나이: {user.age}</p>
  </div>
))}

여기서는 각 사용자 객체의 id를 key로 지정했어요.

이는 성능 최적화뿐 아니라 리액트 내부에서 효율적인 비교 연산을 가능하게 합니다.

고유한 값을 key로 사용해야 해요!

🔍 실제 사용 예시 (게시판)

게시판 데이터를 서버에서 받아온 후 화면에 출력할 때도 거의 동일한 방식이에요.

중요한 건 렌더링하는 컴포넌트 내에서 데이터가 어떤 구조로 되어 있는지, 각 항목을 어떤 방식으로 보여줄지 먼저 정의하는 거죠.

  • 서버 응답은 보통 JSON 형태의 객체 배열
  • map() 함수로 각 항목을 컴포넌트로 매핑
  • key는 id, slug 등 고유 식별자로 설정

실제 개발 프로젝트에서 자주 접하게 되는 패턴이니, 꼭 여러 번 실습하면서 손에 익혀두세요!

다음 섹션에서는 key 속성을 조금 더 자세히 파고들어 보겠습니다.

 

 

3. Key 속성의 중요성과 사용 팁 🔑

리스트를 렌더링할 때 빠지면 안 되는 요소 중 하나가 바로 key 속성입니다.

처음 리액트를 접한 분들이 가장 헷갈려하는 부분이기도 하죠.

하지만 이 key가 없으면 렌더링 성능이 크게 떨어지거나 예기치 않은 버그가 발생할 수 있어요.

🙋‍♂️ key란 도대체 뭐예요?

리액트는 리스트 안의 항목들을 업데이트할 때 DOM을 효율적으로 관리하기 위해 각 항목을 식별할 수 있는 고유한 key 값을 필요로 합니다.

이 key를 기준으로 어떤 항목이 추가되거나 제거됐는지를 판단하는 거죠.

{users.map(user => (
  <div key={user.id}>
    <p>{user.name}</p>
  </div>
))}

이처럼 각 항목에 고유한 id를 key로 사용하는 것이 가장 이상적이에요.

index를 key로 쓰는 경우도 있지만, 항목이 자주 변경되거나 순서가 바뀌는 리스트에서는 사용을 피하는 것이 좋아요.

🚫 index를 key로 사용하면 생기는 문제

  • 항목 순서가 바뀌면 불필요한 리렌더링 발생
  • 애니메이션/입력값 유지가 꼬이는 경우 발생
  • 디버깅이 어려워짐

🛠 key 사용 실전 팁 요약

상황 추천 key 설명
서버에서 가져온 데이터 고유 id primary key 또는 UUID
정적인 배열 index 변경되지 않는 배열이라면 무방

이제 key에 대한 감이 좀 오셨나요?

다음은 조건부 렌더링을 활용해서 리스트를 더 유동적으로 제어하는 방법을 알려드릴게요!

 

 

4. 조건부 렌더링으로 동적 리스트 제어 🎛

리스트를 출력할 때 모든 데이터를 한 번에 보여주는 건 오히려 사용자 경험을 해칠 수도 있어요.

그래서 자주 사용하는 테크닉 중 하나가 조건부 렌더링입니다.

즉, 특정 조건에 따라 리스트 항목을 보여줄지 말지를 결정하는 거죠.

🎯 조건을 활용한 출력 예제

예를 들어 나이가 30세 이상인 사용자만 출력하고 싶다면 어떻게 해야 할까요?

아래처럼 조건을 걸어주면 됩니다.

{users
  .filter(user => user.age >= 30)
  .map(user => (
    <p key={user.id}>{user.name} - {user.age}세</p>
))}

filter()를 먼저 사용해서 조건에 맞는 항목만 남긴 후 map()으로 렌더링하는 패턴이죠.

실무에서도 정말 많이 사용되니까 꼭 기억해두세요.

📦 조건부 렌더링 방식 비교

방법 장점 단점
filter + map 직관적이고 가독성 좋음 한 번 더 순회하므로 성능 손해 가능성
map 내부 조건문 1회 순회로 효율적 코드가 지저분해질 수 있음

🔑 실전 팁

  • 조건이 복잡할수록 filter를 먼저 사용
  • JSX 내부 조건문은 삼항연산자(? :)로 처리 가능
  • 조건을 외부 변수로 선언하면 코드가 훨씬 깔끔해짐

조건부 렌더링은 단순한 리스트 출력보다 훨씬 더 유연하게 화면을 제어할 수 있는 강력한 도구입니다.

다음 챕터에서는 리스트 아이템을 컴포넌트로 분리해서 더 구조적인 코드를 만드는 방법을 알아보겠습니다!

 

 

5. 리스트 아이템 컴포넌트로 분리하기 🧱

리스트가 길어지고 항목이 복잡해질수록, 코드도 금방 지저분해지기 시작합니다.

이런 경우에는 리스트 항목을 별도 컴포넌트로 분리하는 것이 가장 좋은 방법이에요.

유지보수도 쉬워지고 재사용성도 높아지거든요.

🛠 리스트 항목 컴포넌트 만들기

예를 들어 사용자 정보를 출력하는 UserItem 컴포넌트를 따로 만든다고 가정해 볼게요.

function UserItem({ user }) {
  return (
    <div>
      <p>이름: {user.name}</p>
      <p>나이: {user.age}</p>
    </div>
  );
}

그다음에 리스트를 출력할 때는 이렇게 작성하면 되죠.

{users.map(user => (
  <UserItem key={user.id} user={user} />
))}

📋 이렇게 분리하면 좋은 점

  • 복잡한 JSX 로직을 분리할 수 있어 가독성 향상
  • 각 항목의 스타일이나 로직을 독립적으로 관리 가능
  • 테스트나 리팩토링 시 훨씬 유리

컴포넌트를 잘게 나누는 습관은 리액트를 능숙하게 다루기 위한 첫걸음입니다.

다음 섹션에서는 실수 없이 리스트를 잘 출력하기 위한 베스트 프랙티스를 정리해볼게요!

6. 리스트 출력 시 피해야 할 실수와 베스트 프랙티스 📌

여기까지 따라오셨다면 이제 기본적인 리스트 출력은 문제없이 하실 수 있을 거예요.

하지만 실제로 개발을 하다 보면 사소한 실수 하나로 디버깅에 시간을 많이 쏟게 되죠.

그래서 자주 발생하는 실수들과 꼭 알아두어야 할 베스트 프랙티스를 정리해볼게요!

❗ 자주 하는 실수 TOP 3

  1. key 속성 없이 리스트 출력하기 → 렌더링 성능 저하, 경고 발생
  2. map 함수에서 return 누락하기 → 아무것도 안 그려짐
  3. 동일한 key 값을 여러 항목에 사용하기 → 렌더링 꼬임

✅ 안전한 리스트 렌더링을 위한 베스트 프랙티스

  • 항상 key 속성을 고유한 값으로 지정하세요.
  • 복잡한 항목은 별도 컴포넌트로 분리하세요.
  • 조건부 렌더링은 filter() 또는 삼항 연산자(?)로 처리하세요.
  • 리스트 안에서 setState를 호출하면 무한 루프가 발생할 수 있으니 주의하세요.

📎 추가 팁

항상 리스트를 작성할 때는 '만약에 항목이 추가되거나 삭제되면 어떻게 될까?'를 먼저 고민해보세요.

그리고 그 상황에서 리액트가 정상적으로 동작할 수 있도록 key, 조건, 구조화를 잘 챙기면 리스트 출력이 훨씬 안정적이고 효율적이게 됩니다.

지금까지 리액트에서 리스트 데이터를 출력하는 다양한 방법들을 함께 알아봤어요.

단순한 배열부터 복잡한 객체 리스트, 그리고 조건부 렌더링과 컴포넌트 분리까지 단계별로 정리해봤는데요.

하나씩 실습해보면서 익숙해지다 보면 어느새 자연스럽게 리스트 데이터를 다룰 수 있게 될 거예요 😊

핵심은 항상 “가독성과 유지보수성”입니다.

데이터를 잘 출력하는 것보다 중요한 건 나중에 누가 봐도 이해하기 쉬운 코드를 작성하는 거예요.

이번 글이 여러분의 리액트 실력을 한층 끌어올리는 계기가 되었길 바랍니다!

반응형

+ Recent posts