Django

Chapter 7-5 Django 블로그 이미지 포토 및 얻어서 생성하는 썸네일 구현

Chansman 2025. 5. 11. 22:17

📷 Django 블로그 이미지 포토 및 얻어서 생성하는 썸네일 구현

▶️ 이미지가 포함된 게시글을 목록에서 썸네일로 보여주는 기능 구현


✅ 1. 이미지 없는 글 오류 방지 - blog_detail.html 조건문 추가

{% if blog.image %}
    <img src="{{ blog.image.url }}" alt="" class="w-100">
{% endif %}
<p>{{ blog.content | safe }}</p>

🔍 설명:

  • 이미지가 없는 경우에도 에러 없이 페이지가 렌더링되도록 if 조건문 처리
  • blog.image.url은 이미지가 존재할 때만 접근해야 함

🧱 2. models.py에 썸네일 필드 추가

thumbnail = models.ImageField('썸네일', null=True, blank=True, upload_to='blog/%Y/%m/%d/thumbnail')
python manage.py makemigrations
python manage.py migrate

🔍 설명:

  • 원본 이미지와 별개로, 크기가 줄어든 썸네일 이미지를 저장할 공간 설정
  • upload_to로 업로드 경로 분리 (thumbnail 하위 폴더로 저장됨)

📦 3. Pillow 설치

poetry add Pillow
  • 이미지 리사이징 등 Pillow 모듈 필요

🧠 4. 썸네일 자동 생성 - save() 오버라이드

from io import BytesIO
from pathlib import Path
from PIL import Image

class Blog(TimestampModel):
    ...
    def save(self, *args, **kwargs):
        if not self.image:
            return super().save(*args, **kwargs)

        image = Image.open(self.image)
        image.thumbnail((300, 300))  # 최대 300x300 크기로 리사이즈

        image_path = Path(self.image.name)
        thumbnail_name = image_path.stem
        thumbnail_extension = image_path.suffix
        thumbnail_filename = f'{thumbnail_name}_thumb{thumbnail_extension}'

        if thumbnail_extension in ['.jpg', 'jpeg']:
            file_type = 'JPEG'
        elif thumbnail_extension == '.gif':
            file_type = 'GIF'
        elif thumbnail_extension == '.png':
            file_type = 'PNG'
        else:
            return super().save(*args, **kwargs)

        temp_thumb = BytesIO()
        image.save(temp_thumb, file_type)
        temp_thumb.seek(0)

        self.thumbnail.save(thumbnail_filename, temp_thumb, save=False)
        temp_thumb.close()

        return super().save(*args, **kwargs)

🔍 설명:

  • Image.thumbnail()로 이미지 크기 자동 조절
  • 썸네일 이름은 기존 이미지에서 _thumb 접미사 추가하여 생성
  • 임시 메모리(BytesIO)에 썸네일 저장 후, self.thumbnail.save() 호출

🖼️ 5. 목록 페이지에서 썸네일 출력 - blog_list.html

{% if blog.thumbnail %}
    <img src="{{ blog.thumbnail.url }}" alt="" class="col-2">
{% elif blog.image %}
    <img src="{{ blog.image.url }}" alt="" class="col-2">
{% endif %}

🔍 설명:

  • 썸네일이 존재하면 우선 출력, 없으면 원본 이미지 출력
  • 이미지가 없으면 아무것도 출력하지 않음

🔁 6. get_thumbnail_url() 메서드로 로직 분리

def get_thumbnail_url(self):
    if self.thumbnail:
        return self.thumbnail.url
    elif self.image:
        return self.image.url
    return None

🔍 장점:

  • 템플릿에서 조건 분기 없이 blog.get_thumbnail_url 호출만으로 처리 가능
  • 뷰 로직이 간단해지고 재사용성 증가
{% if blog.get_thumbnail_url %}
    <img src="{{ blog.get_thumbnail_url }}" alt="" class="col-2">
{% endif %}

✅ 요약

항목 설명

ImageField 이미지 파일 업로드용 모델 필드
thumbnail 필드 이미지 저장 시 자동 생성되는 축소 이미지
save() 오버라이드 썸네일 생성 및 메모리 저장 처리
템플릿 조건문 이미지 존재 여부에 따라 출력 여부 결정

✅ 테스트용 샘플 이미지 다운로드 사이트:
👉 Pexels 4K 무료 사진


추후 이미지 업로드 시 S3 또는 클라우드 저장소 연동이 필요하면 별도 포스트로 안내해드릴게요. 원하시나요?