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인 값만 추출할 수 있게됐다!
혹시 다른 좋은 방법을 알고 계시다면 공유부탁드립니다 🙇♀️
[참고한 블로그]