์ฌ์ด๋ ํ๋ก์ ํธ ์ค, ์์ ์์ฝ์ ํ ๋์ ๊ฒฐ์ ํ๋ก์ธ์ค๋ฅผ ๊ตฌํ์ค์ด์์ต๋๋ค.
์์ฝ์ ํ์ ํ ๋, ๊ฒฐ์ ํ๋ก์ธ์ค๋ ๋ค์ ์ฌ์ง์ฒ๋ผ ์ฌ๋ฌ ํ๋ก์ธ์ค๋ก ๋๋์ด ์ง๋๋ค.
์ด ๋, ์ ๊ฐ ๊ณ ๋ คํ ๊ฒ์ ์ด 5๊ฐ์ง์ด๋ฉฐ ์ด์ ๋ํด ์ค๋ช ์ ์งํํฉ๋๋ค.
- ๊ฒฐ์ ํ๋ก์ธ์ค์ ํธ๋์ญ์ ์ค์ ๋ฒ์
- '๊ฒฐ์ ์น์ธ์ ์ํ PG์ฌ API ํธ์ถ'๊ณผ ํธ๋์ญ์ ์ ์์
- '๊ฒฐ์ ์น์ธ์ ์ํ PG์ฌ API ํธ์ถ'์ ๋๊ธฐ/๋น๋๊ธฐ ์ค ์ ํ
- ๋์์ฑ ์ ์ด ๋ฐฉ๋ฒ
- ์์ก ๋ถ์กฑ์ผ๋ก ์ธํ ๊ฒฐ์ ์น์ธ ์คํจ๋ ํธ๋์ญ์ ๋กค๋ฐฑ ์ ๋ฐ์ํ๋ ๊ฒฝ์ฐ๋ฅผ ์ด๋ป๊ฒ ์ฒ๋ฆฌํ ๊ฒ์ธ์ง
1. ๊ฒฐ์ ํ๋ก์ธ์ค์ ํธ๋์ญ์ ์ค์ ๋ฒ์
'๊ฒฐ์ ์น์ธ์ ์ํ PG์ฌ API ํธ์ถ' ์ ๋คํธ์ํฌ๋ฅผ ํตํด PG์ฌ์๊ฒ POST ์์ฒญ์ ํตํด ๊ฒฐ์ ๋ฅผ ์น์ธ ๋ฐ๋ ๊ณผ์ ์ผ๋ก ํธ๋์ญ์ ์ ํฌํจ๋์ด ํธ๋์ญ์ ์ด ๊ธธ์ด์ง๊ฒ ๋๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ ๋จ์ ๋ค์ด ์์ ๊ฒ์ด๋ผ ์๊ฐํ์ต๋๋ค.
- Mysql 8.0 InnoDB ์ํคํ ์ฒ ํน์ฑ ์ ํธ๋์ญ์ ์ด ๊ธธ์ด์ง์๋ก ์ธ๋ ์์ญ์ ๋ฐ์ดํฐ๊ฐ ์ญ์ ๋์ง ๋ชปํ๊ณ ์ฑ๋ฅ์ด ๋๋ ค์ง๋๋ค.
- ํธ๋์ญ์ ์ด ๊ธธ๋ฉด DB์ปค๋ฅ์ ์ด ์ฌํ์ฉ๋์ง ๋ชปํ๊ณ , ๋์ ์์ฒญ์ ์๊ฐ ์ค์ด๋ญ๋๋ค.
- ๋คํธ์ํฌ ์์ฒญ ์๊ฐ์ ์ํด DB์ปค๋ฅ์ ์ด timeout ๋๊ฑฐ๋, ์ ๊ธ์ด ์ผ์ด๋ฌ์ ๊ฒฝ์ฐ ์ ๊ธ ๋๊ธฐ ์๊ฐ์ด ๊ธธ์ด์ง๊ฒ ๋ฉ๋๋ค.
๊ทธ๋ ๊ธฐ์ ํธ๋์ญ์ ์์ '๊ฒฐ์ ์น์ธ ์์ฒญ'์ ๋ถ๋ฆฌํ๊ฒ ๋์์ต๋๋ค.
2. '๊ฒฐ์ ์น์ธ์ ์ํ PG์ฌ API ํธ์ถ' ์ ์์
์ด์ '๊ฒฐ์ ์น์ธ์ ์ํ PG์ฌ API ํธ์ถ'(์ดํ ๊ฒฐ์ ์น์ธ ์์ฒญ) ์ ์์๋ฅผ ํธ๋์ญ์ ์์๊ณผ ๋ ์ค ์ด๋์ ๋์ ๊ฒ์ธ์ง ๊ณ ๋ฏผํ์ต๋๋ค.
'๊ฒฐ์ ์น์ธ ์์ฒญ' ์ด ํธ๋์ญ์ ์์ ์ ์ผ ๊ฒฝ์ฐ
- ์ฅ์
- ๊ฒฐ์ ์น์ธ์ด ์คํจ ํ์ ๋, ๊ณ ๋ คํ ๊ฒ์ด ์ ์ด์ง๋ค → DB์ปค๋ฅ์ ์ ์ฐ์ง ์๊ธฐ ๋๋ฌธ์ DB ๊ด๋ จ ์ฒ๋ฆฌ๊ฐ ์์ํ๋ค.
- ๊ฒฐ์ ์น์ธ์ด ์ฑ๊ณตํ๊ณ , ํธ๋์ญ์ ๋ด๋ถ์์ ์์ธ๊ฐ ํฐ์ก์ ๋ ๋กค๋ฐฑํ๊ธฐ๊ฐ ์ฝ๋ค.
- ๋จ์
- ๊ฒฐ์ ์น์ธ์ด ์ฑ๊ณตํ๊ณ , ํธ๋์ญ์ ๋ด๋ถ์์ ์์ธ๊ฐ ํฐ์ก์ ๋, ๋กค๋ฐฑํ๊ธฐ ์ฝ์ง๋ง PG์ฌ์๊ฒ '๊ฒฐ์ ์ทจ์ ์์ฒญ' ์ ์ถ๊ฐ๋ก ๋ณด๋ด์ผ ํ๋ค.
'๊ฒฐ์ ์น์ธ ์์ฒญ'์ด ํธ๋์ญ์ ๋๋ ํ์ผ ๊ฒฝ์ฐ
- ์ฅ์
- ์์๊ฐ ์์ฝ์ด ์ฑ๊ณต์ ์ผ ๋๋ง '๊ฒฐ์ ์น์ธ' ์ด ์งํ๋๋ค.
- ๋จ์
- '๊ฒฐ์ ์น์ธ ์์ฒญ' ์์ ๊ธ์ก ๋ถ์กฑ๊ณผ ๊ฐ์ด ๋ฌธ์ ๊ฐ ๋ฐ์ํด์ ์น์ธ์ด ์ด๋ฃจ์ด์ง์ง ์๋๋ค๋ฉด, ์ปค๋ฐ๋ ํธ๋์ญ์ ์ ์์ ๋กค๋ฐฑํด์ผ ํ๋ค.
- ์ด ๋, '๊ฒฐ์ ์ทจ์ ์์ฒญ์ ๋ณด๋ด๋ ๋น์ฉ'๋ณด๋ค 'ํธ๋์ญ์
์ ๋กค๋ฐฑํ๊ธฐ ์ํด DELETE ์ฟผ๋ฆฌ๋ฅผ ์์ฑ'ํ๋ ๊ฒ์ ๋น์ฉ์ด ๋ ํฝ๋๋ค.
- ๋์์ฑ ์ ์ด๋ฅผ ์ํด ์์ฝ ํ ์ด๋ธ์ ์ ๋ํฌ ์ ์ฝ์กฐ๊ฑด์ ์ฌ์ฉํ๋๋ฐ, ์ ๋ํฌ ์ ์ฝ์กฐ๊ฑด์ DELETE ํ ๋๋ ๋ ์ฝ๋ ์์ค์ ์ฐ๊ธฐ ๋ฝ์ผ๋ก ๊ฑธ๋ฆฌ๊ฒ ๋ฉ๋๋ค. ์ด๋ ๋ฐ๋๋ฝ ๋น๋๋ฅผ ๋์ด๋ ํ์์ ๋๋ค.
- InnoDB ์ํคํ
์ฒ์ ์ฒด์ธ์ง ๋ฒํผ ๊ธฐ๋ฅ์ ์ฌ์ฉํ์ง ๋ชปํฉ๋๋ค.
- ์ฒด์ธ์ง ๋ฒํผ๋ ์ฐ๊ธฐ ์์ ์ ๋์คํฌ์ ์ฆ์ ๋ฐ์ํ๋ ๋์ ๋ฉ๋ชจ๋ฆฌ์ ๋ฐ์ํจ์ผ๋ก์จ ๋์คํฌ I/O ๋ฅผ ์ค์ด๋ ๊ธฐ๋ฅ์ ๋๋ค. ํ์ง๋ง, ์ ๋ํฌ ์ปฌ๋ผ์ ๊ณ ์ ํด์ผ ํ๋ค๋ ํน์ฑ ๋๋ฌธ์ ์ฐ๊ธฐ ์์ ์ ๋์คํฌ์ ์ฆ์ ๋ฐ์์ ํ๊ฒ ๋ฉ๋๋ค.
์ด๋ฌํ ๊ณ ๋ฏผ์ ๋ฐํ์ผ๋ก ์๋์ ์ฌ์ง๊ณผ ๊ฐ์ด '๊ฒฐ์ ์น์ธ ์์ฒญ' ์ ํธ๋์ญ์ ์์ ์ ์ ๋๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค.
3. ๊ฒฐ์ ์น์ธ ์์ฒญ์ ๋ณด๋ด๋ ์ธ๋ถ API ํธ์ถ ๋ฐฉ๋ฒ์ ๋๊ธฐ๋ก ์ ํ
๋น๋๊ธฐ์ ์ฅ๋จ์
- ์ฅ์
- ์ธ๋ถ API ์๋ต์ ๊ธฐ๋ค๋ฆฌ์ง ์์๋ ๋๋ ์ ์๋ฒ์ ์ฑ๋ฅ์ด ์ฌ๋ผ๊ฐ๋๋ค.
- ๋จ์
- ์์ก ๋ถ์กฑ ๊ฐ์ ์ด์ ๋ก ๊ฒฐ์ ์น์ธ์ด ์คํจํ ๊ฒฝ์ฐ, ์์ฝ ํ ์ด๋ธ๊ณผ ๊ฒฐ์ ํ ์ด๋ธ์ INSERT ๋ ๋ฐ์ดํฐ๋ฅผ ๋ค์ DELETE ํด์ผ ํ๋ค.
- ์ด ๊ณผ์ ์์ ํด๋น ํธ๋์ญ์ ์ด ๋ฐ๋๋ฝ์ด ๋์ด DELETE ๊ฐ ์คํจํ๋ฉด ์ฌ์๋ ๋ก์ง์ ์ถ๊ฐํ๊ณ , ์์ธ๋ฅผ ์ก๋ ๋ก์ง์ ์ถ๊ฐํ๋ ๋ฑ ํ์ฒ๋ฆฌ ๋ก์ง์ด ๋์ด๋๋ค.
๋๊ธฐ์ ์ฅ๋จ์
- ์ฅ์
- ๊ฒฐ์ ์น์ธ ์์ฒญ ์คํจํ๋ฉด ํธ๋์ญ์ ์ด ์์๋์ง ์์ผ๋ ๋น๋๊ธฐ์ ๋จ์ ์ ํด๋นํ๋ ๋ก์ง์ด ํ์ ์๋ค.
- ๋จ์
- ์ธ๋ถ API ์๋ต์ ๊ธฐ๋ค๋ ค์ผ ํ๋ ์ธ๋ถ API ์๋ต์ด ๋๋ฆด ๊ฒฝ์ฐ, ์๋ฒ ์ ์ฒด์ ์ฑ๋ฅ์ด ๋๋ ค์ง๋ค.
์ ๋ ๋๊ธฐ ๋ฐฉ์์ผ๋ก ์ธ๋ถ API๋ฅผ ํธ์ถํ๋ ๊ฒ์ ์ ํํ์ต๋๋ค.
๋น๋๊ธฐ์ ๋จ์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๊ฒ๋ณด๋ค ๋๊ธฐ์ ๋จ์ ์ ๊ทน๋ณตํ๋ ๊ฒ์ด ์ฝ๊ธฐ ๋๋ฌธ์ ๋๋ค.
HTTP ์ฐ๋ ๋ ํ์ ์ฐ๊ฒฐ ์๊ฐ ํ์ ์์๊ณผ ์๋ต ์๊ฐ ํ์ ์์์ ์ค์ ํด์ ๊ทน๋ณตํ๊ณ ์ ํฉ๋๋ค.
์ด๋ฅผ ํตํด ์ธ๋ถ API ์ฅ์ ์ ์ํฅ์ ๋ ๋ฐ์ผ๋ฉฐ, ํด๋น ์์ฒญ์ ์ฒ๋ฆฌํ๊ณ ์ ํฉ๋๋ค.
4. ๋์์ฑ ์ ์ด ๋ฐฉ๋ฒ
์ ๋ ์์ฝ ๋ ์ง์ ๋ํด ์์ID ์ ๋ ์ง์ ๋ํด ์ ๋ํฌ ์ ์ฝ์กฐ๊ฑด์ ์ฌ์ฉํ์ต๋๋ค.
์ด์
- ์ต์ด INSERT ์์๋ ๋๊ด์ /๋น๊ด์ ๋ฝ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
- '์์ฝ ๊ฐ๋ฅ ์ฌ๋ถ' ๋ฅผ ํ์ธํ๊ธฐ ์ํด์๋ ์์ID์ ๋ ์ง๋ฅผ ์กฐํํด์ผ ํ๋ฉฐ, ์ธ๋ฑ์ค๊ฐ ํ์ํ๋ค. ์ด ๋, ์ ๋ํฌ ์ ์ฝ์กฐ๊ฑด์ ์ฌ์ฉํ๋ฉด ์ ๋ํฌ ์ธ๋ฑ์ค๊ฐ ์์ฑ๋๋ค.
ํ๊ณ
- ์ ๋ํฌ ์ ์ฝ์กฐ๊ฑด์ ์ฒด์ธ์ง ๋ฒํผ ๊ธฐ๋ฅ์ ์ฌ์ฉํ์ง ๋ชปํ๊ธฐ ๋๋ฌธ์ ์ฐ๊ธฐ ์์ ์ด ๋๋ฆฝ๋๋ค. ๊ทธ๋์, ์์ฝ ํ ์ด๋ธ์ INSERT ๋ก ์ธํด ์ฑ๋ฅ์ด ๋๋ ค์ง๋ค๋ฉด ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ๊ณ ๋ฏผํด์ผ ํฉ๋๋ค.
5. ์์ก ๋ถ์กฑ์ผ๋ก ์ธํ ๊ฒฐ์ ์น์ธ ์คํจ๋ ํธ๋์ญ์ ๋กค๋ฐฑ ์ ๋ฐ์ํ๋ ๊ฒฝ์ฐ์ ๊ตฌํ ๋ฐฉ๋ฒ
์์ก ๋ถ์กฑ์ผ๋ก ์ธํด ๊ฒฐ์ ์น์ธ์ด ์คํจํ๋ค๋ฉด DB ์กฐ์์ด ๋ฐ์ํ๋ฉด ์๋ฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ , ํธ๋์ญ์ ๋กค๋ฐฑ ์, ๊ฒฐ์ ์ทจ์ ์์ฒญ์ ๋ณด๋ด์ผ ํฉ๋๋ค.
ํธ๋์ญ์ ์ ํ์ Facade ํจํด์ ์ฌ์ฉํด์ ์ด๋ฌํ ๊ณผ์ ์ ๊ตฌํํ์ต๋๋ค.
๋จผ์ , ํธ๋์ญ์ ์ ํ์ ๊ธฐ๋ณธ ์ค์ ์ธ REQUIRED๋ฅผ ํตํด ํ์ฌ ์งํ์ค์ธ ํธ๋์ญ์ ์ด ์์ผ๋ฉด ํด๋น ํธ๋์ญ์ ์ ์ฐธ์ฌํ๋๋ก ๊ตฌํํ์ต๋๋ค.
class ๊ฒฐ์ ์๋น์ค {
private final ์์ฝ์๋น์ค;
@Transactional
public void ์์_์์ฝ์_๋ํ_๊ฒฐ์ ์ถ๊ฐ() {
1. ๊ฒฐ์ ์น์ธ ์์ฒญ(์ธ๋ถ API ํธ์ถ)
2. @Transactional
์์ฝ ์๋น์ค ํธ์ถ() -> ์์ฝ ์ค๋ณตํ์ธ, ์์ฝ ํ
์ด๋ธ INSERT
3. ๊ฒฐ์ ํ
์ด๋ธ INSERT
}
}
์ด์ , ๋คํธ์ํฌ๋ฅผ ํ๋ ๊ฒฐ์ ์น์ธ ์์ฒญ์ ํธ๋์ญ์ ์์ ๋ถ๋ฆฌํ๊ณ ์ Facade ํจํด์ ์ฌ์ฉํ์ต๋๋ค.
๊ฒฐ์ Facade๋ ๊ฒฐ์ ์น์ธ ์์ฒญ(์ธ๋ถ API ํธ์ถ)์ ํ๋ TossClient ์ @Transactional์ด ๊ฑธ๋ฆฐ ๊ฒฐ์ ์๋น์ค๋ฅผ ํธ์ถํฉ๋๋ค.
๊ฒฐ์ ์๋น์ค๋ฅผ ํธ์ถํ ๋๋ง @Transactional ์ ๊ฑธ์์ผ๋ก์จ ํธ๋์ญ์ ์์ ๋คํธ์ํฌ ์์ฒญ์ ๋ถ๋ฆฌํ๊ฒ ๋์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ๊ฒฐ์ ์๋น์ค์ ํธ๋์ญ์ ์ ์์ฝ ์๋น์ค๊น์ง ์ ํ์์ผ ๊ฒฐ์ ๋ฐ์ดํฐ INSERT, ์์ฝ ํ์ UPDATE, ์์ฝ ๋ ์ง INSERT ์ค ํ๋๋ผ๋ ๋กค๋ฐฑ์ด ๋์ด ๋ฌผ๋ฆฌ ํธ๋์ญ์ ์ด ๋กค๋ฐฑ๋๊ฒ ๊ตฌํํ์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ , ๋กค๋ฐฑ ๋ ๋ Spring์ด ์ ๊ณตํ๋ DB ์ต๊ณ ์์ ์์ธ์ธ DataAccessException ์ try-catch ๋ก ์ก๊ฒ ๋๋ฉด TossClient ๋ฅผ ํธ์ถํ์ฌ, ๊ฒฐ์ ์ทจ์ ์์ฒญ์ ๋ณด๋ด๋๋ก ๊ตฌํํ์ต๋๋ค.
public ๊ฒฐ์ ์๋ต๋ฐ์ดํฐ ์์ฝํ์ธํ๊ธฐ(PaymentConfirmServiceRequest request) {
// ์์ ๊ฒฐ์ ๋ฐ์ดํฐ ์กด์ฌ & ์์ฒญ์์ ๊ฒฐ์ ์๊ฐ ๊ฐ์์ง ํ์ธ
paymentService.validateExistingPaymentTemporary(request);
// ๊ฒฐ์ ์น์ธ ์์ฒญ(์ธ๋ถ API ํธ์ถ)
TossPaymentConfirm tossPaymentConfirm = tossClient.confirmPayment(request.paymentKey(), request.orderId(),
request.amount());
try {
// ๊ฒฐ์ ๋ฐ ์์ฝ INSERT ์ ๋ํ ํธ๋์ญ์
์์
return paymentService.confirmReservation(tossPaymentConfirm, request.reservationId(), request.memberId());
} catch (DataIntegrityViolationException | BusinessException e) {
log.warn("์์ฝ ์คํจ", e);
// ๊ฒฐ์ ์ทจ์ ์์ฒญ ๋ณด๋ด๊ธฐ
tossClient.cancelPayment(request.paymentKey());
throw new BusinessException(ErrorCode.NOT_CONFIRM_RESERVATION);
}
}
๊ธ์ ๋ง๋ฌด๋ฆฌ ํ๋ฉฐ..
์ ๋ ๊ธฐ๋ฅ์ ์์ ์ฑ์ ์ฐ์ ์ ์ผ๋ก ์๊ฐํฉ๋๋ค.
๋ง์ฝ, ๊ธ์ ์ฝ๊ณ ๋ถ์กฑํ ๋ถ๋ถ์ด ๋ณด์ธ๋ค๋ฉด ์ฃผ์ ์์ด ๋๊ธ๋ก ๋จ๊ฒจ์ฃผ์๋ฉด ๊ณต๋ถํด์ ๋ณด์ํ๋๋ก ํ๊ฒ ์ต๋๋ค๐โ๏ธ