Spring & SpringBoot

SpringBoot 게시판_이미지 대표이미지 출력

예령 : ) 2023. 5. 12. 17:22

[구현하려는 기능]

게시판 목록 조회 기능 구현 중 각 게시물의 대표 이미지도 한 번에 가져오려고 한다.

 

[현재 상황]

현재 목록 조회 기능은 querydsl을 사용해서 구현되어 있는데 각 게시물에 포함된 여러 개의 이미지 중 하나의 이미지만 가져와야 되는 상황이었다.

 

[구현하기 위한 방법]

방법 1.

해당 게시물의 이미지들 중 ImageId가 가장 큰 값으로 추출

 

RehomingRepositoryImpl.java

@Override
public Page<RehomingInfo> rehomingListForMember(Long userId, Pageable pageable) {
    QueryResults<RehomingInfo> results = queryFactory
            .select(
                    Projections.constructor(
                            RehomingInfo.class,
                            rehoming.rehomingId,
                            Expressions.as(
                                    select(image.filePath)
                                            .from(image)
                                            .where(image.postId.eq(rehoming.rehomingId),
                                                    image.postType.eq(PostType.REHOMING),
                                                    image.imageId.eq(image.imageId.max()))
                                            .limit(1)
                                    , "rehomingImg"),
                            rehoming.user.id,
                            rehoming.user.nickname,
                            rehoming.title,
                            rehoming.petName,
                            rehoming.category.categoryGroupName,
                            rehoming.type.petCategoryName,
                            rehoming.gender,
                            rehoming.createdAt,
                            rehoming.updatedAt,
                            rehoming.status,
                            rehoming.postType,
                            ExpressionUtils.as(
                                    select(likes.count())
                                            .from(likes)
                                            .where(
                                                    likes.user.id.eq(userId)
                                                            .and(likes.postId.eq(rehoming.rehomingId))
                                            ), "isLiked"),
                            ExpressionUtils.as(
                                    select(bookmark.count())
                                            .from(bookmark)
                                            .where(
                                                    bookmark.user.id.eq(userId)
                                                            .and(bookmark.postId.eq(rehoming.rehomingId))
                                            ), "isBookmarked"),
                            rehoming.viewCnt,
                            ExpressionUtils.as(
                                    select(likes.count())
                                            .from(likes)
                                            .where(likes.postId.eq(rehoming.rehomingId)),
                                    "likeCnt"),
                            ExpressionUtils.as(
                                    select(bookmark.count())
                                            .from(bookmark)
                                            .where(bookmark.postId.eq(rehoming.rehomingId)),
                                    "bookmarkCnt")
                    )
            )
            .from(rehoming)
            .leftJoin(rehoming.user, user)
            .orderBy(rehoming.createdAt.desc())
            .offset(pageable.getOffset())
            .limit(pageable.getPageSize())
            .fetchResults();
    List<RehomingInfo> content = results.getResults();
    long total = results.getTotal();

    return new PageImpl<>(content, pageable, total);
}


결과 -> subquery 안에서는 limit() 함수가 적용되지 않아 여러 이미지 중 한 개의 이미지만을 추출하는 게 불가능했다.

 

 

방법 2.

이미지 테이블에 index값을 추가해 해당 게시물의 가장 큰 index를 가진 이미지 뽑기

 

그냥 id 값이 가장 크거나 작은 값으로 선택하기에는 보안적으로 취약하다고 생각되어 이 방법을 고민했었다.

 

결과 -> 그러나 많은 조회로 인해 성능 저하가 우려되어 선택하지 않았다,!

 

 

방법 3.

이미지 테이블에 대표이미지를 구분하는 컬럼 추가 ✔️

 

Image.java

@Entity
@Getter
@Table(name = "TB_IMAGE")
public class Image {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "IMAGE_ID")
    private Long imageId;

    @Column(name = "ORIGINAL_FILE_NAME")
    private String originalFileName;

    @Column(name = "FAKE_FILE_NAME")
    private String fakeFileName;

    @Column(name = "FILE_PATH")
    private String filePath;

    @Column(name = "POST_ID")
    private Long postId;

    @Column(name = "POST_TYPE")
    @Enumerated(EnumType.STRING)
    private PostType postType;

    // 대표 이미지를 구분하는 컬럼
    @Column(name = "REPIMGNY") private boolean repImgNY;

 

이미지 테이블에 대표 이미지를 구분하는 컬럼을 추가한다.

 

ImageUploadManager.java

public void uploadPostImage(List<MultipartFile> multipartFiles, Long postId, PostType postType) {
    List<Image> imageList = new ArrayList<>();
    
    for (int i = 0; i < multipartFiles.size(); i++) {
        String fakeFileName = imageUtils.createFileName(multipartFiles.get(i).getOriginalFilename());
        String originalFileName = multipartFiles.get(i).getOriginalFilename();
        String filePath = s3Uploader.uploadFile(multipartFiles.get(i));
        boolean repImgNY = i == 0; // 제일 먼저 등록되는 이미지의 경우 대표이미지로 설정

        Image image = imageUploader.toImageEntity(fakeFileName, originalFileName, filePath, postId, postType, repImgNY);
        imageList.add(image);
    }
    
    imageUploader.savePostImage(imageList);
}

 

이미지를 저장하는 메소드에 제일 먼저 저장되는 이미지를 대표 이미지로 설정하는 기능을 추가한다.

 

RehomingInfo.java

@Getter
@NoArgsConstructor
public class RehomingInfo {
    private Long rehomingId;
    private String rehomingImg;
    private String nickname;
    private String title;
    private String petName;
    private String category;
    private String type;
    private RehomingCommand.PetGender gender;
    private boolean isLiked;
    private boolean isBookmarked;
    private int viewCnt;
    private Long likeCnt;
    private Long bookmarkCnt;

 

RehomingRepositoryImpl.java

/* 분양 글 목록 조회 (회원) */

@Override
public Page<RehomingInfo> rehomingListForMember(Long userId, Pageable pageable) {
        QueryResults<RehomingInfo> results = queryFactory
                .select(
                        Projections.constructor(
                                RehomingInfo.class,
                                rehoming.rehomingId,
                                Expressions.as(
                                        select(image.filePath)
                                                .from(image)
                                                .where(image.postId.eq(rehoming.rehomingId),
                                                        image.postType.eq(PostType.REHOMING),
                                                        image.repImgNY.eq(true))
                                                , "rehomingImg"),
                                rehoming.user.nickname,
                                rehoming.title,
                                rehoming.petName,
                                rehoming.category.categoryGroupName,
                                rehoming.type.petCategoryName,
                                rehoming.gender,
                                ExpressionUtils.as(
                                        select(likes.count())
                                                .from(likes)
                                                .where(
                                                        likes.user.id.eq(userId)
                                                                .and(likes.postId.eq(rehoming.rehomingId))
                                                ), "isLiked"),
                                ExpressionUtils.as(
                                        select(bookmark.count())
                                                .from(bookmark)
                                                .where(
                                                        bookmark.user.id.eq(userId)
                                                                .and(bookmark.postId.eq(rehoming.rehomingId))
                                                ), "isBookmarked"),
                                rehoming.viewCnt,
                                ExpressionUtils.as(
                                        select(likes.count())
                                                .from(likes)
                                                .where(likes.postId.eq(rehoming.rehomingId)),
                                        "likeCnt"),
                                ExpressionUtils.as(
                                        select(bookmark.count())
                                                .from(bookmark)
                                                .where(bookmark.postId.eq(rehoming.rehomingId)),
                                        "bookmarkCnt")
                        )
                )
                .from(rehoming)
                .leftJoin(rehoming.user, user)
                .orderBy(rehoming.createdAt.desc())
                .offset(pageable.getOffset())
                .limit(pageable.getPageSize())
                .fetchResults();
        List<RehomingInfo> content = results.getResults();
        long total = results.getTotal();

        return new PageImpl<>(content, pageable, total);
    }

 

sub query의 조건절에 이미지값이 true인 값만 추출할 수 있게됐다! 

 

혹시 다른 좋은 방법을 알고 계시다면 공유부탁드립니다 🙇‍♀️

 

 

[참고한 블로그]