-
Notifications
You must be signed in to change notification settings - Fork 0
feat: 썸네일 생성 및 callback API 구현 #31
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 External as 외부 서비스
participant Controller as PhotoCallbackController
participant Service as PhotoCallbackService
participant Repo as PhotoRepository
participant DB as Database
External->>Controller: POST /internal/thumbnail/complete\n{ photoId, thumbnailUrl }
Controller->>Service: markUploadCompleted(request)
Service->>Repo: updateStatusAndUrl(photoId, UPLOADING, COMPLETED, thumbnailUrl)
Repo->>DB: UPDATE photo SET status=COMPLETED, thumbnail_url=:thumbnailUrl\nWHERE id=:photoId AND status=UPLOADING
DB-->>Repo: 업데이트된 행 수 (n)
alt 성공 (n == 1)
Repo-->>Service: 1
Service-->>Controller: 정상 완료
Controller-->>External: 200 OK (THUMBNAIL_PRODUCE_COMPLETE)
else 실패 (n == 0)
Repo-->>Service: 0
Service-->>Service: PhotoException(THUMBNAIL_UPDATE_FAILED) 발생
Service-->>Controller: 예외 전파
Controller-->>External: 에러 응답
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. 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.
Actionable comments posted: 4
🧹 Nitpick comments (3)
src/main/java/com/cheeeese/photo/application/PhotoCallbackService.java (1)
7-7: Spring의 @transactional 사용 권장
jakarta.transaction.Transactional대신 Spring의@Transactional을 사용하는 것이 좋습니다. Spring의 버전은 더 많은 기능과 프레임워크 통합을 제공하며, 프로젝트의 다른 서비스 클래스들과 일관성을 유지할 수 있습니다.다음 diff를 적용하세요:
package com.cheeeese.photo.application; import com.cheeeese.photo.domain.PhotoStatus; import com.cheeeese.photo.exception.PhotoException; import com.cheeeese.photo.exception.code.PhotoErrorCode; import com.cheeeese.photo.infrastructure.persistence.PhotoRepository; -import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service @TransactionalAlso applies to: 12-12
src/main/java/com/cheeeese/photo/infrastructure/persistence/PhotoRepository.java (1)
35-35: @param 어노테이션 추가 권장명시성과 일관성을 위해 파라미터에
@Param어노테이션을 추가하는 것이 좋습니다. 기존 메서드(Lines 27-30)도 동일한 패턴을 따르고 있습니다.다음 diff를 적용하세요:
@Modifying(clearAutomatically = true, flushAutomatically = true) @Query("UPDATE Photo p SET p.status = :status WHERE p.id = :photoId") - int updateStatus(Long photoId, PhotoStatus status); + int updateStatus(@Param("photoId") Long photoId, @Param("status") PhotoStatus status);src/main/java/com/cheeeese/photo/presentation/PhotoCallbackController.java (1)
19-23: 로깅 추가 권장외부 시스템(NCP Object Storage)에서 호출되는 중요한 콜백 엔드포인트이므로, 감사(audit) 및 디버깅을 위한 로깅을 추가하는 것이 좋습니다. 최소한 다음 정보를 로깅해야 합니다:
- 요청 수신 (photoId)
- 처리 성공/실패
다음과 같이 로깅을 추가하세요:
package com.cheeeese.photo.presentation; import com.cheeeese.global.common.CommonResponse; import com.cheeeese.photo.dto.request.PhotoCompleteRequest; import com.cheeeese.photo.application.PhotoCallbackService; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import static com.cheeeese.global.common.code.SuccessCode.THUMBNAIL_PRODUCE_COMPLETE; +@Slf4j @RestController @RequestMapping("/internal/thumbnail") @RequiredArgsConstructor public class PhotoCallbackController { private final PhotoCallbackService photoCallbackService; @PostMapping("/complete") public CommonResponse<Void> completeUpload(@Valid @RequestBody PhotoCompleteRequest request) { + log.info("Received thumbnail completion callback for photoId: {}", request.photoId()); photoCallbackService.markUploadCompleted(request.photoId()); + log.info("Successfully marked photo as completed: {}", request.photoId()); return CommonResponse.success(THUMBNAIL_PRODUCE_COMPLETE); } }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
src/main/java/com/cheeeese/global/common/code/SuccessCode.java(1 hunks)src/main/java/com/cheeeese/global/config/SecurityConfig.java(1 hunks)src/main/java/com/cheeeese/photo/application/PhotoCallbackService.java(1 hunks)src/main/java/com/cheeeese/photo/dto/request/PhotoCompleteRequest.java(1 hunks)src/main/java/com/cheeeese/photo/infrastructure/persistence/PhotoRepository.java(1 hunks)src/main/java/com/cheeeese/photo/presentation/PhotoCallbackController.java(1 hunks)
🔇 Additional comments (2)
src/main/java/com/cheeeese/global/common/code/SuccessCode.java (1)
32-32: LGTM!새로운 성공 코드가 기존 패턴을 잘 따르고 있으며, 메시지도 명확합니다.
src/main/java/com/cheeeese/photo/application/PhotoCallbackService.java (1)
18-23: LGTM - 에러 처리가 적절합니다
updateStatus호출 후 업데이트된 행 수를 확인하여 존재하지 않는photoId에 대한 적절한 예외 처리를 하고 있습니다.
src/main/java/com/cheeeese/photo/infrastructure/persistence/PhotoRepository.java
Outdated
Show resolved
Hide resolved
src/main/java/com/cheeeese/photo/presentation/PhotoCallbackController.java
Outdated
Show resolved
Hide resolved
zyovn
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.
수고하셨습니다~~ 🎸
나도 이제 뺑이쳐야지...
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: 0
🧹 Nitpick comments (3)
src/main/java/com/cheeeese/photo/application/PhotoCallbackService.java (3)
8-8: Spring의@Transactional사용을 권장합니다.현재
jakarta.transaction.Transactional을 사용하고 있는데, Spring Boot 애플리케이션에서는 일반적으로org.springframework.transaction.annotation.Transactional을 사용합니다. Spring의 트랜잭션 관리가 더 많은 기능(전파 옵션, 격리 수준, 읽기 전용 등)을 제공하고 Spring 생태계와 더 잘 통합됩니다.다음 diff를 적용하여 Spring의 트랜잭션 애노테이션으로 변경하세요:
-import jakarta.transaction.Transactional; +import org.springframework.transaction.annotation.Transactional;Also applies to: 13-13
19-30: 콜백 재시도를 위한 멱등성(idempotency) 처리를 고려하세요.외부 시스템이 콜백을 재시도할 경우, 이미
COMPLETED상태인 사진에 대해 예외가 발생합니다. 또한updated == 0일 때 사진이 존재하지 않는 경우와 이미 완료된 경우를 구분하지 못합니다.다음과 같이 개선할 수 있습니다:
public void markUploadCompleted(PhotoCompleteRequest request) { + // 먼저 현재 상태 확인 + Photo photo = photoRepository.findById(request.photoId()) + .orElseThrow(() -> new PhotoException(PhotoErrorCode.PHOTO_NOT_FOUND)); + + // 이미 완료된 경우 멱등성 처리 + if (photo.getStatus() == PhotoStatus.COMPLETED) { + return; + } + int updated = photoRepository.updateStatusAndUrl( request.photoId(), PhotoStatus.PROCESSING, PhotoStatus.COMPLETED, request.thumbnailUrl() ); if (updated == 0) { throw new PhotoException(PhotoErrorCode.THUMBNAIL_UPDATE_FAILED); } }이렇게 하면:
- 이미 완료된 경우 재시도가 성공적으로 처리됨 (멱등성)
- 사진이 없는 경우와 상태가 맞지 않는 경우를 명확히 구분
19-30: 모니터링을 위한 로깅 추가를 고려하세요.외부 시스템으로부터의 콜백이므로, 디버깅과 모니터링을 위해 로그를 추가하는 것이 좋습니다.
+import lombok.extern.slf4j.Slf4j; + +@Slf4j @Service @Transactional @RequiredArgsConstructor public class PhotoCallbackService { private final PhotoRepository photoRepository; public void markUploadCompleted(PhotoCompleteRequest request) { + log.info("Thumbnail completion callback received for photoId: {}", request.photoId()); + int updated = photoRepository.updateStatusAndUrl( request.photoId(), PhotoStatus.PROCESSING, PhotoStatus.COMPLETED, request.thumbnailUrl() ); if (updated == 0) { + log.warn("Failed to update photo status for photoId: {}", request.photoId()); throw new PhotoException(PhotoErrorCode.THUMBNAIL_UPDATE_FAILED); } + + log.info("Photo status updated to COMPLETED for photoId: {}", request.photoId()); } }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/main/java/com/cheeeese/photo/application/PhotoCallbackService.java(1 hunks)
🔗 연관된 이슈
🚀 변경 유형
📝 작업 내용
album/{albumCode}/thumbnail/{photoId}_{imageName}으로 저장📸 스크린샷
💬 리뷰 요구사항
Summary by CodeRabbit