-
Notifications
You must be signed in to change notification settings - Fork 0
[Refactor] 이미지 도메인 객체 도입 #101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Walkthrough이미지 파일 처리 로직이 대대적으로 리팩토링되었습니다. 도메인 객체 Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant ImageService
participant ImageStorage
participant ExternalImageStorage
participant FileClient
participant AWS_S3
Client->>ImageService: 이미지 업로드 요청 (Image)
ImageService->>ImageStorage: upload(Image)
ImageStorage->>ExternalImageStorage: upload(Image)
ExternalImageStorage->>FileClient: upload(MultipartFile, key)
FileClient->>AWS_S3: S3 putObject
AWS_S3-->>FileClient: 업로드 결과 반환
FileClient-->>ExternalImageStorage: key 반환
ExternalImageStorage-->>ImageStorage: ImageKey 반환
ImageStorage-->>ImageService: ImageKey 반환
Client->>ImageService: presigned URL 요청 (ImageKey)
ImageService->>ImageStorage: getPreSignedUrl(ImageKey)
ImageStorage->>CachePreSignedUrlStorage: get(ImageKey)
alt 캐시에 없음
ImageStorage->>ExternalImageStorage: getPreSignedUrl(ImageKey)
ExternalImageStorage->>FileClient: getPreSignedUrl(key, duration)
FileClient->>AWS_S3: presignGetObject
AWS_S3-->>FileClient: presigned URL 반환
FileClient-->>ExternalImageStorage: URL 반환
ExternalImageStorage-->>ImageStorage: URL 반환
ImageStorage->>CachePreSignedUrlStorage: put(ImageKey, URL)
ImageStorage-->>ImageService: URL 반환
else 캐시에 있음
CachePreSignedUrlStorage-->>ImageStorage: URL 반환
ImageStorage-->>ImageService: URL 반환
end
Estimated code review effort4 (~90분) Possibly related PRs
Suggested labels
Poem
✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (5)
src/main/java/eatda/client/file/FileClient.java (2)
31-47: 파일 업로드 로직에서 리소스 관리를 개선하세요.현재 구현에서
file.getInputStream()이 예외 발생 시 적절히 닫히지 않을 수 있습니다. AWS SDK의RequestBody.fromInputStream()은 스트림을 자동으로 관리하지만, 명시적인 리소스 관리가 더 안전합니다.public String upload(MultipartFile file, String fileKey) { PutObjectRequest request = PutObjectRequest.builder() .bucket(bucket) .key(fileKey) .contentType(file.getContentType()) .build(); try { - s3Client.putObject(request, RequestBody.fromInputStream(file.getInputStream(), file.getSize())); + try (var inputStream = file.getInputStream()) { + s3Client.putObject(request, RequestBody.fromInputStream(inputStream, file.getSize())); + } return fileKey; } catch (Exception exception) { throw new BusinessException(BusinessErrorCode.FILE_UPLOAD_FAILED); } }
44-46: TODO 주석의 구체적인 예외 처리 계획을 확인하세요.AWS SDK의 구체적인 예외들에 대한 처리 계획이 명시되어 있습니다. 이러한 세분화된 예외 처리가 언제 구현될 예정인지 확인이 필요합니다.
구체적인 AWS 예외 처리 구현을 도와드릴까요? 새로운 이슈를 생성하여 이 작업을 추적하시겠습니까?
src/test/java/eatda/storage/image/CachePreSignedUrlStorageTest.java (1)
31-40: ImageKey 래퍼 사용이 적절하지만 키 형식 검증을 고려해보세요.ImageKey로 래핑하여 캐시 작업을 수행하는 것은 도메인 주도 설계 관점에서 좋습니다. 그러나 하드코딩된 키 형식("story/550e8400-e29b-41d4-a716-446655440000.jpg")이 실제 ImageKey의 유효성 검증 로직과 일치하는지 확인이 필요합니다.
테스트에서 더 명확한 키 형식을 사용하거나, ImageKey 생성을 위한 테스트 헬퍼 메서드를 고려해보세요:
- String key = "story/550e8400-e29b-41d4-a716-446655440000.jpg"; + String key = ImageTestFixture.createValidImageKey();src/main/java/eatda/domain/Image.java (2)
26-30: Content Type 검증 로직을 개선해보세요.현재 검증 로직은 file이 null이 아닐 때만 content type을 검사합니다. 하지만 더 포괄적인 이미지 MIME 타입 지원을 고려해보세요.
다음과 같이 개선할 수 있습니다:
- private static final Set<String> ALLOWED_CONTENT_TYPES = Set.of("image/jpg", "image/jpeg", "image/png"); + private static final Set<String> ALLOWED_CONTENT_TYPES = Set.of("image/jpeg", "image/jpg", "image/png", "image/webp");참고: "image/jpg"는 표준이 아니므로 "image/jpeg"만 사용하는 것이 좋습니다.
32-41: 파일 확장자 추출 로직이 복잡합니다.확장자 추출 로직이 다양한 엣지 케이스를 처리하고 있지만, 복잡성이 높아 테스트와 유지보수가 어려울 수 있습니다.
더 명확한 로직으로 리팩토링을 고려해보세요:
public String getExtension() { + if (file == null) { + return DEFAULT_CONTENT_TYPE; + } String filename = file.getOriginalFilename(); - if (filename == null - || filename.lastIndexOf(EXTENSION_DELIMITER) == -1 - || filename.startsWith(EXTENSION_DELIMITER) - || filename.endsWith(EXTENSION_DELIMITER)) { + if (filename == null || !isValidFilename(filename)) { return DEFAULT_CONTENT_TYPE; } return filename.substring(filename.lastIndexOf(EXTENSION_DELIMITER) + 1); } +private boolean isValidFilename(String filename) { + int lastDotIndex = filename.lastIndexOf(EXTENSION_DELIMITER); + return lastDotIndex > 0 && lastDotIndex < filename.length() - 1; +}
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (33)
src/main/java/eatda/client/file/FileClient.java(1 hunks)src/main/java/eatda/domain/Image.java(1 hunks)src/main/java/eatda/domain/ImageKey.java(1 hunks)src/main/java/eatda/domain/article/Article.java(2 hunks)src/main/java/eatda/domain/store/Cheer.java(3 hunks)src/main/java/eatda/domain/story/Story.java(7 hunks)src/main/java/eatda/repository/store/CheerRepository.java(2 hunks)src/main/java/eatda/service/article/ArticleService.java(1 hunks)src/main/java/eatda/service/store/CheerService.java(3 hunks)src/main/java/eatda/service/store/StoreService.java(1 hunks)src/main/java/eatda/service/story/StoryService.java(4 hunks)src/main/java/eatda/storage/image/CachePreSignedUrlStorage.java(2 hunks)src/main/java/eatda/storage/image/ExternalImageStorage.java(1 hunks)src/main/java/eatda/storage/image/ImageStorage.java(3 hunks)src/test/java/eatda/client/file/FileClientTest.java(1 hunks)src/test/java/eatda/controller/BaseControllerTest.java(3 hunks)src/test/java/eatda/controller/store/CheerControllerTest.java(1 hunks)src/test/java/eatda/controller/story/StoryControllerTest.java(1 hunks)src/test/java/eatda/document/store/CheerDocumentTest.java(2 hunks)src/test/java/eatda/document/story/StoryDocumentTest.java(1 hunks)src/test/java/eatda/domain/ImageKeyTest.java(1 hunks)src/test/java/eatda/domain/ImageTest.java(1 hunks)src/test/java/eatda/domain/store/CheerTest.java(2 hunks)src/test/java/eatda/domain/story/StoryTest.java(4 hunks)src/test/java/eatda/fixture/ArticleGenerator.java(2 hunks)src/test/java/eatda/fixture/CheerGenerator.java(4 hunks)src/test/java/eatda/repository/store/CheerRepositoryTest.java(3 hunks)src/test/java/eatda/service/BaseServiceTest.java(3 hunks)src/test/java/eatda/service/store/CheerServiceTest.java(1 hunks)src/test/java/eatda/service/story/StoryServiceTest.java(6 hunks)src/test/java/eatda/storage/image/CachePreSignedUrlStorageTest.java(1 hunks)src/test/java/eatda/storage/image/ExternalImageStorageTest.java(1 hunks)src/test/java/eatda/storage/image/ImageStorageTest.java(2 hunks)
🧠 Learnings (5)
src/test/java/eatda/service/store/CheerServiceTest.java (1)
Learnt from: leegwichan
PR: #90
File: src/main/java/eatda/service/store/CheerService.java:35-46
Timestamp: 2025-07-20T05:38:13.430Z
Learning: CheerService에서 각 컴포넌트(storeSearchFilter, memberRepository, imageService)들이 자신의 책임 범위 내에서 검증을 수행하므로 서비스 레이어에서 추가적인 중복 검증이 불필요함. 각 레이어의 책임 분리가 잘 되어 있는 구조.
src/main/java/eatda/service/store/CheerService.java (1)
Learnt from: leegwichan
PR: #90
File: src/main/java/eatda/service/store/CheerService.java:35-46
Timestamp: 2025-07-20T05:38:13.430Z
Learning: CheerService에서 각 컴포넌트(storeSearchFilter, memberRepository, imageService)들이 자신의 책임 범위 내에서 검증을 수행하므로 서비스 레이어에서 추가적인 중복 검증이 불필요함. 각 레이어의 책임 분리가 잘 되어 있는 구조.
src/test/java/eatda/fixture/CheerGenerator.java (1)
Learnt from: lvalentine6
PR: #76
File: src/main/java/eatda/domain/store/Cheer.java:50-61
Timestamp: 2025-07-15T09:42:54.091Z
Learning: Cheer 엔티티의 생성자는 데이터베이스 시딩을 위해 의도적으로 ID 매개변수를 받도록 설계되었습니다. 시드 데이터에서 명시적으로 ID를 설정하기 때문에 이 패턴이 필요합니다.
src/test/java/eatda/controller/BaseControllerTest.java (1)
Learnt from: leegwichan
PR: #60
File: src/main/java/eatda/client/map/MapClient.java:24-41
Timestamp: 2025-07-09T07:54:18.446Z
Learning: In MapClient.java, the developer prefers to keep Kakao API-specific values (baseUrl, pageSize) hardcoded rather than extracting them to configuration properties, as these values are inherently tied to the Kakao API specification.
src/test/java/eatda/domain/ImageTest.java (1)
Learnt from: lvalentine6
PR: #68
File: src/main/java/eatda/service/common/ImageService.java:24-24
Timestamp: 2025-07-09T20:11:28.800Z
Learning: ImageService에서 MIME 타입 검증 시 "image/jpg"와 "image/jpeg" 모두 허용해야 함. "image/jpg"는 비표준이지만 실제 환경에서 여전히 사용되어 호환성 문제 방지를 위해 두 타입 모두 지원하는 것이 실용적임.
🧬 Code Graph Analysis (6)
src/test/java/eatda/controller/store/CheerControllerTest.java (1)
src/test/java/eatda/util/ImageUtils.java (1)
ImageUtils(8-22)
src/test/java/eatda/controller/story/StoryControllerTest.java (1)
src/test/java/eatda/util/ImageUtils.java (1)
ImageUtils(8-22)
src/test/java/eatda/document/story/StoryDocumentTest.java (1)
src/test/java/eatda/util/ImageUtils.java (1)
ImageUtils(8-22)
src/test/java/eatda/document/store/CheerDocumentTest.java (1)
src/test/java/eatda/util/ImageUtils.java (1)
ImageUtils(8-22)
src/main/java/eatda/storage/image/ExternalImageStorage.java (2)
src/main/java/eatda/storage/image/ImageStorage.java (1)
Component(10-44)src/main/java/eatda/storage/image/CachePreSignedUrlStorage.java (1)
Component(10-28)
src/main/java/eatda/domain/ImageKey.java (1)
src/main/java/eatda/domain/Image.java (1)
Getter(10-50)
🧰 Additional context used
🧠 Learnings (5)
src/test/java/eatda/service/store/CheerServiceTest.java (1)
Learnt from: leegwichan
PR: #90
File: src/main/java/eatda/service/store/CheerService.java:35-46
Timestamp: 2025-07-20T05:38:13.430Z
Learning: CheerService에서 각 컴포넌트(storeSearchFilter, memberRepository, imageService)들이 자신의 책임 범위 내에서 검증을 수행하므로 서비스 레이어에서 추가적인 중복 검증이 불필요함. 각 레이어의 책임 분리가 잘 되어 있는 구조.
src/main/java/eatda/service/store/CheerService.java (1)
Learnt from: leegwichan
PR: #90
File: src/main/java/eatda/service/store/CheerService.java:35-46
Timestamp: 2025-07-20T05:38:13.430Z
Learning: CheerService에서 각 컴포넌트(storeSearchFilter, memberRepository, imageService)들이 자신의 책임 범위 내에서 검증을 수행하므로 서비스 레이어에서 추가적인 중복 검증이 불필요함. 각 레이어의 책임 분리가 잘 되어 있는 구조.
src/test/java/eatda/fixture/CheerGenerator.java (1)
Learnt from: lvalentine6
PR: #76
File: src/main/java/eatda/domain/store/Cheer.java:50-61
Timestamp: 2025-07-15T09:42:54.091Z
Learning: Cheer 엔티티의 생성자는 데이터베이스 시딩을 위해 의도적으로 ID 매개변수를 받도록 설계되었습니다. 시드 데이터에서 명시적으로 ID를 설정하기 때문에 이 패턴이 필요합니다.
src/test/java/eatda/controller/BaseControllerTest.java (1)
Learnt from: leegwichan
PR: #60
File: src/main/java/eatda/client/map/MapClient.java:24-41
Timestamp: 2025-07-09T07:54:18.446Z
Learning: In MapClient.java, the developer prefers to keep Kakao API-specific values (baseUrl, pageSize) hardcoded rather than extracting them to configuration properties, as these values are inherently tied to the Kakao API specification.
src/test/java/eatda/domain/ImageTest.java (1)
Learnt from: lvalentine6
PR: #68
File: src/main/java/eatda/service/common/ImageService.java:24-24
Timestamp: 2025-07-09T20:11:28.800Z
Learning: ImageService에서 MIME 타입 검증 시 "image/jpg"와 "image/jpeg" 모두 허용해야 함. "image/jpg"는 비표준이지만 실제 환경에서 여전히 사용되어 호환성 문제 방지를 위해 두 타입 모두 지원하는 것이 실용적임.
🧬 Code Graph Analysis (6)
src/test/java/eatda/controller/store/CheerControllerTest.java (1)
src/test/java/eatda/util/ImageUtils.java (1)
ImageUtils(8-22)
src/test/java/eatda/controller/story/StoryControllerTest.java (1)
src/test/java/eatda/util/ImageUtils.java (1)
ImageUtils(8-22)
src/test/java/eatda/document/story/StoryDocumentTest.java (1)
src/test/java/eatda/util/ImageUtils.java (1)
ImageUtils(8-22)
src/test/java/eatda/document/store/CheerDocumentTest.java (1)
src/test/java/eatda/util/ImageUtils.java (1)
ImageUtils(8-22)
src/main/java/eatda/storage/image/ExternalImageStorage.java (2)
src/main/java/eatda/storage/image/ImageStorage.java (1)
Component(10-44)src/main/java/eatda/storage/image/CachePreSignedUrlStorage.java (1)
Component(10-28)
src/main/java/eatda/domain/ImageKey.java (1)
src/main/java/eatda/domain/Image.java (1)
Getter(10-50)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: test
🔇 Additional comments (60)
src/main/java/eatda/client/file/FileClient.java (2)
23-29: 생성자 구현이 깔끔합니다.의존성 주입이 적절하게 구현되어 있고,
@Value어노테이션을 통한 설정값 주입도 올바릅니다.
49-64: PreSigned URL 생성 로직이 적절합니다.메서드 구현이 깔끔하고 예외 처리도 일관성 있게 되어 있습니다.
src/main/java/eatda/service/article/ArticleService.java (1)
27-27: 메서드 명명 변경 일관성 확인 및 승인
- 코드베이스 전체에서
getPresignedUrl호출이 완전히 제거됨을 확인했습니다.- 모든 위치에서
getPreSignedUrl로 일관되게 적용되었습니다.승인합니다.
src/test/java/eatda/document/story/StoryDocumentTest.java (1)
71-71: 테스트 개선: 명시적 MIME 타입 지정이 좋습니다.
multiPart호출에 명시적으로"image/png"MIME 타입을 지정한 것이 테스트의 정확성을 향상시킵니다. 실제 HTTP 요청과 더 유사한 환경을 만들어줍니다.src/test/java/eatda/service/store/CheerServiceTest.java (1)
124-124: 테스트 로직 수정이 정확합니다.이미지가 제공되지 않은 경우(
null파라미터)imageUrl()이null이어야 한다는 것이 논리적으로 맞습니다. 이전의isNotNull()검증은 잘못된 것이었습니다.src/test/java/eatda/controller/store/CheerControllerTest.java (1)
30-30: 테스트 개선: 명시적 MIME 타입 지정이 좋습니다.다른 테스트 파일들과 일관되게
multiPart호출에 명시적으로"image/png"MIME 타입을 지정한 것이 테스트의 정확성을 향상시킵니다.src/main/java/eatda/service/store/StoreService.java (1)
41-41: 메서드 명 변경이 올바르게 적용되었습니다.
getPresignedUrl에서getPreSignedUrl로의 메서드 명 변경이 일관성 있게 적용되어 camelCase 명명 규칙을 따르고 있습니다.src/test/java/eatda/controller/story/StoryControllerTest.java (1)
45-45: 멀티파트 이미지 업로드에 MIME 타입이 명시적으로 지정되었습니다.
"image/png"컨텐츠 타입을 명시적으로 지정하여 테스트의 정확성이 향상되었습니다. 실제 환경에서의 동작을 더 정확하게 모사합니다.src/test/java/eatda/document/store/CheerDocumentTest.java (1)
79-79: 문서화 테스트에서 이미지 MIME 타입이 명시적으로 지정되었습니다.두 테스트 메서드 모두에서
"image/png"컨텐츠 타입을 명시적으로 지정하여 API 문서화의 정확성이 향상되었습니다. API 사용자에게 더 명확한 예시를 제공합니다.Also applies to: 108-108
src/test/java/eatda/domain/store/CheerTest.java (1)
7-7: 도메인 객체 ImageKey 사용으로 타입 안전성이 향상되었습니다.원시 문자열 대신
ImageKey객체를 사용하여 도메인 모델의 캡슐화와 타입 안전성이 개선되었습니다. 테스트는 새로운 도메인 모델을 올바르게 반영합니다.Also applies to: 37-40
src/test/java/eatda/controller/BaseControllerTest.java (1)
14-14: 테스트 인프라가 새로운 도메인 모델에 맞게 업데이트되었습니다.
ImageKey도메인 객체 사용, 메서드 명 변경(getPreSignedUrl), 그리고 업데이트된 메서드 시그니처에 맞는 Mock 설정이 올바르게 적용되었습니다. 모든 컨트롤러 테스트가 새로운 도메인 모델과 일관되게 작동할 수 있습니다.Also applies to: 50-50, 117-118
src/test/java/eatda/repository/store/CheerRepositoryTest.java (1)
5-5: 리팩토링이 일관되게 적용되었습니다.
ImageKey도메인 객체 도입에 따라 테스트 코드가 올바르게 업데이트되었습니다. 타입 안전성이 개선되고 도메인 모델과 일치합니다.Also applies to: 27-27, 29-29, 40-40
src/main/java/eatda/repository/store/CheerRepository.java (1)
3-3: 레포지토리 인터페이스가 올바르게 업데이트되었습니다.
ImageKey도메인 객체 사용으로 타입 안전성이 향상되었으며, JPQL 쿼리는 JPA가 임베디드 타입을 자동으로 처리하므로 수정이 불필요합니다.Also applies to: 24-24
src/test/java/eatda/fixture/CheerGenerator.java (2)
3-3: 리팩토링이 적절히 적용되었습니다.
ImageKey도메인 객체 사용으로 테스트 픽스처가 일관되게 업데이트되었습니다. 상수명 변경도 더 명확한 의미를 전달합니다.Also applies to: 13-13, 23-23
31-33:ImageKey생성자 null 안전성 확인 완료
new ImageKey(null)시 예외가 발생하지 않으며,isEmpty()메서드가value == null을 커버하므로 NPE 우려가 없습니다.
현재 구현대로 유지하셔도 무방합니다.src/test/java/eatda/fixture/ArticleGenerator.java (1)
3-3: 리팩토링이 일관되게 적용되었습니다.
ImageKey도메인 객체 도입에 맞춰 테스트 픽스처가 올바르게 업데이트되었습니다. 타입 안전성이 개선되었습니다.Also applies to: 39-39
src/main/java/eatda/storage/image/CachePreSignedUrlStorage.java (1)
3-3: 캐시 레이어 리팩토링이 올바르게 구현되었습니다.
ImageKey도메인 객체를 사용하여 타입 안전성을 확보하면서도, 내부적으로는getValue()를 통해 실제 문자열 값을 사용하여 캐시와의 호환성을 유지했습니다. 깔끔한 구현입니다.Also applies to: 21-22, 25-26
src/test/java/eatda/domain/ImageKeyTest.java (1)
10-38: 테스트 커버리지가 포괄적이고 잘 구성되어 있습니다.
ImageKey의isEmpty()메서드에 대한 테스트가 다양한 케이스를 잘 다루고 있습니다:
- null, 빈 문자열, 공백 문자열 등 빈 값 케이스
- UUID 기반의 유효한 이미지 키 케이스
- 매개변수화된 테스트를 통한 효율적인 테스트 구조
src/main/java/eatda/domain/ImageKey.java (1)
10-42: 잘 설계된 값 객체입니다.
ImageKey클래스가 JPA 임베디드 값 객체로서 올바르게 구현되었습니다:
- 적절한 JPA 어노테이션 사용 (
@Embeddable,@Column)isBlank()메서드로 null과 공백 처리Objects유틸리티를 사용한 올바른equals/hashCode구현- 값 객체 패턴에 맞는 불변성 보장
src/test/java/eatda/service/BaseServiceTest.java (1)
9-9: 도메인 모델 리팩토링에 맞춰 테스트 기반 클래스가 일관되게 업데이트되었습니다.
MOCKED_IMAGE_KEY가String에서ImageKey인스턴스로 변경- Mock 설정이 새로운 메서드 시그니처에 맞춰 조정 (
getPreSignedUrl,upload메서드)- 매개변수 매처도 도메인 타입에 맞게 수정
Also applies to: 29-29, 67-68
src/main/java/eatda/domain/article/Article.java (1)
4-4: 엔티티가 도메인 값 객체 사용에 맞춰 일관되게 리팩토링되었습니다.
Article엔티티의imageKey필드가 원시String에서ImageKey임베디드 값 객체로 변경되어:
- 타입 안전성 향상
- JPA
@Embedded어노테이션으로 적절한 매핑@NotNull제약조건으로 데이터 무결성 보장- 다른 엔티티들(
Story,Cheer)과 일관된 패턴 적용Also applies to: 6-6, 12-12, 36-38, 40-40
src/main/java/eatda/service/store/CheerService.java (1)
9-11: 서비스 레이어가 도메인 중심 설계에 맞춰 잘 리팩토링되었습니다.개선된 사항들:
- 매개변수 이름 명확화 (
image→imageFile)Image도메인 객체로 파일과 도메인 컨텍스트 캡슐화ImageKey반환 타입으로 타입 안전성 향상- 메서드명 일관성 개선 (
getPreSignedUrl)기존 비즈니스 로직을 유지하면서 도메인 모델과 타입 안전성이 크게 개선되었습니다.
Also applies to: 42-42, 48-48, 53-53, 74-74
src/test/java/eatda/storage/image/CachePreSignedUrlStorageTest.java (2)
15-25: 테스트 설정이 적절합니다.CachePreSignedUrlStorage의 테스트를 위한 설정이 올바르게 구성되어 있습니다. SimpleCacheManager와 ConcurrentMapCache를 사용한 테스트 환경 구성이 적절합니다.
42-49: 존재하지 않는 키에 대한 테스트가 적절합니다.빈 Optional 반환을 확인하는 네거티브 테스트 케이스가 잘 구현되어 있습니다. 캐시 미스 상황을 적절히 검증합니다.
src/main/java/eatda/domain/Image.java (2)
10-24: 도메인 객체 설계가 우수합니다.Image 도메인 객체가 잘 설계되었습니다. ImageDomain과 MultipartFile을 캡슐화하고 적절한 검증 로직을 포함하고 있습니다.
47-49: isEmpty 메서드가 적절합니다.파일의 존재 여부와 비어있는지를 적절히 검사하는 로직입니다.
src/main/java/eatda/service/story/StoryService.java (4)
10-12: 새로운 도메인 객체 임포트가 적절합니다.Image와 ImageKey 도메인 객체를 임포트하여 도메인 주도 설계를 잘 적용했습니다.
41-45: Image 도메인 객체 사용이 우수합니다.ImageDomain.STORY와 함께 Image 객체를 생성하여 도메인 컨텍스트를 명확히 하고, ImageKey를 반환받는 구조가 잘 설계되었습니다. 매개변수명도 'imageFile'로 더 명확해졌습니다.
86-86: 메서드명 변경이 일관성을 높입니다.getPreSignedUrl로 메서드명이 변경되어 네이밍 일관성이 개선되었습니다.
104-104: ImageKey 사용으로 타입 안전성이 향상되었습니다.ImageKey 객체를 사용하여 원시 문자열 대신 타입 안전한 방식으로 이미지 키를 처리하고 있습니다.
src/test/java/eatda/service/story/StoryServiceTest.java (5)
13-13: ImageKey 임포트로 도메인 객체 일관성 확보ImageDomain 대신 ImageKey를 임포트하여 리팩토링된 도메인 모델과 일치합니다.
40-42: MockMultipartFile 사용이 개선되었습니다.명시적인 MIME 타입("image/jpeg")을 지정한 MockMultipartFile 사용으로 더 현실적인 테스트 환경을 구성했습니다.
83-84: ImageKey 래퍼 사용이 적절합니다.원시 문자열 대신 ImageKey 객체를 사용하여 타입 안전성을 확보했습니다.
93-94: 테스트 데이터 생성에서 ImageKey 일관성 유지Story 엔티티 생성 시 ImageKey 객체를 사용하여 도메인 모델 변경사항과 일치합니다.
126-127: 모킹 업데이트가 정확합니다.getPreSignedUrl 메서드명 변경과 ImageKey 매개변수 사용이 실제 구현과 일치하도록 모킹이 적절히 업데이트되었습니다.
src/main/java/eatda/domain/store/Cheer.java (4)
4-4: ImageKey 도메인 객체 임포트가 적절합니다.ImageKey 임포트로 도메인 주도 설계를 위한 값 객체 사용을 준비했습니다.
43-44: JPA @Embedded 사용이 우수합니다.@column 대신 @Embedded를 사용하여 ImageKey 값 객체를 적절히 임베드했습니다. 이는 도메인 모델의 응집성을 높이는 좋은 설계입니다.
49-57: 생성자 업데이트가 일관성 있습니다.ImageKey 매개변수를 받도록 생성자가 적절히 업데이트되었습니다. ImageKey 자체에서 검증을 담당하므로 별도의 imageKey 검증 로직 제거가 적절합니다.
59-62: 관리자 권한 생성자도 일관성 있게 업데이트ImageKey를 사용하는 관리자 권한 생성자도 적절히 업데이트되어 전체적인 일관성을 유지합니다.
src/main/java/eatda/domain/story/Story.java (1)
60-62: ImageKey 도메인 객체 도입이 적절합니다.값 객체(Value Object)로 ImageKey를 도입하고 @Embedded를 사용한 것은 도메인 중심 설계 원칙에 잘 부합합니다. 검증 로직도 ImageKey의
isEmpty()메서드를 활용하여 책임이 적절히 분리되었습니다.Also applies to: 150-154
src/test/java/eatda/domain/ImageTest.java (1)
17-79: Image 도메인 객체에 대한 테스트가 포괄적입니다.이미지 타입 검증과 확장자 추출 로직에 대한 테스트가 잘 작성되었습니다. 특히 "image/jpg"와 "image/jpeg" 모두를 지원하는 것과 엣지 케이스(확장자가 없거나 잘못된 형식)에 대한 처리가 적절합니다.
src/test/java/eatda/storage/image/ExternalImageStorageTest.java (1)
21-43: FileClient 추상화를 통한 테스트 개선이 우수합니다.AWS SDK에 대한 직접적인 의존성을 제거하고 FileClient 추상화를 사용하여 테스트가 더 간결하고 유지보수하기 쉬워졌습니다. ImageKey 형식 검증을 위한 정규식 패턴 매칭도 적절합니다.
src/main/java/eatda/storage/image/ImageStorage.java (1)
17-43: 도메인 객체를 활용한 리팩토링이 잘 구현되었습니다.Image와 ImageKey 도메인 객체를 사용하여 타입 안전성이 향상되었고, null/empty 케이스 처리가 적절합니다. 캐싱 로직도 그대로 유지되어 성능 측면에서도 문제가 없습니다.
src/test/java/eatda/storage/image/ImageStorageTest.java (1)
33-112: 도메인 객체를 활용한 테스트 업데이트가 완벽합니다.Image와 ImageKey 도메인 객체를 사용하도록 테스트가 잘 업데이트되었습니다. 캐시 동작, null/empty 처리, 그리고 외부 저장소와의 상호작용이 모두 적절히 검증되고 있습니다.
src/test/java/eatda/client/file/FileClientTest.java (6)
29-42: 테스트 설정이 잘 구성되어 있습니다.FileClient의 의존성들을 적절히 모킹하고 있으며, 테스트 격리가 잘 되어 있습니다.
47-57: 파일 업로드 성공 케이스 테스트가 적절합니다.MockMultipartFile을 사용하여 파일 업로드를 테스트하고 있으며, 반환값 검증도 올바르게 수행하고 있습니다.
59-69: 예외 처리 테스트가 잘 구현되어 있습니다.SdkClientException 발생 시 BusinessException으로 적절히 변환되는지 검증하고 있으며, 에러 코드도 정확히 확인하고 있습니다.
75-84: PreSigned URL 생성 테스트가 올바르게 구현되어 있습니다.모킹을 통해 URL 생성을 테스트하고 있으며, Duration 파라미터도 적절히 전달하고 있습니다.
86-90: 헬퍼 메서드가 테스트 가독성을 향상시킵니다.PresignedGetObjectRequest 모킹을 위한 헬퍼 메서드가 테스트 코드의 중복을 줄이고 가독성을 개선합니다.
92-102: PreSigned URL 생성 실패 시나리오도 적절히 테스트되고 있습니다.예외 발생 시 올바른 BusinessException과 에러 코드가 반환되는지 검증하고 있습니다.
src/main/java/eatda/storage/image/ExternalImageStorage.java (4)
17-21: 생성자 리팩토링이 의존성 관리를 개선했습니다.FileClient를 주입받아 AWS SDK 의존성을 추상화했으며, 단일 책임 원칙을 잘 따르고 있습니다.
23-27: 업로드 메서드가 도메인 객체를 잘 활용하고 있습니다.Image 도메인 객체에서 도메인명과 확장자를 추출하여 키를 생성하고, FileClient에 위임하는 구조가 깔끔합니다. ImageKey 반환도 적절합니다.
29-32: 키 생성 로직이 명확하고 일관성 있습니다.UUID를 사용한 고유 키 생성과 도메인명/확장자를 조합한 경로 구조가 잘 설계되어 있습니다.
34-36: PreSigned URL 생성이 도메인 객체를 적절히 활용합니다.ImageKey 도메인 객체를 받아 값을 추출하고 고정된 Duration으로 FileClient에 위임하는 구조가 일관성 있습니다.
src/test/java/eatda/domain/story/StoryTest.java (6)
22-35: 공통 빌더 설정이 테스트 코드 중복을 효과적으로 제거했습니다.@beforeeach에서 defaultStoryBuilder를 설정하여 모든 테스트에서 재사용할 수 있도록 했으며, 새로운 ImageKey 도메인 객체도 적절히 사용하고 있습니다.
65-74: 매개변수화된 테스트로 검증 로직이 개선되었습니다.@ParameterizedTest와 @NullAndEmptySource, @valuesource를 사용하여 null, 빈 문자열, 공백 문자열에 대한 검증을 효율적으로 테스트하고 있습니다.
76-85: 가게 이름 검증도 매개변수화된 테스트로 잘 구현되었습니다.동일한 패턴으로 가게 이름 검증 테스트를 구현하여 일관성을 유지하고 있습니다.
96-105: 지번 주소 검증 테스트도 일관된 패턴을 따르고 있습니다.매개변수화된 테스트 패턴을 일관되게 적용하여 코드 중복을 줄이고 가독성을 향상시켰습니다.
120-129: 설명 검증 테스트도 매개변수화된 테스트로 개선되었습니다.동일한 검증 패턴을 설명 필드에도 적용하여 테스트 일관성을 유지하고 있습니다.
132-138: 이미지 키 검증이 도메인 객체를 적절히 활용합니다.ImageKey를 null로 설정하여 빈 이미지 검증을 테스트하고 있으며, 새로운 도메인 모델과 일치합니다.
lvalentine6
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이번 PR도 고생하셨습니다! 🎉
회의에서 논의된 내용들이 잘 반영되어 있는것 같아요
LGTM입니다!
|
🎉 This PR is included in version 1.4.0-develop.29 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
|
🎉 This PR is included in version 1.5.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |



✨ 개요
🧾 관련 이슈
closed #96
🔍 참고 사항 (선택)
Summary by CodeRabbit
신규 기능
Image,ImageKey) 추가 및 이미지 유형·확장자 검증 기능 제공버그 수정
리팩터링
ImageKey)로 대체테스트
스타일
문서화