Skip to content

황두현 Seminar1 과제#55

Open
DoohyunHwang97 wants to merge 5 commits into
wafflestudio:master-week1from
DoohyunHwang97:seminar1
Open

황두현 Seminar1 과제#55
DoohyunHwang97 wants to merge 5 commits into
wafflestudio:master-week1from
DoohyunHwang97:seminar1

Conversation

@DoohyunHwang97
Copy link
Copy Markdown

No description provided.

Copy link
Copy Markdown
Member

@davin111 davin111 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc. @PFCJeong

@DoohyunHwang97 테스트 하나가 실패하는데, 인지하고 계셨나요? 확인해보시고 답변 부탁드립니다~

Comment on lines +21 to +23
@ManyToOne
@JoinColumn(name = "group_id")
val playlistGroup: PlaylistGroupEntity
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

어떠한 경우의 연관관계에도 Lazy 를 지향하는 것이 좋습니다. ManyToOne 의 default 가 EAGER 라 하더라도 이것을 변경해두는 것이 좋아요. wafflestudio/seminar-2023#169 를 참고하시면 좋습니다.

이걸 Lazy 로 해두었다면, 불필요한 N+1 쿼리가 덜 날아가서 곳곳에서 JOIN FETCH 를 덜 써도 되었을 수도 있어요.

@ManyToOne
@JoinColumn(name = "group_id")
val playlistGroup: PlaylistGroupEntity
) No newline at end of file
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

git 에서 파일의 마지막 newline 을 넣는 것이 좋은 습관입니다.

Comment on lines +16 to +17
// @OneToMany(mappedBy = "album")
// val songs: List<SongEntity>,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

사용하지 않는 코드는 아예 지우는 것이 좋습니다.

@Repository
interface AlbumRepository : JpaRepository<AlbumEntity, Long> {
@Query("SELECT a FROM albums a LEFT JOIN FETCH a.artist " +
"WHERE a.title LIKE CONCAT('%',:title,'%') ORDER BY length(a.title) ASC")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

쿼리로 DB 에서 length() 로 order 하는 것보단, 일단 application (서버) 에 가져와서 코드로 sort 하는 게 성능상 더 나은 선택일 것 같습니다.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@davin111 성능상 더 나은 선택이라는 것이 궁금해서 혹시 이유도 설명해주실 수 있을까요? 저는 먼가 DB에서 최대한 덜 가져오는 것이 성능상 이점이 있을 것 같아서 저렇게 짜긴 했는데 인사이트가 궁금합니다(__)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ORDER BY 를 한다고 해서 DB 에서 가져오는 데이터 양이 줄어들진 않을 거고요. 정렬만 하는 거니까요. DB 에서 함수를 써서 연산을 가하면 index 를 일반적으로 사용할 수 없어서 느려집니다. 데이터 양이 많을수록 이는 치명적일 수 있고요.

import org.springframework.data.jpa.repository.Query
import org.springframework.stereotype.Repository

@Repository
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

참고로 JpaRepository interface 를 상속하는 경우, @Repository annotation 을 붙이지 않아도 됩니다.

Comment on lines +39 to +40
@Test
fun `로그인 상태로 플레이리스트 조회`() {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 테스트가 실패하네요.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@davin111 저번 세미나 때 PlaylistIntegrationTest 테스트에 Transactional 어노테이션을 붙히지 않아서 테스트끼리 독립되지 않아 개별 테스트로는 통과하지만 전체 테스트로 돌리게 되면 실패하는 것으로 피드백받았었습니다! 일단 개별 테스트 통과해서 제출은 했었는데 세미니장님이 이번 과제에 한해서 개별테스트는 통과하는 경우에는 통과하는 것으로 인정해주신다고 해서 따로 수정은 안했습니다:)

interface UserRepository : JpaRepository<UserEntity, Long> {
fun findByUsername(username: String): UserEntity?

override fun findById(id: Long): Optional<UserEntity>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이건 override 를 굳이 하셨을 필요가 없었을 거 같아요.

Comment on lines +32 to +34
if (playlistGroupList.isNotEmpty()){
return playlistGroupList
} else throw PlaylistNotFoundException()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

playlistGroupList 가 비었다면 빈 list 응답을 그대로 내려도 될 거 같아요. 그런데 만약 exception 을 던지기로 결정하셨다면, service 동작의 전반부에서 먼저 처리를 하는 식으로 순서를 바꾸면 좋겠습니다. early return pattern 이라고 불렀던 거 같네요.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@davin111 빈 list 응답이라는 것이 playlistGroupList 가 비었다면 서버에서 클라이언트로 빈 리스트를 보내준다는 것인걸까요?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵 그런 스펙과 구현도 충분히 가능하단 얘기였습니다.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

감사합니다:)

Comment on lines +23 to +31
val playlistGroupList = playlistGroupRepository.findAllByOpen(true)
.filter { it.playlists.isNotEmpty() }
.map {
playlistGroupEntity -> PlaylistGroup(
id = playlistGroupEntity.id,
title = playlistGroupEntity.title,
playlists = playlistGroupEntity.playlists.map {
playlistEntity -> PlaylistBrief(playlistEntity.id, playlistEntity.title, playlistEntity.subtitle, playlistEntity.image)
})}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분과 get() 메서드의 코드들이 더 간결할 수 있을 거 같은데, 세미나장의 구현을 참고해보셔도 좋을 듯 합니다. adbc14a#diff-fb8eefb0b18924930e6d751a08235b98aa23ada492f6ae4fe535a1ac8e54da12R21-R29

Comment on lines +11 to +18
@Query("SELECT p FROM playlists p " +
"LEFT JOIN FETCH p.playlistGroup " +
"LEFT JOIN FETCH p.playlistSongs ps " +
"LEFT JOIN FETCH ps.song s " +
"LEFT JOIN FETCH s.album a " +
"LEFT JOIN FETCH a.artist " +
"WHERE p.id = :id")
fun findByIDJoinFetch(id: Long) : PlaylistEntity?
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

막상 service 에서는 쿼리를 songRepository.findAllByIDListJoinFetch() 과 함께 나눠서 실행하는데, 여기서 불필요하게 너무 많이 join 해서 가져오는 듯한 느낌이 있네요. 이거 혹시 연관관계 FetchType 을 EAGER 로 해둬서 발생하는 N+1 때문이었다면, 다른 코멘트와 조합해서 생각해보시면 좋을 듯해요.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

N+1 때문이었던 것 맞아요! LAZY로 고쳐서 한번 시도해봐야겠네요. 감사합니다(__)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants