์์ ๋ฐ๋๋ฝ ๊ด๋ จ ๋ธ๋ก๊ทธ ๊ธ์ ์์ฑํ๋ ๊ณผ์ ์์ ๋๊ด์ ๋ฝ(Optimistic Locking)์ด๋ผ๋ ๊ฐ๋ ๋ ๊ฐ์ด ์ ๋ฆฌํด๋ณด๋ฉด ์ข์๊ฒ ๊ฐ์ ์์ฑํด๋ณด์์ต๋๋ค.๋๊ด์ ๋ฝ์ ์ฑ๋ฅ์ ์ต์ ํํ๋ฉด์๋ ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ์ ์ ์งํ๋ ๋ฐ ํ์ํ ๋๊ตฌ์ธ๋ฐ์. ์ด๋ฒ ๊ธ์์๋ ๋๊ด์ ๋ฝ์ ๊ฐ๋ , ํ์ฉ ์ฌ๋ก, ๊ทธ๋ฆฌ๊ณ ์ค์ ๊ตฌํ ๋ฐฉ๋ฒ๊น์ง ์ ๋ฆฌํด๋ณด๊ฒ ์ต๋๋ค.
๋๊ด์ ๋ฝ์ ๋์์ฑ ์ ์ด๋ฅผ ์ํ ๋ฉ์ปค๋์ฆ ์ค ํ๋๋ก, ๋ฐ์ดํฐ๋ฅผ ๊ฐฑ์ ํ๋ ๋์ ์ถฉ๋์ด ๋๋ฌผ๋ค๊ณ ๊ฐ์ ํ๊ณ ์ค๊ณ๋ ๋ฐฉ์์ ๋๋ค. ์ด๋ ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ณ ๋ ํ ๊ฐฑ์ ์์ ์ ์ถฉ๋ ์ฌ๋ถ๋ฅผ ๊ฒ์ฌํ๋ฉฐ, ์ถฉ๋์ด ๋ฐ์ํ๋ฉด ๋ณ๊ฒฝ์ ๊ฑฐ๋ถํ๊ฑฐ๋ ์ฌ์๋ํฉ๋๋ค.
๋น๊ต: ๋น๊ด์ ๋ฝ(Pessimistic Locking)์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ ๋ ๋ฝ์ ๊ฑธ์ด ๋ค๋ฅธ ํธ๋์ญ์ ์ ์ ๊ทผ์ ์ฐจ๋จํ๋ ๋ฐฉ์์ ๋๋ค.
๋๊ด์ ๋ฝ์ ์ฝ๊ธฐ ์์ ์ด ๋ง๊ณ ์ฐ๊ธฐ ์์ ์ด ์๋์ ์ผ๋ก ์ ์ ํ๊ฒฝ์์ ํจ๊ณผ์ ์ ๋๋ค. ์๋ฅผ ๋ค์ด:
๋๊ด์ ๋ฝ์ ๊ตฌํํ๋ ค๋ฉด ํ ์ด๋ธ์ ๋ฒ์ (Version) ํ๋๋ ํ์์คํฌํ ํ๋๋ฅผ ์ถ๊ฐํด์ผ ํฉ๋๋ค.
CREATE TABLE products (
id BIGINT PRIMARY KEY,
name VARCHAR(255),
stock INT,
version INT
);
์ ๋ฐ์ดํธ ์ ํ์ฌ ๋ฒ์ ์ ๊ธฐ์ค์ผ๋ก ์กฐ๊ฑด์ ๊ฑธ์ด ์ถฉ๋ ์ฌ๋ถ๋ฅผ ํ์ธํฉ๋๋ค.
UPDATE products
SET stock = stock - 1,
version = version + 1
WHERE id = 1 AND version = 5;
id
๊ฐ 1์ธ ์ํ์ ๋ฒ์ ์ด 5์ผ ๋๋ง ์
๋ฐ์ดํธ๋ฅผ ์ํํฉ๋๋ค.Spring Data JPA์ ํจ๊ป ๋๊ด์ ๋ฝ์ ์ ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋๋ค.
import jakarta.persistence.*;
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private Integer stock;
@Version
private Integer version;
// Getter์ Setter ์๋ต
}
@Service
public class ProductService {
@Autowired
private ProductRepository productRepository;
@Transactional
public void updateStock(Long productId, int quantity) {
Product product = productRepository.findById(productId)
.orElseThrow(() -> new RuntimeException("Product not found"));
if (product.getStock() < quantity) {
throw new RuntimeException("Not enough stock");
}
product.setStock(product.getStock() - quantity);
productRepository.save(product);
}
}
@Version
์ ๋ํ ์ด์ ์ ์ฌ์ฉํ๋ฉด JPA๊ฐ ์๋์ผ๋ก ๋ฒ์ ์ ๊ด๋ฆฌํ๋ฉฐ ์ถฉ๋ ์ฌ๋ถ๋ฅผ ํ์ธํฉ๋๋ค.
๋๊ด์ ๋ฝ | ๋น๊ด์ ๋ฝ | |
---|---|---|
๋ฝ ๋ฐฉ์ | ๋ฒ์ ํ๋๋ก ์ถฉ๋ ๊ฐ์ง | ๋ฐ์ดํฐ ์ฝ์ ๋ ๋ฝ ์ค์ |
์ฑ๋ฅ | ์ฝ๊ธฐ ์์ ์ด ๋ง์ ๊ฒฝ์ฐ ์ ๋ฆฌ | ์ฐ๊ธฐ ์์ ์ด ๋ง์ ๊ฒฝ์ฐ ์ ๋ฆฌ |
๋ฐ๋๋ฝ | ๋ฐ์ํ์ง ์์ | ๋ฐ์ ๊ฐ๋ฅ |
์ถฉ๋ ์ฒ๋ฆฌ | ์ถฉ๋ ์ ๊ฐฑ์ ์คํจ ์ฒ๋ฆฌ ํ์ | ์ถฉ๋ ๊ฐ๋ฅ์ฑ์ด ์ ์ |
๋๊ด์ ๋ฝ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋์์ฑ ์ ์ด์์ ๋งค์ฐ ์ ์ฉํ ๋๊ตฌ๋ก, ์ฑ๋ฅ๊ณผ ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ์ ๊ท ํ์ ์ ์งํ ์ ์์ต๋๋ค. ํนํ ์ฝ๊ธฐ ์์ ์ด ๋ง์ ํ๊ฒฝ์์ ํจ๊ณผ์ ์ด๋ฉฐ, ๊ตฌํ์ด ๊ฐ๋จํ๋ค๋ ์ฅ์ ์ด ์์ต๋๋ค. ํ์ง๋ง ์ฐ๊ธฐ ์์ ์ด ๋ง๊ฑฐ๋ ์ถฉ๋์ด ๋น๋ฒํ ํ๊ฒฝ์์๋ ๋น๊ด์ ๋ฝ๊ณผ ๋น๊ตํ์ฌ ์ ์คํ ์ ํํด์ผ ํฉ๋๋ค.
์ฌ๋ฌ๋ถ๋ ํ๋ก์ ํธ์ ๋๊ด์ ๋ฝ์ ๋์
ํด ํจ์จ์ ์ด๊ณ ์์ ์ ์ธ ๋์์ฑ ๊ด๋ฆฌ๋ฅผ ๊ฒฝํํด๋ณด์ธ์! ๐