Search

μ‡Όν•‘λͺ° μƒν’ˆ νŽ˜μ΄μ§€

μ‡Όν•‘λͺ° κΈ°λ³Έ νŽ˜μ΄μ§€

μ‡Όν•‘λͺ° κΈ°λ³Έ νŽ˜μ΄μ§€λ₯Ό λ§Œλ“€μ–΄λ΄…λ‹ˆλ‹€.
1.
메인 ν™”λ©΄
2.
μƒν’ˆ λͺ©λ‘
3.
μƒν’ˆ 상세

ν”„λ‘œμ νŠΈ ꡬ쑰

Django ν”„λ‘œμ νŠΈμ˜ κΈ°λ³Έ 디렉토리 κ΅¬μ‘°λŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:
이 κ΅¬μ‘°λŠ” Django의 ν‘œμ€€ ν”„λ‘œμ νŠΈ λ ˆμ΄μ•„μ›ƒμ„ λ”°λ₯΄λ©°, 정적 파일, λ―Έλ””μ–΄ 파일, ν…œν”Œλ¦Ώ 등이 μ²΄κ³„μ μœΌλ‘œ κ΅¬μ„±λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.
graph TD;
    A["메인 νŽ˜μ΄μ§€ (main.html)"] --> B["μƒν’ˆ λͺ©λ‘ (product_list.html)"];
    B --> C["μƒν’ˆ 상세 (product_detail.html)"];
    
    D["Models"] --> E["Product"];
    E --> F["name"];
    E --> G["price"];
    E --> H["description"];
    E --> I["image"];
    
    J["Views"] --> K["main()"];
    J --> L["product_list()"];
    J --> M["product_detail()"];
    
    N["URLs"] --> O["/ (main)"];
    N --> P["/products/ (list)"];
    N --> Q["/products/<pk>/ (detail)"];
Mermaid
볡사
μœ„μ˜ κ΅¬μ‘°λ„λŠ” Django ν”„λ‘œμ νŠΈμ˜ κΈ°λ³Έ ꡬ쑰와 μ£Όμš” μ»΄ν¬λ„ŒνŠΈλ“€ κ°„μ˜ 관계λ₯Ό λ³΄μ—¬μ€λ‹ˆλ‹€. 메인 νŽ˜μ΄μ§€μ—μ„œ μƒν’ˆ λͺ©λ‘μœΌλ‘œ, 그리고 μƒν’ˆ 상세 νŽ˜μ΄μ§€λ‘œ μ΄μ–΄μ§€λŠ” μ‚¬μš©μž 흐름과 ν•¨κ»˜ λͺ¨λΈ, λ·°, URL의 ꡬ성을 ν‘œν˜„ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

개발 ν”„λ‘œμ„ΈμŠ€

1.
ν”„λ‘œμ νŠΈ ν™˜κ²½ μ„€μ •
β€’
κ°€μƒν™˜κ²½ 생성 및 ν™œμ„±ν™”
β€’
Django 및 ν•„μš”ν•œ νŒ¨ν‚€μ§€ μ„€μΉ˜
β€’
ν”„λ‘œμ νŠΈ 생성
2.
κΈ°λ³Έ ꡬ쑰 μ„€μ •
β€’
μ•± 생성
β€’
settings.py μ„€μ •
β€’
URL λ§€ν•‘
3.
ν”„λ‘ νŠΈμ—”λ“œ ꡬ성
β€’
Bootstrap μ„€μΉ˜
β€’
κΈ°λ³Έ ν…œν”Œλ¦Ώ ꡬ쑰 μž‘μ„±
β€’
static 파일 μ„€μ •
4.
λ°±μ—”λ“œ 개발
β€’
λͺ¨λΈ 섀계 및 κ΅¬ν˜„
β€’
λ·° 둜직 μž‘μ„±
β€’
폼 μž‘μ„±
5.
ν…ŒμŠ€νŠΈ 및 배포
β€’
λ‹¨μœ„ ν…ŒμŠ€νŠΈ μž‘μ„±
β€’
톡합 ν…ŒμŠ€νŠΈ
β€’
배포 μ€€λΉ„

μ£Όμš” λͺ…λ Ήμ–΄ 및 μ½”λ“œ

1. ν”„λ‘œμ νŠΈ ν™˜κ²½ μ„€μ •

κ°€μƒν™˜κ²½ 생성

python -m venv venv
Python
볡사

κ°€μƒν™˜κ²½ ν™œμ„±ν™”

venv\Scripts\activate
Python
볡사

Django μ„€μΉ˜

pip install django
Python
볡사

ν”„λ‘œμ νŠΈ 생성

django-admin startproject shop_project .
Python
볡사

2. μ•± 생성 및 μ„€μ •

μ•± 생성

python manage.py startapp shop
Bash
볡사
settings.pyμ—μ„œ μ•±κ³Ό ν…œν”Œλ¦Ώ μ„€μ •:
# settings.py INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'shop', 'bootstrap5', # Bootstrap 5 μ‚¬μš© ] TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [BASE_DIR / 'templates'], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
Python
볡사

3. URL λ§€ν•‘

# shop_project/urls.py from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('', include('shop.urls')), ] # shop/urls.py from django.urls import path from . import views app_name = 'shop' urlpatterns = [ path('', views.main, name='main'), path('products/', views.product_list, name='product_list'), path('products/<int:pk>/', views.product_detail, name='product_detail'), ]
Python
볡사
각 URL νŒ¨ν„΄μ— λŒ€ν•œ μ„€λͺ…:

1. 메인 νŽ˜μ΄μ§€ URL

path('', views.main, name='main')
Python
볡사
β€’
빈 λ¬Έμžμ—΄('')은 루트 URL을 μ˜λ―Έν•©λ‹ˆλ‹€ (예: http://example.com/)
β€’
views.main ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜μ—¬ 메인 νŽ˜μ΄μ§€λ₯Ό ν‘œμ‹œν•©λ‹ˆλ‹€
β€’
name='main'은 이 URL νŒ¨ν„΄μ˜ μ΄λ¦„μœΌλ‘œ, ν…œν”Œλ¦Ώμ—μ„œ {% url 'shop:main' %}κ³Ό 같이 μ°Έμ‘°ν•  수 μžˆμŠ΅λ‹ˆλ‹€

2. μƒν’ˆ λͺ©λ‘ URL

path('products/', views.product_list, name='product_list')
Python
볡사
β€’
'products/' URL에 λ§€ν•‘λ©λ‹ˆλ‹€ (예: http://example.com/products/)
β€’
views.product_list ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜μ—¬ 전체 μƒν’ˆ λͺ©λ‘μ„ ν‘œμ‹œν•©λ‹ˆλ‹€
β€’
name='product_list'둜 이름이 μ§€μ •λ˜μ–΄ μžˆμ–΄ ν…œν”Œλ¦Ώμ—μ„œ {% url 'shop:product_list' %}둜 μ°Έμ‘° κ°€λŠ₯ν•©λ‹ˆλ‹€

3. μƒν’ˆ 상세 URL

path('products/<int:pk>/', views.product_detail, name='product_detail')
Python
볡사
β€’
'products/숫자/' ν˜•μ‹μ˜ URL에 λ§€ν•‘λ©λ‹ˆλ‹€ (예: http://example.com/products/1/)
β€’
<int:pk>λŠ” URL νŒ¨ν„΄μ˜ 동적 λΆ€λΆ„μœΌλ‘œ, μ •μˆ˜ν˜• primary keyλ₯Ό μΊ‘μ²˜ν•©λ‹ˆλ‹€
β€’
views.product_detail ν•¨μˆ˜μ— pk λ§€κ°œλ³€μˆ˜λ‘œ μ „λ‹¬λ˜μ–΄ νŠΉμ • μƒν’ˆμ˜ 상세 정보λ₯Ό ν‘œμ‹œν•©λ‹ˆλ‹€
β€’
ν…œν”Œλ¦Ώμ—μ„œ {% url 'shop:product_detail' product.pk %}와 같이 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€

4. κΈ°λ³Έ ν…œν”Œλ¦Ώ ꡬ쑰

<!-- templates/base.html --> <!DOCTYPE html> <html> <head> <title>{% block title %}μ‡Όν•‘λͺ°{% endblock %}</title> <!-- Bootstrap CSS --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <nav class="navbar navbar-expand-lg navbar-light bg-light"> <!-- λ„€λΉ„κ²Œμ΄μ…˜ λ°” λ‚΄μš© --> </nav> <div class="container mt-4"> {% block content %} {% endblock %} </div> <!-- Bootstrap JS --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script> </body> </html>
HTML
볡사

6. ν…œν”Œλ¦Ώ μž‘μ„±

β€’
main.html
β€’
product_list.html
β€’
product_detail.html

main.html

<!-- templates/shop/main.html --> {% extends 'base.html' %} {% block title %}메인 νŽ˜μ΄μ§€{% endblock %} {% block content %} <div class="jumbotron"> <h1>Welcome to Our Shop</h1> <p>졜고의 μƒν’ˆμ„ μ΅œμ €κ°€λ‘œ λ§Œλ‚˜λ³΄μ„Έμš”!</p> <a href="{% url 'shop:product_list' %}" class="btn btn-primary">μƒν’ˆ λ³΄λŸ¬κ°€κΈ°</a> </div> {% endblock %}
HTML
볡사

product_list.html

<!-- templates/shop/product_list.html --> {% extends 'base.html' %} {% block title %}μƒν’ˆ λͺ©λ‘{% endblock %} {% block content %} <h2>μƒν’ˆ λͺ©λ‘</h2> <div class="row"> {% for product in products %} <div class="col-md-4 mb-4"> <div class="card"> {% if product.image %} <img src="{{ product.image.url }}" class="card-img-top" alt="{{ product.name }}"> {% endif %} <div class="card-body"> <h5 class="card-title">{{ product.name }}</h5> <p class="card-text">{{ product.price }}원</p> <a href="{% url 'shop:product_detail' product.pk %}" class="btn btn-primary">상세보기</a> </div> </div> </div> {% endfor %} </div> {% endblock %}
HTML
볡사

product_detail.html

<!-- templates/shop/product_detail.html --> {% extends 'base.html' %} {% block title %}{{ product.name }}{% endblock %} {% block content %} <div class="row"> <div class="col-md-6"> {% if product.image %} <img src="{{ product.image.url }}" class="img-fluid" alt="{{ product.name }}"> {% endif %} </div> <div class="col-md-6"> <h2>{{ product.name }}</h2> <p class="lead">가격: {{ product.price }}원</p> <hr> <p>{{ product.description }}</p> <button class="btn btn-primary">μž₯λ°”κ΅¬λ‹ˆμ— λ‹΄κΈ°</button> </div> </div> {% endblock %}
HTML
볡사

5. λͺ¨λΈ μž‘μ„±

# shop/models.py from django.db import models class Product(models.Model): name = models.CharField(max_length=200) price = models.DecimalField(max_digits=10, decimal_places=2) description = models.TextField() image = models.ImageField(upload_to='products/') created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def __str__(self): return self.name
Python
볡사
각 λͺ¨λΈ ν•„λ“œμ— λŒ€ν•œ μ„€λͺ…:
β€’
name: μƒν’ˆλͺ…을 μ €μž₯ν•˜λŠ” CharField, μ΅œλŒ€ 200μžκΉŒμ§€ μž…λ ₯ κ°€λŠ₯
β€’
price: 가격을 μ €μž₯ν•˜λŠ” DecimalField, μ΅œλŒ€ 10자리 μˆ«μžμ™€ μ†Œμˆ˜μ  2μžλ¦¬κΉŒμ§€ 지원
β€’
description: μƒν’ˆ μ„€λͺ…을 μ €μž₯ν•˜λŠ” TextField, 길이 μ œν•œ μ—†μŒ
β€’
image: μƒν’ˆ 이미지λ₯Ό μ €μž₯ν•˜λŠ” ImageField, 'products/' 디렉토리에 μ—…λ‘œλ“œλ¨
β€’
created_at: μƒν’ˆ 생성 μ‹œκ°„μ„ μžλ™μœΌλ‘œ μ €μž₯ν•˜λŠ” DateTimeField
β€’
updated_at: μƒν’ˆ 정보 μˆ˜μ • μ‹œκ°„μ„ μžλ™μœΌλ‘œ μ—…λ°μ΄νŠΈν•˜λŠ” DateTimeField
# settings.py BASE_DIR = os.path.dirname(os.path.dirname(__file__)) MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'upload')
Python
볡사
μ‹€μ œλ‘œ __file__은 ν˜„μž¬ 파일(settings.py)의 κ²½λ‘œλ§Œμ„ κ°€λ¦¬ν‚΅λ‹ˆλ‹€. os.path.dirname을 두 번 μ‚¬μš©ν•˜μ—¬:
β€’
첫 번째 dirname: settings.pyκ°€ μžˆλŠ” 디렉토리(shop_project)의 경둜λ₯Ό μ–»μŒ
β€’
두 번째 dirname: ν”„λ‘œμ νŠΈ 루트 λ””λ ‰ν† λ¦¬μ˜ 경둜λ₯Ό μ–»μŒ
λ”°λΌμ„œ BASE_DIR = os.path.dirname(os.path.dirname(file))와 같이 μ„€μ •ν•˜λ©΄ 더 λͺ…ν™•ν•  것 κ°™μŠ΅λ‹ˆλ‹€:
μ΄λ ‡κ²Œ ν•˜λ©΄ ν”„λ‘œμ νŠΈ 루트 디렉토리에 'upload' 폴더가 μƒμ„±λ©λ‹ˆλ‹€. μ‹€μ œ κ²½λ‘œλŠ” ν”„λ‘œμ νŠΈκ°€ μžˆλŠ” μœ„μΉ˜μ— 따라 λ‹¬λΌμ§ˆ 수 μžˆμŠ΅λ‹ˆλ‹€.
μž₯κ³  ν”„λ‘œμ νŠΈμ˜ URLsμ—μ„œ λ―Έλ””μ–΄ νŒŒμΌμ„ μ„œλΉ™ν•˜κΈ° μœ„ν•œ μ„€μ •:
# urls.py (ν”„λ‘œμ νŠΈ 메인) from django.conf import settings from django.conf.urls.static import static if settings.DEBUG: urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Python
볡사

μ—…λ‘œλ“œ 폴더 생성

C:\ └── ~ └── shop_project\ β”œβ”€β”€ manage.py β”œβ”€β”€ shop_app\ β”œβ”€β”€ shop_project\ └── πŸ“¦ upload\ ← 여기에 생성 (μˆ˜λ™)
Python
볡사

λͺ¨λΈ 생성 ν›„ λ§ˆμ΄κ·Έλ ˆμ΄μ…˜:

λ§ˆμ΄κ·Έλ ˆμ΄μ…˜μ΄λž€ (Migration)?

λ§ˆμ΄κ·Έλ ˆμ΄μ…˜μ€ λ°μ΄ν„°λ² μ΄μŠ€μ˜ ꡬ쑰λ₯Ό λ³€κ²½ν•˜λŠ” μž‘μ—…μ„ μ²΄κ³„μ μœΌλ‘œ κ΄€λ¦¬ν•˜λŠ” Django의 κΈ°λŠ₯μž…λ‹ˆλ‹€. μ£Όμš” νŠΉμ§•μ€ λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:
β€’
λ°μ΄ν„°λ² μ΄μŠ€ μŠ€ν‚€λ§ˆ 버전 관리: λͺ¨λΈ 변경사항을 μΆ”μ ν•˜κ³  λ°μ΄ν„°λ² μ΄μŠ€ μŠ€ν‚€λ§ˆλ₯Ό μ•ˆμ „ν•˜κ²Œ μ—…λ°μ΄νŠΈ
β€’
ν˜‘μ—… 지원: μ—¬λŸ¬ κ°œλ°œμžκ°€ λ™μ‹œμ— μž‘μ—…ν•  λ•Œ λ°μ΄ν„°λ² μ΄μŠ€ 변경사항을 μΌκ΄€λ˜κ²Œ 관리
β€’
λ‘€λ°± κ°€λŠ₯: 문제 λ°œμƒ μ‹œ 이전 μƒνƒœλ‘œ 되돌릴 수 μžˆλŠ” κΈ°λŠ₯ 제곡
β€’
μžλ™ SQL 생성: κ°œλ°œμžκ°€ 직접 SQL을 μž‘μ„±ν•˜μ§€ μ•Šμ•„λ„ Djangoκ°€ μ μ ˆν•œ SQL λͺ…λ Ήμ–΄λ₯Ό 생성
λ§ˆμ΄κ·Έλ ˆμ΄μ…˜μ€ 두 λ‹¨κ³„λ‘œ μ΄λ£¨μ–΄μ§‘λ‹ˆλ‹€:
1.
makemigrations: λͺ¨λΈμ˜ 변경사항을 κ°μ§€ν•˜μ—¬ λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ νŒŒμΌμ„ 생성
2.
migrate: μƒμ„±λœ λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ νŒŒμΌμ„ μ‹€μ œ λ°μ΄ν„°λ² μ΄μŠ€μ— 적용
β€’
λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ 파일 생성
python manage.py makemigrations
Bash
볡사
이 λͺ…λ Ήμ–΄λŠ” λͺ¨λΈμ˜ 변경사항을 κ°μ§€ν•˜κ³  μƒˆλ‘œμš΄ λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ νŒŒμΌμ„ μƒμ„±ν•©λ‹ˆλ‹€. λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ νŒŒμΌμ€ λ°μ΄ν„°λ² μ΄μŠ€ μŠ€ν‚€λ§ˆλ₯Ό λ³€κ²½ν•˜κΈ° μœ„ν•œ Python μ½”λ“œμž…λ‹ˆλ‹€.
β€’
λ§ˆμ΄κ·Έλ ˆμ΄μ…˜
python manage.py migrate
Bash
볡사
이 λͺ…λ Ήμ–΄λŠ” μƒμ„±λœ λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ νŒŒμΌμ„ μ‹€μ œ λ°μ΄ν„°λ² μ΄μŠ€μ— μ μš©ν•©λ‹ˆλ‹€. 이λ₯Ό 톡해 λͺ¨λΈμ—μ„œ μ •μ˜ν•œ ν…Œμ΄λΈ”μ΄ λ°μ΄ν„°λ² μ΄μŠ€μ— μƒμ„±λ©λ‹ˆλ‹€.
λ§ˆμ΄κ·Έλ ˆμ΄μ…˜μ€ λ°μ΄ν„°λ² μ΄μŠ€ μŠ€ν‚€λ§ˆ 변경을 μΆ”μ ν•˜κ³  κ΄€λ¦¬ν•˜λŠ” Django의 λ°©λ²•μž…λ‹ˆλ‹€. 이λ₯Ό 톡해 μ—¬λŸ¬ κ°œλ°œμžκ°€ ν˜‘μ—…ν•˜κ±°λ‚˜ λ°μ΄ν„°λ² μ΄μŠ€ λ³€κ²½ 이λ ₯을 관리할 수 μžˆμŠ΅λ‹ˆλ‹€.