[Spring] 사진 저장하기 - 2

ziwww·2024년 4월 18일

개발

목록 보기
10/14

이전 포스팅에서 사진 업로드 및 삭제를 구현하고 서버에 전달하는 것까지 구현을 해보았다.

https://velog.io/@dhktjr0204/Spring-%EC%82%AC%EC%A7%84-%EC%A0%80%EC%9E%A5%ED%95%98%EA%B8%B0-1

요청받은 데이터을 이제 서버에서 처리를 해주는 것을 구현할 것이다.

Controller

 	@PutMapping("/edit/{id}")
    public ResponseEntity<?> edit(@PathVariable Long id, BoardUpdateRequestDTO boardUpdateRequestDTO,
                                  @RequestPart(value = "images", required = false) List<MultipartFile> images) {


        Board board = boardService.updateBoard(id, boardUpdateRequestDTO, boardUpdateRequestDTO.getImageUrls(), images);

        return ResponseEntity.ok("/board/" + id);
    }

이 코드가 사진들을 처리할 Controller이다.
images라는 이름으로 파일 데이터들을 받고있고 boardUpdateRequestDTO의 imageUrls의 필드로 기존 이미지 사진을 받고있다.

Service

위에 controller에서는 boardService.updateBoard라고 되어있지만 저 로직에서는 태그수정 및 게시글 수정 로직도 포함되어있으므로 사진 수정하는 로직만 살펴보겠다.

	@Transactional
    @Override
    public void updateFileList(Board board, List<String> originalFiles, List<MultipartFile> newFiles) {

        List<Image> images = imageRepository.findAllByBoard_IdOrderByOrder(board.getId())
                .orElseThrow(BoardNotFoundException::new);

        //새로 전송된 사진들이 시작할 순서
        int orderIndex = 0;

        //만약 기존 이미지가 모두 지워졌다면 DB에 저장된 이미지들 모두 삭제
        if (originalFiles == null) {
            for (Image image : images) {
                imageRepository.delete(image);
                deleteS3(image.getName());
            }
        } else {
            // 이미 저장된 사진들의 순서를 바꿔준다.
            orderIndex = originalFiles.size();

            for (Image image : images) {
                int index = originalFiles.indexOf(image.getName());
                //만약 originalFiles에 없으면 사용자가 삭제한 사진이기 때문에 삭제
                if (index == -1) {
                    imageRepository.delete(image);
                    deleteS3(image.getName());
                } else {
                    //사진이 포함되어있다면 순서 업데이트
                    image.update(index + 1);
                }
            }
        }

        //새로운 파일 s3에 저장
        if (newFiles != null) {
            for (int i = 0; i < newFiles.size(); i++) {

                String fileName = saveS3(newFiles.get(i));

                saveImageInDB(board, fileName, orderIndex + i + 1);

            }
        }
    }

엄청.. 길다... 하나씩 살펴보겠다.

List<Image> images = imageRepository.findAllByBoard_IdOrderByOrder(board.getId())
                .orElseThrow(BoardNotFoundException::new);

기존 게시글에 저장되어있던 사진들을 가져온다.

if (originalFiles == null) {
            for (Image image : images) {
                imageRepository.delete(image);
                deleteS3(image.getName());
            }
        } 

만약 전달받은 기존 파일이 없다 -> 사용자가 게시글에 포함되어있던 사진들을 모두 삭제한 것이다.
따라서 데이터베이스에 있던 기존 파일들을 삭제해준다. 또한, s3에 있던 사진들도 삭제한다.

else {
            // 이미 저장된 사진들의 순서를 바꿔준다.
            orderIndex = originalFiles.size();

            for (Image image : images) {
                int index = originalFiles.indexOf(image.getName());
                //만약 originalFiles에 없으면 사용자가 삭제한 사진이기 때문에 삭제
                if (index == -1) {
                    imageRepository.delete(image);
                    deleteS3(image.getName());
                } else {
                    //사진이 포함되어있다면 순서 업데이트
                    image.update(index + 1);
                }
            }
        }
  • orderIndex = 사진의 순서를 결정하는 index이다. 앞서 내가 구현했던 로직은 이미 저장된 사진들이 새로 업로드된 사진들보다 먼저 올 수 밖에 없기 때문에, 기존 사진들의 size만큼 orderIndex를 설정해주었다.
  • int index = originalFiles.indexOf(image.getName()) = 데이터베이스에 저장된 사진 이름들 중 전달 받지 않은 사진이 있는지 확인하는 변수이다. (기존 사진 중 삭제할 사진 찾기)
  • if (index == -1) = 만약 index가 -1이라면 전달받지 못한 것이다. 즉, 사용자가 그 사진을 삭제한 것이다. 그렇기 때문에 데이터베이스 및 s3에서 삭제한다.
  • 만약 사진이 포함되어있다면 순서를 업데이트해준다. 프론트에서 사진을 순서대로 보냈기 때문에 index대로 업데이트하면 됨

이번엔 새로운 사진 저장이다.

        //새로운 파일 s3에 저장
        if (newFiles != null) {
            for (int i = 0; i < newFiles.size(); i++) {

                String fileName = saveS3(newFiles.get(i));

                saveImageInDB(board, fileName, orderIndex + i + 1);

            }
        }
  • 만약 List<MultipartFile>에 아무것도 전달된게 없다면 사용자가 새로운 사진을 업로드하지 않았다는 것이다. 그렇다면 업로드할 필요가 없으니 넘어간다.
  • if (newFiles != null) = 전달받은 파일이 있을 시에만 s3와 데이터베이스에 저장한다.
  • saveImageInDB(board, fileName, orderIndex + i + 1) = orderIndex는 아까 기존 사진에서 지정한 index이다. 기존 사진들은 업로드된 사진보다 무조건 앞에 있기 때문에 기존 사진 갯수만큼 밀려난다.

이렇게 구현하니 정상적으로 잘 저장되고 순서도 제대로 나오게 되었음

profile
반갑습니다. 오늘도 즐거운 하루입니다.

0개의 댓글