์๋ก
์.. ํฌ๊ฒ ์ค๋ฅ๊ฐ ๋์ง ์์๊ณ , ์ด์ ํ๋ก์ ํธ์ ๋นํด ํด๊ฒฐํ๋ ๋ฐ์ ๋ช ์๊ฐ ๊ฑธ๋ฆฌ๋ ์ผ๋ ์์ด์ ๋ฌด์ฒ ๋จ์ํ๊ณ ๊ฐ๋จํ ๊ฒ๋ค์ผ ์๋ ์๋ค.
ํ์ง๋ง ๋๋ ์๋กญ๊ฒ ์๊ฒ๋ ์ ๋ค์ด ์ฐธ ๋ง๋ค........
1. ์ฑ๋ฅ ๊ฐ์
์ฐ๊ด ๊ด๊ณ ๋งคํ? ๋ฉ์๋ ์ฒด์ด๋์ผ๋ก ์กฐํํ๋ ๋ถ๋ถ์ JPQL๋ก ์กฐํํ๋ฉด์ select ๋ฌธ์ด 2๊ฐ์์ 1๊ฐ๋ก ์ค์๋ค.
์ ์ง ์ฑ๋ฅ ๊ฐ์ ์ ์์ฒญ๋ ์ฐจ์ด๋ก ๊ฐ์ ํด์ผํ๋ ๋๋์ธ ๋ฏํ์ฌ.. ์ด๋ฐ ๊ฑธ ์ฑ๋ฅ ๊ฐ์ ์ด๋ผ๊ณ ํํํด๋ ๋ ์ง ๋ชจ๋ฅด๊ฒ ์ง๋ง..?
— ์ด๊ธฐ ์ฝ๋
// Service
UUID ownerUser = menu.getRestaurant().getOwner().getUserId();
์คํ๋๋ select ๋ฌธ๋ค
Hibernate:
select
m1_0.rm_id,
m1_0.created_at,
m1_0.created_by,
m1_0.deleted_at,
m1_0.deleted_by,
m1_0.is_public,
m1_0.modified_at,
m1_0.modified_by,
m1_0.res_id,
m1_0.rm_description,
m1_0.rm_image_url,
m1_0.rm_name,
m1_0.rm_price
from
p_restaurant_menu m1_0
where
m1_0.rm_id=?
Hibernate:
select
r1_0.res_id,
r1_0.created_at,
r1_0.created_by,
r1_0.deleted_at,
r1_0.deleted_by,
r1_0.modified_at,
r1_0.modified_by,
r1_0.res_owner_id,
r1_0.res_address,
r1_0.res_image_url,
r1_0.res_name,
r1_0.res_phone
from
p_restaurant r1_0
where
r1_0.res_id=?
— ์์ ํ
// Service
UUID ownerUser = menuRepository.getRestaurantOwnerId(menu.getRmId());
// Repository
@Query("Select u.userId from User u join Restaurant r on r.owner.userId = u.userId join Menu m on m.restaurant.resId = r.resId where m.rmId = :rmId ")
UUID getRestaurantOwnerId(@Param("rmId") UUID rmId);
์คํ๋๋ select ๋ฌธ
Hibernate:
select
u1_0.user_id
from
p_users u1_0
join
p_restaurant r1_0
on r1_0.res_owner_id=u1_0.user_id
join
p_restaurant_menu m1_0
on m1_0.res_id=r1_0.res_id
where
m1_0.rm_id=?
โ ๏ธ ๊ธฐ์กด ์ฝ๋์ ๋ฌธ์ ์
๊ฐ๋ ์ฑ์ด ์ข์ง ์๊ณ ,
์ฐ๊ด๋ ํ
์ด๋ธ์ ํ๊ณ , ํ๊ณ ๊ฐ์ userId๋ฅผ ์กฐํํ๊ธฐ ๋๋ฌธ์ N+1 ๋ฌธ์ ๊ฐ ๋ฐ์ํ ๊ฐ๋ฅ์ฑ์ด ์์๋ค.
select๋ฌธ์ด 2๋ฒ๋ง ๋๊ฐ ๊ฒ ๋ณด๋ฉด ๋คํํ ๋ฐ์ํ์ง ์์ ๋ฏ ํ์ง๋ง!
์ข์ ์๋์๋ค.
2. Querydsl BooleanExpression
JPA Querydsl์ ํ๋ก์ ํธํ๋ฉด์ ์ฃผ๋จน๊ตฌ๊ตฌ์์ผ๋ก ๊ฒฝํํด๋ณธ ๊ฑฐ๋ผ ๋์น๊ณ ์๋ ๋ถ๋ถ์ด ๋ง์ ๊ฒ ๊ฐ๋ค.
@Override
public List<Menu> findMenusByResIdAndRole(UUID resId, UserDetailsImpl userDetails) {
QMenu menu = QMenu.menu;
UserRoleEnum role = userDetails.getRole();
UUID userId = userDetails.getUserId();
boolean isOwner = isOwner(userId, resId);
BooleanExpression condition = menu.restaurant.resId.eq(resId);
// role๊ณผ OWNER id ์ผ์น ์ฌ๋ถ์ ๋ฐ๋ฅธ condition ์ถ๊ฐ
if (role.equals(UserRoleEnum.CUSTOMER) || (role.equals(UserRoleEnum.OWNER) && !isOwner)) {
log.info("role : {}", role);
// condition.and(menu.isPublic.eq(true)); - ํ๋ฆฐ ์ฝ๋
condition = condition.and(menu.isPublic.eq(true));
}
return jpaQueryFactory.selectFrom(menu).where(condition).fetch();
}
BooleanExpression์ ๋ฐํํ๋ condition ์๋ค๊ฐ ์กฐ๊ฑด์ ๋ฐ๋ผ์ condition์ ์ถ๊ฐํ๋ ์ฝ๋๋ฅผ ์์ฑํ๋๋ฐ ์ ๋๋ก ์๋ํ์ง ์์๋ค.
BoleanExpression์ ๋ถ๋ณ๊ฐ์ฒด์ด๊ธฐ ๋๋ฌธ์ ์๋กญ๊ฒ ์ ์ฅํด์ค์ผ ํ๋ค.
๊ทธ๋์
condition.and(menu.isPublic.eq(true)); ๊ฐ ์๋
condition = condition.and(menu.isPublic.eq(true)); ๋ก ์ ์ด์ ๊ผญ ๊ฐ์ ๋ค์ ๋ฃ์ด์ฃผ์ด์ผ ํ๋ค!!!!โญโญโญโญโญโญโญโญโญ
3. HTTP ์๋ต๊ฐ์ ๋ํ ๊ณ ๋ฏผ
PATCH ๋ฉ์๋๋ก ๋ฐ์ดํฐ๋ฅผ ์์ ํ๋ api์ ์ญ์ ํ๋ api ๋ฅผ ๊ตฌํํ๋๋ฐ ๋ฐํ๊ฐ์ ์ด๋ป๊ฒ ๋ณด๋ด์ผํ ์ง ์กฐ๊ธ ๊ณ ๋ฏผํ๋ค.
- ์์ ์ ๊ฒฝ์ฐ, ์์ ํ ๊ฐ์ ํด๋ผ์ด์ธํธ๊ฐ ๋ค์ ๋ณด์ฌ์ฃผ์ด์ผ ํ ๊ฒ ๊ฐ์์ 200 OK๋ก ๋ฐ์ดํฐ ๊ฐ์ ์๋ต์ ๋ณด๋๋ค.
- ์ญ์ ์ ๊ฒฝ์ฐ, ์ญ์ ํ ๊ฐ์ด ํด๋ผ์ด์ธํธ์ ๋ฐํ๋ ํ์๊ฐ ์์ผ๋๊น 204 NO CONTENT๊ฐ ๋ง๋ ๊ฒ ๊ฐ์๋ฐ, ์ฐ๋ฆฌ ํ๋ก์ ํธ์์ ์๋ต ๊ฐ์ ๋ณด๋ผ ๋ CommonResponse ์ ๋ด์์ ๋ณด๋ด๊ณ , ์ด๊ณณ์๋ SUCCESS CODE์ result๊ฐ ๋ด๊ธฐ๋๋ก ๊ตฌํ๋์ด ์๋ค. ๊ทธ๋์ ๋ณด๋ผ ๋ฐ์ดํฐ๊ฐ ์๋ ๊ฒฝ์ฐ์๋ CommonResponse์ ๋ด์์ ๋ณด๋ด๋ ๊ฒ ๋ง๋์ง..? ๊ทธ๋ฅ nocontent().build()๋ก ๋ง๋ฌด๋ฆฌํ๋ฉด ๋๋์ง ๊ณ ๋ฏผํ๋ค. ์ ํฉํ ๋ต์ด ๋ญ์ง๋ ์ฐพ์ง ๋ชปํ๋ค.. ๊ทธ๋ฅ ๋ฐฉ์์ ๊ฒฐ์ ํ์ ๋ฟ! nocontent().build()๋ก ์์ฑํ๋ค.
< 200๋ฒ๋ HTTP ์ํ ์ฝ๋ >
- 200 OK
- ์์ฒญ ์ฑ๊ณต, ์์ฒญ์ด ์ ์์ ์ผ๋ก ์ฒ๋ฆฌ๋จ
- 201 Created
- ์์ฒญ ์ฑ๊ณต, ์๋ก์ด ๋ฆฌ์์ค๊ฐ ์์ฑ๋จ
- 202 Accepted
- ์์ฒญ ์๋ฝ, ์์ฒญ์ด ์ฑ๊ณต์ ์ผ๋ก ์๋ฝ๋์์ง๋ง, ์์ง ์๋ฃ๋์ง ์์ (๋น๋๊ธฐ์ ์ฒ๋ฆฌ)
- 204 No Content
- ์์ฒญ ์ฑ๊ณต, ๋ฐํํ ๋ด์ฉ์ด ์์ (์ฃผ๋ก DELETE ์์ฒญ์ ์๋ต)
Exception ๋ํ ๋ฌด์ ๊ฒฝํ๊ฒ ์์ฑํ๋ค๊ฐ ์์ ํ๋ค.
< Exception HTTP ์ํ ์ฝ๋ >
- 401 UNAUTHORIZED
- ์ธ์ฆ์ด ํ์ํ ์์ฒญ์ด๊ฑฐ๋ ์ธ์ฆ์ ์คํจํจ
- 403 FORBIDDEN
- ๋ฆฌ์์ค๋ ์กด์ฌํ์ง๋ง, ํด๋ผ์ด์ธํธ์๊ฒ ํด๋น ๋ฆฌ์์ค์ ๋ํ ์ ๊ทผ ๊ถํ์ด ์์
- 404 NOT_FOUND
- ์์ฒญํ ๋ฆฌ์์ค๋ฅผ ์ฐพ์ ์ ์์
๋๋ ์
์์ ์๋ ๊ทธ๋ฅ OK๋ก ๋ชจ๋ ๋ณด๋ด๋ฒ๋ ธ๊ณ , ๊ฐ๊ฐ์ ์ฐจ์ด๋ ์ ์์ง ๋ชปํ๋๋ฐ (์์๋ณผ ์๊ฐ๋ ์ํ๊ณ ๊ทธ๋ฅ ๊ธฐ๋ฅ ๊ตฌํ์๋ง ์ด์ ์ ๋์๋ ์๋ ..ใ ) ์ง์ ์ข ์ฐพ์๋ณผ ๊ฑธ ๊ทธ๋ฌ๋ค ใ ใ ..............
'TIL' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
PageableArgumentResolver๋ฅผ ํ์ฉํ @Pageable ํ์ด์ง ์ฌ์ด์ฆ ์ ํ (0) | 2025.02.24 |
---|---|
WebClient์ RestTemplate ๊ทธ๋ฆฌ๊ณ RestClient (0) | 2025.02.21 |
REST API | ๋ฐ์ดํฐ ์์ api ์ด๋ป๊ฒ ๊ตฌํํ ๊น? (PATCH์ @DynamicUpdate ์ฐจ์ด์ ) (0) | 2025.02.19 |
REST API ์์์ HTTP ์๋ต ์ฝ๋ (HTTP 201 Created) (2) | 2025.02.18 |
Spring JPA | Entity์ Dto ๋ถ๋ฆฌ (0) | 2025.02.17 |