5.2 KiB
5.2 KiB
이미지 크롭 범위 보정 PRD
문서 정보
| 항목 | 내용 |
|---|---|
| 문서 상태 | 구현 기준 확정 |
| 작성일 | 2026-08-03 |
| 최종 수정일 | 2026-08-03 |
| 대상 제품 | SodaLive 이미지 선택 후 크롭 편집기 |
| 관련 구현 계획 | docs/20260803_이미지_크롭_범위_보정/plan-task.md |
| 관련 과거 기록 | docs/plan-task/20260317_이미지등록크롭재구현.md, docs/plan-task/20260317_이미지선택크롭지연및미적용수정.md |
1. Overview
이미지를 선택한 뒤 표시되는 공통 ImageCropEditorView가 crop 비율에 맞는 원본 최대 범위를 사용하도록 보정한다. 외부 cropper 의존성은 추가하지 않고 현재 편집 흐름과 서버 전송 규격을 유지한다.
2. Problem Statement
- 고정 1:1 crop 영역은 canvas 최소 변의 72%로 계산되어 원본 표시 영역보다 불필요하게 작을 수 있다.
- 자유 crop 영역의 초기 크기와 최대 크기도 canvas 기준이라 원본 표시 영역과 일치하지 않는다.
- 따라서 crop 비율에 따라 원본의 가로 또는 세로 한 축 전체를 포함할 수 있어도 더 작은 영역만 잘린다.
문제 해결 여부는 세로·가로 이미지에서 현재 crop 비율을 유지하는 최대 사각형이 원본 표시 영역의 가로 또는 세로 한 축과 일치하는지로 판정한다.
3. Goals
- 어떤 crop 비율에서도 원본 표시 영역 안에 들어가는 최대 crop 사각형을 계산한다.
- 세로 이미지는 가능한 경우 표시된 이미지의 전체 가로를, 가로 이미지는 전체 세로를 crop 영역에 포함한다.
- 자유 crop은 최대 범위를 fitted image 기준으로 제한하면서 기존 모서리 resize 동작을 유지한다.
- 최종 crop 결과의 긴 변 최대 800px 정책과 기존 서버 multipart 경로를 유지한다.
4. Non-Goals
- 외부 cropper 라이브러리 추가 또는 기존 편집기 교체
- 새로운 crop 비율 선택 UI 추가
- 이미지 선택 화면, 업로드 API, multipart 필드 변경
- 회전, 반전, 원근 보정 기능 추가
5. 핵심 사용자 흐름
- 사용자가 기존 화면에서 이미지를 선택한다.
- 앱이 이미지를 정규화하고
ImageCropEditorView를 표시한다. - 편집기는 현재 crop 비율에 맞는 최대 영역을 fitted image 안에서 계산한다.
- 사용자가 이동·확대 또는 자유 crop resize 후 적용한다.
- 앱은 기존처럼 crop 결과를 긴 변 최대 800px로 축소해 각 ViewModel의 기존 업로드 경로로 전달한다.
6. 기능 요구사항
| ID | 상태 | 요구사항 | 수용 기준 |
|---|---|---|---|
CROP-001 |
확정 | crop 비율을 유지하는 최대 크기를 fitted image 안에서 계산한다. | 반환 rect의 가로 또는 세로가 fitted image의 같은 축과 일치하고 두 축 모두 경계를 넘지 않는다. |
CROP-002 |
확정 | 고정 1:1 crop에 최대 범위 계산을 적용한다. | 세로 이미지는 전체 가로, 가로 이미지는 전체 세로를 초기 crop 영역으로 사용한다. |
CROP-003 |
확정 | 자유 crop의 초기 영역과 resize 상한을 fitted image 기준으로 계산한다. | 초기 영역은 현재 기본 비율의 최대 크기이며 모서리 resize 결과가 fitted image 크기를 넘지 않는다. |
CROP-004 |
확정 | 최종 전송 이미지 크기 정책을 유지한다. | cropImage()가 계속 resizedToMaxDimension(800) 결과를 반환한다. |
CROP-005 |
확정 | 기존 호출부 계약을 유지한다. | ImageCropAspectPolicy, onCancel, onComplete(UIImage)와 5개 호출부 수정이 없다. |
7. 기술 제약
- iOS 16.6 이상, SwiftUI와 UIKit을 유지한다.
- geometry 계산은 UI와 분리된 순수 함수로 두어 독립 실행 검증이 가능해야 한다.
- 테스트 번들 타깃이 없는 현재 저장소 구조에서는
swiftc로 순수 geometry check를 실행한다. Pods/**,generated/**, 업로드 API는 수정하지 않는다.
8. 성공 기준
- 세로 fitted image
350x700, 비율1:1에서 crop 크기가350x350이다. - 가로 fitted image
400x200, 비율4:3에서 crop 크기가 약266.67x200이다. - fitted image와 crop 비율이 같으면 전체 fitted image 크기를 반환한다.
- 0 이하 크기 또는 비율은
.zero를 반환한다. - 자유 crop resize 상한이 fitted image를 넘지 않는다.
- 앱 빌드가 성공하고 최종 crop 결과의 긴 변 최대 800px 정책이 유지된다.
9. Open Questions
해당 없음.
10. Decision Log
| 날짜 | ID | 상태 | 결정 | 근거 | 영향 요구사항 |
|---|---|---|---|---|---|
| 2026-08-03 | DEC-001 |
확정 | 외부 라이브러리 대신 기존 cropper geometry를 보정한다. | 현재 문제는 공통 cropSize와 fitted image 경계 계산에서 발생하며 한 컴포넌트에서 해결 가능하다. |
CROP-001~005 |
| 2026-08-03 | DEC-002 |
확정 | 1:1은 예시이며 모든 crop 비율에 최대 fitted 영역 규칙을 적용한다. | 사용자 확인 | CROP-001~003 |
| 2026-08-03 | DEC-003 |
확정 | 최종 이미지 긴 변 최대 800px 정책을 유지한다. | 서버 전송 크기를 기존과 동일하게 유지한다는 사용자 확인 | CROP-004 |