feat: 완료 사진 HEIC 지원 및 관리함 수정 기능 개선

 새로운 기능:
- iPhone HEIC 사진 업로드 지원 (pillow-heif 라이브러리 추가)
- 완료 사진 업로드/교체 기능
- 완료 코멘트 수정 기능
- 통합 이슈 수정 모달 (진행 중/완료 대기 공통)

🔧 기술적 개선:
- HEIC 파일 자동 감지 및 원본 저장
- Base64 이미지 처리 로직 강화
- 상세한 디버깅 로그 추가
- 프론트엔드 파일 정보 로깅

📝 문서화:
- 배포 가이드 (DEPLOYMENT_GUIDE_20251026.md) 추가
- DB 변경사항 로그 업데이트
- 마이그레이션 스크립트 (020_add_management_completion_fields.sql)

🐛 버그 수정:
- loadManagementData -> initializeManagement 함수명 통일
- 모달 저장 후 즉시 닫히는 문제 해결
- 422 Unprocessable Entity 오류 해결
This commit is contained in:
Hyungi Ahn
2025-10-26 14:18:30 +09:00
parent 20965f8a42
commit e7b51f80a0
11 changed files with 798 additions and 53 deletions

View File

@@ -6,6 +6,14 @@ import uuid
from PIL import Image
import io
# HEIF/HEIC 지원을 위한 라이브러리
try:
from pillow_heif import register_heif_opener
register_heif_opener()
HEIF_SUPPORTED = True
except ImportError:
HEIF_SUPPORTED = False
UPLOAD_DIR = "/app/uploads"
def ensure_upload_dir():
@@ -18,15 +26,70 @@ def save_base64_image(base64_string: str, prefix: str = "image") -> Optional[str
try:
ensure_upload_dir()
# Base64 헤더 제거
# Base64 헤더 제거 및 정리
if "," in base64_string:
base64_string = base64_string.split(",")[1]
# Base64 문자열 정리 (공백, 개행 제거)
base64_string = base64_string.strip().replace('\n', '').replace('\r', '').replace(' ', '')
print(f"🔍 정리된 Base64 길이: {len(base64_string)}")
print(f"🔍 Base64 시작 20자: {base64_string[:20]}")
# 디코딩
image_data = base64.b64decode(base64_string)
try:
image_data = base64.b64decode(base64_string)
print(f"🔍 디코딩된 데이터 길이: {len(image_data)}")
print(f"🔍 바이너리 시작 20바이트: {image_data[:20]}")
except Exception as decode_error:
print(f"❌ Base64 디코딩 실패: {decode_error}")
raise decode_error
# 파일 시그니처 확인
file_signature = image_data[:20]
print(f"🔍 파일 시그니처 (hex): {file_signature.hex()}")
# HEIC 파일 시그니처 확인
is_heic = b'ftyp' in image_data[:20] and (b'heic' in image_data[:50] or b'mif1' in image_data[:50])
print(f"🔍 HEIC 파일 여부: {is_heic}")
# 이미지 검증 및 형식 확인
image = Image.open(io.BytesIO(image_data))
try:
# HEIC 파일인 경우 바로 HEIF 처리 시도
if is_heic and HEIF_SUPPORTED:
print("🔄 HEIC 파일 감지, HEIF 처리 시도...")
image = Image.open(io.BytesIO(image_data))
print(f"✅ HEIF 이미지 로드 성공: {image.format}, 모드: {image.mode}, 크기: {image.size}")
else:
# 일반 이미지 처리
image = Image.open(io.BytesIO(image_data))
print(f"🔍 이미지 형식: {image.format}, 모드: {image.mode}, 크기: {image.size}")
except Exception as e:
print(f"❌ 이미지 열기 실패: {e}")
# HEIC 파일인 경우 원본 파일로 저장
if is_heic:
print("🔄 HEIC 파일 - 원본 바이너리 파일로 저장 시도...")
filename = f"{prefix}_{datetime.now().strftime('%Y%m%d%H%M%S')}_{uuid.uuid4().hex[:8]}.heic"
filepath = os.path.join(UPLOAD_DIR, filename)
with open(filepath, 'wb') as f:
f.write(image_data)
print(f"✅ 원본 HEIC 파일 저장: {filepath}")
return f"/uploads/{filename}"
# HEIC가 아닌 경우에만 HEIF 재시도
elif HEIF_SUPPORTED:
print("🔄 HEIF 형식으로 재시도...")
try:
image = Image.open(io.BytesIO(image_data))
print(f"✅ HEIF 재시도 성공: {image.format}, 모드: {image.mode}, 크기: {image.size}")
except Exception as heif_e:
print(f"❌ HEIF 처리도 실패: {heif_e}")
print("❌ 지원되지 않는 이미지 형식")
raise e
else:
print("❌ HEIF 지원 라이브러리가 설치되지 않거나 처리 불가")
raise e
# iPhone의 .mpo 파일이나 기타 형식을 JPEG로 강제 변환
# RGB 모드로 변환 (RGBA, P 모드 등을 처리)