데이터 구조 설계 (DB에서 데이터를 가져왔다고 가정)
1. Product 클래스 - 상품
- 제품 id
- 제품명
- 바지
- 티셔츠
package model;
public class Product {
private int id; // 제품 id
private String name; // 제품명(바지, 티)
// 생성자
public Product(int id, String name) {
this.id = id;
this.name = name;
}
// getter setter
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}2. ProductOption 클래스 - 상품 옵션
- 옵션 id
- 옵션명
- 가격
- 수량
- ProductOpton의 fk가 될 상품 id
package model;
public class ProductOption {
private int id; // 옵션 id
private String name; // 옵션명
private int price; // 가격
private int qty; // 수량(qantity)
private Product product; // DB에서는 product_id가 될것(fk)
// 생성자
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;
}
// getter setter
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public int getQty() {
return qty;
}
public void setQty(int qty) {
this.qty = qty;
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
}3. Order 클래스 - 주문
- 주문 번호(id)
package model;
public class Order {
private int id; // 주문 번호(id)
// 생성자
public Order(int id) {
this.id = id;
}
// getter setter
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}4. OrderOption 클래스 - 주문 옵션
- 주문 옵션 id
- 주문 옵션명 (ex. 하얀티)
- 주문 수량 (ex. 5개)
- 주문 금액 (ex. 10000원)
- OrderOption의 fk가 될 상품 id
- OrderOption의 fk가 될 주문 번호(id)
package model;
public class OrderOption {
private int id; // 주문 옵션 id
private String optionName; // 주문 옵션명 ex)하얀티
private int qty; // 주문량 ex)5개
private int totalPrice; // 주문 금액 ex)10000원
private Product product; // DB에서는 product_id가 될것(fk)
private Order order; // DB에서는 order_id가 될것(fk)
// 생성자
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;
}
// getter setter
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getOptionName() {
return optionName;
}
public void setOptionName(String optionName) {
this.optionName = optionName;
}
public int getQty() {
return qty;
}
public void setQty(int qty) {
this.qty = qty;
}
public int getTotalPrice() {
return totalPrice;
}
public void setTotalPrice(int totalPrice) {
this.totalPrice = totalPrice;
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
public Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
}5. App1 클래스 (main) - 실습 문제
- 문제 별 DTO에 넣을 데이터 주어짐
- 문제 1. 상품 목록 화면 구현
- 문제 2-1, 2-2. 상품 상세 화면 구현
- 문제3. 주문 확인 상세 화면 구현 (주문 번호 2)
- 문제 4. 주문 확인 상세 화면 구현 (주문 번호 1)
import com.google.gson.Gson;
import dto.OrderDetailDTO;
import dto.ProductDTO;
import dto.ProductDetailDTO;
import model.Order;
import model.OrderOption;
import model.ProductOption;
import model.Product;
import java.util.ArrayList;
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, "티");
// 2. 옵션 4개 생성 (2-1, 2-2)
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);
// 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. 상품 목록 화면 (products) -> List<ProductDTO>
List<Product> products = Arrays.asList(p1, p2); // 1번 문제 -> products DTO로 옮기기
// 알고리즘
// 4-1(1번 문제). product -> new ProductDTO(product);
List<ProductDTO> productDTOS = new ArrayList<>();
// 5. 상품 상세 화면 (p1Options) -> ProductDetailDTO
// 2-1번 문제 -> p1, p1Options DTO로 옮기기
List<ProductOption> p1Options = Arrays.asList(op1, op2);
// 2-2번 문제 -> p2, p2Options DTO로 옮기기
List<ProductOption> p2Options = Arrays.asList(op3, op4);
// 6-1. 주문 확인 상세 화면 (or2Options) -> OrderDetailDTO
// 3번문제 데이터 (이것만 넣고 DTO 만들기)
List<OrderOption> or2Options = Arrays.asList(orOption4);
// 6-2. 주문 확인 상세 화면 (or1Options) -> OrderDetailDTO
// 4번문제 데이터 (이것만 넣고 DTO 만들기)
List<OrderOption> or1Options = Arrays.asList(orOption1, orOption2, orOption3);
}
}풀이
- 구현 예상 화면을 보고 나타낼 데이터를 생각하기
- 각 클래스들의 정보를 어느 DTO에 어떻게 넣을지 생각하기
- 라이브러리 lombok, gson 활용
1. 프로젝트에 라이브러리 설정
- 프로젝트 우클릭 - 모듈 설정 열기

- 라이브러리 - +아이콘 클릭 - lombok 검색 - 버전 찾아서 선택

- 라이브러리 - +아이콘 클릭 - gson 검색 - 버전 찾아서 선택

- 라이브러리 추가된 것 확인

2. ProductDTO 클래스
- 문제1. 상품 목록 화면 구현

package dto;
// 1번 문제(App1의 main 참고)
import lombok.Data;
import model.Product;
@Data // getter setter toString 다 포함
public class ProductDTO {
private int id; // 제품 id
private String name; // 제품명(바지, 티)
// 생성자
public ProductDTO(Product product) {
this.id = product.getId();
this.name = product.getName();
}
}3. ProductDetailDTO 클래스
- 문제2-1, 2-2. 상품 상세 보기 화면 구현
- 해당 상품과 옵션들 나타내기
- 옵션 id(3), 옵션명(노란티), 가격(1000), 수량(3)
- 옵션 id(4), 옵션명(하얀티), 가격(2000), 수량(5)

package dto;
// 2번 문제(App1의 main 참고)
import lombok.Data;
import model.ProductOption;
import java.util.ArrayList;
import java.util.List;
@Data
public class ProductDetailDTO {
private int productId;
private String productName;
private List<ProductOptionDTO> options = new ArrayList<>();
// 생성자
public ProductDetailDTO(List<ProductOption> options) {
this.productId = options.get(0).getProduct().getId();
this.productName = options.get(0).getProduct().getName();
// for-each문으로 순회
// models(ProductOption)를 dtos에 옮기기
for (ProductOption option : options) {
this.options.add(new ProductOptionDTO(option));
}
}
@Data
class ProductOptionDTO {
private int id; // 옵션 id
private String name; // 옵션명
private int price; // 가격
private int qty; // 수량(qantity)
// 생성자
// ProductOption의 정보를 통째로 가져옴 (생성자의 파라미터)
public ProductOptionDTO(ProductOption option) {
this.id = option.getId();
this.name = option.getName();
this.price = option.getPrice();
this.qty = option.getQty();
}
}
}4. OrderDetailDTO 클래스
- 문제3. 주문 상세 보기 화면 구현 (주문 번호 2)
- 주문 번호 2의 구매 내역 상세 나타내기
- 상품 2번(티셔츠), 옵션(옵션id = 3 / 노란티), 수량(7), 총 금액(7000원)
- 주문 합계 금액(sumPrice) 7000원

- 문제4. 주문 상세 보기 화면 구현 (주문 번호 1)
- 주문 번호 1의 구매 내역 상세 나타내기
- 상품 1번(바지), 옵션(옵션id=1 / 파랑, 옵션 id = 2 / 빨강), 수량(파란바지2, 빨간바지2), 총 금액(파란바지 2000원, 빨강바지 4000원)
- 상품 2번(티셔츠), 옵션(옵션id=3 / 하얀티), 수량(5), 총 금액(10000원)
- 주문 합계 금액(sumPrice) 16000원

package dto;
// 3번 문제(App1의 main 참고)
// 4번 문제(App1의 main 참고)
import lombok.Data;
import model.OrderOption;
import java.util.*;
@Data
public class OrderDetailDTO {
private int orderId;
private List<OrderProductDTO> products = new ArrayList<>();
private int sumPrice;
// 생성자
public OrderDetailDTO(List<OrderOption> options) {
// 1. orderId
this.orderId = options.get(0).getOrder().getId();
// 2. sumPrice
// options의 크기만큼 OrderOption 순회해서 정보 가져와서 합연산
for (OrderOption option : options) {
this.sumPrice += option.getTotalPrice();
}
// 3. products
// 3-1. 주문 옵션들 productId [1,1,2] -> [1,2] 2개 만들기
Set<Integer> ids = new HashSet<>(); // Set은 중복을 알아서 제거해줌
for (OrderOption option : options) {
ids.add(option.getProduct().getId()); // [1,2]를 들고있게됨
}
// 3-2. 중복된 상품의 크기만큼 반복하면서 주문 옵션 추가하기
// ids의 크기(이 경우 2)만큼 순회
for (Integer id : ids) {
List<OrderOption> temp = new ArrayList<>();
for (OrderOption option : options) {
// if문의 중괄호 생략하고 간소화
if (id == option.getProduct().getId()) temp.add(option);
}
OrderProductDTO product = new OrderProductDTO(temp);
products.add(product);
}
}
@Data
class OrderProductDTO {
private int productId;
private List<OrderOptionDTO> options = new ArrayList<>();
public OrderProductDTO(List<OrderOption> options) {
this.productId = options.get(0).getProduct().getId(); // OrderOprion의 fk인 Product의 id
// options의 크기만큼 OrderOption 순회해서 정보 가져옴
for (OrderOption option : options) {
this.options.add(new OrderOptionDTO(option));
}
}
@Data
class OrderOptionDTO {
private int id; // 주문 옵션 id
private String optionName; // 주문 옵션명
private int qty; // 주문량
private int totalPrice; // 주문 금액
public OrderOptionDTO(OrderOption option) {
this.id = option.getId();
this.optionName = option.getOptionName();
this.qty = option.getQty();
this.totalPrice = option.getTotalPrice();
}
}
}
}5. App1 클래스 (main) - 결과 확인
- gson을 이용한 결과 콘솔 출력
- JSON Viewer 사이트에서 콘솔 출력된 문자열(gson)을 text에 복사붙여넣기 하고 Viewer를 확인하면 JSON 형태로 보여줌
import com.google.gson.Gson;
import dto.OrderDetailDTO;
import dto.ProductDTO;
import dto.ProductDetailDTO;
import model.Order;
import model.OrderOption;
import model.ProductOption;
import model.Product;
import java.util.ArrayList;
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, "티");
// 2. 옵션 4개 생성 (2-1, 2-2)
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);
// 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);
// gson
Gson gson = new Gson();
// 4. 상품 목록 화면 (products) -> List<ProductDTO>
List<Product> products = Arrays.asList(p1, p2); // 1번 문제 -> products DTO로 옮기기
// 알고리즘
// 4-1(1번 문제). product -> new ProductDTO(product);
List<ProductDTO> productDTOS = new ArrayList<>();
// for-each로 Product의 정보를 담은 리스트 products를 순회해서 productsDTOs에 add
for (Product product : products) {
productDTOS.add(new ProductDTO(product));
}
String r1 = gson.toJson(productDTOS); // JSON 형태의 스트링으로 출력
System.out.println(r1);
// 5. 상품 상세 화면 (p1Options) -> ProductDetailDTO
// 2-1번 문제 -> p1, p1Options DTO로 옮기기
List<ProductOption> p1Options = Arrays.asList(op1, op2);
ProductDetailDTO productDetailDTO1 = new ProductDetailDTO(p1Options);
String r2 = gson.toJson(productDetailDTO1);
System.out.println(r2);
// 2-2번 문제 -> p2, p2Options DTO로 옮기기
List<ProductOption> p2Options = Arrays.asList(op3, op4);
ProductDetailDTO productDetailDTO2 = new ProductDetailDTO(p2Options);
String r3 = gson.toJson(productDetailDTO2);
System.out.println(r3);
// 6-1. 주문 확인 상세 화면 (or2Options) -> OrderDetailDTO
// 3번문제 데이터 (이것만 넣고 DTO 만들기)
List<OrderOption> or2Options = Arrays.asList(orOption4);
OrderDetailDTO orderDetailDTO1 = new OrderDetailDTO(or2Options);
String r4 = gson.toJson(orderDetailDTO1);
System.out.println(r4);
// 6-2. 주문 확인 상세 화면 (or1Options) -> OrderDetailDTO
// 4번문제 데이터 (이것만 넣고 DTO 만들기)
List<OrderOption> or1Options = Arrays.asList(orOption1, orOption2, orOption3);
OrderDetailDTO orderDetailDTO2 = new OrderDetailDTO(or1Options);
String r5 = gson.toJson(orderDetailDTO2);
System.out.println(r5);
}
}- 문제 1 결과
Q1 콘솔 출력
[{"id":1,"name":"바지"},{"id":2,"name":"티"}]
- 문제 2 결과
Q2 콘솔 출력
{"productId":1,"productName":"바지","options":[{"id":1,"name":"파란바지","price":1000,"qty":8},{"id":2,"name":"빨간바지","price":2000,"qty":8}]}
- 문제 3 결과
Q3 콘솔 출력
{"orderId":2,"products":[{"productId":2,"options":[{"id":4,"optionName":"노랑티","qty":7,"totalPrice":7000}]}],"sumPrice":7000}
- 문제 4 결과
Q4 콘솔 출력
{"orderId":1,"products":[{"productId":1,"options":[{"id":1,"optionName":"파란바지","qty":2,"totalPrice":2000},{"id":2,"optionName":"빨간바지","qty":2,"totalPrice":4000}]},{"productId":2,"options":[{"id":3,"optionName":"하얀티","qty":5,"totalPrice":10000}]}],"sumPrice":16000}
Share article