Skip to content

[Refactor] 업로드 이미지 다운샘플 + JPEG 압축 (ImageIO)#34

Merged
ddodle merged 2 commits into
mainfrom
refactor/upload-image-compression
Jul 1, 2026
Merged

[Refactor] 업로드 이미지 다운샘플 + JPEG 압축 (ImageIO)#34
ddodle merged 2 commits into
mainfrom
refactor/upload-image-compression

Conversation

@ddodle

@ddodle ddodle commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

✨ PR 유형

어떤 변경 사항이 있나요??

  • 새로운 기능 추가
  • 버그 수정
  • 사용자 UI 디자인 변경 및 추가
  • 코드에 영향을 주지 않는 변경사항(오타 수정, 탭 사이즈 변경, 변수명 변경)
  • 코드 리팩토링
  • 주석 추가 및 수정
  • 문서 수정
  • 테스트 추가, 테스트 리팩토링
  • 빌드 부분 혹은 패키지 매니저 수정
  • 파일 혹은 폴더명 수정
  • 파일 혹은 폴더 삭제

🛠️ 작업내용

리팩토링 계획 Step 7(성능 최적화) 의 "업로드 전 이미지 압축" 항목입니다.

원본 이미지를 그대로 업로드하던 방식을 ImageIO 기반 다운샘플 + JPEG 압축으로 교체했습니다.

  • CGImageSourceCreateThumbnailAtIndex디코드 시점에 다운샘플(max 2048px) → 풀해상도 비트맵을 메모리에 올리지 않아 피크 메모리 절감 (UIImage(data:).jpegData()는 4000x3000 기준 ~36MB 비트맵이 메모리에 튐)
  • JPEG 압축(quality 0.8)으로 업로드 용량/대역폭 절감
  • kCGImageSourceCreateThumbnailWithTransform로 EXIF 회전 반영 → 세로 사진이 눕는 문제 방지
  • 위치/촬영시간은 압축 전 EXIF에서 이미 추출하므로 메타데이터 손실 영향 없음
  • #if DEBUG 압축 전후 용량 로그 추가 (압축률 확인용)

📋 추후 진행 상황

  • Step 7 잔여: DateFormatter 캐싱, ETag 기반 캐시, 태그 O(1) 조회

📌 리뷰 포인트

  • 다운샘플 목표 크기(2048px)와 품질(0.8)이 적절한지
  • EXIF 회전 반영(...WithTransform)이 의도대로 동작하는지

✅ Checklist

  • 커밋 메시지 컨벤션에 맞게 작성했습니다
  • 유지-보수를 위해 주석처리를 잘 작성하였는가?

Closes #33

Summary by CodeRabbit

  • 버그 수정
    • 사진 업로드 시 원본 이미지를 그대로 전송하던 방식을, 더 작은 크기의 JPEG로 최적화해 전송하도록 개선했습니다.
    • 위치 정보와 촬영 시간 등 EXIF 메타데이터는 기존과 동일하게 유지됩니다.
  • 개선
    • 일부 임시 파일 경로 해석 오류 가능성을 줄이기 위해 파일명 표기를 안정화했습니다.

원본 그대로 업로드하던 것을 ImageIO 기반 다운샘플(max 2048px) +
JPEG 압축(quality 0.8)으로 변경.

- CGImageSourceCreateThumbnailAtIndex로 디코드 시점에 다운샘플하여
  풀해상도 비트맵을 메모리에 올리지 않음 → 피크 메모리 절감
- kCGImageSourceCreateThumbnailWithTransform로 EXIF 회전 반영
- 위치/촬영시간은 압축 전 EXIF에서 이미 추출하므로 메타 손실 무관
@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: ff17ec70-13f8-41f2-81f6-080243e7f070

📥 Commits

Reviewing files that changed from the base of the PR and between d8d2a79 and 9283a76.

📒 Files selected for processing (1)
  • Rephoto_iOS/Features/Home/Domain/Services/PhotoMetadataExtractor.swift
🚧 Files skipped from review as they are similar to previous changes (1)
  • Rephoto_iOS/Features/Home/Domain/Services/PhotoMetadataExtractor.swift

Walkthrough

PhotoMetadataExtractor가 원본 이미지를 그대로 저장하던 흐름을 ImageIO 기반 다운샘플링·JPEG 재인코딩으로 바꾸고, 임시 파일명 정규화와 디버그 로그를 추가했다.

Changes

업로드 이미지 다운샘플 + JPEG 압축

Layer / File(s) Summary
ImageIO / UTType import 추가
Rephoto_iOS/Features/Home/Domain/Services/PhotoMetadataExtractor.swift
ImageIOUniformTypeIdentifiers를 import하여 썸네일 생성 및 JPEG 인코딩 API를 사용할 수 있도록 의존성 추가.
downsampledJPEG 헬퍼 구현
Rephoto_iOS/Features/Home/Domain/Services/PhotoMetadataExtractor.swift
CGImageSourceCreateThumbnailAtIndex로 목표 해상도(max 2048px)까지 디코드하고 EXIF 회전을 반영한 뒤, CGImageDestination으로 lossy JPEG(quality 0.8)를 메모리 버퍼에 인코딩하여 Data?로 반환하는 헬퍼 신규 추가.
extract(from:) 업로드 경로 수정
Rephoto_iOS/Features/Home/Domain/Services/PhotoMetadataExtractor.swift
원본 data 대신 downsampledJPEG 결과(compressed)를 임시 JPEG 파일로 기록하도록 변경. 압축 실패 시 nil 반환하며, #if DEBUG 블록에서 원본/압축 크기, 비율, 픽셀 치수 로그 출력.

Estimated code review effort: 2 (Simple) | ~10 minutes

Poem

🐰 원본 사진이 폴짝 줄었네
ImageIO 바람 타고 가볍게 변신
EXIF는 그대로, 메타도 그대로
임시 파일은 쓱— 안전하게 저장
업로드 길이 훨씬 산뜻해졌네 🌸

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning itemIdentifier 슬래시 치환은 #33의 다운샘플/압축 요구와 직접 관련 없는 추가 변경입니다. 이 파일명 정규화는 별도 PR로 분리하거나 필요성을 설명해 범위 내 변경임을 명확히 해주세요.
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 업로드 이미지 다운샘플과 JPEG 압축(ImageIO)이라는 핵심 변경을 정확히 요약합니다.
Description check ✅ Passed 템플릿의 주요 섹션(PR 유형, 작업내용, 추후 진행 상황, 리뷰 포인트, 체크리스트)을 모두 채워 비교적 완성도가 높습니다.
Linked Issues check ✅ Passed 다운샘플 2048px, JPEG 0.8, EXIF 회전 반영, 메타데이터 선추출 등 #33의 핵심 요구를 충족합니다.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/upload-image-compression

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Rephoto_iOS/Features/Home/Domain/Services/PhotoMetadataExtractor.swift`:
- Around line 10-11: Move the image-processing implementation out of
PhotoMetadataExtractor in the Home Domain layer: the current Domain file is
importing ImageIO/UniformTypeIdentifiers and handling PhotosPickerItem
conversion, JPEG re-encoding, and temporary-file I/O, which violates the
pure-Domain boundary. Keep PhotoMetadataExtractor as a Domain protocol/use-case
contract only, and relocate the concrete implementation and all
platform/file/image handling into the Data layer, preserving the existing
symbols so callers continue to depend on the Domain abstraction.
- Around line 34-55: `PhotoMetadataExtractor`의 임시 JPEG 파일명 생성에서
`PhotosPickerItem.itemIdentifier`를 그대로 쓰는 부분이 문제이며, 슬래시가 포함되면
`appendingPathComponent`가 하위 경로로 해석되어 `compressed.write(to:)`가 실패할 수 있습니다.
`itemIdentifier`를 직접 파일명으로 쓰지 말고, `fileName`을 `UUID()` 기반 값이나 안전하게 sanitize된
문자열로 생성하도록 바꿔서 `destURL` 생성과 저장이 항상 유효한 단일 파일 경로가 되게 수정하세요.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 44f72039-7d87-4a3a-9465-fc0ba1f35050

📥 Commits

Reviewing files that changed from the base of the PR and between dcf4ea6 and d8d2a79.

📒 Files selected for processing (1)
  • Rephoto_iOS/Features/Home/Domain/Services/PhotoMetadataExtractor.swift

Comment thread Rephoto_iOS/Features/Home/Domain/Services/PhotoMetadataExtractor.swift Outdated
PhotosPickerItem.itemIdentifier가 'UUID/L0/001'처럼 슬래시를
포함하면 appendingPathComponent가 하위 경로로 해석해
write(to:)가 실패하고 사진이 누락됐다. 슬래시를 '_'로 치환.
@ddodle ddodle merged commit f71697f into main Jul 1, 2026
2 checks passed
@ddodle ddodle deleted the refactor/upload-image-compression branch July 1, 2026 07:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

♻️ Refactor: 업로드 이미지 다운샘플 + JPEG 압축 (ImageIO)

1 participant