1. 문제 정의
본인 선택 가게 주문 내역 받아오기 기능을 생성 후 기능을 사용하였을 때 여러건의 주문이 있는경우 리스트 형태로 잘 나오기는 하지만 변경된 시간과 상관없이 나중에 만들어진 주문이 상단에 나타나는 현상이 있음
해당 기존 코드 - ( OwnerStoreService.java 일부 )
public CommonListResDto<ResponseViewOrderDto> viewStoreOrders(Long id, HttpServletRequest request) {
User user = (User) request.getSession().getAttribute(Const.LOGIN_USER);
Store store = ownerStoreRepository.findByIdAndUserId(id, user.getId())
.orElseThrow(() -> new StoreNotFoundException("가게를 찾을 수 없습니다."));
if(store.getStatus() == StoreStatus.CLOSED){
throw new StoreNotFoundException("폐업된 가게입니다.");
}
List<Order> orders = store.getOrders();
List<ResponseViewOrderDto> orderDtos = new ArrayList<>();
for (Order order : orders) {
String mainMenu = "";
double maxPrice = 0.0;
int totalMenuCount = order.getOrderMenus().size();
for (OrderMenu orderMenu : order.getOrderMenus()) {
double menuPrice = orderMenu.getMenu().getPrice();
if (menuPrice > maxPrice) {
maxPrice = menuPrice;
mainMenu = orderMenu.getMenu().getName();
}
}
ResponseViewOrderDto dto = new ResponseViewOrderDto(
order.getId(),
order.getStatus(),
order.getUser().getAddress(),
mainMenu,
totalMenuCount
);
orderDtos.add(dto);
}
return new CommonListResDto<>("주문내역 조회 완료", orderDtos);
}
해당 메서드의 흐름을 살펴보면
1. 세션에서 사용자의 정보를 가져오고, ownerStoreRepository를 통해 가게Id와 유저Id로 해당 가게를 조회한다.
2. 주문내역을 List<Order>에 담는다.
3. DTO 형식에 맞게 생성하여 반환한다
기존의 코드는 위와 같은 형태를 가지고 있었다.
2. 원인
내가 생각하는 원인은 테이블에 저장된 그대로를 불러오기 때문이라고 생각했다.
List<Order> orders = store.getOrders(); //주문 내역을 받아오는 기능
당시에는 주문 내역을 받아와 리스트에 저장을 하고 있었다.
명시적으로 정렬을 해주지 않을 경우 레코드가 반환되는 순서는 보장되지 않는데 많은 데이터베이스에서 정렬이 사용되지 않은 경우에는 기본키(id)의 순서대로 레코드를 반환한다고 한다.
나도 정렬을 따로 수행해주지 않았기 때문에 이러한 문제가 발생한 것이라 의심하였다.
3. 해결방안
그럼 정렬만 해주면 되겠다. 라는 생각이 들었다.
orders.sort((o1, o2) -> o2.getUpdatedAt().compareTo(o1.getUpdatedAt()));
List.sort메서드와 람다표현식을 이용하여 정렬을 진행하기로 하였고 정렬의 기준은 각 Order객체의 updatedAt필드를 기준으로 잡았다.
이 코드를 이용하여 updatedAt이 가장 최신순으로 정렬을 진행하였더니 원하던대로 최근에 수정된 레코드의 값을 더 상위에 노출되게 할 수 있었다.
이로써 명시적으로 정렬을 해주었기 때문에 더 이상 기본키의 순서대로 레코드를 반환하는 일 없이 가장 최근에 변경된 레코드 부터 상위에 노출이 될 것이다.
수정된 메서드
public CommonListResDto<ResponseViewOrderDto> viewStoreOrders(Long id, HttpServletRequest request) {
User user = (User) request.getSession().getAttribute(Const.LOGIN_USER);
Store store = ownerStoreRepository.findByIdAndUserId(id, user.getId())
.orElseThrow(() -> new StoreNotFoundException("가게를 찾을 수 없습니다."));
if(store.getStatus() == StoreStatus.CLOSED){
throw new StoreNotFoundException("폐업된 가게입니다.");
}
List<Order> orders = store.getOrders();
orders.sort((o1, o2) -> o2.getUpdatedAt().compareTo(o1.getUpdatedAt()));
List<ResponseViewOrderDto> orderDtos = new ArrayList<>();
for (Order order : orders) {
String mainMenu = "";
double maxPrice = 0.0;
int totalMenuCount = order.getOrderMenus().size();
for (OrderMenu orderMenu : order.getOrderMenus()) {
double menuPrice = orderMenu.getMenu().getPrice();
if (menuPrice > maxPrice) {
maxPrice = menuPrice;
mainMenu = orderMenu.getMenu().getName();
}
}
ResponseViewOrderDto dto = new ResponseViewOrderDto(
order.getId(),
order.getStatus(),
order.getUser().getAddress(),
mainMenu,
totalMenuCount
);
orderDtos.add(dto);
}
return new CommonListResDto<>("주문내역 조회 완료", orderDtos);
}
4. 테스트
수정된 api가 제대로 작동하는지 확인을 위한 테스트를 진행하였다.

두개의 주문을 넣어서 진행하였고 코드를 수정하기 전과는 별다른 차이를 보이지 않는다.
updatedAt이 만들어질때 생성되기 때문에 나중에 만들어진 순서대로 3번, 2번 .. 이런식으로 보이고 있는 것이다.
코드가 제대로 작동하는지 확인을 위하여 id값 2번의 주문의 상태를 변경해주었다.
unchecked -> cooking으로 상태를 변경해 주었고 이를 실행함에 있어 updatedAt의 값이 최신값으로 변경 되는것을 볼 수 있었다.


테이블을 확인해 보아도 확실히 id값 2번의 updated_at의 값이 3번의 값보다 최근의 시간값으로 들어가 있음을 확인할 수 있다.
5. 결론
이 트러블 슈팅을 통해 주문내역의 정렬문제를 해결하였다. 정렬을 해주지 않을 경우 DB마다 어떻게 처리가 되는지 다르다는 것을 확인해 보았고 사용하게 되는 DB별로 한번씩 확인해 봐야겠다는 생각이 들었다. 또한 명시적인 정렬을 통해 사용자가 가장 최근에 업데이트된 주문 내역을 확인할 수 있게 되었고, 이러한 내역들은 사용자 경험을 크게 향상시킬 것이다.