From 98f3a17bced12efd88d539a7406b06d893ff5f4d Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Wed, 26 Jun 2024 15:33:12 +0900
Subject: [PATCH 01/56] feat(global): create global controller
---
src/main/java/gift/GlobalController.java | 12 ++++++++++++
1 file changed, 12 insertions(+)
create mode 100644 src/main/java/gift/GlobalController.java
diff --git a/src/main/java/gift/GlobalController.java b/src/main/java/gift/GlobalController.java
new file mode 100644
index 000000000..b1f8ebf84
--- /dev/null
+++ b/src/main/java/gift/GlobalController.java
@@ -0,0 +1,12 @@
+package gift;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+
+@Controller
+public class GlobalController {
+ @GetMapping("/")
+ public String index() {
+ return "index";
+ }
+}
From e114c0ebe1d374f4c1576c5d18d5bcaa22157d87 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Tue, 25 Jun 2024 18:19:22 +0900
Subject: [PATCH 02/56] docs(global): summerize list of features
---
README.md | 47 ++++++++++++++++++-
.../product/controller/ProductController.java | 7 +++
.../java/gift/product/entity/Product.java | 38 +++++++++++++++
.../java/gift/product/entity/ProductInfo.java | 25 ++++++++++
4 files changed, 116 insertions(+), 1 deletion(-)
create mode 100644 src/main/java/gift/product/controller/ProductController.java
create mode 100644 src/main/java/gift/product/entity/Product.java
create mode 100644 src/main/java/gift/product/entity/ProductInfo.java
diff --git a/README.md b/README.md
index cafde8a2c..10c0c5c6c 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,46 @@
-# spring-gift-product
\ No newline at end of file
+# spring-gift-product
+
+---
+
+## Step1
+
+**요구 사항**
+아래와 같이 http 메세지를 받도록 구현한다
+
+```http request
+GET /api/products HTTP/1.1
+```
+
+```http request
+HTTP/1.1 200
+Content-Type: application/json
+
+[
+ {
+ "id": 8146027,
+ "name": "아이스 카페 아메리카노 T",
+ "price": 4500,
+ "imageUrl": "https://st.kakaocdn.net/product/gift/product/20231010111814_9a667f9eccc943648797925498bdd8a3.jpg"
+ }
+]
+```
+
+
+**필요 조건**
+상품 데이터 관리
+현재는 별도의 데이터베이스가 없으므로 적절한 컬렉션을 이용하여 메모리에 저장한다.
+```java
+public class ProductController {
+ private final Map productMap = new HashMap<>();
+}
+```
+----
+## 구현 기능
+- product 조회
+- product 추가
+- product 수정
+- product 삭제
+
+
+
+
diff --git a/src/main/java/gift/product/controller/ProductController.java b/src/main/java/gift/product/controller/ProductController.java
new file mode 100644
index 000000000..78fd78ed1
--- /dev/null
+++ b/src/main/java/gift/product/controller/ProductController.java
@@ -0,0 +1,7 @@
+package gift.product.controller;
+
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class ProductController {
+}
diff --git a/src/main/java/gift/product/entity/Product.java b/src/main/java/gift/product/entity/Product.java
new file mode 100644
index 000000000..4ee94b567
--- /dev/null
+++ b/src/main/java/gift/product/entity/Product.java
@@ -0,0 +1,38 @@
+package gift.product.entity;
+
+public class Product {
+ private Long id;
+ private String name;
+ private int price;
+ private String imageUrl;
+
+ public Product(Long id, String name, int price, String imageUrl) {
+ this.id = id;
+ this.name = name;
+ this.price = price;
+ this.imageUrl = imageUrl;
+ }
+
+ public Product(Long id, ProductInfo productInfo) {
+ this.id = id;
+ this.name = productInfo.getName();
+ this.price = productInfo.getPrice();
+ this.imageUrl = productInfo.getImageUrl();
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public int getPrice() {
+ return price;
+ }
+
+ public String getImageUrl() {
+ return imageUrl;
+ }
+}
diff --git a/src/main/java/gift/product/entity/ProductInfo.java b/src/main/java/gift/product/entity/ProductInfo.java
new file mode 100644
index 000000000..538581711
--- /dev/null
+++ b/src/main/java/gift/product/entity/ProductInfo.java
@@ -0,0 +1,25 @@
+package gift.product.entity;
+
+public class ProductInfo {
+ private String name;
+ private int price;
+ private String imageUrl;
+
+ public ProductInfo(String name, int price, String imageUrl) {
+ this.name = name;
+ this.price = price;
+ this.imageUrl = imageUrl;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public int getPrice() {
+ return price;
+ }
+
+ public String getImageUrl() {
+ return imageUrl;
+ }
+}
From 5b377756dea992d7cfbcbfddf83e831fa44bcdd3 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Tue, 25 Jun 2024 18:20:04 +0900
Subject: [PATCH 03/56] feat(product): create product controller
---
src/main/java/gift/product/controller/ProductController.java | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/main/java/gift/product/controller/ProductController.java b/src/main/java/gift/product/controller/ProductController.java
index 78fd78ed1..4e0047a2e 100644
--- a/src/main/java/gift/product/controller/ProductController.java
+++ b/src/main/java/gift/product/controller/ProductController.java
@@ -1,7 +1,8 @@
package gift.product.controller;
+import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
-@RestController
+@RestController("/api")
public class ProductController {
}
From 2b52d04de7514e70a851fc602b152d0df1ff4373 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Tue, 25 Jun 2024 18:21:00 +0900
Subject: [PATCH 04/56] feat(product): create product entity
---
.../java/gift/product/entity/Product.java | 15 +----------
.../java/gift/product/entity/ProductInfo.java | 25 -------------------
2 files changed, 1 insertion(+), 39 deletions(-)
delete mode 100644 src/main/java/gift/product/entity/ProductInfo.java
diff --git a/src/main/java/gift/product/entity/Product.java b/src/main/java/gift/product/entity/Product.java
index 4ee94b567..699e456ca 100644
--- a/src/main/java/gift/product/entity/Product.java
+++ b/src/main/java/gift/product/entity/Product.java
@@ -1,29 +1,16 @@
package gift.product.entity;
public class Product {
- private Long id;
private String name;
private int price;
private String imageUrl;
- public Product(Long id, String name, int price, String imageUrl) {
- this.id = id;
+ public Product(String name, int price, String imageUrl) {
this.name = name;
this.price = price;
this.imageUrl = imageUrl;
}
- public Product(Long id, ProductInfo productInfo) {
- this.id = id;
- this.name = productInfo.getName();
- this.price = productInfo.getPrice();
- this.imageUrl = productInfo.getImageUrl();
- }
-
- public Long getId() {
- return id;
- }
-
public String getName() {
return name;
}
diff --git a/src/main/java/gift/product/entity/ProductInfo.java b/src/main/java/gift/product/entity/ProductInfo.java
deleted file mode 100644
index 538581711..000000000
--- a/src/main/java/gift/product/entity/ProductInfo.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package gift.product.entity;
-
-public class ProductInfo {
- private String name;
- private int price;
- private String imageUrl;
-
- public ProductInfo(String name, int price, String imageUrl) {
- this.name = name;
- this.price = price;
- this.imageUrl = imageUrl;
- }
-
- public String getName() {
- return name;
- }
-
- public int getPrice() {
- return price;
- }
-
- public String getImageUrl() {
- return imageUrl;
- }
-}
From f54b33a13a05222a42334197b3be842fa9683410 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Tue, 25 Jun 2024 18:25:53 +0900
Subject: [PATCH 05/56] fix(product): add column id into product entity
---
src/main/java/gift/product/entity/Product.java | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/main/java/gift/product/entity/Product.java b/src/main/java/gift/product/entity/Product.java
index 699e456ca..72b0b58d6 100644
--- a/src/main/java/gift/product/entity/Product.java
+++ b/src/main/java/gift/product/entity/Product.java
@@ -1,15 +1,20 @@
package gift.product.entity;
public class Product {
+ private Long id;
private String name;
private int price;
private String imageUrl;
- public Product(String name, int price, String imageUrl) {
+ public Product(Long id, String name, int price, String imageUrl) {
+ this.id = id;
this.name = name;
this.price = price;
this.imageUrl = imageUrl;
}
+ public Long getId() {
+ return id;
+ }
public String getName() {
return name;
@@ -22,4 +27,5 @@ public int getPrice() {
public String getImageUrl() {
return imageUrl;
}
+
}
From f376876bae07a856acea70afe751e627bbb8d372 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Tue, 25 Jun 2024 18:26:28 +0900
Subject: [PATCH 06/56] feat(product): add method get product by id in
controller
---
.../gift/product/controller/ProductController.java | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/src/main/java/gift/product/controller/ProductController.java b/src/main/java/gift/product/controller/ProductController.java
index 4e0047a2e..859e52de6 100644
--- a/src/main/java/gift/product/controller/ProductController.java
+++ b/src/main/java/gift/product/controller/ProductController.java
@@ -1,8 +1,17 @@
package gift.product.controller;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RestController;
+import gift.product.entity.Product;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.HashMap;
+import java.util.Map;
@RestController("/api")
public class ProductController {
+ private final Map productMap = new HashMap<>();
+
+ @GetMapping("/product/{id}")
+ public Product getProductById(@PathVariable Long id) {
+ return productMap.get(id);
+ }
}
From 0ded7d37054e6ea77c57557178d3da0310892e94 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Tue, 25 Jun 2024 18:37:20 +0900
Subject: [PATCH 07/56] feat(product): create product request record
---
src/main/java/gift/product/dto/ProductRequest.java | 10 ++++++++++
1 file changed, 10 insertions(+)
create mode 100644 src/main/java/gift/product/dto/ProductRequest.java
diff --git a/src/main/java/gift/product/dto/ProductRequest.java b/src/main/java/gift/product/dto/ProductRequest.java
new file mode 100644
index 000000000..7dfba414f
--- /dev/null
+++ b/src/main/java/gift/product/dto/ProductRequest.java
@@ -0,0 +1,10 @@
+package gift.product.dto;
+
+import java.util.Objects;
+
+public record ProductRequest(String name, int price, String imageUrl) {
+ public ProductRequest {
+ Objects.requireNonNull(name);
+ Objects.requireNonNull(imageUrl);
+ }
+}
From dc565f44d4d7c6fea916271825878f6a91f3a7de Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Tue, 25 Jun 2024 18:44:25 +0900
Subject: [PATCH 08/56] feat(product): add constructor to initialize Product
from ProductRequest
---
src/main/java/gift/product/entity/Product.java | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/src/main/java/gift/product/entity/Product.java b/src/main/java/gift/product/entity/Product.java
index 72b0b58d6..f31d5a6a9 100644
--- a/src/main/java/gift/product/entity/Product.java
+++ b/src/main/java/gift/product/entity/Product.java
@@ -1,5 +1,7 @@
package gift.product.entity;
+import gift.product.dto.ProductRequest;
+
public class Product {
private Long id;
private String name;
@@ -12,6 +14,15 @@ public Product(Long id, String name, int price, String imageUrl) {
this.price = price;
this.imageUrl = imageUrl;
}
+
+ public Product(Long id, ProductRequest productRequest) {
+ this.id = id;
+ this.name = productRequest.name();
+ this.price = productRequest.price();
+ this.imageUrl = productRequest.imageUrl();
+ }
+
+
public Long getId() {
return id;
}
From 5507db1a93e28fe6a1845ca32699f9d79dd72526 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Tue, 25 Jun 2024 18:54:46 +0900
Subject: [PATCH 09/56] fix(product): change RequestMapping url error
---
src/main/java/gift/product/controller/ProductController.java | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/main/java/gift/product/controller/ProductController.java b/src/main/java/gift/product/controller/ProductController.java
index 859e52de6..f69814490 100644
--- a/src/main/java/gift/product/controller/ProductController.java
+++ b/src/main/java/gift/product/controller/ProductController.java
@@ -6,7 +6,8 @@
import java.util.HashMap;
import java.util.Map;
-@RestController("/api")
+@RestController
+@RequestMapping("/api")
public class ProductController {
private final Map productMap = new HashMap<>();
From fa94538ae5d35dc33b0dec412a609f783e88a960 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Tue, 25 Jun 2024 18:58:21 +0900
Subject: [PATCH 10/56] feat(product): add create product method
---
.../product/controller/ProductController.java | 21 ++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/src/main/java/gift/product/controller/ProductController.java b/src/main/java/gift/product/controller/ProductController.java
index f69814490..ea9a1ba5d 100644
--- a/src/main/java/gift/product/controller/ProductController.java
+++ b/src/main/java/gift/product/controller/ProductController.java
@@ -1,5 +1,6 @@
package gift.product.controller;
+import gift.product.dto.ProductRequest;
import gift.product.entity.Product;
import org.springframework.web.bind.annotation.*;
@@ -12,7 +13,25 @@ public class ProductController {
private final Map productMap = new HashMap<>();
@GetMapping("/product/{id}")
- public Product getProductById(@PathVariable Long id) {
+ public Product getProductById(@PathVariable(name = "id") Long id) {
return productMap.get(id);
}
+
+ @PostMapping("/product")
+ public Product createProduct(@RequestBody ProductRequest productRequest) {
+ Long id = addProduct(productRequest);
+ return productMap.get(id);
+ }
+
+ private Long addProduct(ProductRequest productRequest) {
+ Long id = getMaxKey();
+ productMap.put(id, new Product(id, productRequest));
+ return id;
+ }
+
+ private Long getMaxKey() {
+ return 1L + productMap.keySet().stream()
+ .max(Long::compare)
+ .orElse(0L);
+ }
}
From 30282134214efd77bff4533d2a1617f753622711 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Tue, 25 Jun 2024 18:59:31 +0900
Subject: [PATCH 11/56] fix(product): change endpoint product to products
---
src/main/java/gift/product/controller/ProductController.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/main/java/gift/product/controller/ProductController.java b/src/main/java/gift/product/controller/ProductController.java
index ea9a1ba5d..d1eb169a9 100644
--- a/src/main/java/gift/product/controller/ProductController.java
+++ b/src/main/java/gift/product/controller/ProductController.java
@@ -12,12 +12,12 @@
public class ProductController {
private final Map productMap = new HashMap<>();
- @GetMapping("/product/{id}")
+ @GetMapping("/products/{id}")
public Product getProductById(@PathVariable(name = "id") Long id) {
return productMap.get(id);
}
- @PostMapping("/product")
+ @PostMapping("/products")
public Product createProduct(@RequestBody ProductRequest productRequest) {
Long id = addProduct(productRequest);
return productMap.get(id);
From eedb420cf533ab5e459d2826576c155bfc55d148 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Tue, 25 Jun 2024 19:04:25 +0900
Subject: [PATCH 12/56] feat(product): add update product method
---
.../java/gift/product/controller/ProductController.java | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/main/java/gift/product/controller/ProductController.java b/src/main/java/gift/product/controller/ProductController.java
index d1eb169a9..16046ff0a 100644
--- a/src/main/java/gift/product/controller/ProductController.java
+++ b/src/main/java/gift/product/controller/ProductController.java
@@ -23,6 +23,12 @@ public Product createProduct(@RequestBody ProductRequest productRequest) {
return productMap.get(id);
}
+ @PutMapping("/products/{id}")
+ public Product updateProduct(@PathVariable(name = "id") Long id, @RequestBody ProductRequest productRequest) {
+ productMap.replace(id, new Product(id, productRequest));
+ return productMap.get(id);
+ }
+
private Long addProduct(ProductRequest productRequest) {
Long id = getMaxKey();
productMap.put(id, new Product(id, productRequest));
From c3c5908589673e4f75c1a324879f94dd0dcdb83d Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Tue, 25 Jun 2024 19:09:00 +0900
Subject: [PATCH 13/56] feat(product): add delete product method
---
.../java/gift/product/controller/ProductController.java | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/main/java/gift/product/controller/ProductController.java b/src/main/java/gift/product/controller/ProductController.java
index 16046ff0a..f1d90f513 100644
--- a/src/main/java/gift/product/controller/ProductController.java
+++ b/src/main/java/gift/product/controller/ProductController.java
@@ -29,6 +29,12 @@ public Product updateProduct(@PathVariable(name = "id") Long id, @RequestBody Pr
return productMap.get(id);
}
+ @DeleteMapping("/products/{id}")
+ public String deleteProduct(@PathVariable(name = "id") Long id) {
+ productMap.remove(id);
+ return "product " + id + " is deleted";
+ }
+
private Long addProduct(ProductRequest productRequest) {
Long id = getMaxKey();
productMap.put(id, new Product(id, productRequest));
From 317a4bab495355c45d3c51d13f5b5affae756158 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Tue, 25 Jun 2024 19:10:19 +0900
Subject: [PATCH 14/56] feat(product): create http request file
---
src/main/http/product/Product.http | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
create mode 100644 src/main/http/product/Product.http
diff --git a/src/main/http/product/Product.http b/src/main/http/product/Product.http
new file mode 100644
index 000000000..73fdd75e1
--- /dev/null
+++ b/src/main/http/product/Product.http
@@ -0,0 +1,27 @@
+### get product
+GET http://localhost:8080/api/products/1
+Content-Type: application/json
+
+### create product
+POST http://localhost:8080/api/products
+Content-Type: application/json
+
+{
+ "name": "아메리카노",
+ "price": "4500",
+ "imageUrl": "http://hello"
+}
+
+### update product
+PUT http://localhost:8080/api/products/1
+Content-Type: application/json
+
+{
+ "name": "아메리카노2",
+ "price": "5000",
+ "imageUrl": "http://hello"
+}
+
+### delete product
+DELETE http://localhost:8080/api/products/1
+Content-Type: application/json
\ No newline at end of file
From 5d21ad18fde656c16a4ee7da158f6d3f15da2448 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Wed, 26 Jun 2024 15:49:17 +0900
Subject: [PATCH 15/56] refactor(global): combine common parts of API URLs
---
.../gift/product/controller/ProductController.java | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/main/java/gift/product/controller/ProductController.java b/src/main/java/gift/product/controller/ProductController.java
index f1d90f513..27a109ad6 100644
--- a/src/main/java/gift/product/controller/ProductController.java
+++ b/src/main/java/gift/product/controller/ProductController.java
@@ -8,28 +8,28 @@
import java.util.Map;
@RestController
-@RequestMapping("/api")
+@RequestMapping("/api/products")
public class ProductController {
private final Map productMap = new HashMap<>();
- @GetMapping("/products/{id}")
+ @GetMapping("/{id}")
public Product getProductById(@PathVariable(name = "id") Long id) {
return productMap.get(id);
}
- @PostMapping("/products")
+ @PostMapping("")
public Product createProduct(@RequestBody ProductRequest productRequest) {
Long id = addProduct(productRequest);
return productMap.get(id);
}
- @PutMapping("/products/{id}")
+ @PutMapping("/{id}")
public Product updateProduct(@PathVariable(name = "id") Long id, @RequestBody ProductRequest productRequest) {
productMap.replace(id, new Product(id, productRequest));
return productMap.get(id);
}
- @DeleteMapping("/products/{id}")
+ @DeleteMapping("/{id}")
public String deleteProduct(@PathVariable(name = "id") Long id) {
productMap.remove(id);
return "product " + id + " is deleted";
From c42e11782e4b20d64ea84a1c45ee29fe325b0630 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Wed, 26 Jun 2024 15:51:29 +0900
Subject: [PATCH 16/56] feat(product): add get all product method
---
src/main/http/product/Product.http | 4 ++++
.../java/gift/product/controller/ProductController.java | 6 ++++++
2 files changed, 10 insertions(+)
diff --git a/src/main/http/product/Product.http b/src/main/http/product/Product.http
index 73fdd75e1..c465f395d 100644
--- a/src/main/http/product/Product.http
+++ b/src/main/http/product/Product.http
@@ -1,3 +1,7 @@
+### get product list
+GET http://localhost:8080/api/products/list
+Content-Type: application/json
+
### get product
GET http://localhost:8080/api/products/1
Content-Type: application/json
diff --git a/src/main/java/gift/product/controller/ProductController.java b/src/main/java/gift/product/controller/ProductController.java
index 27a109ad6..dae648724 100644
--- a/src/main/java/gift/product/controller/ProductController.java
+++ b/src/main/java/gift/product/controller/ProductController.java
@@ -5,6 +5,7 @@
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
@RestController
@@ -12,6 +13,11 @@
public class ProductController {
private final Map productMap = new HashMap<>();
+ @GetMapping("/list")
+ public List getAllProducts() {
+ return productMap.values().stream().toList();
+ }
+
@GetMapping("/{id}")
public Product getProductById(@PathVariable(name = "id") Long id) {
return productMap.get(id);
From 225aaf7bf375942303a06b245685fc6f86d612f2 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Wed, 26 Jun 2024 15:56:27 +0900
Subject: [PATCH 17/56] chore(product): rename global controller to view
controller
---
.../{GlobalController.java => view/ViewController.java} | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
rename src/main/java/gift/{GlobalController.java => view/ViewController.java} (58%)
diff --git a/src/main/java/gift/GlobalController.java b/src/main/java/gift/view/ViewController.java
similarity index 58%
rename from src/main/java/gift/GlobalController.java
rename to src/main/java/gift/view/ViewController.java
index b1f8ebf84..dfff0dff4 100644
--- a/src/main/java/gift/GlobalController.java
+++ b/src/main/java/gift/view/ViewController.java
@@ -1,12 +1,13 @@
-package gift;
+package gift.view;
import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
-public class GlobalController {
+public class ViewController {
@GetMapping("/")
- public String index() {
+ public String index(Model model) {
return "index";
}
}
From ebc23b24578391d3dfa409fc829329e9d9c06b9a Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Wed, 26 Jun 2024 16:29:56 +0900
Subject: [PATCH 18/56] fix(global): change get products list api url
---
src/main/java/gift/product/controller/ProductController.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/main/java/gift/product/controller/ProductController.java b/src/main/java/gift/product/controller/ProductController.java
index dae648724..2881b7836 100644
--- a/src/main/java/gift/product/controller/ProductController.java
+++ b/src/main/java/gift/product/controller/ProductController.java
@@ -13,7 +13,7 @@
public class ProductController {
private final Map productMap = new HashMap<>();
- @GetMapping("/list")
+ @GetMapping("")
public List getAllProducts() {
return productMap.values().stream().toList();
}
From bf7afcd32ead59e8d707d95aa3bcce1eebf6cfed Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Thu, 27 Jun 2024 14:56:47 +0900
Subject: [PATCH 19/56] chore(view): delete unnecssary parameter
---
src/main/java/gift/view/ViewController.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/main/java/gift/view/ViewController.java b/src/main/java/gift/view/ViewController.java
index dfff0dff4..06b16be34 100644
--- a/src/main/java/gift/view/ViewController.java
+++ b/src/main/java/gift/view/ViewController.java
@@ -1,13 +1,13 @@
package gift.view;
import org.springframework.stereotype.Controller;
-import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class ViewController {
+
@GetMapping("/")
- public String index(Model model) {
+ public String index() {
return "index";
}
}
From ecc4ff9685a265f5252cd18d211e183d3c951b8f Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Thu, 27 Jun 2024 14:58:47 +0900
Subject: [PATCH 20/56] feat(view): create product management UI
---
src/main/resources/templates/index.html | 213 ++++++++++++++++++++++++
1 file changed, 213 insertions(+)
create mode 100644 src/main/resources/templates/index.html
diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html
new file mode 100644
index 000000000..93586bc56
--- /dev/null
+++ b/src/main/resources/templates/index.html
@@ -0,0 +1,213 @@
+
+
+
+
+ Manage Products
+
+
+
+
+
+
+
+
+
Manage Products
+
+
+
+
+
+
+
+
+
+
+
+
Name
+
Price
+
Image URL
+
Actions
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Add New Product
+
+
+
+
+
+
+
+
+
+
+
+
+
+
From 199c89413f2c2ec11bdd9d8bcacda34f902e6360 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Thu, 27 Jun 2024 15:58:41 +0900
Subject: [PATCH 21/56] feat(product): create ServiceDto
---
.../product/controller/ProductController.java | 19 +++++++++++--------
.../java/gift/product/dto/ServiceDto.java | 4 ++++
2 files changed, 15 insertions(+), 8 deletions(-)
create mode 100644 src/main/java/gift/product/dto/ServiceDto.java
diff --git a/src/main/java/gift/product/controller/ProductController.java b/src/main/java/gift/product/controller/ProductController.java
index 2881b7836..bfb271b75 100644
--- a/src/main/java/gift/product/controller/ProductController.java
+++ b/src/main/java/gift/product/controller/ProductController.java
@@ -1,32 +1,35 @@
-package gift.product.controller;
+package gift.product.presentation;
-import gift.product.dto.ProductRequest;
+import gift.product.presentation.dto.ProductRequest;
import gift.product.entity.Product;
+import gift.product.service.ProductService;
import org.springframework.web.bind.annotation.*;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
@RestController
@RequestMapping("/api/products")
public class ProductController {
- private final Map productMap = new HashMap<>();
+ private final ProductService productService;
+
+ public ProductController(ProductService productService) {
+ this.productService = productService;
+ }
@GetMapping("")
public List getAllProducts() {
- return productMap.values().stream().toList();
+ return productService.getAllProducts();
}
@GetMapping("/{id}")
public Product getProductById(@PathVariable(name = "id") Long id) {
- return productMap.get(id);
+ return productService.getProductById(id);
}
@PostMapping("")
public Product createProduct(@RequestBody ProductRequest productRequest) {
Long id = addProduct(productRequest);
- return productMap.get(id);
+ return productService.createProduct();
}
@PutMapping("/{id}")
diff --git a/src/main/java/gift/product/dto/ServiceDto.java b/src/main/java/gift/product/dto/ServiceDto.java
new file mode 100644
index 000000000..9e41b8e5a
--- /dev/null
+++ b/src/main/java/gift/product/dto/ServiceDto.java
@@ -0,0 +1,4 @@
+package gift.product.dto;
+
+public record ServiceDto(Long id, String name, int price, String imageUrl) {
+}
From a38cc6f031b1675feb2a9974f1efb6fea03237ae Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Thu, 27 Jun 2024 16:01:15 +0900
Subject: [PATCH 22/56] feat(product): add toServiceDto method to convert
ProductRequest
---
src/main/java/gift/product/dto/ProductRequest.java | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/main/java/gift/product/dto/ProductRequest.java b/src/main/java/gift/product/dto/ProductRequest.java
index 7dfba414f..0e2c70f23 100644
--- a/src/main/java/gift/product/dto/ProductRequest.java
+++ b/src/main/java/gift/product/dto/ProductRequest.java
@@ -1,5 +1,7 @@
package gift.product.dto;
+import gift.product.service.ProductService;
+
import java.util.Objects;
public record ProductRequest(String name, int price, String imageUrl) {
@@ -7,4 +9,8 @@ public record ProductRequest(String name, int price, String imageUrl) {
Objects.requireNonNull(name);
Objects.requireNonNull(imageUrl);
}
+
+ public ServiceDto toServiceDto() {
+ return new ServiceDto(null, this.name, this.price, this.imageUrl);
+ }
}
From 4c57bf17d3122f93dc861b89e38b97724d5172fa Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Thu, 27 Jun 2024 17:29:36 +0900
Subject: [PATCH 23/56] feat(product): change all method to use productService
---
.../product/controller/ProductController.java | 26 +++++--------------
1 file changed, 7 insertions(+), 19 deletions(-)
diff --git a/src/main/java/gift/product/controller/ProductController.java b/src/main/java/gift/product/controller/ProductController.java
index bfb271b75..a1810ad95 100644
--- a/src/main/java/gift/product/controller/ProductController.java
+++ b/src/main/java/gift/product/controller/ProductController.java
@@ -1,11 +1,13 @@
-package gift.product.presentation;
+package gift.product.controller;
-import gift.product.presentation.dto.ProductRequest;
+import gift.product.dto.ProductRequest;
import gift.product.entity.Product;
import gift.product.service.ProductService;
import org.springframework.web.bind.annotation.*;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
@RestController
@RequestMapping("/api/products")
@@ -28,31 +30,17 @@ public Product getProductById(@PathVariable(name = "id") Long id) {
@PostMapping("")
public Product createProduct(@RequestBody ProductRequest productRequest) {
- Long id = addProduct(productRequest);
- return productService.createProduct();
+ return productService.createProduct(productRequest.toServiceDto());
}
@PutMapping("/{id}")
public Product updateProduct(@PathVariable(name = "id") Long id, @RequestBody ProductRequest productRequest) {
- productMap.replace(id, new Product(id, productRequest));
- return productMap.get(id);
+ return productService.updateProduct(productRequest.toServiceDto(id));
}
@DeleteMapping("/{id}")
public String deleteProduct(@PathVariable(name = "id") Long id) {
- productMap.remove(id);
+ productService.deleteProduct(id);
return "product " + id + " is deleted";
}
-
- private Long addProduct(ProductRequest productRequest) {
- Long id = getMaxKey();
- productMap.put(id, new Product(id, productRequest));
- return id;
- }
-
- private Long getMaxKey() {
- return 1L + productMap.keySet().stream()
- .max(Long::compare)
- .orElse(0L);
- }
}
From 20d14b73ad0280050badb42049f89fdbb39f41c0 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Thu, 27 Jun 2024 17:51:43 +0900
Subject: [PATCH 24/56] feat(product): create Product Not Found Exception
---
.../gift/product/exception/ProductNotFoundException.java | 7 +++++++
1 file changed, 7 insertions(+)
create mode 100644 src/main/java/gift/product/exception/ProductNotFoundException.java
diff --git a/src/main/java/gift/product/exception/ProductNotFoundException.java b/src/main/java/gift/product/exception/ProductNotFoundException.java
new file mode 100644
index 000000000..2ff1af342
--- /dev/null
+++ b/src/main/java/gift/product/exception/ProductNotFoundException.java
@@ -0,0 +1,7 @@
+package gift.product.exception;
+
+public class ProductNotFoundException extends Exception{
+ public ProductNotFoundException() {
+ super("Product Not Found Exception");
+ }
+}
From dd3d0e5fc14f61f5086d446c8f61f7f63075ff12 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Thu, 27 Jun 2024 17:52:33 +0900
Subject: [PATCH 25/56] feat(product): create Service Dto
---
src/main/java/gift/product/dto/ProductRequest.java | 4 ++++
src/main/java/gift/product/dto/ServiceDto.java | 5 +++++
2 files changed, 9 insertions(+)
diff --git a/src/main/java/gift/product/dto/ProductRequest.java b/src/main/java/gift/product/dto/ProductRequest.java
index 0e2c70f23..2a5d42f58 100644
--- a/src/main/java/gift/product/dto/ProductRequest.java
+++ b/src/main/java/gift/product/dto/ProductRequest.java
@@ -13,4 +13,8 @@ public record ProductRequest(String name, int price, String imageUrl) {
public ServiceDto toServiceDto() {
return new ServiceDto(null, this.name, this.price, this.imageUrl);
}
+
+ public ServiceDto toServiceDto(Long id) {
+ return new ServiceDto(id, this.name, this.price, this.imageUrl);
+ }
}
diff --git a/src/main/java/gift/product/dto/ServiceDto.java b/src/main/java/gift/product/dto/ServiceDto.java
index 9e41b8e5a..9df4cd2dd 100644
--- a/src/main/java/gift/product/dto/ServiceDto.java
+++ b/src/main/java/gift/product/dto/ServiceDto.java
@@ -1,4 +1,9 @@
package gift.product.dto;
+import gift.product.entity.Product;
+
public record ServiceDto(Long id, String name, int price, String imageUrl) {
+ public Product toProduct() {
+ return new Product(id, name, price, imageUrl);
+ }
}
From fc49319a1efcb8fa78011cd2d4e0e22b009fb275 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Thu, 27 Jun 2024 17:53:56 +0900
Subject: [PATCH 26/56] feat(product): create Product Service and methods
---
.../gift/product/service/ProductService.java | 47 +++++++++++++++++++
1 file changed, 47 insertions(+)
create mode 100644 src/main/java/gift/product/service/ProductService.java
diff --git a/src/main/java/gift/product/service/ProductService.java b/src/main/java/gift/product/service/ProductService.java
new file mode 100644
index 000000000..f193564ad
--- /dev/null
+++ b/src/main/java/gift/product/service/ProductService.java
@@ -0,0 +1,47 @@
+package gift.product.service;
+
+import gift.product.dto.ServiceDto;
+import gift.product.entity.Product;
+import gift.product.exception.ProductNotFoundException;
+import gift.product.repository.ProductRepository;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class ProductService {
+ private final ProductRepository productRepository;
+
+ public ProductService(ProductRepository productRepository) {
+ this.productRepository = productRepository;
+ }
+
+ public List getAllProducts() {
+ return productRepository.findAll();
+ }
+
+ public Product getProductById(Long id) {
+ return productRepository.findById(id)
+ .orElseThrow(ProductNotFoundException::new);
+ }
+
+ public Product createProduct(ServiceDto serviceDto) {
+ return productRepository.save(serviceDto.toProduct());
+ }
+
+ public Product updateProduct(ServiceDto serviceDto) {
+ validateProductExists(serviceDto.id());
+ return productRepository.save(serviceDto.toProduct());
+ }
+
+ public void deleteProduct(Long id) {
+ validateProductExists(id);
+ productRepository.deleteById(id);
+ }
+
+ private void validateProductExists(Long id) {
+ if (!productRepository.existsById(id)) {
+ throw new ProductNotFoundException();
+ }
+ }
+}
From a94447576330fb4c2952a1d36f9861fbf6dcfb9c Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Fri, 28 Jun 2024 09:12:17 +0900
Subject: [PATCH 27/56] feat(product): add isNew method in product entity
---
src/main/java/gift/product/entity/Product.java | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/main/java/gift/product/entity/Product.java b/src/main/java/gift/product/entity/Product.java
index f31d5a6a9..981f14a03 100644
--- a/src/main/java/gift/product/entity/Product.java
+++ b/src/main/java/gift/product/entity/Product.java
@@ -39,4 +39,7 @@ public String getImageUrl() {
return imageUrl;
}
+ public boolean isNew() {
+ return id == null;
+ }
}
From 56f5f57b88ef4d4207831cb4361f8337d001e624 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Fri, 28 Jun 2024 09:32:29 +0900
Subject: [PATCH 28/56] chore(global): add data jdbc dependency
---
build.gradle | 1 +
1 file changed, 1 insertion(+)
diff --git a/build.gradle b/build.gradle
index df7db9334..c13eda0cf 100644
--- a/build.gradle
+++ b/build.gradle
@@ -19,6 +19,7 @@ repositories {
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
+ implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
runtimeOnly 'com.h2database:h2'
From 29cf8c42641a63be955354c3753b79132b799565 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Fri, 28 Jun 2024 12:19:31 +0900
Subject: [PATCH 29/56] feat(product): create product repository and methods
---
.../product/repository/ProductRepository.java | 63 +++++++++++++++++++
1 file changed, 63 insertions(+)
create mode 100644 src/main/java/gift/product/repository/ProductRepository.java
diff --git a/src/main/java/gift/product/repository/ProductRepository.java b/src/main/java/gift/product/repository/ProductRepository.java
new file mode 100644
index 000000000..76c1ae34e
--- /dev/null
+++ b/src/main/java/gift/product/repository/ProductRepository.java
@@ -0,0 +1,63 @@
+package gift.product.repository;
+
+import gift.product.entity.Product;
+import org.springframework.jdbc.core.simple.JdbcClient;
+import org.springframework.stereotype.Repository;
+import org.springframework.util.Assert;
+
+import java.util.List;
+import java.util.Optional;
+
+@Repository
+public class ProductRepository {
+ private final JdbcClient jdbcClient;
+
+ public ProductRepository(JdbcClient jdbcClient) {
+ this.jdbcClient = jdbcClient;
+ }
+
+ public List findAll() {
+ String sql = "select * from products";
+ return jdbcClient.sql(sql)
+ .query(Product.class)
+ .list();
+ }
+
+ public Optional findById(Long id) {
+ String sql = "select * from products where id = ?";
+ return jdbcClient.sql(sql)
+ .param(id)
+ .query(Product.class)
+ .optional();
+ }
+
+ public Product save(Product product) {
+ Assert.notNull(product, "Product must not be null");
+ if (product.isNew()) {
+ String sql = "INSERT INTO products (name, price, image_url) VALUES (?, ?, ?)";
+ jdbcClient.sql(sql)
+ .param(product.getName())
+ .param(product.getPrice())
+ .param(product.getImageUrl())
+ .update();
+
+ }
+ if (!product.isNew()) {
+ String sql = "UPDATE products SET name = ?, price = ?, image_url = ? WHERE id = ?";
+ jdbcClient.sql(sql)
+ .param(product.getName())
+ .param(product.getPrice())
+ .param(product.getImageUrl())
+ .param(product.getId())
+ .update();
+ }
+ return product;
+ }
+
+ public void deleteById(Long id) {
+ String sql = "delete from products where id = ?";
+ jdbcClient.sql(sql)
+ .param(id)
+ .update();
+ }
+}
From 714baf2256f9a4d06727af5904267ea1356c415e Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Fri, 28 Jun 2024 12:25:56 +0900
Subject: [PATCH 30/56] feat(global): setting global exception handler
---
.../gift/global/exception/BusinessException.java | 7 +++++++
.../global/response/GlobalExceptionHandler.java | 14 ++++++++++++++
.../exception/ProductNotFoundException.java | 4 +++-
3 files changed, 24 insertions(+), 1 deletion(-)
create mode 100644 src/main/java/gift/global/exception/BusinessException.java
create mode 100644 src/main/java/gift/global/response/GlobalExceptionHandler.java
diff --git a/src/main/java/gift/global/exception/BusinessException.java b/src/main/java/gift/global/exception/BusinessException.java
new file mode 100644
index 000000000..f0dac8c6a
--- /dev/null
+++ b/src/main/java/gift/global/exception/BusinessException.java
@@ -0,0 +1,7 @@
+package gift.global.exception;
+
+public class BusinessException extends RuntimeException {
+ public BusinessException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/gift/global/response/GlobalExceptionHandler.java b/src/main/java/gift/global/response/GlobalExceptionHandler.java
new file mode 100644
index 000000000..010b34ba9
--- /dev/null
+++ b/src/main/java/gift/global/response/GlobalExceptionHandler.java
@@ -0,0 +1,14 @@
+package gift.global.response;
+
+import gift.global.exception.BusinessException;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+@RestControllerAdvice
+public class GlobalExceptionHandler {
+ @ExceptionHandler(BusinessException.class)
+ public ResponseEntity handleBusinessException(BusinessException e) {
+ return ResponseEntity.status(400).body(e.getMessage());
+ }
+}
diff --git a/src/main/java/gift/product/exception/ProductNotFoundException.java b/src/main/java/gift/product/exception/ProductNotFoundException.java
index 2ff1af342..08446c981 100644
--- a/src/main/java/gift/product/exception/ProductNotFoundException.java
+++ b/src/main/java/gift/product/exception/ProductNotFoundException.java
@@ -1,6 +1,8 @@
package gift.product.exception;
-public class ProductNotFoundException extends Exception{
+import gift.global.exception.BusinessException;
+
+public class ProductNotFoundException extends BusinessException {
public ProductNotFoundException() {
super("Product Not Found Exception");
}
From 902f597fddd813e1a83a83d3619ae5ef257ea7bc Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Fri, 28 Jun 2024 12:43:36 +0900
Subject: [PATCH 31/56] feat(global): setting db properties
---
src/main/resources/application.properties | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 3d16b65f4..763017f2c 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -1 +1,15 @@
spring.application.name=spring-gift
+
+spring.datasource.url=jdbc:h2:mem:testdb
+spring.datasource.driverClassName=org.h2.Driver
+spring.datasource.username=sa
+spring.datasource.password=1234
+
+# H2 Console Configuration
+spring.h2.console.enabled=true
+spring.h2.console.path=/h2-console
+
+# SQL Script Initialization
+spring.sql.init.mode=always
+spring.sql.init.schema-locations=classpath:schema.sql
+spring.sql.init.data-locations=classpath:data.sql
\ No newline at end of file
From 71fb6edbaa90f0dd902ad7cf5cc627cafc6d6043 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Fri, 28 Jun 2024 12:44:25 +0900
Subject: [PATCH 32/56] feat(product): create input initial data sql
---
src/main/resources/data.sql | 2 ++
1 file changed, 2 insertions(+)
create mode 100644 src/main/resources/data.sql
diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql
new file mode 100644
index 000000000..594dd9348
--- /dev/null
+++ b/src/main/resources/data.sql
@@ -0,0 +1,2 @@
+INSERT INTO products (name, price, image_url) VALUES ('test1', 10000, 'http://');
+INSERT INTO products (name, price, image_url) VALUES ('test2', 20000, 'http://');
From b00ee6f67c33f685b69d640181bc32bdaf0e36f5 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Fri, 28 Jun 2024 12:44:54 +0900
Subject: [PATCH 33/56] feat(product): create schema sql to make table products
---
src/main/resources/schema.sql | 6 ++++++
1 file changed, 6 insertions(+)
create mode 100644 src/main/resources/schema.sql
diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql
new file mode 100644
index 000000000..e38d50c96
--- /dev/null
+++ b/src/main/resources/schema.sql
@@ -0,0 +1,6 @@
+CREATE TABLE IF NOT EXISTS products (
+ id BIGINT AUTO_INCREMENT PRIMARY KEY,
+ name VARCHAR(255) NOT NULL,
+ price BIGINT NOT NULL,
+ image_url VARCHAR(255)
+);
\ No newline at end of file
From 1d4f2bbad9bd7b3a557731ab713b89fa71114531 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Fri, 28 Jun 2024 12:47:41 +0900
Subject: [PATCH 34/56] fix(product): add default constructor and change
directory entity to domain
---
.../java/gift/product/controller/ProductController.java | 4 +---
.../java/gift/product/{entity => domain}/Product.java | 9 ++++++++-
src/main/java/gift/product/dto/ServiceDto.java | 2 +-
.../java/gift/product/repository/ProductRepository.java | 2 +-
src/main/java/gift/product/service/ProductService.java | 7 +++----
5 files changed, 14 insertions(+), 10 deletions(-)
rename src/main/java/gift/product/{entity => domain}/Product.java (73%)
diff --git a/src/main/java/gift/product/controller/ProductController.java b/src/main/java/gift/product/controller/ProductController.java
index a1810ad95..3a1ac212d 100644
--- a/src/main/java/gift/product/controller/ProductController.java
+++ b/src/main/java/gift/product/controller/ProductController.java
@@ -1,13 +1,11 @@
package gift.product.controller;
import gift.product.dto.ProductRequest;
-import gift.product.entity.Product;
+import gift.product.domain.Product;
import gift.product.service.ProductService;
import org.springframework.web.bind.annotation.*;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
@RestController
@RequestMapping("/api/products")
diff --git a/src/main/java/gift/product/entity/Product.java b/src/main/java/gift/product/domain/Product.java
similarity index 73%
rename from src/main/java/gift/product/entity/Product.java
rename to src/main/java/gift/product/domain/Product.java
index 981f14a03..b062d7fd7 100644
--- a/src/main/java/gift/product/entity/Product.java
+++ b/src/main/java/gift/product/domain/Product.java
@@ -1,13 +1,20 @@
-package gift.product.entity;
+package gift.product.domain;
import gift.product.dto.ProductRequest;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.relational.core.mapping.Table;
+@Table("products")
public class Product {
+ @Id
private Long id;
private String name;
private int price;
private String imageUrl;
+ // JDBC 에서 엔티티 클래스를 인스턴스화할 때 반드시 기본 생성자와 파라미터 생성자가 필요하다
+ public Product() {}
+
public Product(Long id, String name, int price, String imageUrl) {
this.id = id;
this.name = name;
diff --git a/src/main/java/gift/product/dto/ServiceDto.java b/src/main/java/gift/product/dto/ServiceDto.java
index 9df4cd2dd..019e1842a 100644
--- a/src/main/java/gift/product/dto/ServiceDto.java
+++ b/src/main/java/gift/product/dto/ServiceDto.java
@@ -1,6 +1,6 @@
package gift.product.dto;
-import gift.product.entity.Product;
+import gift.product.domain.Product;
public record ServiceDto(Long id, String name, int price, String imageUrl) {
public Product toProduct() {
diff --git a/src/main/java/gift/product/repository/ProductRepository.java b/src/main/java/gift/product/repository/ProductRepository.java
index 76c1ae34e..66efae5aa 100644
--- a/src/main/java/gift/product/repository/ProductRepository.java
+++ b/src/main/java/gift/product/repository/ProductRepository.java
@@ -1,6 +1,6 @@
package gift.product.repository;
-import gift.product.entity.Product;
+import gift.product.domain.Product;
import org.springframework.jdbc.core.simple.JdbcClient;
import org.springframework.stereotype.Repository;
import org.springframework.util.Assert;
diff --git a/src/main/java/gift/product/service/ProductService.java b/src/main/java/gift/product/service/ProductService.java
index f193564ad..34c6b377a 100644
--- a/src/main/java/gift/product/service/ProductService.java
+++ b/src/main/java/gift/product/service/ProductService.java
@@ -1,7 +1,7 @@
package gift.product.service;
import gift.product.dto.ServiceDto;
-import gift.product.entity.Product;
+import gift.product.domain.Product;
import gift.product.exception.ProductNotFoundException;
import gift.product.repository.ProductRepository;
import org.springframework.stereotype.Service;
@@ -40,8 +40,7 @@ public void deleteProduct(Long id) {
}
private void validateProductExists(Long id) {
- if (!productRepository.existsById(id)) {
- throw new ProductNotFoundException();
- }
+ productRepository.findById(id)
+ .orElseThrow(ProductNotFoundException::new);
}
}
From 199a7ff9fb89d2e504c489270f7dfb295aab6afd Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Fri, 28 Jun 2024 12:57:47 +0900
Subject: [PATCH 35/56] feat(global): create result code enum
---
.../java/gift/global/response/ResultCode.java | 20 +++++++++++++++++++
1 file changed, 20 insertions(+)
create mode 100644 src/main/java/gift/global/response/ResultCode.java
diff --git a/src/main/java/gift/global/response/ResultCode.java b/src/main/java/gift/global/response/ResultCode.java
new file mode 100644
index 000000000..0bfc77f09
--- /dev/null
+++ b/src/main/java/gift/global/response/ResultCode.java
@@ -0,0 +1,20 @@
+package gift.global.response;
+
+import org.springframework.http.HttpStatusCode;
+
+public enum ResultCode {
+ // Product
+
+
+ ;
+ // HttpStatusCode 로 관리하는 것이 좋을까, 아니면 String으로 관리하는 것이 좋을까?
+ private final HttpStatusCode status;
+ private final String resultCode;
+ private final String message;
+
+ ResultCode(HttpStatusCode status, String resultCode, String message) {
+ this.status = status;
+ this.resultCode = resultCode;
+ this.message = message;
+ }
+}
From b388095bdffbdc129d0985828661b88fe99c1734 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Fri, 28 Jun 2024 13:05:10 +0900
Subject: [PATCH 36/56] feat(product): set result code of product api
---
.../java/gift/global/response/ResultCode.java | 27 ++++++++++++++-----
1 file changed, 21 insertions(+), 6 deletions(-)
diff --git a/src/main/java/gift/global/response/ResultCode.java b/src/main/java/gift/global/response/ResultCode.java
index 0bfc77f09..f2af50d2d 100644
--- a/src/main/java/gift/global/response/ResultCode.java
+++ b/src/main/java/gift/global/response/ResultCode.java
@@ -1,20 +1,35 @@
package gift.global.response;
-import org.springframework.http.HttpStatusCode;
-
public enum ResultCode {
// Product
-
+ GET_ALL_PRODUCTS_SUCCESS("200", "P001", "모든 제품 조회 성공"),
+ GET_PRODUCT_BY_ID_SUCCESS("200", "P002", "단일 제품 조회 성공"),
+ CREATE_PRODUCT_SUCCESS("200", "P003", "제품 추가 성공"),
+ UPDATE_PRODUCT_SUCCESS("200", "P002", "제품 수정 성공"),
+ DELETE_PRODUCT_SUCCESS("200", "P002", "제품 삭제 성공"),
;
- // HttpStatusCode 로 관리하는 것이 좋을까, 아니면 String으로 관리하는 것이 좋을까?
- private final HttpStatusCode status;
+
+ // status 를 HttpStatus 로 관리하는 것이 좋을까, 아니면 String으로 관리하는 것이 좋을까?
+ private final String status;
private final String resultCode;
private final String message;
- ResultCode(HttpStatusCode status, String resultCode, String message) {
+ ResultCode(String status, String resultCode, String message) {
this.status = status;
this.resultCode = resultCode;
this.message = message;
}
+
+ public String getStatus() {
+ return status;
+ }
+
+ public String getResultCode() {
+ return resultCode;
+ }
+
+ public String getMessage() {
+ return message;
+ }
}
From 8a22e261089440ab172b395deac2e78baae525ae Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Fri, 28 Jun 2024 13:11:15 +0900
Subject: [PATCH 37/56] feat(global): create result response
---
src/main/java/gift/global/response/ResultResponse.java | 8 ++++++++
1 file changed, 8 insertions(+)
create mode 100644 src/main/java/gift/global/response/ResultResponse.java
diff --git a/src/main/java/gift/global/response/ResultResponse.java b/src/main/java/gift/global/response/ResultResponse.java
new file mode 100644
index 000000000..24bb682a3
--- /dev/null
+++ b/src/main/java/gift/global/response/ResultResponse.java
@@ -0,0 +1,8 @@
+package gift.global.response;
+
+public record ResultResponse(String code, String message, T data) {
+ // 자바 record 에서 생성자를 만들 경우, 반드시 canonical(표준) 생성자를 사용해야 한다!!
+ ResultResponse(ResultCode resultCode, T data) {
+ this(resultCode.getResultCode(), resultCode.getMessage(), data);
+ }
+}
From 9410cc5b3146fd7ffcf4f95bca9a78e28b6e407e Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Fri, 28 Jun 2024 13:14:16 +0900
Subject: [PATCH 38/56] fix(global): change result code status type String to
int
---
.../java/gift/global/response/ResultCode.java | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/src/main/java/gift/global/response/ResultCode.java b/src/main/java/gift/global/response/ResultCode.java
index f2af50d2d..b7e87fae2 100644
--- a/src/main/java/gift/global/response/ResultCode.java
+++ b/src/main/java/gift/global/response/ResultCode.java
@@ -2,26 +2,26 @@
public enum ResultCode {
// Product
- GET_ALL_PRODUCTS_SUCCESS("200", "P001", "모든 제품 조회 성공"),
- GET_PRODUCT_BY_ID_SUCCESS("200", "P002", "단일 제품 조회 성공"),
- CREATE_PRODUCT_SUCCESS("200", "P003", "제품 추가 성공"),
- UPDATE_PRODUCT_SUCCESS("200", "P002", "제품 수정 성공"),
- DELETE_PRODUCT_SUCCESS("200", "P002", "제품 삭제 성공"),
+ GET_ALL_PRODUCTS_SUCCESS(200, "P001", "모든 제품 조회 성공"),
+ GET_PRODUCT_BY_ID_SUCCESS(200, "P002", "단일 제품 조회 성공"),
+ CREATE_PRODUCT_SUCCESS(200, "P003", "제품 추가 성공"),
+ UPDATE_PRODUCT_SUCCESS(200, "P002", "제품 수정 성공"),
+ DELETE_PRODUCT_SUCCESS(200, "P002", "제품 삭제 성공"),
;
- // status 를 HttpStatus 로 관리하는 것이 좋을까, 아니면 String으로 관리하는 것이 좋을까?
- private final String status;
+ // status 를 HttpStatus 로 관리하는 것이 좋을까, 아니면 int로 관리하는 것이 좋을까?
+ private final int status;
private final String resultCode;
private final String message;
- ResultCode(String status, String resultCode, String message) {
+ ResultCode(int status, String resultCode, String message) {
this.status = status;
this.resultCode = resultCode;
this.message = message;
}
- public String getStatus() {
+ public int getStatus() {
return status;
}
From c3736c505f233c8a072e2281588f1f7bf13aea58 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Fri, 28 Jun 2024 13:17:01 +0900
Subject: [PATCH 39/56] fix(global): change result response private to public
---
src/main/java/gift/global/response/ResultResponse.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/main/java/gift/global/response/ResultResponse.java b/src/main/java/gift/global/response/ResultResponse.java
index 24bb682a3..50ed06353 100644
--- a/src/main/java/gift/global/response/ResultResponse.java
+++ b/src/main/java/gift/global/response/ResultResponse.java
@@ -2,7 +2,7 @@
public record ResultResponse(String code, String message, T data) {
// 자바 record 에서 생성자를 만들 경우, 반드시 canonical(표준) 생성자를 사용해야 한다!!
- ResultResponse(ResultCode resultCode, T data) {
+ public ResultResponse(ResultCode resultCode, T data) {
this(resultCode.getResultCode(), resultCode.getMessage(), data);
}
}
From 7bac451fdbcc97d298a1058aa4303560af030133 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Fri, 28 Jun 2024 13:22:12 +0900
Subject: [PATCH 40/56] chore(global): change ResultResponse name to
ResultResponseDto
---
.../response/{ResultResponse.java => ResultResponseDto.java} | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
rename src/main/java/gift/global/response/{ResultResponse.java => ResultResponseDto.java} (62%)
diff --git a/src/main/java/gift/global/response/ResultResponse.java b/src/main/java/gift/global/response/ResultResponseDto.java
similarity index 62%
rename from src/main/java/gift/global/response/ResultResponse.java
rename to src/main/java/gift/global/response/ResultResponseDto.java
index 50ed06353..1829813c0 100644
--- a/src/main/java/gift/global/response/ResultResponse.java
+++ b/src/main/java/gift/global/response/ResultResponseDto.java
@@ -1,8 +1,8 @@
package gift.global.response;
-public record ResultResponse(String code, String message, T data) {
+public record ResultResponseDto(String code, String message, T data) {
// 자바 record 에서 생성자를 만들 경우, 반드시 canonical(표준) 생성자를 사용해야 한다!!
- public ResultResponse(ResultCode resultCode, T data) {
+ public ResultResponseDto(ResultCode resultCode, T data) {
this(resultCode.getResultCode(), resultCode.getMessage(), data);
}
}
From 0759818c10d891b8f3b7757b1bd8a779eb452b2e Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Fri, 28 Jun 2024 13:24:46 +0900
Subject: [PATCH 41/56] fix(http): update url for get all products
---
src/main/http/product/Product.http | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/main/http/product/Product.http b/src/main/http/product/Product.http
index c465f395d..e5f6a467f 100644
--- a/src/main/http/product/Product.http
+++ b/src/main/http/product/Product.http
@@ -1,5 +1,5 @@
### get product list
-GET http://localhost:8080/api/products/list
+GET http://localhost:8080/api/products
Content-Type: application/json
### get product
From 7e61e4199adb38c0a5f8ca26e9c9ae64256a9591 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Fri, 28 Jun 2024 13:25:24 +0900
Subject: [PATCH 42/56] feat(global): create simple result response dto
---
.../java/gift/global/response/SimpleResultResponseDto.java | 7 +++++++
1 file changed, 7 insertions(+)
create mode 100644 src/main/java/gift/global/response/SimpleResultResponseDto.java
diff --git a/src/main/java/gift/global/response/SimpleResultResponseDto.java b/src/main/java/gift/global/response/SimpleResultResponseDto.java
new file mode 100644
index 000000000..2abcd9905
--- /dev/null
+++ b/src/main/java/gift/global/response/SimpleResultResponseDto.java
@@ -0,0 +1,7 @@
+package gift.global.response;
+
+public record SimpleResultResponseDto(String code, String message) {
+ public SimpleResultResponseDto(ResultCode resultCode) {
+ this(resultCode.getResultCode(), resultCode.getMessage());
+ }
+}
From 3ef0273a54848efc442976f2cdfcde3d7fc5f309 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Fri, 28 Jun 2024 14:38:46 +0900
Subject: [PATCH 43/56] chore(global): move global exception handler package
response to handler
---
.../global/{response => handler}/GlobalExceptionHandler.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
rename src/main/java/gift/global/{response => handler}/GlobalExceptionHandler.java (94%)
diff --git a/src/main/java/gift/global/response/GlobalExceptionHandler.java b/src/main/java/gift/global/handler/GlobalExceptionHandler.java
similarity index 94%
rename from src/main/java/gift/global/response/GlobalExceptionHandler.java
rename to src/main/java/gift/global/handler/GlobalExceptionHandler.java
index 010b34ba9..2f64b1248 100644
--- a/src/main/java/gift/global/response/GlobalExceptionHandler.java
+++ b/src/main/java/gift/global/handler/GlobalExceptionHandler.java
@@ -1,4 +1,4 @@
-package gift.global.response;
+package gift.global.handler;
import gift.global.exception.BusinessException;
import org.springframework.http.ResponseEntity;
From 1d83a5799eee9a2469b4afa0bd4c1f0461417771 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Fri, 28 Jun 2024 14:40:15 +0900
Subject: [PATCH 44/56] feat(product): change all method response to use
ResponseEntity
---
.../product/controller/ProductController.java | 42 ++++++++++++++-----
1 file changed, 31 insertions(+), 11 deletions(-)
diff --git a/src/main/java/gift/product/controller/ProductController.java b/src/main/java/gift/product/controller/ProductController.java
index 3a1ac212d..a95d5edb7 100644
--- a/src/main/java/gift/product/controller/ProductController.java
+++ b/src/main/java/gift/product/controller/ProductController.java
@@ -1,8 +1,12 @@
package gift.product.controller;
+import gift.global.response.ResultCode;
+import gift.global.response.ResultResponseDto;
+import gift.global.response.SimpleResultResponseDto;
import gift.product.dto.ProductRequest;
import gift.product.domain.Product;
import gift.product.service.ProductService;
+import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@@ -17,28 +21,44 @@ public ProductController(ProductService productService) {
}
@GetMapping("")
- public List getAllProducts() {
- return productService.getAllProducts();
+ public ResponseEntity>> getAllProducts() {
+ List products = productService.getAllProducts();
+ return createResponse(ResultCode.GET_ALL_PRODUCTS_SUCCESS, products);
}
@GetMapping("/{id}")
- public Product getProductById(@PathVariable(name = "id") Long id) {
- return productService.getProductById(id);
+ public ResponseEntity> getProductById(@PathVariable(name = "id") Long id) {
+ Product product = productService.getProductById(id);
+ return createResponse(ResultCode.GET_PRODUCT_BY_ID_SUCCESS, product);
}
@PostMapping("")
- public Product createProduct(@RequestBody ProductRequest productRequest) {
- return productService.createProduct(productRequest.toServiceDto());
+ public ResponseEntity createProduct(@RequestBody ProductRequest productRequest) {
+ productService.createProduct(productRequest.toServiceDto());
+ return createSimpleResponse(ResultCode.CREATE_PRODUCT_SUCCESS);
}
@PutMapping("/{id}")
- public Product updateProduct(@PathVariable(name = "id") Long id, @RequestBody ProductRequest productRequest) {
- return productService.updateProduct(productRequest.toServiceDto(id));
+ public ResponseEntity updateProduct(@PathVariable(name = "id") Long id, @RequestBody ProductRequest productRequest) {
+ productService.updateProduct(productRequest.toServiceDto(id));
+ return createSimpleResponse(ResultCode.UPDATE_PRODUCT_SUCCESS);
}
@DeleteMapping("/{id}")
- public String deleteProduct(@PathVariable(name = "id") Long id) {
+ public ResponseEntity deleteProduct(@PathVariable(name = "id") Long id) {
productService.deleteProduct(id);
- return "product " + id + " is deleted";
+ return createSimpleResponse(ResultCode.DELETE_PRODUCT_SUCCESS);
}
-}
+
+ private ResponseEntity> createResponse(ResultCode resultCode, T data) {
+ ResultResponseDto resultResponseDto = new ResultResponseDto<>(resultCode, data);
+ return ResponseEntity.status(resultCode.getStatus())
+ .body(resultResponseDto);
+ }
+
+ private ResponseEntity createSimpleResponse(ResultCode resultCode) {
+ var resultResponseDto = new SimpleResultResponseDto(resultCode);
+ return ResponseEntity.status(resultCode.getStatus())
+ .body(resultResponseDto);
+ }
+}
\ No newline at end of file
From c3005316188c55283db9689dde7e56b963922eba Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Fri, 28 Jun 2024 14:44:15 +0900
Subject: [PATCH 45/56] fix(product): remove return value from create and
update methods
---
.../java/gift/product/repository/ProductRepository.java | 3 +--
src/main/java/gift/product/service/ProductService.java | 8 ++++----
2 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/src/main/java/gift/product/repository/ProductRepository.java b/src/main/java/gift/product/repository/ProductRepository.java
index 66efae5aa..aa48a117e 100644
--- a/src/main/java/gift/product/repository/ProductRepository.java
+++ b/src/main/java/gift/product/repository/ProductRepository.java
@@ -31,7 +31,7 @@ public Optional findById(Long id) {
.optional();
}
- public Product save(Product product) {
+ public void save(Product product) {
Assert.notNull(product, "Product must not be null");
if (product.isNew()) {
String sql = "INSERT INTO products (name, price, image_url) VALUES (?, ?, ?)";
@@ -51,7 +51,6 @@ public Product save(Product product) {
.param(product.getId())
.update();
}
- return product;
}
public void deleteById(Long id) {
diff --git a/src/main/java/gift/product/service/ProductService.java b/src/main/java/gift/product/service/ProductService.java
index 34c6b377a..1a2dda1f0 100644
--- a/src/main/java/gift/product/service/ProductService.java
+++ b/src/main/java/gift/product/service/ProductService.java
@@ -25,13 +25,13 @@ public Product getProductById(Long id) {
.orElseThrow(ProductNotFoundException::new);
}
- public Product createProduct(ServiceDto serviceDto) {
- return productRepository.save(serviceDto.toProduct());
+ public void createProduct(ServiceDto serviceDto) {
+ productRepository.save(serviceDto.toProduct());
}
- public Product updateProduct(ServiceDto serviceDto) {
+ public void updateProduct(ServiceDto serviceDto) {
validateProductExists(serviceDto.id());
- return productRepository.save(serviceDto.toProduct());
+ productRepository.save(serviceDto.toProduct());
}
public void deleteProduct(Long id) {
From 77076beddfd3b85c5b78b8fa9eb4c299833af336 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Fri, 28 Jun 2024 14:51:42 +0900
Subject: [PATCH 46/56] feat(global): create response helper util
---
.../gift/global/utils/ResponseHelper.java | 20 +++++++++++++++++++
1 file changed, 20 insertions(+)
create mode 100644 src/main/java/gift/global/utils/ResponseHelper.java
diff --git a/src/main/java/gift/global/utils/ResponseHelper.java b/src/main/java/gift/global/utils/ResponseHelper.java
new file mode 100644
index 000000000..22ddedd4c
--- /dev/null
+++ b/src/main/java/gift/global/utils/ResponseHelper.java
@@ -0,0 +1,20 @@
+package gift.global.utils;
+
+import gift.global.response.ResultCode;
+import gift.global.response.ResultResponseDto;
+import gift.global.response.SimpleResultResponseDto;
+import org.springframework.http.ResponseEntity;
+
+public class ResponseHelper {
+ public static ResponseEntity> createResponse(ResultCode resultCode, T data) {
+ ResultResponseDto resultResponseDto = new ResultResponseDto<>(resultCode, data);
+ return org.springframework.http.ResponseEntity.status(resultCode.getStatus())
+ .body(resultResponseDto);
+ }
+
+ public static ResponseEntity createSimpleResponse(ResultCode resultCode) {
+ var resultResponseDto = new SimpleResultResponseDto(resultCode);
+ return ResponseEntity.status(resultCode.getStatus())
+ .body(resultResponseDto);
+ }
+}
From fd8961965d7987d0a0c3a5a301a54172dd902f90 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Fri, 28 Jun 2024 14:53:46 +0900
Subject: [PATCH 47/56] refactor(product): apply ResponseHelper for response
creation in ProductController
---
.../product/controller/ProductController.java | 23 +++++--------------
1 file changed, 6 insertions(+), 17 deletions(-)
diff --git a/src/main/java/gift/product/controller/ProductController.java b/src/main/java/gift/product/controller/ProductController.java
index a95d5edb7..296856a96 100644
--- a/src/main/java/gift/product/controller/ProductController.java
+++ b/src/main/java/gift/product/controller/ProductController.java
@@ -3,6 +3,7 @@
import gift.global.response.ResultCode;
import gift.global.response.ResultResponseDto;
import gift.global.response.SimpleResultResponseDto;
+import gift.global.utils.ResponseHelper;
import gift.product.dto.ProductRequest;
import gift.product.domain.Product;
import gift.product.service.ProductService;
@@ -23,42 +24,30 @@ public ProductController(ProductService productService) {
@GetMapping("")
public ResponseEntity>> getAllProducts() {
List products = productService.getAllProducts();
- return createResponse(ResultCode.GET_ALL_PRODUCTS_SUCCESS, products);
+ return ResponseHelper.createResponse(ResultCode.GET_ALL_PRODUCTS_SUCCESS, products);
}
@GetMapping("/{id}")
public ResponseEntity> getProductById(@PathVariable(name = "id") Long id) {
Product product = productService.getProductById(id);
- return createResponse(ResultCode.GET_PRODUCT_BY_ID_SUCCESS, product);
+ return ResponseHelper.createResponse(ResultCode.GET_PRODUCT_BY_ID_SUCCESS, product);
}
@PostMapping("")
public ResponseEntity createProduct(@RequestBody ProductRequest productRequest) {
productService.createProduct(productRequest.toServiceDto());
- return createSimpleResponse(ResultCode.CREATE_PRODUCT_SUCCESS);
+ return ResponseHelper.createSimpleResponse(ResultCode.CREATE_PRODUCT_SUCCESS);
}
@PutMapping("/{id}")
public ResponseEntity updateProduct(@PathVariable(name = "id") Long id, @RequestBody ProductRequest productRequest) {
productService.updateProduct(productRequest.toServiceDto(id));
- return createSimpleResponse(ResultCode.UPDATE_PRODUCT_SUCCESS);
+ return ResponseHelper.createSimpleResponse(ResultCode.UPDATE_PRODUCT_SUCCESS);
}
@DeleteMapping("/{id}")
public ResponseEntity deleteProduct(@PathVariable(name = "id") Long id) {
productService.deleteProduct(id);
- return createSimpleResponse(ResultCode.DELETE_PRODUCT_SUCCESS);
- }
-
- private ResponseEntity> createResponse(ResultCode resultCode, T data) {
- ResultResponseDto resultResponseDto = new ResultResponseDto<>(resultCode, data);
- return ResponseEntity.status(resultCode.getStatus())
- .body(resultResponseDto);
- }
-
- private ResponseEntity createSimpleResponse(ResultCode resultCode) {
- var resultResponseDto = new SimpleResultResponseDto(resultCode);
- return ResponseEntity.status(resultCode.getStatus())
- .body(resultResponseDto);
+ return ResponseHelper.createSimpleResponse(ResultCode.DELETE_PRODUCT_SUCCESS);
}
}
\ No newline at end of file
From 8fdd8ea2a4a4690e89e25efc09bade9747ac1935 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Fri, 28 Jun 2024 15:04:50 +0900
Subject: [PATCH 48/56] fix(product): change method name from isNew to checkNew
to fix JSON serialization
---
src/main/java/gift/product/domain/Product.java | 2 +-
src/main/java/gift/product/repository/ProductRepository.java | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/main/java/gift/product/domain/Product.java b/src/main/java/gift/product/domain/Product.java
index b062d7fd7..d0d473e73 100644
--- a/src/main/java/gift/product/domain/Product.java
+++ b/src/main/java/gift/product/domain/Product.java
@@ -46,7 +46,7 @@ public String getImageUrl() {
return imageUrl;
}
- public boolean isNew() {
+ public boolean checkNew() {
return id == null;
}
}
diff --git a/src/main/java/gift/product/repository/ProductRepository.java b/src/main/java/gift/product/repository/ProductRepository.java
index aa48a117e..72df257f5 100644
--- a/src/main/java/gift/product/repository/ProductRepository.java
+++ b/src/main/java/gift/product/repository/ProductRepository.java
@@ -33,7 +33,7 @@ public Optional findById(Long id) {
public void save(Product product) {
Assert.notNull(product, "Product must not be null");
- if (product.isNew()) {
+ if (product.checkNew()) {
String sql = "INSERT INTO products (name, price, image_url) VALUES (?, ?, ?)";
jdbcClient.sql(sql)
.param(product.getName())
@@ -42,7 +42,7 @@ public void save(Product product) {
.update();
}
- if (!product.isNew()) {
+ if (!product.checkNew()) {
String sql = "UPDATE products SET name = ?, price = ?, image_url = ? WHERE id = ?";
jdbcClient.sql(sql)
.param(product.getName())
From ebee7f4600a2d0444fd03bb24d4d7cd31bfd4a50 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Fri, 28 Jun 2024 15:16:07 +0900
Subject: [PATCH 49/56] fix(view): update index.html to use response.data for
request parameter
---
src/main/resources/templates/index.html | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html
index 93586bc56..6b8985ecd 100644
--- a/src/main/resources/templates/index.html
+++ b/src/main/resources/templates/index.html
@@ -90,12 +90,12 @@
Add New Product
// 제품 목록을 서버에서 가져와서 테이블에 표시하는 함수
function loadProducts() {
- $.get(apiBaseUrl, function (data) {
+ $.get(apiBaseUrl, function (response) {
// 테이블 본문을 비우기
$('#productTableBody').empty();
// products 데이터로 테이블 행 생성
- data.forEach(product => {
+ response.data.forEach(product => {
$('#productTableBody').append(`
@@ -164,12 +164,12 @@
Add New Product
// "Edit" 버튼 클릭 시 해당 제품 데이터를 가져와 모달에 표시
$(document).on('click', '.editProduct', function () {
const productId = $(this).closest('tr').data('id');
- $.get(apiBaseUrl + '/' + productId, function (data) {
+ $.get(apiBaseUrl + '/' + productId, function (response) {
$('#productModalLabel').text('Edit Product');
- $('#productId').val(data.id);
- $('#productName').val(data.name);
- $('#productPrice').val(data.price);
- $('#productImageUrl').val(data.imageUrl);
+ $('#productId').val(response.data.id);
+ $('#productName').val(response.data.name);
+ $('#productPrice').val(response.data.price);
+ $('#productImageUrl').val(response.data.imageUrl);
$('#productModal').modal('show');
});
});
From d512a900f1e5bac77f687ff25d51a3c92a52f690 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Fri, 28 Jun 2024 15:23:01 +0900
Subject: [PATCH 50/56] refactor(global): change resultCode variable to code in
ResultCode enum
---
src/main/java/gift/global/response/ResultCode.java | 10 +++++-----
.../java/gift/global/response/ResultResponseDto.java | 2 +-
.../gift/global/response/SimpleResultResponseDto.java | 2 +-
3 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/main/java/gift/global/response/ResultCode.java b/src/main/java/gift/global/response/ResultCode.java
index b7e87fae2..bf2c46adc 100644
--- a/src/main/java/gift/global/response/ResultCode.java
+++ b/src/main/java/gift/global/response/ResultCode.java
@@ -12,12 +12,12 @@ public enum ResultCode {
// status 를 HttpStatus 로 관리하는 것이 좋을까, 아니면 int로 관리하는 것이 좋을까?
private final int status;
- private final String resultCode;
+ private final String code;
private final String message;
- ResultCode(int status, String resultCode, String message) {
+ ResultCode(int status, String code, String message) {
this.status = status;
- this.resultCode = resultCode;
+ this.code = code;
this.message = message;
}
@@ -25,8 +25,8 @@ public int getStatus() {
return status;
}
- public String getResultCode() {
- return resultCode;
+ public String getCode() {
+ return code;
}
public String getMessage() {
diff --git a/src/main/java/gift/global/response/ResultResponseDto.java b/src/main/java/gift/global/response/ResultResponseDto.java
index 1829813c0..bb3aec0c1 100644
--- a/src/main/java/gift/global/response/ResultResponseDto.java
+++ b/src/main/java/gift/global/response/ResultResponseDto.java
@@ -3,6 +3,6 @@
public record ResultResponseDto(String code, String message, T data) {
// 자바 record 에서 생성자를 만들 경우, 반드시 canonical(표준) 생성자를 사용해야 한다!!
public ResultResponseDto(ResultCode resultCode, T data) {
- this(resultCode.getResultCode(), resultCode.getMessage(), data);
+ this(resultCode.getCode(), resultCode.getMessage(), data);
}
}
diff --git a/src/main/java/gift/global/response/SimpleResultResponseDto.java b/src/main/java/gift/global/response/SimpleResultResponseDto.java
index 2abcd9905..895a220db 100644
--- a/src/main/java/gift/global/response/SimpleResultResponseDto.java
+++ b/src/main/java/gift/global/response/SimpleResultResponseDto.java
@@ -2,6 +2,6 @@
public record SimpleResultResponseDto(String code, String message) {
public SimpleResultResponseDto(ResultCode resultCode) {
- this(resultCode.getResultCode(), resultCode.getMessage());
+ this(resultCode.getCode(), resultCode.getMessage());
}
}
From bedd0c2b6de5930cf7622f99abae04543b5014b0 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Fri, 28 Jun 2024 15:23:28 +0900
Subject: [PATCH 51/56] feat(global): create ErrorCode enum
---
.../java/gift/global/response/ErrorCode.java | 28 +++++++++++++++++++
1 file changed, 28 insertions(+)
create mode 100644 src/main/java/gift/global/response/ErrorCode.java
diff --git a/src/main/java/gift/global/response/ErrorCode.java b/src/main/java/gift/global/response/ErrorCode.java
new file mode 100644
index 000000000..ccf8c8953
--- /dev/null
+++ b/src/main/java/gift/global/response/ErrorCode.java
@@ -0,0 +1,28 @@
+package gift.global.response;
+
+public enum ErrorCode {
+ // Product
+ PRODUCT_NOT_FOUND_ERROR(400, "EP001", "Product Not Found Error"),
+ ;
+ private final int status;
+ private final String code;
+ private final String message;
+
+ ErrorCode(int status, String code, String message) {
+ this.status = status;
+ this.code = code;
+ this.message = message;
+ }
+
+ public int getStatus() {
+ return status;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+}
From 9d897c44dd911c17b2137b50f2408c0a0f24cbca Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Fri, 28 Jun 2024 15:25:32 +0900
Subject: [PATCH 52/56] feat(global): create ErrorResponseDto record
---
src/main/java/gift/global/response/ErrorResponseDto.java | 7 +++++++
1 file changed, 7 insertions(+)
create mode 100644 src/main/java/gift/global/response/ErrorResponseDto.java
diff --git a/src/main/java/gift/global/response/ErrorResponseDto.java b/src/main/java/gift/global/response/ErrorResponseDto.java
new file mode 100644
index 000000000..1c631b9c1
--- /dev/null
+++ b/src/main/java/gift/global/response/ErrorResponseDto.java
@@ -0,0 +1,7 @@
+package gift.global.response;
+
+public record ErrorResponseDto(String code, String message) {
+ public ErrorResponseDto(ErrorCode errorCode) {
+ this(errorCode.getCode(), errorCode.getMessage());
+ }
+}
From 39cddd4f2d26940fe23d60f85a9c0024d99ea2f6 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Fri, 28 Jun 2024 15:27:39 +0900
Subject: [PATCH 53/56] fix(global): add private constructor to ResponseHelper
class
---
src/main/java/gift/global/utils/ResponseHelper.java | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/main/java/gift/global/utils/ResponseHelper.java b/src/main/java/gift/global/utils/ResponseHelper.java
index 22ddedd4c..0be286587 100644
--- a/src/main/java/gift/global/utils/ResponseHelper.java
+++ b/src/main/java/gift/global/utils/ResponseHelper.java
@@ -6,6 +6,8 @@
import org.springframework.http.ResponseEntity;
public class ResponseHelper {
+ private ResponseHelper() {}
+
public static ResponseEntity> createResponse(ResultCode resultCode, T data) {
ResultResponseDto resultResponseDto = new ResultResponseDto<>(resultCode, data);
return org.springframework.http.ResponseEntity.status(resultCode.getStatus())
From 18efb9c19f451ecc42484f92586f80c4e8c34646 Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Fri, 28 Jun 2024 15:41:28 +0900
Subject: [PATCH 54/56] refactor(global): update error handling to return
ErrorResponseDto instead of String
---
.../global/exception/BusinessException.java | 18 ++++++++++++++++--
.../global/handler/GlobalExceptionHandler.java | 6 ++++--
.../java/gift/global/utils/ResponseHelper.java | 10 +++++++---
.../exception/ProductNotFoundException.java | 3 ++-
4 files changed, 29 insertions(+), 8 deletions(-)
diff --git a/src/main/java/gift/global/exception/BusinessException.java b/src/main/java/gift/global/exception/BusinessException.java
index f0dac8c6a..8c46ea1b5 100644
--- a/src/main/java/gift/global/exception/BusinessException.java
+++ b/src/main/java/gift/global/exception/BusinessException.java
@@ -1,7 +1,21 @@
package gift.global.exception;
+import gift.global.response.ErrorCode;
+
public class BusinessException extends RuntimeException {
- public BusinessException(String message) {
- super(message);
+ private final ErrorCode errorCode;
+
+ public BusinessException(ErrorCode errorCode) {
+ super(errorCode.getMessage());
+ this.errorCode = errorCode;
+ }
+
+ public ErrorCode getErrorCode() {
+ return errorCode;
+ }
+
+ @Override
+ public String toString() {
+ return errorCode.toString() + " : " + super.toString();
}
}
diff --git a/src/main/java/gift/global/handler/GlobalExceptionHandler.java b/src/main/java/gift/global/handler/GlobalExceptionHandler.java
index 2f64b1248..48486ee22 100644
--- a/src/main/java/gift/global/handler/GlobalExceptionHandler.java
+++ b/src/main/java/gift/global/handler/GlobalExceptionHandler.java
@@ -1,6 +1,8 @@
package gift.global.handler;
import gift.global.exception.BusinessException;
+import gift.global.response.ErrorResponseDto;
+import gift.global.utils.ResponseHelper;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@@ -8,7 +10,7 @@
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(BusinessException.class)
- public ResponseEntity handleBusinessException(BusinessException e) {
- return ResponseEntity.status(400).body(e.getMessage());
+ public ResponseEntity handleBusinessException(BusinessException e) {
+ return ResponseHelper.createErrorResponse(e.getErrorCode());
}
}
diff --git a/src/main/java/gift/global/utils/ResponseHelper.java b/src/main/java/gift/global/utils/ResponseHelper.java
index 0be286587..928d30f68 100644
--- a/src/main/java/gift/global/utils/ResponseHelper.java
+++ b/src/main/java/gift/global/utils/ResponseHelper.java
@@ -1,8 +1,6 @@
package gift.global.utils;
-import gift.global.response.ResultCode;
-import gift.global.response.ResultResponseDto;
-import gift.global.response.SimpleResultResponseDto;
+import gift.global.response.*;
import org.springframework.http.ResponseEntity;
public class ResponseHelper {
@@ -19,4 +17,10 @@ public static ResponseEntity createSimpleResponse(Resul
return ResponseEntity.status(resultCode.getStatus())
.body(resultResponseDto);
}
+
+ public static ResponseEntity createErrorResponse(ErrorCode errorCode) {
+ ErrorResponseDto errorResponseDto = new ErrorResponseDto(errorCode);
+ return ResponseEntity.status(errorCode.getStatus())
+ .body(errorResponseDto);
+ }
}
diff --git a/src/main/java/gift/product/exception/ProductNotFoundException.java b/src/main/java/gift/product/exception/ProductNotFoundException.java
index 08446c981..693aadee3 100644
--- a/src/main/java/gift/product/exception/ProductNotFoundException.java
+++ b/src/main/java/gift/product/exception/ProductNotFoundException.java
@@ -1,9 +1,10 @@
package gift.product.exception;
import gift.global.exception.BusinessException;
+import gift.global.response.ErrorCode;
public class ProductNotFoundException extends BusinessException {
public ProductNotFoundException() {
- super("Product Not Found Exception");
+ super(ErrorCode.PRODUCT_NOT_FOUND_ERROR);
}
}
From 025b774f611f863701c7a88159bf43750a9b349b Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Fri, 28 Jun 2024 15:51:11 +0900
Subject: [PATCH 55/56] refactor(product): rename ProductRequest to
ProductRequestDto
---
.../gift/product/controller/ProductController.java | 10 +++++-----
src/main/java/gift/product/domain/Product.java | 10 +++++-----
.../{ProductRequest.java => ProductRequestDto.java} | 6 ++----
3 files changed, 12 insertions(+), 14 deletions(-)
rename src/main/java/gift/product/dto/{ProductRequest.java => ProductRequestDto.java} (72%)
diff --git a/src/main/java/gift/product/controller/ProductController.java b/src/main/java/gift/product/controller/ProductController.java
index 296856a96..e3356b1d4 100644
--- a/src/main/java/gift/product/controller/ProductController.java
+++ b/src/main/java/gift/product/controller/ProductController.java
@@ -4,7 +4,7 @@
import gift.global.response.ResultResponseDto;
import gift.global.response.SimpleResultResponseDto;
import gift.global.utils.ResponseHelper;
-import gift.product.dto.ProductRequest;
+import gift.product.dto.ProductRequestDto;
import gift.product.domain.Product;
import gift.product.service.ProductService;
import org.springframework.http.ResponseEntity;
@@ -34,14 +34,14 @@ public ResponseEntity> getProductById(@PathVariable(n
}
@PostMapping("")
- public ResponseEntity createProduct(@RequestBody ProductRequest productRequest) {
- productService.createProduct(productRequest.toServiceDto());
+ public ResponseEntity createProduct(@RequestBody ProductRequestDto productRequestDto) {
+ productService.createProduct(productRequestDto.toServiceDto());
return ResponseHelper.createSimpleResponse(ResultCode.CREATE_PRODUCT_SUCCESS);
}
@PutMapping("/{id}")
- public ResponseEntity updateProduct(@PathVariable(name = "id") Long id, @RequestBody ProductRequest productRequest) {
- productService.updateProduct(productRequest.toServiceDto(id));
+ public ResponseEntity updateProduct(@PathVariable(name = "id") Long id, @RequestBody ProductRequestDto productRequestDto) {
+ productService.updateProduct(productRequestDto.toServiceDto(id));
return ResponseHelper.createSimpleResponse(ResultCode.UPDATE_PRODUCT_SUCCESS);
}
diff --git a/src/main/java/gift/product/domain/Product.java b/src/main/java/gift/product/domain/Product.java
index d0d473e73..edc7add4b 100644
--- a/src/main/java/gift/product/domain/Product.java
+++ b/src/main/java/gift/product/domain/Product.java
@@ -1,6 +1,6 @@
package gift.product.domain;
-import gift.product.dto.ProductRequest;
+import gift.product.dto.ProductRequestDto;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;
@@ -22,11 +22,11 @@ public Product(Long id, String name, int price, String imageUrl) {
this.imageUrl = imageUrl;
}
- public Product(Long id, ProductRequest productRequest) {
+ public Product(Long id, ProductRequestDto productRequestDto) {
this.id = id;
- this.name = productRequest.name();
- this.price = productRequest.price();
- this.imageUrl = productRequest.imageUrl();
+ this.name = productRequestDto.name();
+ this.price = productRequestDto.price();
+ this.imageUrl = productRequestDto.imageUrl();
}
diff --git a/src/main/java/gift/product/dto/ProductRequest.java b/src/main/java/gift/product/dto/ProductRequestDto.java
similarity index 72%
rename from src/main/java/gift/product/dto/ProductRequest.java
rename to src/main/java/gift/product/dto/ProductRequestDto.java
index 2a5d42f58..e2dfd53ff 100644
--- a/src/main/java/gift/product/dto/ProductRequest.java
+++ b/src/main/java/gift/product/dto/ProductRequestDto.java
@@ -1,11 +1,9 @@
package gift.product.dto;
-import gift.product.service.ProductService;
-
import java.util.Objects;
-public record ProductRequest(String name, int price, String imageUrl) {
- public ProductRequest {
+public record ProductRequestDto(String name, int price, String imageUrl) {
+ public ProductRequestDto {
Objects.requireNonNull(name);
Objects.requireNonNull(imageUrl);
}
From 52a232e2e12af9c1a24c8332a58df6ff2178f1fb Mon Sep 17 00:00:00 2001
From: JaeBin <201924576@pusan.ac.kr>
Date: Fri, 28 Jun 2024 16:21:17 +0900
Subject: [PATCH 56/56] feat(view): add search product by productId
---
src/main/resources/templates/index.html | 74 +++++++++++++++++++------
1 file changed, 58 insertions(+), 16 deletions(-)
diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html
index 6b8985ecd..72fc92ae8 100644
--- a/src/main/resources/templates/index.html
+++ b/src/main/resources/templates/index.html
@@ -17,6 +17,15 @@
Manage Products
+
+
+
+
+
+
+
+
+
@@ -29,9 +38,6 @@
Manage Products
Actions
-
-
-
@@ -114,18 +120,9 @@
Add New Product
// "Add New Product" 버튼 클릭 시 모달을 열고 폼 초기화
$('#addProduct').click(function () {
- // modal title 지정
$('#productModalLabel').text('Add New Product');
-
- // productForm 을 지정
- // jQuery 객체는 배열 형태로 반환되기 때문에, 순수 DOM 요소를 선택하기 위해 배열의 첫 번째 요소를 선택
- // 폼 내의 모든 입력 필드를 초기화
$('#productForm')[0].reset();
-
- // hidden 필드값인 id 제거
$('#productId').val('');
-
- // close 로 되어 있던 modal 속성을 show 로 수정
$('#productModal').modal('show');
});
@@ -138,7 +135,7 @@
}
};
- // 만약 아이디 값이 존재한다면 => 기존 객체를 수정
- // 따라서 url 과 method를 PUT에 맞게 수정해준다
+ // 만약 productId 값이 할당되어 있으면, 해당 데이터 수정 요청이다
+ // 때문에, PUT 으로 요청을 바꾼다
if (productId) {
ajaxOptions.url = apiBaseUrl + '/' + productId;
ajaxOptions.type = 'PUT';
@@ -160,9 +157,11 @@
Add New Product
$.ajax(ajaxOptions);
});
-
// "Edit" 버튼 클릭 시 해당 제품 데이터를 가져와 모달에 표시
$(document).on('click', '.editProduct', function () {
+ // $(this)는 jQuery 선택자로, 현재 이벤트가 발생한 요소를 선택
+ // .closest('tr')는 선택된 요소(this)부터 시작하여 가장 가까운 tr (테이블 행) 요소를 찾는다
+ // .data('id')는 선택된 요소의 data-id 속성 값을 가져온다
const productId = $(this).closest('tr').data('id');
$.get(apiBaseUrl + '/' + productId, function (response) {
$('#productModalLabel').text('Edit Product');
@@ -205,6 +204,49 @@
Add New Product
$('.productCheckbox').prop('checked', this.checked);
});
+ // 제품 ID로 검색
+ $('#searchProduct').click(function () {
+ const productId = $('#searchProductId').val();
+ if (productId) {
+ $.ajax({
+ url: apiBaseUrl + '/' + productId,
+ type: 'GET',
+ success: function (response) {
+ // 검색 결과를 테이블 본문에 표시
+ const $productTableBody = $('#productTableBody');
+ $productTableBody.empty();
+ const product = response.data;
+ $productTableBody.append(`
+
+
+
${product.name}
+
${product.price}
+
${product.imageUrl}
+
+
+
+
+
+ `);
+ },
+ // 'xhr'은 XMLHttpRequest 객체로 요청에 대한 상세 정보를 저장한다
+ //
+ error: function (xhr) {
+ // response 에 json 값이 있는 지 확인하고, error code를 확인한다
+ if (xhr.responseJSON && xhr.responseJSON.code === 'EP001') {
+ alert(xhr.responseJSON.message);
+ return
+ }
+ alert('An error occurred while fetching the product.');
+ }
+ });
+ }
+ if (!productId) {
+ // 검색 필드가 비어 있을 때 전체 제품 목록을 로드
+ loadProducts();
+ }
+ });
+
// 페이지 로드 시 제품 목록을 불러오기
loadProducts();
});