๐Ÿ”ฅ TIL - Day 63

Kim Dae Hyunยท2021๋…„ 11์›” 23์ผ
0

TIL

๋ชฉ๋ก ๋ณด๊ธฐ
74/93

ํŒ€ ํ”„๋กœ์ ํŠธ 2์ผ์ฐจ!

๐Ÿ“Œ ์˜ค๋Š˜์˜ ๊ตฌํ˜„์ด์Šˆ

  • ์ฒ˜์Œ๋ณด๋Š” ์—๋Ÿฌ.. 406 not acceptable
  • ์ฝ”๋“œ๋ฆฌ๋ทฐ ์ƒ์„ธ์ •๋ณด ์ฟผ๋ฆฌ ์ตœ์ ํ™”

๐Ÿ“Œ 406 not acceptable

์ฐพ์•„๋ณด๋‹ˆ ๊ฝค๋‚˜ ํ”ํ•œ? ์—๋Ÿฌ์ฝ”๋“œ์— ํ•ด๋‹นํ•˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค.
๋ฐœ์ƒํ•˜๋Š” ์ผ€์ด์Šค๊ฐ€ ๊ต‰์žฅํžˆ ๋งŽ์€ ๊ฒƒ ๊ฐ™๋‹ค.

๋‚˜์˜ ๊ฒฝ์šฐ 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 ์ ˆ์ด ํญ๋ฐœ์ ์œผ๋กœ ๋Š˜์—ˆ์ง€๋งŒ ๊ฒฐ๊ณผ์ ์œผ๋กœ ์ฟผ๋ฆฌ์˜ ์ˆ˜๊ฐ€ ๋Œ€ํญ ์ค„์–ด๋“ค์—ˆ๋‹ค.



์ด๋ฒˆ ํ”„๋กœ์ ํŠธ๋Š” ํ•„์ˆ˜์ ์œผ๋กœ ๋ถ€ํ•˜ํ…Œ์ŠคํŠธ๋ฅผ ํฌํ•จํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Ÿฐ ์ตœ์ ํ™” ํฌ์ธํŠธ๋ฅผ ๋‚จ๊ฒจ๋†“๊ณ  ํ”„๋กœ์ ํŠธ ๋ง‰๋ฐ”์ง€์— ์„ฑ๋Šฅ๋น„๊ต๋ฅผ ํ•ด๋ด์•ผ๊ฒ ๋‹ค.

profile
์ข€ ๋” ์ฒœ์ฒœํžˆ ๊นŒ๋จน๊ธฐ ์œ„ํ•ด ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค. ๐Ÿง

0๊ฐœ์˜ ๋Œ“๊ธ€