ํ ํ๋ก์ ํธ 2์ผ์ฐจ!
์ฐพ์๋ณด๋ ๊ฝค๋ ํํ? ์๋ฌ์ฝ๋์ ํด๋นํ๋ ๊ฒ ๊ฐ๋ค.
๋ฐ์ํ๋ ์ผ์ด์ค๊ฐ ๊ต์ฅํ ๋ง์ ๊ฒ ๊ฐ๋ค.
๋์ ๊ฒฝ์ฐ Springboot ํ๊ฒฝ์์ ๋ฐ์ํ๋ค.
์ผ๋จ ์๋ฌ์ ์ด์ ๋ ์๋ต๊ฐ์ฒด๋ฅผ Json์ผ๋ก ๋ณํํ์ง ๋ชปํ๋ ๋ฌธ์ ๋๋ฌธ์ด์๋ค.
์ด๊ฒ ์ 406์ธ์ง๋ ์ ๋ฉ๋์ด ์ ๋์ง๋ง ๊ทธ๋ ๋ค๊ณ ํ๋ค.. (๊ฐ์ฒด์ ์ ๊ทผ์ ๋ชปํ๋ค๋ ๋ป..?)
์๋ต๊ฐ์ฒด (์๋ตdto)๋ฅผ ๊ตฌ์ฑํ๊ณ Getter๋ฅผ ์ถ๊ฐํด์ค์ผ Spring์ด ๋ด๋ถ์ ์ผ๋ก Jsonํฌ๋งท์ผ๋ก ๋ณํํด์ค ์ ์๋ ๊ฒ์ด๋ค. ๊ธฐ์กด dto์ ๊ฒํฐ๋ฅผ ์ถ๊ฐํจ์ผ๋ก ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋๋ค.
ํ์ฌ ์ฝ๋๋ฆฌ๋ทฐ ์์ธ์ ๋ณด์๋ ์ฝ๋๋ฆฌ๋ทฐ์ ๋ํ ์ ๋ณด์ ํด๋น ์ฝ๋๋ฆฌ๋ทฐ๋ฅผ ๋จ๊ธด User, ํด๋น ์ฝ๋๋ฆฌ๋ทฐ์ ๋จ๊ฒจ์ง Comment(๋๊ธ)๋ก ์ด๋ค์ ธ ์๋ค.
์์ธ์ ๋ณด๋ฅผ ์กฐํํ ๋ User์ ๋ํ ์ ๋ณด์ Comment(๋๊ธ)์ ๋ํ ์ ๋ณด๋ฅผ ํจ๊ป ๊ฐ์ ธ์์ผ ํ๋ค.
์ฒ์ ์์ฑํ ์ฟผ๋ฆฌ๋ ์๋์ ๊ฐ๋ค. (๊ทธ๋ฅ ์ชผ์ธ..)
@Override
public ReviewRequestDetailResponseDto getReviewRequestDetailWithComment(Long id) {
ReviewRequest result = query.select(reviewRequest)
.from(reviewRequest)
.join(reviewRequest.reviewRequestComments, reviewRequestComment)
.join(reviewRequest.requestUser, user)
.where(reviewRequest.id.eq(id))
.fetchFirst();
List<CommentResponseDto> comments = result.getReviewRequestComments().stream().map(
c -> new CommentResponseDto(c.getId(), c.getUser().getId(), c.getUser().getUsername(), c.getContent(), c.getCreatedAt())
).collect(Collectors.toList());
return new ReviewRequestDetailResponseDto(
result.getId(), result.getRequestUser().getUsername(), result.getTitle(), result.getCode(), result.getComment(),
result.getStatus().toString(), result.getCreatedAt(), comments
);
}
์ฟผ๋ฆฌ๊ฒฐ๊ณผ๋ฅผ ๋ณด์.
ํ ๊ฐ์ ์ฝ๋๋ฆฌ๋ทฐ ์์ฒญ์์ ๋ ๋ช
์ ์ ์ ๊ฐ ๊ฐ๊ฐ ๋ ๊ฐ์ฉ ์ด 4๊ฐ์ ๋๊ธ์ด ๋ฌ๋ฆฐ ๊ฒฝ์ฐ์ ์ฟผ๋ฆฌ์ด๋ค.
Hibernate:
select
reviewrequ0_.id as id1_3_,
reviewrequ0_.created_at as created_2_3_,
reviewrequ0_.updated_at as updated_3_3_,
reviewrequ0_.answer_user_id as answer_u9_3_,
reviewrequ0_.code as code4_3_,
reviewrequ0_.comment as comment5_3_,
reviewrequ0_.language_name as language6_3_,
reviewrequ0_.request_user_id as request10_3_,
reviewrequ0_.review_answer_id as review_11_3_,
reviewrequ0_.status as status7_3_,
reviewrequ0_.title as title8_3_
from
review_request reviewrequ0_
inner join
review_request_comment reviewrequ1_
on reviewrequ0_.id=reviewrequ1_.review_request_id
inner join
user user2_
on reviewrequ0_.request_user_id=user2_.id
where
reviewrequ0_.id=? limit ?
Hibernate:
select
reviewrequ0_.review_request_id as review_r5_4_0_,
reviewrequ0_.id as id1_4_0_,
reviewrequ0_.id as id1_4_1_,
reviewrequ0_.created_at as created_2_4_1_,
reviewrequ0_.updated_at as updated_3_4_1_,
reviewrequ0_.content as content4_4_1_,
reviewrequ0_.review_request_id as review_r5_4_1_,
reviewrequ0_.user_id as user_id6_4_1_
from
review_request_comment reviewrequ0_
where
reviewrequ0_.review_request_id=?
Hibernate:
select
user0_.id as id1_5_0_,
user0_.created_at as created_2_5_0_,
user0_.updated_at as updated_3_5_0_,
user0_.password as password4_5_0_,
user0_.ranking_point as ranking_5_5_0_,
user0_.review_count as review_c6_5_0_,
user0_.user_role as user_rol7_5_0_,
user0_.username as username8_5_0_
from
user user0_
where
user0_.id=?
Hibernate:
select
user0_.id as id1_5_0_,
user0_.created_at as created_2_5_0_,
user0_.updated_at as updated_3_5_0_,
user0_.password as password4_5_0_,
user0_.ranking_point as ranking_5_5_0_,
user0_.review_count as review_c6_5_0_,
user0_.user_role as user_rol7_5_0_,
user0_.username as username8_5_0_
from
user user0_
where
user0_.id=?
Hibernate:
select
user0_.id as id1_5_0_,
user0_.created_at as created_2_5_0_,
user0_.updated_at as updated_3_5_0_,
user0_.password as password4_5_0_,
user0_.ranking_point as ranking_5_5_0_,
user0_.review_count as review_c6_5_0_,
user0_.user_role as user_rol7_5_0_,
user0_.username as username8_5_0_
from
user user0_
where
user0_.id=?
์ง____์ ๋ถ
๊ตณ์ด ํ๊ฐ ํ๊ฐ ์ถ์ ํด๋ณด์ง ์์๋ N+1์ด ํฐ์ง ๊ฒ์ ์ ์ ์๋ค.
์ฟผ๋ฆฌ์ ๊ฒฐ๊ณผ๋ฅผ DTO๋ก ๋ณํํ ๋ Lazy๋ก ์ค์ ๋ ํ๋ก์ ๊ฐ์ฒด๋ฅผ ์ค์ ๊ฐ์ฒด๋ก ๊ฐ์ ธ์ค๊ธฐ ์ํด ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ฆฐ๋ค. N+1 !..!
N+1์ ํนํจ์ฝ์ Fetch Join ์ด๋ค.
Querydsl์ ์ด์ฉํด์ ํจ์น์กฐ์ธ์ ์ ์ฉํด๋ดค๋ค.
@Override
public ReviewRequestDetailResponseDto getReviewRequestDetailWithComment(Long id) {
ReviewRequest result = query.select(reviewRequest).distinct()
.from(reviewRequest)
.join(reviewRequest.reviewRequestComments, reviewRequestComment).fetchJoin()
.join(reviewRequest.requestUser, user).fetchJoin()
.where(reviewRequest.id.eq(id))
.fetchFirst();
List<CommentResponseDto> comments = result.getReviewRequestComments().stream().map(
c -> new CommentResponseDto(c.getId(), c.getUser().getId(), c.getUser().getUsername(), c.getContent(), c.getCreatedAt())
).collect(Collectors.toList());
return new ReviewRequestDetailResponseDto(
result.getId(), result.getRequestUser().getUsername(), result.getTitle(), result.getCode(), result.getComment(),
result.getStatus().toString(), result.getCreatedAt(), comments
);
}
์ปฌ๋ ์
(๋๊ธ)์ ๊ธฐ์ค์ผ๋ก ํจ์น์กฐ์ธ์ ํ๋ ๊ฒฝ์ฐ ๋ฐ์ํ ์ ์๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด distinct()
๋ฅผ ์ถ๊ฐํ๋ค. (์ปฌ๋ ์
์ชฝ์ ๋ง์ถฐ์ ์กฐํ๊ฒฐ๊ณผ๊ฐ ๋์ด๋๋ ๋ฌธ์ )
fetchJoin() ์ ์ ์ฉํ ๊ฒฐ๊ณผ์ด๋ค.
Hibernate:
select
distinct reviewrequ0_.id as id1_3_0_,
reviewrequ1_.id as id1_4_1_,
user2_.id as id1_5_2_,
reviewrequ0_.created_at as created_2_3_0_,
reviewrequ0_.updated_at as updated_3_3_0_,
reviewrequ0_.answer_user_id as answer_u9_3_0_,
reviewrequ0_.code as code4_3_0_,
reviewrequ0_.comment as comment5_3_0_,
reviewrequ0_.language_name as language6_3_0_,
reviewrequ0_.request_user_id as request10_3_0_,
reviewrequ0_.review_answer_id as review_11_3_0_,
reviewrequ0_.status as status7_3_0_,
reviewrequ0_.title as title8_3_0_,
reviewrequ1_.created_at as created_2_4_1_,
reviewrequ1_.updated_at as updated_3_4_1_,
reviewrequ1_.content as content4_4_1_,
reviewrequ1_.review_request_id as review_r5_4_1_,
reviewrequ1_.user_id as user_id6_4_1_,
reviewrequ1_.review_request_id as review_r5_4_0__,
reviewrequ1_.id as id1_4_0__,
user2_.created_at as created_2_5_2_,
user2_.updated_at as updated_3_5_2_,
user2_.password as password4_5_2_,
user2_.ranking_point as ranking_5_5_2_,
user2_.review_count as review_c6_5_2_,
user2_.user_role as user_rol7_5_2_,
user2_.username as username8_5_2_
from
review_request reviewrequ0_
inner join
review_request_comment reviewrequ1_
on reviewrequ0_.id=reviewrequ1_.review_request_id
inner join
user user2_
on reviewrequ0_.request_user_id=user2_.id
where
reviewrequ0_.id=?
Hibernate:
select
user0_.id as id1_5_0_,
user0_.created_at as created_2_5_0_,
user0_.updated_at as updated_3_5_0_,
user0_.password as password4_5_0_,
user0_.ranking_point as ranking_5_5_0_,
user0_.review_count as review_c6_5_0_,
user0_.user_role as user_rol7_5_0_,
user0_.username as username8_5_0_
from
user user0_
where
user0_.id in (
?, ?
)
select ์ ์ด ํญ๋ฐ์ ์ผ๋ก ๋์์ง๋ง ๊ฒฐ๊ณผ์ ์ผ๋ก ์ฟผ๋ฆฌ์ ์๊ฐ ๋ํญ ์ค์ด๋ค์๋ค.
์ด๋ฒ ํ๋ก์ ํธ๋ ํ์์ ์ผ๋ก ๋ถํํ ์คํธ๋ฅผ ํฌํจํด์ผ ํ๊ธฐ ๋๋ฌธ์ ์ด๋ฐ ์ต์ ํ ํฌ์ธํธ๋ฅผ ๋จ๊ฒจ๋๊ณ ํ๋ก์ ํธ ๋ง๋ฐ์ง์ ์ฑ๋ฅ๋น๊ต๋ฅผ ํด๋ด์ผ๊ฒ ๋ค.