▶️ DRF
[▶️Back-end] 사용자 입력의 Prompt를 다듬는 기능 구현 1차
▲ 본 게시물은 serializer, url, view 코드를 구현 하는 내용을 담았어요!
★ 변경 사항 ★
1. prompt 앱을 생성해서 새로 시작했어요.
2. dev/0.0.3은 DRF이기 때문에 새로 생성한 거예요! (이전은 Django였어요.)
3. API 명세서가 수정될 예정이에요.
▶️ 로직 구현 시작
🗣️ 앱 생성
# bash
python manage.py startapp prompts
🗣️ core/settings.py
1. DRF 기본 설정
더보기
# DRF 설정
REST_FRAMEWORK = {
# **API 설정**
# 1. 기본 인증 방식 (Authentication Classes)
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication', # Django 세션 인증 (웹 브라우저)
'rest_framework.authentication.TokenAuthentication', # 토큰 인증 (API 클라이언트)
# 필요에 따라 JWT 인증 추가 가능:
# 'rest_framework_simplejwt.authentication.JWTAuthentication',
],
# 2. 기본 권한 설정 (Permission Classes)
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticatedOrReadOnly', # 읽기 권한은 누구나, 쓰기 권한은 인증된 사용자만
# 'rest_framework.permissions.IsAuthenticated', # 인증된 사용자만 접근 가능
# 'rest_framework.permissions.AllowAny', # 누구나 접근 가능 (개발/테스트 환경)
],
# **페이지네이션 설정**
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', # 페이지 번호 기반 페이지네이션
'PAGE_SIZE': 10, # 한 페이지당 항목 수
# **기타 설정**
# 3. 예외 처리 (Exception Handling)
'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler', # DRF 기본 예외 처리 사용
# 4. Content Negotiation 설정 (콘텐츠 협상)
'DEFAULT_CONTENT_TYPE': 'application/json', # 기본 콘텐츠 타입
# 5. Renderer 설정 (응답 형식)
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer', # JSON 형식
'rest_framework.renderers.BrowsableAPIRenderer', # browsable API (웹 브라우저)
],
# 6. 파서 설정 (요청 형식)
'DEFAULT_PARSER_CLASSES': [
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser'
],
# 7. API 버전 관리
'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.AcceptHeaderVersioning', # Accept 헤더 기반 버전 관리
'DEFAULT_VERSION': 'v1', # 기본 API 버전
# 8. 스키마 생성 설정
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
}
1차 게시물에서 DRF의 기본 설정들을 추가해주었어야 했는데, 까먹고 안 했더라고요.
그래서 이번에 추가해 주었어요.
출처 : https://www.django-rest-framework.org/api-guide/settings/
2. prompt 앱 등록
# Application definition
INSTALLED_APPS = [
...
# Create app list
...
"prompts", # 유저의 프롬프트를 좀 더 좋게 보완해주는 앱
...
]
새로 추가해 준 앱도 주석과 함께 등록해 주었어요.
🗣️ core/urls.py
urlpatterns = [
...
path("prompts/", include("prompts.urls")),
]
urls.py에 prompts 앱의 urls을 포함하도록 설정해 주었어요.
🗣️ prompts/urls.py
from django.urls import path
from .views import GenerateMesh
app_name="prompts"
urlpatterns = [
path("", GenerateMesh.as_view(), name="generate_mesh"),
]
🗣️ prompts/serializers.py
from rest_framework import serializers
class GenerateMeshRequestSerializer(serializers.Serializer):
prompt = serializers.CharField(
help_text="생성할 3D 모델에 대한 프롬프트 (예: '귀여운 강아지')."
)
art_style = serializers.CharField(
default="realistic",
required=False,
help_text="모델의 스타일 (예: 'realistic', 'cartoon'). 기본값은 'realistic'입니다."
)
def validate_art_style(self, value):
"""art_style 유효성 검사."""
allowed_styles = ["realistic", " artoon", "abstract", "horror", "industrial aesthetic", "game figure"] # 허용되는 스타일 목록
if value not in allowed_styles:
raise serializers.ValidationError(
f"잘못된 art_style입니다. 다음 중 하나를 선택하세요: {', '.join(allowed_styles)}"
)
return value
🗣️ prompts/views.py
프롬프트 보강해 주는 로직
더보기
import logging
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from .models import MeshPromptModel
# utils
from workspace.meshy_utils import call_meshy_api # Meshy API 호출 함수
from .serializers import GenerateMeshRequestSerializer # Serializer 임포트
# 로깅 설정
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
class GenerateMesh(APIView):
"""Mesh 생성 요청 & job_id 반환"""
permission_classes = [IsAuthenticated] # 로그인된 사용자만 접근 가능
def get(self, request):
"""최근 생성된 Mesh 모델 목록 조회"""
meshes = MeshPromptModel.objects.filter(user=request.user).order_by("-created_at")[:5] # 최근 5개 조회
results = [{"job_id": mesh.job_id, "status": mesh.status, "prompt": mesh.create_prompt, "art_style": mesh.art_style} for mesh in meshes]
return Response({"recent_meshes": results}, status=status.HTTP_200_OK)
def post(self, request):
serializer = GenerateMeshRequestSerializer(data=request.data)
if serializer.is_valid():
prompt = serializer.validated_data['prompt']
art_style = serializer.validated_data.get('art_style', 'realistic')
# 프롬프트 보강: 중복 확인 후 "4K, highly detailed" 추가
if "4K" not in prompt and "highly detailed" not in prompt:
enhanced_prompt = prompt + ", 4K, highly detailed"
else:
enhanced_prompt = prompt # 이미 포함된 경우 그대로 사용
response_data = call_meshy_api("/openapi/v2/text-to-3d", "POST", {
"mode": "preview", "prompt": enhanced_prompt, "art_style": art_style
})
if not response_data:
return Response({"error": "Meshy API 응답 없음"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
job_id = response_data.get("result")
if not job_id:
return Response({"error": "Meshy API에서 job_id를 받지 못했습니다."}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
MeshPromptModel.objects.create(
user=request.user,
job_id=job_id,
status="processing",
create_prompt=enhanced_prompt, # 보강된 프롬프트 정보 저장
art_style=art_style
)
return Response({"job_id": job_id, "message": "Mesh 생성 시작!"}, status=status.HTTP_200_OK)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
서버

이렇게
"prompt" : "A cute baby dog, 4K, highly detailed"로 보완되도록 DRF로는 구현했어요.
하지만 LLM을 활용해서 이 작업을 수행해야 하기 때문에, 이제는 LLM 공부로 넘어갑시다. 😭
'👥 최종 팀 프로젝트(250227~250331) > 구현 과정 ▶️' 카테고리의 다른 글
[▶️Back-end] 사용자 입력의 Prompt를 다듬는 기능 구현 4차_LLM (5) | 2025.03.20 |
---|---|
[▶️Back-end] 사용자 입력의 Prompt를 다듬는 기능 구현 3차_LLM (1) | 2025.03.19 |
[▶️Back-end] 사용자 입력의 Prompt를 다듬는 기능 구현 1차 (0) | 2025.03.17 |
[▶️중간 점검] 2주 동안의 구현된 현황 (2) | 2025.03.17 |
[▶️Front-end] 메인 페이지에 좋아요, 싫어요 버튼 기능 구현 (0) | 2025.03.06 |