[SpringBoot]

게시글 읽어올 때, 좋아요 수랑 댓글 수를 어떻게 처리할 것인가?

Hevton 2024. 4. 10. 00:03
반응형

 

서비스를 처음 운영할 때에는, 프론트와 백을 모두 개발해야 하기 때문에,, 보통 비용 감소를 위해 서버리스를 많이 도입하고 있지만

(고정 비용도 나가지 않아서 좋음)

 

최근에 개발중인 서비스는 백엔드까지 개발하고 있습니다.

한정된 AWS 프리티어로 초반을 유지해야 하기 때문에, 쿼리 최적화도 당연히 필수적으로 생각해보게 되었습니다.

 

Post - Comment 는 1 : N 관계이고

Post - UserLike 또한 1 : N 관계이며

Post - UserDownload 또한 1 : N 관계입니다.

 

JPQL을 이용한 Fetch Join 쿼리를 작성하던, EntityGraph를 이용하던, QueryDSL을 이용하던

OneToMany 여러개의 Fetch Join은 메모리와 성능상 이슈가 존재합니다.

 

Fetch Join은 영속성을 관리하며 Entity 전체를 메모리에 불러오기 때문에, 2개 이상의 Fetch Join 시에 Hibernate에서 Exception을 발생시키기도 합니다.

 

그래서 하나의 포스트의 세부 정보를 가져올 때에는 Post를 기준점으로 하는게 아니라, 각 Comment, UserLike, UserDownload 를 기준으로 3번을 각각 호출하는 것이 좋습니다.

 

또한 영속성 관리가 필요없다면, OneToMany 관계 자체를 지워버리고 Many 측에서 FK를 관리해주기만 하면 되기도 합니다.

 

 

본론으로 들어가서, 여느 커뮤니티처럼 게시글들의 리스트들을 가져올 때, OneToMany 관계의 데이터들의 갯수 (댓글 수, 좋아요 수, 다운로드 수)를 매번 join해서 가져오는 것은.. 매우 코스트가 비쌉니다.

 

그리고, Write보다 Read가 훨씬 많은 커뮤니티의 특성 상

CommentCount와 LikeCount같은 것들을 꼭 관리해주어야겠다고 결정했습니다.

@Entity
class Post(
	// 중략
    @Column(name = "comments")
    @BatchSize(size = 100)
    @OneToMany(mappedBy = "post", fetch = FetchType.LAZY, orphanRemoval = true, cascade = [CascadeType.ALL])
    val comments: Set<Comment>? = emptySet(),
    
    @Column(name = "comment_count")
    val commentCount: Long = 0,
    
    @Column(name = "liked_users")
    @BatchSize(size = 100)
    @OneToMany(mappedBy = "post", fetch = FetchType.LAZY, orphanRemoval = true, cascade = [CascadeType.ALL])
    val likedUsers: Set<UserLike>? = emptySet(),
    
    @Column(name = "like_count")
    val likeCount: Long = 0,
    
    @Column(name = "downloaded_users")
    @BatchSize(size = 100)
    @OneToMany(mappedBy = "post", fetch = FetchType.LAZY, orphanRemoval = true, cascade = [CascadeType.ALL])
    val downloadedUsers: Set<UserDownload>? = emptySet(),
    
    @Column(name = "download_count")
    val downloadCount: Long = 0,
)

 

이렇게 field로 관리해주면, 매번 join 하는 cost를 줄일 수 있고

대신에 comment나 like 시에 field의 count를 증가해주어야 하고, 이를 위해 Transaction 처리를 보장해주면 됩니다.

 

 

질의응답

반응형