거래내역의 실종
입사하자마자 흥미로운 주제의 CS가 들어왔습니다.

몇달 동안 지속적으로 유입되던 문의였습니다. 내용은
"거래를 분명히 했고 잘 됐다고 떳는데요.."
"거래내역에 제 거래가 없는데요?"

가장 먼저 확인했던 것은 메서드에 @Transactional 이 걸려있는가 였습니다.

문제 없이 걸려있던 점을 확인했고 그렇다면 어딘가 Exception 이 발생하여 Rollback 된 것으로 보였습니다.
그런데 말입니다. 쿠폰, 포인트는 사용 됐어요
@Transactional 이 적용된 메서드에서
거래내역은 저장이 안되고 거래내역 저장 후 일어나는 동작인 쿠폰 사용 처리와 포인트 사용 처리는
정상적으로 적용이 된 것이였습니다.
당연히 checked Exception 을 catch 로 잡은게 아닐까 생각했지만.. 아쉽게도 그런 로직은 없었고
제가 보유한 지식으로는 한계에 다다를 때 팀장님에게 한가지 힌트를 얻었습니다.
SP(Stored Procedure)에서 아마 잘못 됐을 가능성이 크다는 조언이였습니다.
💡 SP란?
- Stored Procedure 의 약자로 DB 에서 제공하는 프로그래밍 기능이다.
- 쉽게 말해서 DB가 어느정도 롤을 가져가고 인터페이스를 제공하는 것이라고 볼 수 있다.
현재 거래 프로세스에서 사용되는 프로시저가 몇가지 있었는데 이 프로시저들을 중점적으로 살펴보기로 했습니다.
경계 포인트를 찾자
가장 먼저 롤백되는 경계지점을 찾아 범인을 잡는 것을 목표로 했습니다.
- 쿠폰 포인트 사용 지점 확인
- 롤백되는 거래 내역 저장 지점 확인
- 그 사이 실행된 프로시저 확인
이 3가지 과정을 통해 의심되는 프로시저를 도출 할 수 있었습니다.
의심되는 프로시저에서 validating을 통해 롤백 되는 몇가지 포인트를 발견했고
실제로 프로시저의 롤백에서 문제가 되는가를 판별하기 위해 상황을 재현해봤습니다.
상황을 재현해보자
재현해야 하는 상황은 다음과 같습니다.
- 거래내역 저장
- 문제 프로시저 실행 ( 여기서 강제 롤백 처리 )
- 쿠폰, 포인트 사용 내역 저장

간단하게 Order 와 Coupon 정보를 저장하는 프로세스를 구현하고

실행시켜서 거래내역과 쿠폰이 저장 되는 것을 확인합니다.


모두 잘 저장된 것을 확인하고 중간에 프로시저를 투입합니다.

간단하게 userId가 22가 들어오면 에러를 반환하고 catch 에서 현재 트랜잭션을 rollback 하도록 구현하였습니다.


333으로 다시 실행해봅니다.


잘 저장된 것을 확인 할 수 있습니다.
userId 22로 저장을 시도해봅니다.

성공 한 것을 확인 할 수 있습니다.
데이터를 확인해보겠습니다.



유령 쿠폰 히스토리 데이터가 생성되었다 (!)
실제로 프로시저에서 rollback을 해서 order 내역에 대한 정보는 rollback 되었지만,
application 에서는 이를 감지하지 못하고 성공했다고 판단을 하고 이후 로직을 실행 한 것이였습니다..!
잡았다 요놈
원인은 찾았고 문제가 되는 프로시저를 수정하여 특정 오류에 대해서 롤백 후
오류에 대한 식별 할 수 있는 값을 반환하고 로깅처리했습니다.
오류 상황에 대해 어플리케이션 레벨에서 롤백을 하게되면 갑자기 거래가 안되는 상황에 즉각적인 대응이 어려울 것으로 판단되어
상황에 대한 로깅을 진행하고 점진적으로 해결하기로 결정했습니다.
그 결과 특정 유저들의 포인트 데이터가 이상하다는 것이 검출되었고,
데이터 정합성을 맞추고 추가적인 상황이 발생하지 않도록 조치하는 것으로 마무리 되었습니다.
그렇다면 이제 알아봐야 할 것은...
왜 이런일이 발생하는 것일까요?
우리는 Transaction 어노테이션이 Spring의 관점지향 프로그래밍인 AOP 로 동작 한다는 것을 알고있습니다.
그런데 이 정도 추상화 된 내용으로 이해하고 있고 어떻게 Transaction을 맺고
이 Transaction 을 어떻게 관리하는지에 대한 지식이 없어 이런 오류에 즉각적인 반응이 어려웠습니다.
따라서 다음 포스팅에서는 이 AOP에서 실제로 어떻게 Transaction을 관리하고 있기에 SP에서 실패한 로직을 파악 할 수 없었던 것인지
추가적으로 알아보는 시간을 가져보겠습니다.
다음 이야기
https://kyeum-d.tistory.com/36
[Transactional] 거래가 왜 없었을까요?
지난글...https://kyeum-d.tistory.com/35 [Transactional] 거래가 있었는데요.. 없었습니다거래내역의 실종입사하자마자 흥미로운 주제의 CS가 들어왔습니다. 몇달 동안 지속적으로 유입되던 문의였습니다.
kyeum-d.tistory.com
'Java' 카테고리의 다른 글
[Base64] 빼앗긴 Parameter 찾습니다. (3) | 2024.10.11 |
---|---|
[Transactional] 거래가 왜 없었을까요? (0) | 2024.08.18 |
[Java의 동시성] - Java에서 동시성 문제를 해결하는 방법 (1) | 2023.05.07 |
[동시성 문제] - 동시성 문제란 무엇이며 어떻게 해결해야할까? (0) | 2023.05.01 |
Comparator - <제네릭 타입 추론> (2) | 2023.04.16 |
거래내역의 실종
입사하자마자 흥미로운 주제의 CS가 들어왔습니다.

몇달 동안 지속적으로 유입되던 문의였습니다. 내용은
"거래를 분명히 했고 잘 됐다고 떳는데요.."
"거래내역에 제 거래가 없는데요?"

가장 먼저 확인했던 것은 메서드에 @Transactional 이 걸려있는가 였습니다.

문제 없이 걸려있던 점을 확인했고 그렇다면 어딘가 Exception 이 발생하여 Rollback 된 것으로 보였습니다.
그런데 말입니다. 쿠폰, 포인트는 사용 됐어요
@Transactional 이 적용된 메서드에서
거래내역은 저장이 안되고 거래내역 저장 후 일어나는 동작인 쿠폰 사용 처리와 포인트 사용 처리는
정상적으로 적용이 된 것이였습니다.
당연히 checked Exception 을 catch 로 잡은게 아닐까 생각했지만.. 아쉽게도 그런 로직은 없었고
제가 보유한 지식으로는 한계에 다다를 때 팀장님에게 한가지 힌트를 얻었습니다.
SP(Stored Procedure)에서 아마 잘못 됐을 가능성이 크다는 조언이였습니다.
💡 SP란?
- Stored Procedure 의 약자로 DB 에서 제공하는 프로그래밍 기능이다.
- 쉽게 말해서 DB가 어느정도 롤을 가져가고 인터페이스를 제공하는 것이라고 볼 수 있다.
현재 거래 프로세스에서 사용되는 프로시저가 몇가지 있었는데 이 프로시저들을 중점적으로 살펴보기로 했습니다.
경계 포인트를 찾자
가장 먼저 롤백되는 경계지점을 찾아 범인을 잡는 것을 목표로 했습니다.
- 쿠폰 포인트 사용 지점 확인
- 롤백되는 거래 내역 저장 지점 확인
- 그 사이 실행된 프로시저 확인
이 3가지 과정을 통해 의심되는 프로시저를 도출 할 수 있었습니다.
의심되는 프로시저에서 validating을 통해 롤백 되는 몇가지 포인트를 발견했고
실제로 프로시저의 롤백에서 문제가 되는가를 판별하기 위해 상황을 재현해봤습니다.
상황을 재현해보자
재현해야 하는 상황은 다음과 같습니다.
- 거래내역 저장
- 문제 프로시저 실행 ( 여기서 강제 롤백 처리 )
- 쿠폰, 포인트 사용 내역 저장

간단하게 Order 와 Coupon 정보를 저장하는 프로세스를 구현하고

실행시켜서 거래내역과 쿠폰이 저장 되는 것을 확인합니다.


모두 잘 저장된 것을 확인하고 중간에 프로시저를 투입합니다.

간단하게 userId가 22가 들어오면 에러를 반환하고 catch 에서 현재 트랜잭션을 rollback 하도록 구현하였습니다.


333으로 다시 실행해봅니다.


잘 저장된 것을 확인 할 수 있습니다.
userId 22로 저장을 시도해봅니다.

성공 한 것을 확인 할 수 있습니다.
데이터를 확인해보겠습니다.



유령 쿠폰 히스토리 데이터가 생성되었다 (!)
실제로 프로시저에서 rollback을 해서 order 내역에 대한 정보는 rollback 되었지만,
application 에서는 이를 감지하지 못하고 성공했다고 판단을 하고 이후 로직을 실행 한 것이였습니다..!
잡았다 요놈
원인은 찾았고 문제가 되는 프로시저를 수정하여 특정 오류에 대해서 롤백 후
오류에 대한 식별 할 수 있는 값을 반환하고 로깅처리했습니다.
오류 상황에 대해 어플리케이션 레벨에서 롤백을 하게되면 갑자기 거래가 안되는 상황에 즉각적인 대응이 어려울 것으로 판단되어
상황에 대한 로깅을 진행하고 점진적으로 해결하기로 결정했습니다.
그 결과 특정 유저들의 포인트 데이터가 이상하다는 것이 검출되었고,
데이터 정합성을 맞추고 추가적인 상황이 발생하지 않도록 조치하는 것으로 마무리 되었습니다.
그렇다면 이제 알아봐야 할 것은...
왜 이런일이 발생하는 것일까요?
우리는 Transaction 어노테이션이 Spring의 관점지향 프로그래밍인 AOP 로 동작 한다는 것을 알고있습니다.
그런데 이 정도 추상화 된 내용으로 이해하고 있고 어떻게 Transaction을 맺고
이 Transaction 을 어떻게 관리하는지에 대한 지식이 없어 이런 오류에 즉각적인 반응이 어려웠습니다.
따라서 다음 포스팅에서는 이 AOP에서 실제로 어떻게 Transaction을 관리하고 있기에 SP에서 실패한 로직을 파악 할 수 없었던 것인지
추가적으로 알아보는 시간을 가져보겠습니다.
다음 이야기
https://kyeum-d.tistory.com/36
[Transactional] 거래가 왜 없었을까요?
지난글...https://kyeum-d.tistory.com/35 [Transactional] 거래가 있었는데요.. 없었습니다거래내역의 실종입사하자마자 흥미로운 주제의 CS가 들어왔습니다. 몇달 동안 지속적으로 유입되던 문의였습니다.
kyeum-d.tistory.com
'Java' 카테고리의 다른 글
[Base64] 빼앗긴 Parameter 찾습니다. (3) | 2024.10.11 |
---|---|
[Transactional] 거래가 왜 없었을까요? (0) | 2024.08.18 |
[Java의 동시성] - Java에서 동시성 문제를 해결하는 방법 (1) | 2023.05.07 |
[동시성 문제] - 동시성 문제란 무엇이며 어떻게 해결해야할까? (0) | 2023.05.01 |
Comparator - <제네릭 타입 추론> (2) | 2023.04.16 |