Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 | 31 |
Tags
- R
- coding test
- C 언어 코딩 도장
- 이스케이프 문자
- Serialization
- s
- Graph
- insertion sort
- list 컬렉션
- JSON
- 윤성우 열혈자료구조
- 알기쉬운 알고리즘
- datastructure
- buffer
- 메모리구조
- Selection Sorting
- 이것이 자바다
- C programming
- stream
- 혼자 공부하는 C언어
- Stack
- 윤성우의 열혈 자료구조
- Algorithm
Archives
- Today
- Total
Engineering Note
[Java] Stream API 실전 예제(Entity/DTO 변환 과정: forEach -> map 리팩토링) 본문
Programming Language/Java
[Java] Stream API 실전 예제(Entity/DTO 변환 과정: forEach -> map 리팩토링)
Software Engineer Kim 2025. 10. 4. 22:44Entity와 DTO 변환 과정을 for문 대신 Stream으로 변환하면서 알게된 내용을 정리하려고 한다.
1. 초기 forEach를 사용한 비효율적인 방식 코드
public List<OrderDto> converWithForEach(List<Order> orderEntities) {
List<OrderDto> orderDtos = new ArrayList<>();
orderEntities.stream().forEach(order ->{
OrderDto dto = OrderDto.from(order);
orderDtos.add(dto);
});
return orderDtos;
}
forEach 방식의 문제점
함수형 프로그래밍 위반
: 스트림 파이프라인 외부에서 선언된 orderDtos라는 변이 가능한 상태를 스트림 내부에서 변경해야 하는데 이는 함수형 프로그래밍 원칙에 위반됩니다.(병렬 스트림 처리시 스레드 안전성 문제를 야기할 수 있습니다.)
: 가독성 측면에서도 new ArrayList<>() 선언과 forEach 내부 로직 때문에 코드가 불필요하게 늘어납니다.
2. 리팩토링:map과 collect를 사용한 모범 사례
map을 사용하여 Entity를 DTO로 변환하고, collect를 사용하여 변환된 결과를 새로운 리스트로 안전하게 수집합니다.
public List<OrderDto> convertWithStreamMap(List<Order> orderEntities){
List<OrderDto> orderDtos = orderEntities.stream().map(OrderDto::from).collect(Collectors.toList());
return orderDtos;
}
3. 사용된 디자인 패턴 :정적 팩터리 메서드(OrderDto.from)
이 방식의 효율성은 DTO 클래스 내에 변환 로직을 캡슐화한 정적 팩터리 메서드가 있기에 가능합니다.
@Getter
@Setter
@AllArgsConstructors
public class OrderDto{
private Long id;
private String orderNumber;
private List<OrderItemDto> items;
//정적 팩터리 메서드: Entity를 받아 DTO 생성, 반환
public static OrderDto from(Order order){
//중적 리스트 속성은 내부에서 다시 stream map을 통해 재귀적 변환
List<OrderItemDto> itemDtos = ordergetItems().stream().map(OrderItemDto::from).collect(Collectors.toList());
return new OrderDto(order.getId(), order.getOrderNumber(), itemDtos);
}
}
4. 핵심 동작 원리: map 함수의 역할
map 함수는 stream 파이프라인에서 중간 연산을 담당하는 가장 중요한 메서드입니다.
Map 함수의 정의
map 함수는 이 스트림의 각 요소에 주어진 함수(mapper)를 적용한 결과로 구성된 새로운 스트림을 반환 합니다.
| 요소 | 동작 설명 |
| 입력 스트림 | Stream<Order> (Entity 타입의 요소들) |
| 주어진 함수 (Mapper) | OrderDto::from (Orer Entity를 OrderDto로 변환하는 정적 팩터리 메서드) |
| 변환 | map은 스트림의 각 Order 요소에 OrderDto::from을 적용합니다. 이 함수의 반환 값은 새로운 OrderDto 객체입니다. |
| 출력 스트림 | Stream<OrderDto> (새로운 DTO 타입의 요소들로 구성된 스트림) |
ModelMapper 라이브러리를 사용하면 DTO와 Entity 간 변환을 편리하게 할 수 있지만, 이번 리팩토링을 통해 정적 팩토리 메서드를 통해 코드의 가독성을 높이는 방식과 stream map 함수의 사용 방식에 대해 자세히 알게 되었다.
'Programming Language > Java' 카테고리의 다른 글
| [Java] Lambda expression (0) | 2025.08.27 |
|---|---|
| [Java] Stream, map() (0) | 2025.08.27 |
| [Java] Thread 구현과 실행 (1) | 2025.08.02 |
| [Java] main thread 실행 흐름과 call stack, stack frame, main thread 개념 (1) | 2025.08.02 |
| [Java] Interface와 DI(Dependency Injection)를 통해 객체간 결합 낮추기, Interface를 사용하는 이유 (4) | 2025.08.01 |
Comments