(4월28일)
storeId로 가게를 찾고OrderResponseDto로 변환해서@Transactional
public List<OrderResponseDto> getOrderList(Long storeId) {
Store store = entityFetcher.getStoreOrThrow(storeId);
List<Order> orderList = orderRepository.findAllByStore(store);
List<OrderResponseDto> orderResponseDtoList = new ArrayList<>();
for (Order order : orderList) {
OrderResponseDto orderResponseDto = new OrderResponseDto(order);
orderResponseDtoList.add(orderResponseDto);
}
return orderResponseDtoList;
}
@Transactional이 메서드는 트랜잭션 안에서 실행된다는 뜻
데이터베이스 작업(조회/수정 등)을 하나의 묶음으로 처리할 때 사용
여기서는 조회만 하니까, 엄밀히 말하면 @Transactional(readOnly = true)를 붙이면 더 최적화된다
public List<OrderResponseDto> getOrderList(Long storeId) {public:
→ 다른 클래스에서도 이 메서드를 자유롭게 호출할 수 있게 함
List<OrderResponseDto>:
→ 이 메서드가 반환(return) 하는 값은
OrderResponseDto 객체들의 리스트(목록) 라는 뜻
getOrderList(Long storeId):
→ 메서드 이름은 getOrderList고,
Long 타입의 storeId를 매개변수(parameter) 로 받음
Store store = entityFetcher.getStoreOrThrow(storeId);storeId를 가지고, Store 객체를 하나 가져온다
만약 storeId에 해당하는 가게가 없으면 예외를 던진다(throw)
List<Order> orderList = orderRepository.findAllByStore(store);방금 가져온 Store에 해당하는 모든 주문(Order) 들을 데이터베이스에서 가져온다
그래서 orderList 안에는 Order 객체들이 쭉 여러 개 담긴다
List<OrderResponseDto> orderResponseDtoList = new ArrayList<>();이제 결과를 담을 빈 리스트(empty list) 하나 만든다
타입은 OrderResponseDto들의 리스트
처음에는 아무것도 안 들어있음
for (Order order : orderList) { ... }향상된 for문(Enhanced For Loop) 이다
orderList 안에 있는 각 Order 객체를 하나씩 꺼내서
order라는 이름으로 사용하겠다는 뜻
예를 들면:
orderList = [OrderA, OrderB, OrderC]
첫 번째 반복: order = OrderA
두 번째 반복: order = OrderB
세 번째 반복: order = OrderC
즉, orderList에 있는 주문들을 하나하나 다루는 것
OrderResponseDto orderResponseDto = new OrderResponseDto(order);Order 객체 하나를
OrderResponseDto라는 DTO 객체로 변환한다
DTO는
"Data Transfer Object" — 즉,
데이터를 주고받을 때 필요한 형식으로 만든 객체를 말한다
(프론트엔드나 다른 서비스에 넘길 때 쓸 모델)
orderResponseDtoList.add(orderResponseDto);새로 만든 OrderResponseDto를
아까 만든 orderResponseDtoList에 추가(add)한다
반복될 때마다
orderResponseDto가 하나씩 리스트에 쌓인다
return orderResponseDtoList;마지막으로, 모든 변환이 끝난 OrderResponseDto 리스트를
결과값으로 반환(return) 한다
@Transactional(readOnly = true)
public List<OrderResponseDto> getOrderList(Long storeId) {
Store store = entityFetcher.getStoreOrThrow(storeId);
List<Order> orderList = orderRepository.findAllByStore(store);
List<OrderResponseDto> orderResponseDtoList = orderList.stream()
.map(order -> new OrderResponseDto(order))
.collect(Collectors.toList());
return orderResponseDtoList;
}
orderList.stream()orderList를 스트림(Stream) 으로 변환
스트림은 "데이터의 흐름"을 만들어서 데이터를 하나하나 다루는 파이프라인처럼 동작한다
orderList = [OrderA, OrderB, OrderC]
stream()을 호출하면
OrderA → OrderB → OrderC 하나씩 처리할 수 있는 흐름(Stream)이 만들어진다
.map(order -> new OrderResponseDto(order))스트림 안의 Order 하나를 꺼내서
OrderResponseDto로 변환하는 작업을 정의하는 것
map은:
"무언가를 받아서 다른 무언가로 변환" 하는 역할을 한다
예시로 보면:
OrderA → OrderResponseDtoA
OrderB → OrderResponseDtoB
OrderC → OrderResponseDtoC
이렇게 각각 변환된다
order -> new OrderResponseDto(order)new OrderResponseDto(order)를 반환하라"는 뜻이다.collect(Collectors.toList())OrderResponseDto들을 하나하나 다시 리스트(List) 로 모은다collect는:
"스트림 작업이 끝나면 결과를 모아서 담아라"는 뜻
Collectors.toList()는 스트림으로 흘러간 결과를List<OrderResponseDto> orderResponseDtoList = ...List<OrderResponseDto>를 변수에 저장한다return orderResponseDtoList;orderList를 Stream으로 → 각 Order를 OrderResponseDto로 변환(map) →
변환한 것들을 모아서 List로 수집(collect) → 반환
| 구분 | for문 방식 | Stream 방식 |
|---|---|---|
| Order 하나씩 꺼내기 | for (Order order : orderList) | orderList.stream() |
| 변환 방법 | new OrderResponseDto(order) | .map(order -> new OrderResponseDto(order)) |
| 리스트에 추가하기 | orderResponseDtoList.add(orderResponseDto) | .collect(Collectors.toList()) |
가독성: 코드가 짧고 깔끔해진다
선언형 프로그래밍: "어떻게"가 아니라 "무엇을 할지"를 표현할 수 있다
병렬처리(Parallel Stream) 도 쉽게 적용할 수 있다 (.parallelStream())
List<Order> orderList
↓ stream()
Order 객체 하나하나 흐름 만들기
↓ map()
Order를 OrderResponseDto로 변환
↓ collect()
변환한 것들 리스트로 모으기
↓ return
for문은 익숙하고 이해가 쉽다.
Stream은 간결하고 트렌디하다.
성능은 거의 차이 없다. (아주 극한 상황 아니면)