2525import org .springframework .data .domain .Pageable ;
2626import org .springframework .data .domain .Slice ;
2727import org .springframework .data .domain .SliceImpl ;
28+ import org .springframework .data .redis .core .Cursor ;
2829import org .springframework .data .redis .core .ListOperations ;
2930import org .springframework .data .redis .core .RedisTemplate ;
31+ import org .springframework .data .redis .core .ScanOptions ;
3032import org .springframework .stereotype .Service ;
3133import org .springframework .transaction .annotation .Transactional ;
3234
@@ -360,19 +362,68 @@ public void deleteAlbum(Long albumId, UserPrincipal userPrincipal) {
360362 savingJoyRepository .deleteByAlbumAlbumId (albumId );
361363 albumRepository .deleteById (albumId );
362364 }
365+ //
366+ // public void deleteAlbums(List<Long> albumIds, UserPrincipal userPrincipal) {
367+ // final User user = UserServiceHelper.findExistingUser(userRepository, userPrincipal);
368+ //
369+ // Set<String> keys = redisTemplate.keys(KEY_PREFIX + "*");
370+ // ListOperations<String, String> listOps = redisTemplate.opsForList();
371+ //
372+ // // 실패한 albumId와 예외 메시지를 저장
373+ // Map<Long, String> failedAlbumMap = new HashMap<>();
374+ //
375+ // // 먼저 모든 유효성 및 권한 체크를 먼저 한 후, 삭제는 그 다음에 수행
376+ // List<Album> albumsToDelete = new ArrayList<>();
377+ //
378+ // for (Long albumId : albumIds) {
379+ // try {
380+ // Album album = albumRepository.findById(albumId)
381+ // .orElseThrow(() -> CustomException.of(ErrorDetails.ALBUM_NOT_FOUND));
382+ //
383+ // if (!album.getUser().getUserId().equals(user.getUserId())) {
384+ // throw CustomException.of(ErrorDetails.NOT_MY_ALBUM);
385+ // }
386+ //
387+ // albumsToDelete.add(album);
388+ // } catch (Exception e) {
389+ // failedAlbumMap.put(albumId, e.getMessage());
390+ // }
391+ // }
392+ //
393+ // // 하나라도 실패한 경우 전체 중단 및 rollback
394+ // if (!failedAlbumMap.isEmpty()) {
395+ // for (Map.Entry<Long, String> entry : failedAlbumMap.entrySet()) {
396+ // log.warn("앨범 삭제 실패 - albumId: {}, 이유: {}", entry.getKey(), entry.getValue());
397+ // }
398+ // throw CustomException.of(ErrorDetails.DELETE_ALBUM_FAILED); // 커스텀 예외 처리
399+ // }
400+ //
401+ // // 실제 삭제 (캐시, 연관 엔티티, 앨범)
402+ // for (Album album : albumsToDelete) {
403+ // Long albumId = album.getAlbumId();
404+ //
405+ // for (String key : keys) {
406+ // List<String> cachedAlbumIds = listOps.range(key, 0, -1);
407+ // if (cachedAlbumIds != null && cachedAlbumIds.contains("albumId:" + albumId)) {
408+ // listOps.remove(key, 0, "albumId:" + albumId);
409+ // }
410+ // }
411+ //
412+ // savingAlbumRepository.deleteByAlbumAlbumId(albumId);
413+ // savingJoyRepository.deleteByAlbumAlbumId(albumId);
414+ // albumRepository.deleteById(albumId);
415+ // }
416+ // }
363417
364418 public void deleteAlbums (List <Long > albumIds , UserPrincipal userPrincipal ) {
365419 final User user = UserServiceHelper .findExistingUser (userRepository , userPrincipal );
366420
367- Set < String > keys = redisTemplate . keys ( KEY_PREFIX + "*" );
368- ListOperations < String , String > listOps = redisTemplate . opsForList ();
421+ // 먼저 모든 유효성 및 권한 체크를 먼저 한 후, 삭제는 그 다음에 수행
422+ List < Album > albumsToDelete = new ArrayList <> ();
369423
370424 // 실패한 albumId와 예외 메시지를 저장
371425 Map <Long , String > failedAlbumMap = new HashMap <>();
372426
373- // 먼저 모든 유효성 및 권한 체크를 먼저 한 후, 삭제는 그 다음에 수행
374- List <Album > albumsToDelete = new ArrayList <>();
375-
376427 for (Long albumId : albumIds ) {
377428 try {
378429 Album album = albumRepository .findById (albumId )
@@ -396,23 +447,35 @@ public void deleteAlbums(List<Long> albumIds, UserPrincipal userPrincipal) {
396447 throw CustomException .of (ErrorDetails .DELETE_ALBUM_FAILED ); // 커스텀 예외 처리
397448 }
398449
399- // 실제 삭제 (캐시, 연관 엔티티, 앨범)
400- for (Album album : albumsToDelete ) {
401- Long albumId = album .getAlbumId ();
450+ // Redis 삭제 (SCAN 사용)
451+ try (Cursor <byte []> cursor = redisTemplate .getConnectionFactory ()
452+ .getConnection ()
453+ .scan (ScanOptions .scanOptions ().match (KEY_PREFIX + "*" ).count (100 ).build ())) {
454+
455+ ListOperations <String , String > listOps = redisTemplate .opsForList ();
402456
403- for (String key : keys ) {
404- List <String > cachedAlbumIds = listOps .range (key , 0 , -1 );
405- if (cachedAlbumIds != null && cachedAlbumIds .contains ("albumId:" + albumId )) {
406- listOps .remove (key , 0 , "albumId:" + albumId );
457+ while (cursor .hasNext ()) {
458+ String key = new String (cursor .next ());
459+ for (Album album : albumsToDelete ) {
460+ String target = "albumId:" + album .getAlbumId ();
461+ listOps .remove (key , 0 , target );
407462 }
408463 }
409464
410- savingAlbumRepository .deleteByAlbumAlbumId (albumId );
411- savingJoyRepository .deleteByAlbumAlbumId (albumId );
412- albumRepository .deleteById (albumId );
465+ } catch (Exception e ) {
466+ log .error ("Redis 삭제 중 오류 발생" , e );
467+ // 필요 시 fallback 로직 추가
468+ }
469+
470+ // DB 삭제 (트랜잭션 보장)
471+ for (Album album : albumsToDelete ) {
472+ savingAlbumRepository .deleteByAlbumAlbumId (album .getAlbumId ());
473+ savingJoyRepository .deleteByAlbumAlbumId (album .getAlbumId ());
474+ albumRepository .deleteById (album .getAlbumId ());
413475 }
414476 }
415477
478+
416479 public List <AlbumGetCreatedResponse > getCreatedAlbums (UserPrincipal userPrincipal ) {
417480 final User user = UserServiceHelper .findExistingUser (userRepository , userPrincipal );
418481
0 commit comments