사용자가 많은 혹은 사용자가 적더라도 동시성이 잦은 기능을 개발하면 개발 할 수록, 동시성 제어에 대한 심사숙고가 필요하다고 생각한다.
지금까지는 대부분 트랜잭션으로 일반적인 이슈들을 처리를 해오다보니 데드락이 걸린 경우도 있었고, 혹은 트랜잭션을 사용하지 않아 발생한 이슈들은 데이터의 일관성이 떨어지는 이슈가 있었다.
앞선 글에 데드락에 대해 설명을 했으니, 트랜잭션으로 처리하지 않고 어플리케이션 레이어에서 처리할 수 있는 방법인 낙관적 락에 대해서 설명해보고자 한다. (feat. 비관적 락)
소개
지금까지의 락에 관련된 포스트들을 보다보면 계속해서 언급했듯이, 데이터의 일관성을 지키는 것은 매우 중요한 일이다.
특히나 여러 유저가 동시에 접근했을 때, 발생할 수 있는 문제점들을 미리 알고 예방하는 차원에서 말이다.
락킹 메커니즘을 사용하여 일관성을 유지할 수 있는데, 락이 발생할 수 있는 상황에 있어 락을 어떤 시점으로 바라보느냐에 따라 비관적 락과 낙관적 락으로 나눌 수 있다.
비관적 락(Pessimistic Lock)
낙관적 락(Optimistic Lock)
일반적으로 자원에 락을 걸지 않고 Application Level에서 처리하는 방식이며, 동일한 조건으로 값을 수정할 수 없게 하는 것이다.
일반적으로 version이라는 칼럼을 추가하여 구분하여 충돌을 예방한다. (hashcode, timestmap로도 처리가 가능하며, JPA에서는 @Version 칼럼을 활용할 수 있다고 한다.)
Request1, Request2의 조회시점은 같아 동일한 데이터를 불러왔지만, Request1이 조회한 데이터 버전을 먼저 올려 업데이트를 했기때문에 원본 데이터에 변경이 있어, Request2는 version이 1이었던 데이터를 찾을 수 없기 때문에 업데이트가 불가능한 경우이다.
성능 비교
비관적 락 < 낙관적 락
•
낙관적 락은 일반적으로 트랜잭션을 필요로하지 않기 때문에, 성능적으로 비관적 락보다 더 좋다.
•
비관적 락은 데이터에 락이 걸리기 때문에 동시성이 떨어지며, 블로킹 및 데드락이 발생하면 성능저하 혹은 서비스 불가 상태가 된다.
결론
•
비관적 락을 사용하면 좋은 경우
◦
금융시스템과 같이 데이터의 일관성이 더 중요한 경우
◦
데이터 충돌이 많이 발생할 것으로 예상되는 경우
◦
롤백처리가 까다로운 경우
•
낙관적 락을 사용하면 좋은 경우
◦
데이터 충돌이 자주 일어나지 않을 것으로 예상되는 경우
◦
조회 작업이 많아 동시 접근 성능이 중요한 경우
Ref:
지난 나의 경험에서는, 데이터 충돌이 동시다발적으로 굉장히 많이 발생했지만 데이터 일관성이 더 중요한 경우였다. 그렇다면 당연히 비관적 락을 사용했어야 했지만, 특이하게 데이터 업데이트는 되지 않아도 되지만 속도는 중요했던 케이스였다. (따라오는 다른 요청에게 데이터 일관성 위임)
그래서 결국 낙관적 락을 선택했고, 무사히 이슈를 해결할 수 있었다.
무조건적인 방법은 없는 것 같다. 각 케이스별로 특이성을 잘 고려하여 처리할 필요가 있어보인다.
결국은, 시스템의 안정성과 사용자 경험을 향상시키는데에 초점을 맞추어 개발하는 게 중요한 것 같다!
락 시리즈 끝!