[FEAT] 푸드트럭 메뉴 수정/삭제 API 구현#43
Conversation
Walkthrough푸드트럭 메뉴 수정/삭제 기능이 추가되었습니다. 도메인(Menu)에 업데이트 메서드가 생기고, OwnerController/OwnerService/MyFoodTruckMenuService에 수정/삭제 흐름이 추가되었습니다. 요청 DTO(UpdateMenuRequest)와 Swagger 응답 설명 항목이 신규로 포함되었습니다. 삭제 시 S3 이미지 삭제 처리도 포함됩니다. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor Owner as Owner
participant C as OwnerController
participant S as OwnerService
participant M as MyFoodTruckMenuService
participant R as Repositories
participant D as Domain(Menu)
rect rgba(200,230,255,0.3)
note over Owner,C: 메뉴 수정 (PUT /me/food-trucks/{id}/menus/{menuId})
Owner->>C: UpdateMenuRequest
C->>S: updateMenu(ownerId, foodTruckId, menuId, request)
S->>M: updateMenu(...)
M->>R: validate owner & truck(approved), find menu
R-->>M: entities
M->>D: menu.updateMenu(name, price, desc, imageUrl)
D-->>M: updated
M-->>S: OK
S-->>C: OK
C-->>Owner: 200 BaseResponse<Void>
end
sequenceDiagram
autonumber
actor Owner as Owner
participant C as OwnerController
participant S as OwnerService
participant M as MyFoodTruckMenuService
participant R as Repositories
participant CDN as CdnUrlResolver
participant S3 as S3Service
rect rgba(255,230,200,0.3)
note over Owner,C: 메뉴 삭제 (DELETE /me/food-trucks/{id}/menus/{menuId})
Owner->>C: Delete request
C->>S: deleteMenu(ownerId, foodTruckId, menuId)
S->>M: deleteMenu(...)
M->>R: validate owner & truck(approved), find menu
R-->>M: entities
M->>CDN: resolveKey(menu.imageUrl?)
CDN-->>M: key or null
alt key exists
M->>S3: delete(key)
S3-->>M: OK
end
M->>R: delete menu
R-->>M: OK
M-->>S: OK
S-->>C: OK
C-->>Owner: 200 BaseResponse<Void>
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 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.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/main/java/konkuk/chacall/domain/owner/application/myfoodtruckmenu/MyFoodTruckMenuService.java (1)
92-125: 선택적 리팩토링: 검증 로직 추출을 고려해 보세요.
updateMenu와deleteMenu메서드에서 소유권 및 승인 상태 검증 로직(lines 94-97, 109-111)과 메뉴 조회 로직(lines 100-101, 114-115)이 중복됩니다.필요시 헬퍼 메서드로 추출하여 코드 중복을 줄일 수 있습니다.
예시:
private Menu validateAndGetMenu(Long ownerId, Long foodTruckId, Long menuId) { if (!foodTruckRepository.existsByFoodTruckIdAndOwnerIdAndFoodTruckStatusIn( foodTruckId, ownerId, List.of(FoodTruckStatus.ON, FoodTruckStatus.OFF))) { throw new BusinessException(ErrorCode.FOOD_TRUCK_NOT_APPROVED); } return menuRepository.findByMenuIdAndFoodTruckId(menuId, foodTruckId) .orElseThrow(() -> new BusinessException(ErrorCode.MENU_NOT_FOUND)); }그러면 두 메서드를 다음과 같이 단순화할 수 있습니다:
public void updateMenu(Long ownerId, Long foodTruckId, Long menuId, UpdateMenuRequest request) { Menu menu = validateAndGetMenu(ownerId, foodTruckId, menuId); menu.updateMenu(request.name(), request.price(), request.description(), request.photoUrl()); } public void deleteMenu(Long ownerId, Long foodTruckId, Long menuId) { Menu menu = validateAndGetMenu(ownerId, foodTruckId, menuId); String key = cdnUrlResolver.extractKeyFromUrl(menu.getImageUrl()); if (key != null) { s3Service.delete(key); } menuRepository.delete(menu); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
src/main/java/konkuk/chacall/domain/foodtruck/domain/model/Menu.java(1 hunks)src/main/java/konkuk/chacall/domain/owner/application/OwnerService.java(1 hunks)src/main/java/konkuk/chacall/domain/owner/application/myfoodtruckmenu/MyFoodTruckMenuService.java(3 hunks)src/main/java/konkuk/chacall/domain/owner/presentation/OwnerController.java(1 hunks)src/main/java/konkuk/chacall/domain/owner/presentation/dto/request/UpdateMenuRequest.java(1 hunks)src/main/java/konkuk/chacall/global/common/swagger/SwaggerResponseDescription.java(1 hunks)
🔇 Additional comments (7)
src/main/java/konkuk/chacall/domain/foodtruck/domain/model/Menu.java (1)
56-61: LGTM!엔티티 업데이트 메서드가 올바르게 구현되었습니다. 입력 검증은 DTO 레이어에서 처리되므로 이 레벨에서의 구현이 적절합니다.
src/main/java/konkuk/chacall/domain/owner/application/OwnerService.java (1)
167-183: LGTM!파사드 패턴이 일관되게 적용되었습니다. 사장님 검증 후 서비스 레이어로 위임하는 구조가 기존 메서드들과 동일하며, 트랜잭션 경계도 적절하게 설정되어 있습니다.
src/main/java/konkuk/chacall/global/common/swagger/SwaggerResponseDescription.java (1)
110-121: LGTM!Swagger 응답 설명이 적절하게 추가되었습니다. 에러 코드 세트가 유사한 오너 메뉴 작업들과 일관성을 유지하고 있습니다.
src/main/java/konkuk/chacall/domain/owner/presentation/OwnerController.java (1)
243-272: LGTM!두 엔드포인트 모두 기존 컨트롤러 패턴을 일관되게 따르고 있으며, 적절한 어노테이션과 검증이 적용되어 있습니다.
src/main/java/konkuk/chacall/domain/owner/presentation/dto/request/UpdateMenuRequest.java (1)
1-30: LGTM!DTO 검증이 적절하게 구현되었습니다. 필드별 제약 조건이 엔티티 스키마와 일치하며, 유효성 검증 어노테이션이 올바르게 적용되어 있습니다.
src/main/java/konkuk/chacall/domain/owner/application/myfoodtruckmenu/MyFoodTruckMenuService.java (2)
92-104: LGTM!메뉴 수정 로직이 올바르게 구현되었습니다. 소유권 검증, 메뉴 조회, 업데이트 순서가 적절하며, JPA 더티 체킹을 통한 영속성 관리가 상위 트랜잭션 컨텍스트에서 정상적으로 작동합니다.
106-125: 메뉴 삭제 로직이 적절하게 구현되었습니다.S3 이미지 삭제가 포함된 메뉴 삭제 흐름이 올바르게 구현되었습니다.
extractKeyFromUrl이 null을 반환하는 경우를 적절히 처리하고 있습니다.다만, S3 삭제 실패 시 DB에서는 메뉴가 삭제되어 S3에 고아 이미지가 남을 수 있습니다. 현재 구현은 이미지 정리 실패가 전체 작업을 롤백하지 않도록 하는 것으로 보이며, 이는 사용자 경험 측면에서 합리적인 선택일 수 있습니다.
S3 삭제 실패 시의 에러 처리 정책이 의도된 것인지 확인해 주세요. 필요하다면 별도의 이미지 정리 작업이나 로깅을 고려할 수 있습니다.
| String key = cdnUrlResolver.extractKeyFromUrl(menu.getImageUrl()); | ||
|
|
||
| // 메뉴 이미지를 S3 에서 삭제 | ||
| if (key != null) { | ||
| s3Service.delete(key); | ||
| } |
#️⃣연관된 이슈
📝작업 내용
푸드트럭 메뉴 수정/삭제 기능을 구현하였습니다.
푸드트럭 메뉴 수정의 경우, 푸드트럭 메뉴 등록과 같이 메뉴의 이름, 이미지 url, 가격, 설명 등을 입력받고 그것들을 기반으로 푸드트럭의 정보를 업데이트 하는 형식인 것으로 확인되었습니다.
따라서 Put 메서드를 사용하도록 구현하였습니다.
푸드트럭 메뉴 삭제의 경우 푸드트럭 메뉴가 삭제될 때 S3에 존재하는 메뉴의 이미지까지 삭제될 수 있도록 CdnUrlResolver, S3Service 를 주입하여 메뉴 삭제시 S3에서 이미지도 동시에 삭제되도록 구현하였습니다.
스크린샷 (선택)
💬리뷰 요구사항(선택)
Summary by CodeRabbit