[REST API] 1. DTO

문정준's avatar
Apr 28, 2025
[REST API] 1. DTO
 

1. Java Project 생성

 
notion image
 
설계
Order
package model; import lombok.Builder; import lombok.Data; // 주문 번호 @Data public class Order { private int id; @Builder public Order(int id) { this.id = id; } }
OrderOption
package model; import lombok.Builder; import lombok.Data; // 주문 옵션(메뉴) @Data public class OrderOption { private int id; private String optionName; // 하얀티 private int qty; // 5개 private int totalPrice; // 10000원 private Product product; private Order order; @Builder public OrderOption(int id, String optionName, int qty, int totalPrice, Product product, Order order) { this.id = id; this.optionName = optionName; this.qty = qty; this.totalPrice = totalPrice; this.product = product; this.order = order; } }
Product
package model; import lombok.Builder; import lombok.Data; @Data public class Product { private int id; private String name; // 바지 @Builder public Product(int id, String name) { this.id = id; this.name = name; } }
ProductOption
package model; import lombok.Builder; import lombok.Data; @Data public class ProductOption { private int id; private String name; private int price; private int qty; private Product product; @Builder public ProductOption(int id, String name, int price, int qty, Product product) { this.id = id; this.name = name; this.price = price; this.qty = qty; this.product = product; } }
 
 

2. 문제 풀이

  • 1 ~ 4번 문제 : 화면 출력에 알맞은 DTO 제작
package ex01; import com.google.gson.Gson; import model.Order; import model.OrderOption; import model.Product; import model.ProductOption; import java.util.Arrays; import java.util.List; public class App1 { public static void main(String[] args) { // 판매자 로직 // 1. 상품 2개 Product p1 = new Product(1, "바지"); Product p2 = new Product(2, "티"); List<Product> products = Arrays.asList(p1, p2); // 1번 문제 -> List<Product>를 List<ProductDTO>로 옮기기 // 2. 상품 옵션 4개 생성 ProductOption op1 = new ProductOption(1, "파란바지", 1000, 10, p1); ProductOption op2 = new ProductOption(2, "빨간바지", 2000, 10, p1); ProductOption op3 = new ProductOption(3, "노랑티", 1000, 10, p2); ProductOption op4 = new ProductOption(4, "하얀티", 2000, 10, p2); List<ProductOption> p1Options = Arrays.asList(op1, op2); List<ProductOption> p2Options = Arrays.asList(op3, op4); // 2번 문제 -> p2, p2Options -> ProductDetailDTO 로 옮기기 // 구매자 로직 // 3. 구매 Order or1 = new Order(1); OrderOption orOption1 = new OrderOption(1, "파란바지", 2, 2000, p1, or1); OrderOption orOption2 = new OrderOption(2, "빨간바지", 2, 4000, p1, or1); OrderOption orOption3 = new OrderOption(3, "하얀티", 5, 10000, p2, or1); op1.setQty(op1.getQty() - 2); op2.setQty(op2.getQty() - 2); op4.setQty(op4.getQty() - 5); Order or2 = new Order(2); OrderOption orOption4 = new OrderOption(4, "노랑티", 7, 7000, p2, or2); op3.setQty(op3.getQty() - 7); // 4. 상품 출력 // 1번 문제 : 상품 목록 화면 // List<Product> -> List<ProductDTO> // 2번 문제 : 상품 상세 화면 (p2) // Product(p2, p2Options) -> ProductDetail // 3번 문제 : 주문 확인 상세 화면 (or2) // 틀렸음 : DTO 담기 // 4번 문제 : 주문 확인 상세 화면 (or1) // (orOption1, orOption2), (orOption3) -> OrderDetailDTO } }
 

해답

1번 문제

  • Product를 저장하는 DTO : 깊은 복사
package ex01; import lombok.Data; import model.Product; @Data public class ProductDTO { private int id; private String name; public ProductDTO(Product product) { this.id = product.getId(); this.name = product.getName(); } }
List<ProductDTO> productsDTO = Arrays.asList(new ProductDTO(p1), new ProductDTO(p2));
 
  • 출력은 GSON 활용 : JSON 형태로 결과를 출력
Gson gson = new Gson(); String ex01 = gson.toJson(productsDTO); System.out.println(ex01);
notion image
 

2번 문제

  • 하나의 DTO 안에 여러 객체가 저장되어야 함
package ex01; import lombok.Data; import model.Product; import model.ProductOption; import java.util.ArrayList; import java.util.List; @Data public class ProductDetailDTO { private Integer productId; private String productName; List<ProductOptionDTO> options = new ArrayList<>(); public ProductDetailDTO(Product p, List<ProductOption> options) { this.productId = p.getId(); this.productName = p.getName(); for (ProductOption op : options) { this.options.add(new ProductOptionDTO(op)); } } @Data public class ProductOptionDTO { private int optionId; private String optionName; private int optionPrice; private int optionQty; public ProductOptionDTO(ProductOption op) { this.optionId = op.getId(); this.optionName = op.getName(); this.optionPrice = op.getPrice(); this.optionQty = op.getQty(); } } }
ProductDetailDTO productDetailDTO = new ProductDetailDTO(p2, p2Options);
String ex02 = gson.toJson(productDetailDTO); System.out.println(ex02);
notion image

3번 문제

  • Order와 Product의 구분을 확실히 해야 함
package ex01; import lombok.Data; import model.OrderOption; // 3번 문제만을 위한 DTO @Data public class TempDTO { private Integer orderId; private Integer productId; private Integer orderOptionId; private String orderOptionName; private Integer orderOptionQty; private Integer totalPrice; public TempDTO(OrderOption orderOption) { this.orderId = orderOption.getOrder().getId(); this.productId = orderOption.getProduct().getId(); // Lazy Loading (조인 안했다면) this.orderOptionId = orderOption.getId(); this.orderOptionName = orderOption.getOptionName(); this.orderOptionQty = orderOption.getQty(); this.totalPrice = orderOption.getTotalPrice(); } }
TempDTO tempDTO = new TempDTO(orOption4);
String ex03 = gson.toJson(tempDTO); System.out.println(ex03);
notion image

4번 문제

  • DTO → DTO → DTO의 연쇄 작용
package ex01; import lombok.Data; import model.OrderOption; import java.util.ArrayList; import java.util.List; @Data public class OrderDetailDTO { private Integer orderId; private List<X> products; private Integer totalPrice = 0; public OrderDetailDTO(List<OrderOption> orderOptions) { // p1(orOption1, orOption2), p2(orOption3) System.out.println("*"); this.orderId = orderOptions.getFirst().getOrder().getId(); List<OrderOption> op1s = new ArrayList<>(); op1s.add(orderOptions.get(0)); op1s.add(orderOptions.get(1)); List<OrderOption> op2s = new ArrayList<>(); op2s.add(orderOptions.get(2)); X x1 = new X(op1s); X x2 = new X(op2s); List<X> xList = new ArrayList<>(); xList.add(x1); xList.add(x2); this.products = xList; for (OrderOption op : orderOptions) { this.totalPrice += op.getTotalPrice(); } } @Data public class X { private Integer productId; private List<Y> orderOptions; public X(List<OrderOption> orderOptions) { System.out.println("**"); this.productId = orderOptions.getFirst().getProduct().getId(); List<Y> yList = new ArrayList<>(); for (OrderOption orderOption : orderOptions) { yList.add(new Y(orderOption)); } this.orderOptions = yList; } @Data public class Y { private Integer orderOptionId; private String orderOptionName; private Integer orderOptionQty; private Integer orderOptionTotalPrice; public Y(OrderOption orderOption) { System.out.println("***"); this.orderOptionId = orderOption.getId(); this.orderOptionName = orderOption.getOptionName(); this.orderOptionQty = orderOption.getQty(); this.orderOptionTotalPrice = orderOption.getTotalPrice(); } } } }
List<OrderOption> or1Options = Arrays.asList(orOption1, orOption2, orOption3); OrderDetailDTO orderDetailDTO = new OrderDetailDTO(or1Options);
String ex04 = gson.toJson(orderDetailDTO); System.out.println(ex04);
 
 
notion image
 

4번 문제 풀이 보완

  1. 리스트 동적 제작
  1. 멤버 동적 삽입
notion image
 
package ex01; import lombok.Data; import model.OrderOption; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; @Data public class OrderDetailDTO { private int orderId; private List<ProductDTO> products = new ArrayList<>(); private int sumPrice; public OrderDetailDTO(List<OrderOption> orderOptions) { this.orderId = orderOptions.getFirst().getId(); // 중복이 제거된 상품 ids + 전체금액 계산 Set<Integer> productIds = new HashSet<>(); for (OrderOption orderOption : orderOptions) { productIds.add(orderOption.getProduct().getId()); this.sumPrice += orderOption.getTotalPrice(); } // 상품별 주문한 상품옵션 만들기 for (Integer productId : productIds) { List<OrderOption> selectedOptions = new ArrayList<>(); for (OrderOption orderOption : orderOptions) { if (productId == orderOption.getProduct().getId()) { selectedOptions.add(orderOption); } } ProductDTO productDTO = new ProductDTO(productId, selectedOptions); this.products.add(productDTO); } } @Data class ProductDTO { private int productId; private List<OrderOptionDTO> orderOptions = new ArrayList<>(); public ProductDTO(int productId, List<OrderOption> orderOptions) { this.productId = productId; for (OrderOption orderOption : orderOptions) { this.orderOptions.add(new OrderOptionDTO(orderOption)); } } @Data class OrderOptionDTO { private int orderOptionId; private String orderOptionName; private int orderQty; private int orderTotalPrice; public OrderOptionDTO(OrderOption orderOption) { this.orderOptionId = orderOption.getId(); this.orderOptionName = orderOption.getOptionName(); this.orderQty = orderOption.getQty(); this.orderTotalPrice = orderOption.getTotalPrice(); } } } }

productId 중복 제거 : HashSet 사용

  • set의 크기 만큼 리스트를 제작, 받는 orderOption의 크기만큼 매핑
  • 2 * 3 = 6번 반복
  • 결과는 동일
 
Share article

sxias