Skip to content

Conversation

@dungbik
Copy link
Contributor

@dungbik dungbik commented Dec 4, 2025

📝 변경 내용


✅ 체크리스트

  • 코드가 정상적으로 동작함
  • 테스트 코드 통과함
  • 문서(README 등)를 최신화함
  • 코드 스타일 가이드 준수

💬 기타 참고 사항

Summary by CodeRabbit

릴리스 노트

  • New Features
    • 그룹 내 카드 세트 삭제 기능 추가 (DELETE 엔드포인트)
    • 카드 세트 삭제 시 관련 콘텐츠, 증분 데이터 및 메타데이터(이미지 포함)도 함께 제거
    • 카드 세트 삭제 시 연관된 북마크 및 좋아요 자동 정리

✏️ Tip: You can customize this high-level summary in your review settings.

@dungbik dungbik self-assigned this Dec 4, 2025
@dungbik dungbik added the enhancement New feature or request label Dec 4, 2025
@coderabbitai
Copy link

coderabbitai bot commented Dec 4, 2025

Walkthrough

카드셋 삭제 흐름을 위한 엔티티·저장소·서비스·컨트롤러가 추가되었고, 타깃 타입·ID 기반의 북마크/라이크 삭제 저장소 메서드와 이를 위임하는 Writer 서비스들이 도입되어 컨트롤러에 DELETE 엔드포인트가 추가되었습니다.

Changes

코호트 / 파일(s) 변경 요약
북마크 삭제 기능
src/main/java/project/flipnote/bookmark/repository/BookmarkRepository.java, src/main/java/project/flipnote/bookmark/service/BookmarkWriter.java
deleteByTargetTypeAndTargetId(BookmarkTargetType, Long) 저장소 메서드 추가 및 해당 메서드를 호출하는 BookmarkWriter 서비스 클래스 추가
라이크 삭제 기능
src/main/java/project/flipnote/like/repository/LikeRepository.java, src/main/java/project/flipnote/like/service/LikeWriter.java
deleteByTargetTypeAndTargetId(LikeTargetType, Long) 저장소 메서드 추가 및 해당 메서드를 호출하는 LikeWriter 서비스 클래스 추가
카드셋 엔티티
src/main/java/project/flipnote/cardset/entity/CardSetContent.java, src/main/java/project/flipnote/cardset/entity/CardSetIncremental.java
CardSetContent, CardSetIncremental JPA 엔티티 추가 (테이블 매핑, 필드, Lombok 어노테이션 포함)
카드셋 저장소
src/main/java/project/flipnote/cardset/repository/CardSetContentRepository.java, src/main/java/project/flipnote/cardset/repository/CardSetIncrementalRepository.java, src/main/java/project/flipnote/cardset/repository/CardSetManagerRepository.java
콘텐츠/인크리멘털용 리포지토리 추가(각각 deleteByCardSetId(Long)), CardSetManagerRepositoryint deleteByCardSet_Id(Long) 메서드 추가
카드셋 서비스 및 컨트롤러
src/main/java/project/flipnote/cardset/service/CardSetService.java, src/main/java/project/flipnote/cardset/controller/GroupCardSetController.java
CardSetService.deleteCardSet(Long userId, Long groupId, Long cardSetId) 트랜잭션 삭제 흐름 추가(정책 검증, 관련 저장소 삭제, 이미지 참조 삭제, Like/Bookmark Writer 호출) 및 컨트롤러에 DELETE /v1/groups/{groupId}/card-sets/{cardSetId} 엔드포인트 추가(응답: IdResponse)

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Controller as GroupCardSetController
    participant Service as CardSetService
    participant Policy as CardSetPolicyService
    participant CardSetMgrRepo as CardSetManagerRepository
    participant ContentRepo as CardSetContentRepository
    participant IncrementalRepo as CardSetIncrementalRepository
    participant MetadataRepo as CardSetMetadataRepository
    participant CardSetRepo as CardSetRepository
    participant ImageService as ImageReferenceService
    participant BookmarkWriter
    participant LikeWriter

    Client->>Controller: DELETE /v1/groups/{groupId}/card-sets/{cardSetId}
    Controller->>Service: deleteCardSet(userId, groupId, cardSetId)
    Service->>Policy: validateEditPermission(userId, groupId, cardSetId)
    Service->>CardSetMgrRepo: deleteByCardSet_Id(cardSetId)
    Service->>ContentRepo: deleteByCardSetId(cardSetId)
    Service->>IncrementalRepo: deleteByCardSetId(cardSetId)
    Service->>MetadataRepo: deleteByCardSetId(cardSetId)
    Service->>ImageService: removeImageReferences(cardSetId)
    Service->>CardSetRepo: delete(cardSet)
    Service->>BookmarkWriter: delete(CARD_SET, cardSetId)
    Service->>LikeWriter: delete(CARD_SET, cardSetId)
    Service-->>Controller: IdResponse(cardSetId)
    Controller-->>Client: 200 OK + IdResponse
Loading

Estimated code review effort

🎯 3 (보통) | ⏱️ ~20분

  • 주의할 파일/영역:
    • CardSetService.deleteCardSet() — 트랜잭션 경계와 삭제 순서(무결성, 외래키) 확인
    • 새 엔티티(CardSetContent, CardSetIncremental)의 JPA 매핑(Lob/컬럼 설정) 검토
    • 저장소 파생 메서드 네이밍 일관성(deleteByCardSet_Id vs deleteByCardSetId)
    • Like/Bookmark Writer가 원하는 범위(타입/ID)만 삭제하는지 검증

Possibly related PRs

Suggested reviewers

  • stoneTiger0912

Poem

🐰 폴짝폴짝, 삭제의 봄이 왔네
카드셋이 사라지고 흔적도 정리되네
북마크와 라이크도 조용히 손을 흔들고,
DB는 숨을 고르며 평온을 되찾네 —
토끼가 기뻐 뛰며 코드에 박수를 보낸다 🥕✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 17.65% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목은 카드셋 삭제 API 기능 추가를 명확하게 설명하며, 변경사항의 주요 내용(DELETE 엔드포인트 추가 및 관련 서비스 구현)과 잘 부합합니다.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/cardset-delete

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 64873ae and 7b6fbbc.

📒 Files selected for processing (1)
  • src/main/java/project/flipnote/cardset/service/CardSetService.java (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/project/flipnote/cardset/service/CardSetService.java
⏰ 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: build

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 and usage tips.

Copy link

@coderabbitai coderabbitai bot left a 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/project/flipnote/cardset/service/CardSetService.java (1)

376-382: 리포지토리 메서드 반환 타입 불일치를 해결하세요.

CardSetManagerRepository.deleteByCardSet_Id는 int를 반환하지만, CardSetContentRepository.deleteByCardSetId와 CardSetIncrementalRepository.deleteByCardSetId는 void를 반환합니다. 일관성을 위해 모든 삭제 메서드가 동일한 반환 타입(int 권장)을 사용하도록 수정하는 것이 좋습니다.

CardSetContentRepository와 CardSetIncrementalRepository의 삭제 메서드를 다음과 같이 수정하세요:

CardSetContentRepository.java:

-void deleteByCardSetId(Long cardSetId);
+int deleteByCardSetId(Long cardSetId);

CardSetIncrementalRepository.java:

-void deleteByCardSetId(Long cardSetId);
+int deleteByCardSetId(Long cardSetId);
src/main/java/project/flipnote/cardset/repository/CardSetIncrementalRepository.java (1)

7-9: 반환 타입을 int로 변경하여 일관성을 유지하세요.

deleteByCardSetId 메서드가 void를 반환하는데, 다른 삭제 메서드들(CardSetManagerRepository.deleteByCardSet_Id, LikeRepository.deleteByTargetTypeAndTargetId, BookmarkRepository.deleteByTargetTypeAndTargetId)은 int를 반환합니다. 삭제된 레코드 수를 확인할 수 있도록 int를 반환하는 것이 좋습니다.

-void deleteByCardSetId(Long cardSetId);
+int deleteByCardSetId(Long cardSetId);
src/main/java/project/flipnote/cardset/repository/CardSetContentRepository.java (1)

7-9: 반환 타입을 int로 변경하여 일관성을 유지하세요.

deleteByCardSetId 메서드가 void를 반환하는데, 다른 삭제 메서드들(CardSetManagerRepository.deleteByCardSet_Id, LikeRepository.deleteByTargetTypeAndTargetId, BookmarkRepository.deleteByTargetTypeAndTargetId)은 int를 반환합니다. 삭제된 레코드 수를 확인할 수 있도록 int를 반환하는 것이 좋습니다.

-void deleteByCardSetId(Long cardSetId);
+int deleteByCardSetId(Long cardSetId);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f517a5d and 55b675a.

📒 Files selected for processing (11)
  • src/main/java/project/flipnote/bookmark/repository/BookmarkRepository.java (1 hunks)
  • src/main/java/project/flipnote/bookmark/service/BookmarkWriter.java (1 hunks)
  • src/main/java/project/flipnote/cardset/controller/GroupCardSetController.java (3 hunks)
  • src/main/java/project/flipnote/cardset/entity/CardSetContent.java (1 hunks)
  • src/main/java/project/flipnote/cardset/entity/CardSetIncremental.java (1 hunks)
  • src/main/java/project/flipnote/cardset/repository/CardSetContentRepository.java (1 hunks)
  • src/main/java/project/flipnote/cardset/repository/CardSetIncrementalRepository.java (1 hunks)
  • src/main/java/project/flipnote/cardset/repository/CardSetManagerRepository.java (1 hunks)
  • src/main/java/project/flipnote/cardset/service/CardSetService.java (5 hunks)
  • src/main/java/project/flipnote/like/repository/LikeRepository.java (1 hunks)
  • src/main/java/project/flipnote/like/service/LikeWriter.java (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
src/main/java/project/flipnote/bookmark/service/BookmarkWriter.java (1)
src/main/java/project/flipnote/like/service/LikeWriter.java (1)
  • RequiredArgsConstructor (9-24)
src/main/java/project/flipnote/cardset/entity/CardSetIncremental.java (1)
src/main/java/project/flipnote/cardset/entity/CardSetContent.java (1)
  • Getter (16-38)
src/main/java/project/flipnote/cardset/entity/CardSetContent.java (1)
src/main/java/project/flipnote/cardset/entity/CardSetIncremental.java (1)
  • Getter (18-44)
⏰ 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: build
🔇 Additional comments (9)
src/main/java/project/flipnote/cardset/repository/CardSetManagerRepository.java (1)

12-13: LGTM!

CardSet 삭제 시 연관된 관리자 레코드를 삭제하는 메서드가 올바르게 구현되었습니다. 반환 타입이 int로 설정되어 삭제된 레코드 수를 확인할 수 있습니다.

src/main/java/project/flipnote/bookmark/repository/BookmarkRepository.java (1)

24-25: LGTM!

타겟 타입과 ID로 즐겨찾기를 삭제하는 메서드가 올바르게 구현되었습니다. LikeRepository와 일관된 패턴을 따르고 있습니다.

src/main/java/project/flipnote/like/repository/LikeRepository.java (1)

18-19: LGTM!

타겟 타입과 ID로 좋아요를 삭제하는 메서드가 올바르게 구현되었습니다. BookmarkRepository와 일관된 패턴을 따르고 있습니다.

src/main/java/project/flipnote/like/service/LikeWriter.java (1)

9-24: LGTM!

LikeWriter 서비스가 BookmarkWriter와 일관된 패턴으로 잘 구현되었습니다. 트랜잭션 경계는 호출자(CardSetService)에서 관리하므로 현재 구조가 적절합니다.

src/main/java/project/flipnote/cardset/service/CardSetService.java (3)

15-15: LGTM!

새로운 의존성 주입이 올바르게 추가되었습니다. Writer 패턴을 사용하여 삭제 로직을 분리한 것은 좋은 설계입니다.

Also applies to: 28-29, 34-34, 50-50, 74-77


369-373: LGTM!

트랜잭션 어노테이션과 권한 검증 로직이 올바르게 구현되었습니다.


398-399: LGTM!

IdResponse를 반환하는 것은 삭제된 리소스 ID를 클라이언트에 전달하는 좋은 패턴입니다.

src/main/java/project/flipnote/bookmark/service/BookmarkWriter.java (1)

9-24: LGTM!

BookmarkWriter 서비스가 LikeWriter와 일관된 패턴으로 잘 구현되었습니다. 트랜잭션 경계는 호출자에서 관리하므로 현재 구조가 적절합니다.

src/main/java/project/flipnote/cardset/controller/GroupCardSetController.java (1)

6-6: 삭제 API 구현은 일관성 있게 잘 추가되었습니다

  • 인증 정보에서 userId 추출 후 서비스에 위임하는 패턴이 기존 메서드들과 일관적이고,
  • IdResponse로 삭제된 리소스 ID를 반환하는 것도 클라이언트 입장에서 유용해 보입니다.

다만 아래 두 가지는 한 번만 확인해 주세요.

  1. GroupCardSetControllerDocs 및 API 문서(Swagger/RestDocs 등)에 DELETE 엔드포인트가 반영되었는지
  2. 삭제 성공 시 200 OK + body를 사용하는 것이 팀 REST 스타일 가이드와 일치하는지 (일부 팀은 204 No Content를 기본으로 사용하기도 합니다)

위 두 점만 정리되면 컨트롤러 레벨에서는 크게 추가 코멘트 없습니다.

Also applies to: 26-26, 81-90

Comment on lines 375 to 390
// 카드셋 관리자
cardSetManagerRepository.deleteByCardSet_Id(cardSetId);

// 카드셋 내용
cardSetContentRepository.deleteByCardSetId(cardSetId);

// 카드셋 증분값
cardSetIncrementalRepository.deleteByCardSetId(cardSetId);

// 카드셋 스냅샷

// 카드셋 메타데이터
cardSetMetadataRepository.deleteById(cardSetId);

// 카드셋
cardSetRepository.delete(cardSet);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

이미지 리소스 정리 로직이 누락되었습니다.

CardSet에 연관된 이미지(ImageRef, ImageMeta)를 삭제하는 로직이 없습니다. createCardSet 메서드(line 120, 135)와 updateCardSet 메서드(line 212)에서 이미지를 관리하는 것처럼, 삭제 시에도 imageService 또는 imageRefService를 통해 연관된 이미지를 정리해야 합니다.

CardSet 삭제 전에 이미지 정리 로직을 추가하세요:

 	cardSetPolicyService.validateCardSetEditable(userId, cardSetId);
+
+	// 이미지 정리
+	imageRefService.findByTypeAndReferenceId(REFERENCE_TYPE, cardSetId)
+		.ifPresent(imageRef -> imageService.deleteImageRef(imageRef.getId()));

 	// 카드셋 관리자
 	cardSetManagerRepository.deleteByCardSet_Id(cardSetId);

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/main/java/project/flipnote/cardset/service/CardSetService.java around
lines 375-390, the deletion sequence is missing cleanup of image resources
associated with the CardSet (ImageRef, ImageMeta); before deleting
cardSetMetadata and the cardSet itself, call the appropriate image cleanup
methods (e.g., imageService.deleteByCardSetId(cardSetId) and/or
imageRefService.deleteByCardSetId(cardSetId) and
imageMetaService.deleteByCardSetId(cardSetId)) to remove ImageRef and ImageMeta
entries, perform these calls prior to deleting metadata and the CardSet, ensure
the calls run within the same transaction or handle failures (log and rethrow)
so partial deletes do not leave orphaned images.

Comment on lines +384 to +385
// 카드셋 스냅샷

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

CardSetSnapshot 삭제 로직을 구현하거나 TODO로 명확히 표시하세요.

카드셋 스냅샷 삭제가 주석 처리되어 있어 해당 데이터가 고아 데이터로 남을 수 있습니다. 스냅샷 기능이 아직 구현되지 않았다면 TODO 주석을 추가하고, 구현되었다면 삭제 로직을 추가해야 합니다.

스냅샷 삭제 구현이 필요하다면 코드를 생성해드릴 수 있습니다. 필요하신가요?

🤖 Prompt for AI Agents
In src/main/java/project/flipnote/cardset/service/CardSetService.java around
lines 384-385, the CardSetSnapshot deletion is commented out leaving potential
orphaned snapshot data; either implement the deletion logic or add a clear TODO
explaining why it's omitted. If implementing, load related CardSetSnapshot
entities (by cardset id or relevant FK), delete them within the same
transactional context as the parent CardSet (or use cascade remove if modeled),
handle nulls and exceptions, and ensure tests cover snapshot removal; if not
implementing now, add a TODO comment explaining the missing feature, link to an
issue/PR, and include a FIXME with intended behavior and owner.

@dungbik dungbik merged commit 887788b into develop Dec 4, 2025
3 checks passed
@dungbik dungbik deleted the feat/cardset-delete branch December 4, 2025 09:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants