๐ ์ค๋์ ์ด๋ค ํ๋ฃจ์์ง..
์ค์ ์๋ ์ํ ๊ฐ๊ฒฉ ๋ณ๋ ๋ก์ง์ ๋ง๋ฌด๋ฆฌํ๋ ๋ฐ ์๊ฐ์ ์์๋ค.
// ๊ฐ๊ฒฉ ๊ด๋ จ Kafka Listener
@KafkaListener(topics = "${kafka.topic.price}", groupId = "${spring.kafka.consumer.product-combination.group-id}")
public void listenPriceChange(@Header(KafkaHeaders.RECEIVED_KEY) String key, String value) {
log.info("๐ฅ ๊ฐ๊ฒฉ๋ณ๋ ๋ฉ์์ง ์์ : key={}, value={}", key, value);
try {
OperationWrapperDto wrapperDto = JsonHelper.fromJson(value, OperationWrapperDto.class);
// PRICE_CHANGE ํ์
์ด ์๋ ๋ฉ์์ง๊ฐ ์๋ชป ๋ค์ด์์ ๊ฒฝ์ฐ ๋ฌด์
if (!wrapperDto.operationType().equals(OperationType.PRICE_CHANGE)) {
log.info("โ ๏ธ PRICE_CHANGE ํ์
์ด ์๋ ๋ฉ์์ง ์์ : {}", wrapperDto.operationType());
return;
}
ProductOptionCombinationPriceDto priceDto = JsonHelper.fromJson(wrapperDto.payload(), ProductOptionCombinationPriceDto.class);
productOptionCombinationService.changePrice(priceDto, wrapperDto, key);
} catch (NotFoundException e) {
log.warn("โ ๏ธ ํ์ ๋ฐ์ดํฐ ๋๋ฝ์ผ๋ก ๊ฐ๊ฒฉ ๋ณ๊ฒฝ ๋ฉ์์ง ์ฒ๋ฆฌ ์คํจ ({}): {}", e.getErrorCode(), e.getMessage());
} catch (Exception e) {
log.error("โ ์๊ธฐ์น ๋ชปํ ์ค๋ฅ๋ก ๊ฐ๊ฒฉ ๋ณ๊ฒฝ ๋ฉ์์ง ์ฒ๋ฆฌ ์คํจ: {}", e.getMessage());
}
}
๊ฐ๊ฒฉ ๊ด๋ จํด์ KafkaListener๋ฅผ ์์ฑํ๊ณ , ์ด๋ฏธ ๋ง๋ค์ด์ง ํ์ ๋ด๊ฐ ๋ง๋ค ๋ก์ง์ด ์ ์์ ์ผ๋ก ๋ค์ด๊ฐ ์ ์๋๋ก ํ๋ ๊ฒ ์๊ฐ๋ณด๋ค ์ด๋ ค์ ๋ค..
@Transactional
public void changePrice(ProductOptionCombinationPriceDto priceDto, OperationWrapperDto wrapperDto, String key) {
Long combinationId = priceDto.productOptionCombinationId();
Integer newPrice = priceDto.price();
String lockKey = "softLock:priceChange:combination:" + combinationId;
ProductOptionCombination combination = productOptionCombinationRepository.findById(combinationId)
.orElseThrow(() -> new NotFoundException(ErrorCode.PRODUCT_OPTION_COMBINATION_NOT_FOUND));
Integer currentPrice = combination.getPrice();
// ๊ฐ๊ฒฉ ๋ณ๊ฒฝ
if (!newPrice.equals(currentPrice)) {
combination.updatePrice(newPrice);
log.info("โ
๊ฐ๊ฒฉ ๋ณ๊ฒฝ ๊ฐ์ง ๋ฐ ๋ฐ์ ์๋ฃ: combinationId={}", combinationId);
} else {
log.info("โ ๊ฐ๊ฒฉ ๋ณ๋ ์์: combinationId={}", combinationId);
}
// soft Lock ํด์
redisTemplate.delete(lockKey);
log.info("๐ soft lock ํด์ ์๋ฃ: {}", lockKey);
redisTemplate.opsForValue().set("status:" + priceDto.operationId(), true, Duration.ofMinutes(5));
}
๋ค์๊ณผ ๊ฐ์ด ๋ค๋ฅธ ํ์๋ค์ด ๊ฐ๋ฐํ ํ์ ๋ง์ถฐ์ ๋ก์ง์ ๊ตฌํํ๊ณ ์ฑ๊ณต์ ์ผ๋ก ๊ฐ๊ฒฉ ๋ณ๊ฒฝ์ด ์ด๋ฃจ์ด์ง๋ ๊ฒ์ ํ์ธํ๋ค.
๊ทธ๋ฆฌ๊ณ ์คํ์๋ ์ง๊ธ๊น์ง ๊ฐ๋ฐํ ๋ด์ฉ์ ๋ง์ถฐ์ API ๋ช ์ธ์๋ฅผ ์์ ํ๋ค. ํ๋ํ๋ ์์ ํ๋ฉด์ ํ์ํ ๋ด์ฉ๋ ์์ฑํ๋๋ผ ์๊ฐ์ ๊ฝค ๋ง์ด ์ก์๋จน์๋ค.
๋ง์ง๋ง์ผ๋ก ํ๋ก์ ํธ ๋ง๋ฌด๋ฆฌ ๊ฒธ ๊ฐ์ ๊ฐ๋ฐํ ๋ด์ฉ ๋ฐํํ๊ธฐ๋ก ํด์ ๋ด๊ฐ ๊ตฌํํ ๋ด์ฉ๋ค์ ๋ํด ์ด๋ป๊ฒ ๋ณด์ฌ์ฃผ๋ฉด ์ข์์ง ์๊ฐํ๊ณ ์ค๋น๋ฅผ ํ๋ฉด์ ํ๋ฃจ๋ฅผ ๋ง๋ฌด๋ฆฌํ๋ค.
๋ด์ผ ๋ฐํ ์์ ์๊ฐ
๋ฐฐ์ก, ํ๋ฐฐ์ฌ, ์ก์ฅ, ์ถ๊ณ ์ง(๋ฌผ๋ฅ์ผํฐ), ์ฌ๊ณ ๊ฐ์, ๊ฐ๊ฒฉ ๋ณ๊ฒฝ
- ํ๋ฐฐ์ฌ ๊ด๋ จ ๊ธฐ๋ฅ ๊ตฌํ
- ํ๋ฐฐ์ฌ ์์ฑ
- ํ๋ฐฐ์ฌ ์์ฑ
- ํ๋ฐฐ์ฌ ์กฐํ
- ํ๋ฐฐ์ฌ ์์
- ์ถ๊ณ ์ง ๊ด๋ จ ๊ธฐ๋ฅ ๊ตฌํ
- ์ถ๊ณ ์ง ์์ฑ
- ์ถ๊ณ ์ง ์์ฑ
- ํ๋ฐฐ์ฌ ์ญ์ → ์ถ๊ณ ์ง์ ๋ฑ๋ก๋์ด ์๋ ํ๋ฐฐ์ฌ ์ญ์ X
- ์ถ๊ณ ์ง ์กฐํ
- ์ถ๊ณ ์ง ์์
- ์ถ๊ณ ์ง ์ญ์
- ์ฌ๊ณ ๊ฐ์ → ๋ฐฐ์ก ์์ฑ ๊ตฌํ → ์ฌ๋ ์๋ฆผ ๋ฉ์์ง
- ๊ฒฐ์ ํ ์ฌ๊ณ ๊ฐ์ ๋ก์ง ์คํ
- ์ฌ๊ณ ๊ฐ์ ์๋ฃ ํ ๋ฐฐ์ก ์์ฑ ํ ํฝ์ผ๋ก ๋ฉ์์ง ์ ์ก
- ๋ฐฐ์ก ์์ฑ ์ฑ๊ณต ์ ์ฌ๋ ์๋ฆผ ๋ฉ์์ง ์ ์ก
- ๋ฐฐ์ก ์์ฑ ์คํจ ์ ์ฌ๋ ์๋ฆผ ๋ฉ์์ง ์ ์ก + ์ฌ๊ณ ๋ณต์ ๋ก์ง ์งํ
- ์ก์ฅ ๊ด๋ จ ๊ธฐ๋ฅ ๊ตฌํ
- ์ก์ฅ ์์ฑ
- ์ถ๊ณ → ์นด์นด์คํก ์๋ฆผ ๋ฉ์์ง
- ๋ฐฐ์ก ์์ → ์ก์ฅ ๋ฒํธ ๋ฑ๋ก + ์ํ ์ถ๊ณ ๋ก ๋ณ๊ฒฝ ํ ์นด์นด์คํก ์๋ฆผ ๋ฉ์์ง ์ ์ก
- ๋ฐฐ์ก์ค, ๋ฐฐ์ก ์๋ฃ → ์นด์นด์คํก ์๋ฆผ ๋ฉ์์ง
- ๋ฐฐ์ก ์ํ ์์ ํ ์นด์นด์คํก ์๋ฆผ ๋ฉ์์ง ์ ์ก
- ๊ฐ๊ฒฉ ๋ณ๊ฒฝ ๊ตฌํ
- ๊ฐ๊ฒฉ ๋ณ๊ฒฝ ๋ก์ง ์งํ
๐๏ธ ๋ด์ผ์ ๋ญ ํ์ง?!
โ๏ธ ๋ด๊ฐ ๊ตฌํํ ๋ด์ฉ ๋ฐํํ๊ธฐ
'๐ฅ๏ธ ๋ญ๊ฐ๋ญ๊ฐํ๋ก์ ํธ > โ๏ธ TIL' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[TIL] ํ๋ก์ ํธ 24์ผ์ฐจ.. ์ ์ฒด์ ์ธ ๋ก์ง ๋ง๋ฌด๋ฆฌํ๊ธฐ!! (0) | 2025.06.11 |
---|---|
[TIL] ํ๋ก์ ํธ 23์ผ์ฐจ.. ์นด์นด์คํก ์๋ฆผ ๊ตฌํํ๊ธฐ!! (0) | 2025.06.10 |
[TIL] ํ๋ก์ ํธ 22์ผ์ฐจ.. ํ๋ก์ ํธ ๊ณ ๋ํ ์์ ํ๊ธฐ!! (0) | 2025.06.09 |
[TIL] ํ๋ก์ ํธ 18์ผ์ฐจ.. ์ฌ๋ ์๋ฆผ ๋ง๋ฌด๋ฆฌํ๊ธฐ!! (0) | 2025.06.05 |
[TIL] ํ๋ก์ ํธ 17์ผ์ฐจ.. Slack ์๋ฆผ ๊ตฌํํ๊ธฐ!! (0) | 2025.06.04 |