Backend/spring cloud (MSA)

๋ฐ์ดํ„ฐ ํ†ตํ•ฉ ์กฐํšŒ ๋ฐฉ๋ฒ• ์„ค๊ณ„

dddzr 2025. 4. 6. 21:59

๐Ÿ“Œ ๋ฌธ์ œ

  • MSA์—์„œ๋Š” ๊ฐ ์„œ๋น„์Šค๊ฐ€ ๋…๋ฆฝ์ ์œผ๋กœ DB๋ฅผ ๊ด€๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ํ•œ ์„œ๋น„์Šค์—์„œ ๋‹ค๋ฅธ ์„œ๋น„์Šค์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ง์ ‘์ ์œผ๋กœ ์กฐํšŒํ•  ์ˆ˜ ์—†๋‹ค.
  • ์˜ˆ๋ฅผ ๋“ค์–ด, ์ฃผ๋ฌธ ๋ชฉ๋ก์„ ์กฐํšŒํ•  ๋•Œ, ์ฃผ๋ฌธ ์•„์ดํ…œ์ •๋ณด ์ œ๊ณต์„ ์œ„ํ•ด ์ƒํ’ˆ ์ •๋ณด๋ฅผ JOIN์œผ๋กœ ๊ฐ€์ ธ์˜ค์ง€ ๋ชป ํ•˜๊ณ  ์ฃผ๋ฌธ ์•„์ดํ…œ ๋งˆ๋‹ค ์ƒํ’ˆ ์„œ๋น„์Šค์— ์š”์ฒญ์„ ๋ณด๋‚ด์•ผ ํ•œ๋‹ค.
  • ์ด ๊ณผ์ •์—์„œ ์—ฌ๋Ÿฌ ๋ฒˆ์˜ API ํ˜ธ์ถœ์ด ๋ฐœ์ƒํ•˜๊ธฐ์— ์„ฑ๋Šฅ ์ €ํ•˜ ์šฐ๋ ค๊ฐ€ ์žˆ์—ˆ๋‹ค.

 

๐Ÿ“Œ ๋ฐฉ๋ฒ• ๋น„๊ต

โœ… 1. ์ฃผ๋ฌธ ์•„์ดํ…œ๋งˆ๋‹ค ์ƒํ’ˆ API ํ˜ธ์ถœ

์ฃผ๋ฌธ 1๊ฐœ → ์ฃผ๋ฌธ ์•„์ดํ…œ1๊ฐœ ๋งˆ๋‹ค ์ƒํ’ˆ ์„œ๋น„์Šค API๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์ƒํ’ˆ ์ •๋ณด๋ฅผ ๋ฐ›์•„์˜ค๊ณ  ์ด๋ฅผ ํ•ฉ์นœ๋‹ค.

โœ” ์žฅ์ 

  • ๊ฐ„๋‹จํ•˜๊ณ  ์ง๊ด€์ ์ธ ๋ฐฉ์‹

โŒ ๋‹จ์ 

  • ์ฃผ๋ฌธ๋งˆ๋‹ค ์ƒํ’ˆ ์ •๋ณด๋ฅผ ๋ณ„๋„๋กœ API ํ˜ธ์ถœํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋„คํŠธ์›Œํฌ ์š”์ฒญ์ด ๋งŽ์•„์ ธ ์„ฑ๋Šฅ์ด ์ €ํ•˜๋  ์ˆ˜ ์žˆ์Œ.

 

โœ… 2. ์บ์‹œ(redis)๋ฅผ ์ด์šฉํ•ด ์ฃผ๋ฌธ ์ •๋ณด ์ €์žฅ

์ฃผ๋ฌธ + ์ƒํ’ˆ ์ •๋ณด๋ฅผ ๊ฒฐํ•ฉํ•˜์—ฌ ์บ์‹œ์— ์ €์žฅํ•˜๊ณ , ์กฐํšŒ ์‹œ์—๋Š” ์บ์‹œ์—์„œ ๋ฐ”๋กœ ์กฐํšŒํ•œ๋‹ค.

์ฃผ๋ฌธ ์ƒ์„ฑ ์‹œ ์บ์‹œ ์ƒ์„ฑํ•˜์—ฌ ๊ฐ ์„œ๋น„์Šค(์ฃผ๋ฌธ, ์ƒํ’ˆ, ๋ฐฐ์†ก, ๊ฒฐ์ œ ๋“ฑ)์—์„œ ์—…๋ฐ์ดํŠธ.

โœ” ์žฅ์ 

  • ์กฐํšŒ ์‹œ ๋ฐ์ดํ„ฐ ํ•ฉํ•˜๋Š” ๋กœ์ง(for๋ฌธ ์‚ฌ์šฉ)์ด ํ•„์š” ์—†๊ณ  ๋น ๋ฅธ ์†๋„๋กœ ์‘๋‹ต ๊ฐ€๋Šฅ.

โŒ ๋‹จ์ 

  • ์ฃผ๋ฌธ ๋ชฉ๋ก์€ ๋™์ ์œผ๋กœ ๋ฐ”๋€” ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ์ฃผ๋ฌธ์ด ์ž์ฃผ ๋ณ€๊ฒฝ๋˜๋Š” ๊ฒฝ์šฐ ์บ์‹œ ๊ด€๋ฆฌ๊ฐ€ ๋ณต์žกํ•ด์งˆ ์ˆ˜ ์žˆ๋‹ค.
  • ์ฃผ๋ฌธ ๋ชฉ๋ก์€ ์‚ฌ์šฉ์ž๋ณ„๋กœ ์ €์žฅํ•ด์•ผ ํ•˜๋ฏ€๋กœ, ์‚ฌ์šฉ์ž์˜ ์ฃผ๋ฌธ ์ •๋ณด๋ฅผ ์บ์‹œ์— ๋ณ„๋„๋กœ ๊ด€๋ฆฌํ•ด์•ผ ํ•œ๋‹ค. โžก๏ธ ๋ฉ”๋ชจ๋ฆฌ ์†Œ๋ชจ๊ฐ€ ์ปค์ง€๊ณ , ์‚ฌ์šฉ์ž ๊ฐœ์ธ์ •๋ณด ๊ด€๋ฆฌ ์œ„ํ—˜์ด ์žˆ๋‹ค.

 

โœ… 3. ์บ์‹œ(redis)์— ์ƒํ’ˆ ์ •๋ณด๋งŒ ์ €์žฅ, ์ฃผ๋ฌธ ์กฐํšŒ ์‹œ ์บ์‹œ ์กฐํšŒ

์ƒํ’ˆ ์ •๋ณด๋ฅผ ๋ฏธ๋ฆฌ ์บ์‹ฑ(์ƒํ’ˆ ์ƒ์„ฑ/์ˆ˜์ • ์‹œ)ํ•˜๊ณ , ์ฃผ๋ฌธ ๋ชฉ๋ก ์กฐํšŒ ์‹œ ๋จผ์ € ์บ์‹œ๋ฅผ ์กฐํšŒํ•œ ํ›„, ์บ์‹œ์— ์—†์œผ๋ฉด ์ƒํ’ˆ API๋ฅผ ํ˜ธ์ถœ(์ด๋•Œ, ์ƒํ’ˆ์„œ๋น„์Šค๋Š” ์ƒํ’ˆ ์ •๋ณด๋ฅผ ๋ฆฌํ„ด & ์ƒํ’ˆ ์ •๋ณด ์บ์‹ฑ)

โœ” ์žฅ์ 

  • ์ฃผ๋ฌธ ๋ชฉ๋ก ์กฐํšŒ ์‹œ ์ƒํ’ˆ ์ •๋ณด๋ฅผ ๋น ๋ฅด๊ฒŒ ๊ฐ€์ ธ์˜ค๋ฉฐ, ์บ์‹œ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ์—๋งŒ ์™ธ๋ถ€ API ํ˜ธ์ถœ์„ ํ•˜๋ฏ€๋กœ ๋ถˆํ•„์š”ํ•œ API ํ˜ธ์ถœ์„ ์ค„์ผ ์ˆ˜ ์žˆ์Œ.
  • ์—ฌ์ „ํžˆ ๋ฐ˜๋ณต๋ฌธ ์‚ฌ์šฉํ•˜์—ฌ ํ•ฉ์„ฑํ•˜๋Š” ๊ณผ์ •์ด ํ•„์š”ํ•˜์ง€๋งŒ ์ธ๋ฉ”๋ชจ๋ฆฌ ์บ์‹œ๋Š” ์กฐํšŒ ์†๋„ ์ž์ฒด๊ฐ€ ๋น ๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ์„ฑ๋Šฅ ๋ถ€๋‹ด์ด ๋œํ•จ.

โŒ ๋‹จ์ 

  • ์ƒํ’ˆ ์ •๋ณด๊ฐ€ ์บ์‹œ์— ์—†์œผ๋ฉด API ํ˜ธ์ถœ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์บ์‹œ ๊ฐฑ์‹  ์ฃผ๊ธฐ๋ฅผ ์„ค์ •ํ•˜์—ฌ ์„ฑ๋Šฅ์„ ๋ณด์žฅํ•  ์ˆ˜ ์žˆ์Œ.

 

๐Ÿ“Œ ์ฑ„ํƒํ•œ ๋ฐฉ๋ฒ•

์„ธ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์„ ์ฑ„ํƒํ•˜์—ฌ, ์ƒํ’ˆ ์ •๋ณด๋ฅผ ์บ์‹œ(Redis)๋กœ ๊ด€๋ฆฌํ•˜๊ณ , ์ฃผ๋ฌธ ๋ชฉ๋ก ์กฐํšŒ ์‹œ ๋จผ์ € ์บ์‹œ๋ฅผ ์กฐํšŒํ•œ ํ›„, ์บ์‹œ์— ์—†์œผ๋ฉด ์ƒํ’ˆ API๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

// ๊ณ ๊ฐ ์ฃผ๋ฌธ ๋ชฉ๋ก ์กฐํšŒ (์ฃผ๋ฌธ + ์ƒํ’ˆ ์ •๋ณด)
public List<OrderSummary> getCustomerOrders(OrderListRequest request) {
    List<OrderSummary> orderSummaries = new ArrayList<>(); // ์‘๋‹ต DTO

    // 1. ์ฃผ๋ฌธ DB์—์„œ ์œ ์ € ์ฃผ๋ฌธ ๋ชฉ๋ก ์กฐํšŒ
    List<Orders> orders = orderRepository.findOrdersByRequest(request);
    for (Orders order : orders) {
        OrderSummary orderSummary = new OrderSummary();
        orderSummary = objectMapper.convertValue(order, OrderSummary.class);

        // 2. ์ฃผ๋ฌธ ์ƒํ’ˆ๋ณ„ ์ƒํ’ˆ ์ •๋ณด ์„ธํŒ…
        List<OrderItemDetail> orderItemDetails = new ArrayList<>();
        for (OrderItems orderItem : order.getOrderItems()) {
            OrderItemDetail orderItemDetail = objectMapper.convertValue(orderItem, OrderItemDetail.class);

            // ์ƒํ’ˆ ์บ์‹œ ์กฐํšŒ
            CachedProduct cachedProduct = getCachedProduct(orderItem.getProductId());

            // ์บ์‹œ์—์„œ ์กฐํšŒ๋œ ์ƒํ’ˆ ์ •๋ณด๋ฅผ ์ฃผ๋ฌธ ์•„์ดํ…œ์— ๋งคํ•‘
            OrderItemDetail.OrderedProductInfo orderedProductInfo = mapToOrderedProductInfo(cachedProduct, orderItem.getColorId(), orderItem.getSizeId());

            orderedProductInfo.setPrice(orderItem.getPrice()); // ๊ฒฐ์ œ ๋‹น์‹œ ๊ฐ€๊ฒฉ!!
            orderItemDetail.setOrderedProductInfo(orderedProductInfo);
            orderItemDetails.add(orderItemDetail);
        }

        orderSummary.setOrderItemDetails(orderItemDetails);
        orderSummaries.add(orderSummary);
    }

    return orderSummaries;
}

// ์ƒํ’ˆ ์„œ๋น„์Šค API ํ˜ธ์ถœ (FeignClient ์‚ฌ์šฉ)
private CachedProduct getCachedProduct(int productId) {
    CachedProduct cachedProduct = new CachedProduct();

    // 1. ์บ์‹œ์—์„œ ์ƒํ’ˆ ์ •๋ณด ์กฐํšŒ
    cachedProduct = cacheService.getOrderedProductInfo(productId);

    // 2. ์บ์‹œ์—์„œ ์ƒํ’ˆ ์ •๋ณด๊ฐ€ ์—†์œผ๋ฉด ์ƒํ’ˆ ์„œ๋น„์Šค API์— ์š”์ฒญ
    // ์ƒํ’ˆ ์„œ๋น„์Šค์—์„œ ์บ์‹œ์— ์ €์žฅํ•˜๊ณ  CachedProduct ํ˜•ํƒœ๋กœ ๋ฆฌํ„ดํ•œ๋‹ค.
    if (cachedProduct == null) {
        cachedProduct = productClient.getProductForCache(productId);
    }
    return cachedProduct;
}

 

'Backend > spring cloud (MSA)' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

MSA ํ™˜๊ฒฝ์—์„œ ์ธ์ฆ/ํ† ํฐ ์žฌ์š”์ฒญ  (0) 2025.04.06
์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ ์ „์†ก  (0) 2025.02.23
[Kafka] ๊ณ ๊ธ‰ ์„ค์ •  (0) 2025.02.23
Kafka๋ž€?  (0) 2025.02.23
Eureka๋ž€?  (0) 2025.02.16