봐봐


공유데이터에는 락을 무조건 걸고보자는 주의가 러스트잖아.

물론 내가 자꾸 무조건 무조건 이러면서 러스트를 바보취급하는거같긴한데

러스트에서도 락을 풀고 프로그래머 재량껏 위험한 코드를 쓸수도 있음.



근데, 여하튼 안전한 코드

그리고 때에 따라서는 동시성문제를 제어하는것.


이거는 중요한 문제야.



러스트에서는 공유변수가 생길때마다 컴파일러단계에서 검증을하는데



우리 웹개발자들아


데이터베이스는 광범위한 공유공간인데

우리는 이거에 락을 안걸고 사용하고 있었다고.

여기서 락이라는 단어에 너무 발작하지마. 뭐 락프린지 뭔지 일단 통과시키고 롤백하는것도 나는 락이라고 부르는 중이야.


그래서


흐음... 아무생각없이 지내다가 일이 터지면 그때서야 해결책을 강구하는거 말고


좀 코딩스타일 그 자체로 동시성을 미리 컨트롤하고자 하는 욕구 없어?



이게 문제가 터지면 생각하는 방식은 뭐가 문제냐면

지금은 안전할 수 있어.

지금까지 코드로는 안전성을 보장할수있는데


미래에 코드가 바뀌면 그 검증을 또 다시 진행해야함.


이거 뭔말인지 알잖아 다들...


그래서 이걸 도구를 써서 잡아야하는거야.

자동으로 코드가 바뀐것에 대해서 문제가 잡히게끔 해야돼.



자 얘들아.


그러면 이런 방식을 생각해볼수있어.


아, 그러면 그냥 get 해올때마다 select for update 써버려!

그냥 싹다 락 걸어!!


이게 문제가 있어.


일단, db 에서 락은 내가 마음대로 해제할수가 없고

트랜잭션이 종료될때까지 유지돼.


그러니까 이렇게 락을 잡아버리면 범위가 너무 커짐.


그리고 우리 JPA쓰는 이유 뭐야.

모르면 메모해.


영속성컨텍스트에서 변경감지 자동으로 해주는거?

너희 이게 뭐 초보자들 코드 한줄 아끼자고 자동으로 해주는거 같니?


아니야


서비스1에서 서비스2를 호출해.

서비스2는 다른데에서 재활용돼.

서비스1이 끝나야 트랜잭션이 종료돼.

라고 가정해봐


이 상태에서

서비스2 에서 업데이트문을 발송해.

그러면 원래 서비스1이 끝날때까지 해당 row에는 업데이트 락이 걸린다고


서비스2에서 발송한 업데이트시점과

서비스1이 끝나는 시점까지 락이 걸리는거야.


근데, 서비스2에서 발송한 update문을 너는 서비스1에 옮겨놓을수 있겠니?

이걸 최적화 하려면

모든 로직마다

업데이트를 예약시킨담에

서비스1에서 해당 업데이트문을 날려야돼


너 이거 할수있어???


이거 진짜 굉장히 귀찮은일이고

심지어 서비스1 서비스2만 고려할게아니라

서비스 2는 재사용될거고

서비스1에다가 코드를 박자니 서비스2코드가 바뀔때마다 모든 서비스2를 호출하는 바깥 서비스 코드를 바꿀거니? 이게 지금 말이 된다고 생각해??



그래서 AOP쓴다고


이러려고 AOP쓰는거야


그리고 이래서 영속성컨텍스트 쓰는거야.


바깥 트랜잭션이 어딘지 스프링이 체크하고

그 시점에 업데이트해야하는것들 쭈루룩 체크하고 커밋 직전에 업데이트 날리는거야


왜?


커밋 직전에 업데이트 날려야 해당 row에 업데이트 락이 걸리는 시점이 최소화되니까.


나 솔직히 지금 너무 친절하게 설명한다 맞지??


여기까지


"어 뭐야 이거 진짜개발잔가?" 라는 생각이 들면 공부 다시하고 와.


내가 자바, 스프링이랑 JPA, 객체지향만 잘해도 취직 잘된다는거 개소리가아님.

일단 나는 뽑아 쓸거야


이 베이스가 되어있다는건

뭘해도 잘할거란뜻임. 물론 웹개발에 한정해서는.



여하튼


select for update는 그래서 안돼...


그래서 optimistic lock을 사용해야한다고


와 근데 이거 사용하면

이제 안전하게 코딩도 할수있고 참 좋다 그치??


근데 문제가 하나가 있어


일단


옵티미스틱 락 쓰기 전에

이게 진짜로 안전한지

기본블록으로 검증 똑바로해.


기본블록은 트랜잭션 격리수준, 그리고 DB row lock 과 table lock 이야. 이정도만해. 뭐 갭락 이런 짜잘한 규칙은 내가보기에 SQL 구현체들마다 다를거같고 필요할때 찾아보셈 큰 줄기는 아님.


여하튼 기본블록들로 제대로 검증해.


그나마 DB 동기화 블록들은 쉬움.

왜냐면 디비락이랑 격리수준 자체가 이미 하드웨어 OS수준의 동기화블록으로 만들어진 고수준 동기화블록이고

이것만가지고 디비쪽 동기화를 다 만들어냈으니까 쉬움.


그 밑바닥은 안건드려도됨. (물론 궁금해서 건드리고 싶어야 정상임.)



여하튼 옵티미스틱락을 쓰기로 했는데 여기까진 좋은데



분명히 네카라 이새끼들 옵티미스틱 락 안쓴단말이지?


나만,


나만 고집한다??


나만 이 규칙 고집한다??


그리고 러스트조차 풀때는 락을 풀고 그냥 위험하게 쓰기도 해


그니까 락을 푸는 방법이 중요함.


옵티미스틱 락 써보려고해봐. 락 푸는 방법이 없음 ㅋㅋㅋㅋㅋㅋ


씨발 그냥 업데이트하라고!! 이게 안됨.


내가 그래서 그 방법을 찾아냈다.


2편에서 얘기해줌.



그니까 그냥 요약하자면 이거임


엔티티별로


이게 동기화가 필요한지 아닌지 고민하고 필요하면 그냥 옵티미스틱 박아


그러면 자동으로 안전하게 검증해줌.


물론, 익셉션 튕기는 처리도 자동화 시켜놔. 상속이건 AOP건 뭐든 좋으니까 익셉션처리 자동화해.

어노테이션으로 리트라이인지 에러메세지반출인지 이런거 자동화시키는것도 좋고.

여기까지만 해


그 다음부터는 무비용으로 안전성 보장받을 수 있고


어 대표님, 새로만든 테이블에서 api가 유저 좀 몰리면 실패율이 너무 올라갑니다


라고 하면


그제서야 대응이 가능함.


이게 나는 데이터가 깨져서 엉망되는것보단 낫다고 본다.


중요한 데이터에 대해서는 트래픽같은거는 우리가 직접 만들어서 실험해볼수도 있는거고


데이터가 깨지는걸 인지도 못하고 먼 미래에 데이터가 오류인걸 깨닫는거보다는 훨씬 나아 진짜로


에러가 곧장 터지는게 맞다고 ㅇㅇㅇㅇ




여하튼 그냥 옵티미스틱 필요한곳에 박고 옵티미스틱 자동으로 설정되게 하고 실패율 체크해.



그리고?


옵티미스틱 풀고싶으면??


2편에 나올 방법을 쓰면 된다.



어때 깔끔하지?



우리 회사 오면


나랑 같이 이런거 고민하고 나랑 치고박고 싸울새끼 환영한다