안녕하세요 이번글은 제가 메뉴리스트를 우선순위별로 불러오면서 겪었던 문제입니다.
메뉴그룹과 메뉴를 불러와야하기때문에 저는 아래 코드와같이
1. 먼저 storeId가 존재하는지 확인하고
2. 매장의 메뉴그룹리스트를 불러옵니다.
3. 메뉴그룹리스트의 메뉴그룹의 아이디를 통해서 menuMapper를 통해 각 메뉴리스트들을 가져옵니다.
MenuListResponseDto에는 ( id, List<MenuDto>) 를 속성으로 가집니다.
쿼리에서 정렬을 수행해주기때문에 저는 이상이없다고 생각했습니다.
그런데 문제점이있습니다. 위의 코드와 같이 한다면 steam을 돌면서 매장의 메뉴그룹마다 db를 호출해야하기때문에 수가 많아진다면 n번 만큼 호출하게 됩니다. 그래서 다음 작업은 db호출을 줄이고 Map 자료구조를 이용하는방법입니다.
HashMap을 사용한다면 자료가 들어간 순서대로 담아지지 않기때문에 LinkedHashMap을 사용했습니다.
/**
* LinkedHashMap을 사용한 이유는 menuGroupId를 우선순위별로 정렬해서 받아오기때문에
* map에 넣으면서 조회한 순서대로 담기위해서 사용했습니다.
*/
public Map<Long, List<MenuDto>> getMenuList(Long storeId) {
storeMapper.findById(storeId).orElseThrow(
() -> new MenuException("존재하지않는 매장입니다", HttpStatus.NOT_FOUND)
);
List<MenuDto> menuList = menuMapper.findAllByStoreId(storeId);
Map<Long, MenuListResponseDto> map = new LinkedHashMap<>();
for (int i = 0; i < menuList.size(); i++) {
MenuDto menuDto = menuList.get(i);
Long menuGroupId = menuDto.getMenuGroupId();
if (!map.containsKey(menuGroupId)) {
map.put(menuGroupId, new MenuListResponseDto(menuGroupId));
}
MenuListResponseDto menuListResponseDto = map.get(menuGroupId);
menuListResponseDto.insertMenu(menuDto);
map.put(menuGroupId, menuListResponseDto);
}
List<MenuListResponseDto> responseList = new ArrayList<>(map.values());
return map;
}
}
세번째 Map을 반환하지않고 Dto List를 반환하는코드입니다.
public List<MenuListResponseDto> getMenuList(Long storeId) {
storeMapper.findById(storeId).orElseThrow(
() -> new MenuException("존재하지않는 매장입니다", HttpStatus.NOT_FOUND)
);
List<MenuDto> menuList = menuMapper.findAllByStoreId(storeId);
Map<Long, MenuListResponseDto> map = new LinkedHashMap<>();
for (int i = 0; i < menuList.size(); i++) {
MenuDto menuDto = menuList.get(i);
Long menuGroupId = menuDto.getMenuGroupId();
if (!map.containsKey(menuGroupId)) {
map.put(menuGroupId, new MenuListResponseDto(menuGroupId));
}
MenuListResponseDto menuListResponseDto = map.get(menuGroupId);
menuListResponseDto.insertMenu(menuDto);
map.put(menuGroupId, menuListResponseDto);
}
return new ArrayList<>(map.values());
}
결과는 원하는대로 우선순위가 정렬되도록 나옵니다.
그러나, 너무 db를 줄이는대신 자바코드로 활용할려고했던것입니다. 그리고 처리하는게 많아지기때문에 속도도 더 느려집니다.
그래서 더 좋은 방법이 있습니다.
마지막 최종 코드입니다.
<select id="findAllByStoreId" resultType="MenuDto">
SELECT m.id, m.menu_group_id, m.name, m.info, m.price, m.status, m.priority
FROM menu m, menu_group mg
WHERE m.menu_group_id = mg.id AND mg.store_id = #{storeId}
ORDER BY mg.priority ASC, m.priority ASC;
</select>
바로 쿼리문으로 간단하게 정렬을 해주는 기능을 이용하는것이었습니다.
제가 놓치고있던부분은
이번프로젝트에서는 db를 I/O를 생각하면서 코딩하자 였는데 db를 줄이는대신 자바코드로만 해결하자는걸로만 생각을 해서 바로 이 결과에 도달하지못했습니다.
그리고 추가적으로 존재하는지는 List를 보내줄때 존재하지않으면 빈 리스트를 보내주면되기때문에 존재여부를 코드맨앞에서 체크를 안해도된다고 생각했습니다.
결론적으로는 간단한부분이지만 코딩하면서 꼭 어렵게만 생각했기때문에 이런 과정을 거친 결과가 나온것같습니다.
또한 이전까지는 JPA를 사용해 자동으로 되었던것을 사용하다가 mybatis를 사용하면서 쿼리를 사용하지 않으려고 했던것도있습니다. 쉬운 코드지만 많은 느낌을 받게되었습니다.
'Delivery' 카테고리의 다른 글
Redis 장바구니 - 2 (Redis pipelining) (0) | 2022.08.18 |
---|---|
Redis를 이용한 장바구니 - 1 (0) | 2022.08.15 |
캐싱전략, 메모리 (0) | 2022.08.05 |
레디스를 선택한 이유, 세션클러스터링 (0) | 2022.08.05 |
레디스에 대해 알아보자 (0) | 2022.08.05 |