๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Back-end ๋ฐ๋ธŒ์ฝ”์Šค/week 06 - 07 TIL (clone project)

[TIL] 221123 - ํด๋ก  ์ฝ”๋”ฉ : ์ปคํ”ผ๋นˆ ์ฃผ๋ฌธ ๊ด€๋ฆฌ ์„œ๋น„์Šค

by young-ji 2022. 11. 26.

[ํด๋ก  ์ฝ”๋”ฉ] ์ปคํ”ผ๋นˆ ์ฃผ๋ฌธ ๊ด€๋ฆฌ ์„œ๋น„์Šค

 

0.  ์š”๊ตฌ์‚ฌํ•ญ

  • ๋งค์ผ ์ „๋‚  ์˜คํ›„ 2์‹œ๋ถ€ํ„ฐ ์˜ค๋Š˜ ์˜ค๋ฃจ 2์‹œ๊นŒ์ง€์˜ ์ฃผ๋ฌธ์„ ๋ชจ์•„์„œ ์ฒ˜๋ฆฌ
  • ํ˜„์žฌ ์ด 4๊ฐœ์˜ ์ƒํ’ˆ ์กด์žฌ
  • ๋ณ„๋„์˜ ํšŒ์›์„ ๊ด€๋ฆฌํ•˜์ง€ ์•Š๊ณ , email๋กœ ๊ตฌ๋ถ„
    • ํ•˜๋ฃจ์— ๊ฐ™์€ email๋กœ ์—ฌ๋Ÿฌ๋ฒˆ ์ฃผ๋ฌธ์ด ๋“ค์–ด์˜ฌ ๊ฒฝ์šฐ ํ•˜๋‚˜๋กœ ํ•ฉ์ณ์„œ ๋‹ค์Œ๋‚  ๋ฐฐ์†ก
  • ๊ณ ๊ฐ์—๊ฐœ “๋‹น์ผ ์˜คํ›„ 2์‹œ ์ดํ›„์˜ ์ฃผ๋ฌธ์€ ๋‹ค์Œ๋‚  ๋ฐฐ์†ก์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.”๋ผ๊ณ  ์•Œ๋ ค์ค๋‹ˆ๋‹ค.

 

 

1.  ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ

Spring initializr

 

2.  domain ๋ชจ๋ธ ์ •์˜

→ ์ƒํ’ˆ ๋„๋ฉ”์ธ

→ ์ฃผ๋ฌธ ๋„๋ฉ”์ธ

 

ERD

 

  • validation Object ๋งŒ๋“ค๊ธฐ
public class Email {
    private final String address;

    public Email(String address) {
        Assert.notNull(address);
        Assert.isTrue(address.length() >= 4 && address.length() <= 50,"address length must be between 4 and 50 characters");
        Assert.isTrue(checkAddress(address), "Invalid email address");
        this.address = address;
    }

    private boolean checkAddress(String address) {
        return Pattern.matches("\\\\b[\\\\w\\\\.-]+@[\\\\w\\\\.-]+\\\\.\\\\w{2,4}\\\\b",address);
    }

    //validation ํ• ๋•Œ, equals๋‚˜ hashcode๋ฅผ ์ง์ ‘ ๊ตฌํ˜„ํ•ด ์ฃผ๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Email email = (Email) o;
        return Objects.equals(address, email.address);
    }

    @Override
    public int hashCode() {
        return Objects.hash(address);
    }

    @Override
    public String toString() {
        return "Email{" +
                "address='" + address + '\\'' +
                '}';
    }

    public String getAddress() {
        return address;
    }
}

์ •๊ทœ ๋ถ„ํฌ์‹ ๊ตฌํ•˜๊ธฐ → https://regexr.com/

 

RegExr: Learn, Build, & Test RegEx

RegExr is an online tool to learn, build, & test Regular Expressions (RegEx / RegExp).

regexr.com

Email ์ •๊ทœ๋ถ„ํฌ์‹

 

3.  repository ๊ตฌํ˜„, test ์ฝ”๋“œ ์ž‘์„ฑ

 

@Repository
public class OrderJdbcRepository implements OrderRepository {

  private final NamedParameterJdbcTemplate jdbcTemplate;

  public OrderJdbcRepository(NamedParameterJdbcTemplate jdbcTemplate) {
    this.jdbcTemplate = jdbcTemplate;
  }

  @Override
  @Transactional
  public Order insert(Order order) {
    jdbcTemplate.update("INSERT INTO orders(order_id, email, address, postcode, order_status, create_at, update_at) " +
        "VALUES (UUID_TO_BIN(:orderId), :email, :address, :postcode, :orderStatus, :createAt, :updateAt)",
      toOrderParamMap(order));
    order.getOrderItems()
      .forEach(item ->
        jdbcTemplate.update("INSERT INTO order_item(order_id, product_id, category, price, quantity, create_at, update_at) " +
            "VALUES (UUID_TO_BIN(:orderId), UUID_TO_BIN(:productId), :category, :price, :quantity, :createAt, :updateAt)",
          toOrderItemParamMap(order.getOrderId(), order.getCreatedAt(), order.getUpdateAt(), item)));
    return order;
  }


  private Map<String, Object> toOrderParamMap(Order order) {
    var paramMap = new HashMap<String, Object>();
    paramMap.put("orderId", order.getOrderId().toString().getBytes());
    paramMap.put("email", order.getEmail().getAddress());
    paramMap.put("address", order.getAddress());
    paramMap.put("postcode", order.getPostcode());
    paramMap.put("orderStatus", order.getOrderStatus().toString());
    paramMap.put("createAt", order.getCreatedAt());
    paramMap.put("updateAt", order.getUpdateAt());
    return paramMap;
  }

  private Map<String, Object> toOrderItemParamMap(UUID orderId, LocalDateTime createdAt, LocalDateTime updatedAt, OrderItem item) {
    var paramMap = new HashMap<String, Object>();
    paramMap.put("orderId", orderId.toString().getBytes());
    paramMap.put("productId", item.productId().toString().getBytes());
    paramMap.put("category", item.category().toString());
    paramMap.put("price", item.price());
    paramMap.put("quantity", item.quantity());
    paramMap.put("createAt", createdAt);
    paramMap.put("updateAt", updatedAt);
    return paramMap;
  }

}

 

Map ์ดˆ๊ธฐํ™”์‹œ ์ฃผ์˜ ์‚ฌํ•ญ

1. ์ด์ค‘ ์ค‘๊ด„ํ™”๋ฅผ ์‚ฌ์šฉํ•œ ์ดˆ๊ธฐํ™” ์ง€์–‘

https://www.baeldung.com/java-double-brace-initialization

2. ํŒฉํ† ๋ฆฌ ๋ฉ”์†Œ๋“œ(map.of)๋ฅผ ์‚ฌ์šฉํ•œ ์ดˆ๊ธฐํ™”์˜ ๋ฌธ์ œ -> nullableํ•œ ๊ฐ’์ด ๋“ค์–ด์˜ฌ๋•Œ map์ด null๊ฐ’์— ๋Œ€ํ•œ error๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค. 

 

=> ๋ฌด๋‚œํ•˜๊ฒŒ HashMap์„ ์ด์šฉํ•ด ์ดˆ๊ธฐํ™”๋ฅผ ํ•˜์ž

 

 

4.  service ๊ตฌํ˜„

@Service
public class DefaultOrderService implements OrderService {

  private final OrderRepository orderRepository;

  public DefaultOrderService(OrderRepository orderRepository) {
    this.orderRepository = orderRepository;
  }

  @Override
  public Order createOrder(Email email, String address, String postcode, List<OrderItem> orderItems) {
    Order order = new Order(
      UUID.randomUUID(),
      email,
      address,
      postcode,
      orderItems,
      OrderStatus.ACCEPTED,
      LocalDateTime.now(),
      LocalDateTime.now());
    return orderRepository.insert(order);
  }

}

 

 

5.  controller ๊ตฌํ˜„

REST API ๋ฅผ ๋งŒ๋“ ๋Š” controller๊ฐ€ ์•„๋‹ˆ๋ผ ์›นํŽ˜์ด์ง€์— ์ ‘์†ํ•˜๊ธฐ์œ„ํ•œ view๋ฅผ ๋ฐ˜ํ™˜ํ•ด์ฃผ๋Š” controller

controller๋Š” ์™ธ๋ถ€๋กœ ๋ถ€ํ„ฐ DTO๋กœ ๋ฐ›์•„์„œ Validation์ด๋‚˜, http ํ•ธ๋“ค์„ ์ˆ˜ํ–‰ํ•œ๋‹ค. ๋„๋ฉ”์ธ ๋กœ์ง์€ Service์™€ entity์—์„œ!

@Controller 
public class ProductController {

    private final ProductService productService;

    public ProductController(ProductService productService) {
        this.productService = productService;
    }

    @GetMapping("/products")
    public String productsPage(Model model){
        var products = productService.getAllProducts();
        model.addAttribute("products",products);
        return "product-list";
    }

    @GetMapping("new-product")
    public String newProductPage(Model model){
        return "new-product";
    }

    @PostMapping("/products")
    public String newProduct(CreateProductRequest createProductRequest){
        productService.createProduct(createProductRequest.productName(),createProductRequest.category(),
                createProductRequest.price(),createProductRequest.description());
        return "redirect:/products";
    }
}

 

6.  template ์ž‘์„ฑ

  •  new-product.html
  •  product-list.html

 

7.  React ์ฝ”๋“œ ์ž‘์„ฑ

: axios ์‚ฌ์šฉ

 

8 . API

  • CORS ์„ค์ •
@Configuration
public class MvcConfiguration implements WebMvcConfigurer { // mvc ์„ค์ • ํ™•์žฅ
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**").allowedOrigins("*");
    }
}

 

  • ์ฃผ๋ฌธ ์ฒ˜๋ฆฌ API ๊ตฌํ˜„
@RestController
public class OrderRestController {

    private final OrderService orderService;

    public OrderRestController(OrderService orderService) {
        this.orderService = orderService;
    }

    @PostMapping("/api/v1/orders")
    public Order createOrder(@RequestBody CreateOrderRequest createOrderRequest){
        return orderService.createOrder(
               new Email(createOrderRequest.email()),
                createOrderRequest.address(),
                createOrderRequest.postcode(),
                createOrderRequest.orderItems()
        );
    }

}

 

  •  CreateOrderRequest -> json์„ ํ‘œํ˜„ํ•˜๊ธฐ ์œ„ํ•œ ํƒ€์ž…์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค. (DTO๋ฅผ messageํฌ๋งท์œผ๋กœ ๋ณ€๊ฒฝ์‹œํ‚ค๊ธฐ ์œ„ํ•œ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.)
  • service์—์„œ ์ธ์ง€ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค. service๋Š” service ์ž์ฒด์˜ ๋ฉ”์„ธ์ง€ ์‹œ๊ทธ๋‹ˆ์ณ๋ฅผ ๊ฐ€์ ธ๊ฐ€๊ณ  controller๊ฐ€ service๊ฐ€ ํ•„์š”ํ•œ value Object๋‚˜ parameter์˜ ๋ณ€์ˆ˜๋กœ ๋ณ€ํ™˜ํ•˜๋„๋ก ๋™์ผํ•œ ๊ฐ’์„ ๋„˜๊ฒจ ์ค„์ง€๋ผ๊ณ  ๊ณ„์ธต์„ ๊ตฌ๋ถ„ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

 


์†Œ์Šค์ฝ”๋“œ 

https://github.com/youngjijang/prgrms-be-devcourse

 

GitHub - youngjijang/prgrms-be-devcourse: ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค ๋ฐ๋ธŒ์ฝ”์Šค ๋ฐฑ์—”๋“œ ์‹ค์Šต repo

ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค ๋ฐ๋ธŒ์ฝ”์Šค ๋ฐฑ์—”๋“œ ์‹ค์Šต repo. Contribute to youngjijang/prgrms-be-devcourse development by creating an account on GitHub.

github.com

 

๋Œ“๊ธ€