불안정한 네트워크, 채팅 메시지의 누락을 막자-(1)

Alex·2024년 12월 3일
0

Plaything

목록 보기
42/118

채팅을 보내는 코드다.
그런데, 이 코드를 보면서 든 생각이 있다.

트랜잭션이 정말 필요한가?

보통 트랜잭션은 비즈니스 로직들을 원자적으로 관리하기 위해서 사용한다.

비즈니스 로직이 a->b->c->d->e라고 할 때 d를 작업하다가 실패하면 앞에서 했던 db 저장/업데이트/삭제를 모두 롤백시키기 위해서 쓰는 것이다.

채팅의 경우를 생각해보자.
채팅을 쓰는 웹소켓은 네트워크 에러를 비롯해 여러 불안정한 상황에 처할 수 있다. 이때 예외가 발생하면? db에 저장한 채팅 메시지가 롤백돼서 사라진다. 웹소켓을 통해서 상대방에게 메시지가 전달되지도 않는다.

오히려 트랜잭션을 걸어두면 메시지 유실을 막을 수가 없는 상황이다.

별도로 레디스나 카프카같은 메시지큐를 써서 보관하지 않는 이상... 굳이 트랜잭션을 걸어줄 필요가 없는 것..!

긴가민가하면 테스트를 해보자

중간에 runtime 예외를 던저본다.


예외가 터지면 메시지가 도착하지 않는다.


DB에는 잘 저장이 됐다..!

내가 트랜잭션의 범위에 대해서 착각을 했던 것이다.

The recommended way to indicate to the Spring Framework’s transaction infrastructure that a transaction’s work is to be rolled back is to throw an Exception from code that is currently executing in the context of a transaction. The Spring Framework’s transaction infrastructure code catches any unhandled Exception as it bubbles up the call stack and makes a determination whether to mark the transaction for rollback.출처:공식문서

트랜잭션 범위안에서만 롤백이 된다.

트랜잭션 범위안에서 예외가 터졌을 땐?

저장되지 않는다.

그렇다면 이 구조가 맞는걸까?

메시지는 저장돼야 한다.

위 구조의 문제를 분석해보자.

채팅을 보내다가 어떤 문제가 발생해서 저장과 채팅바 업데이트 과정에서 에러가 발생한다.

그러면,


내 세션에서는 이렇게 메시지가 갔다고 뜰거다.
하지만, db에도 저장이 되지 않고 상대방에게도 메시지가 가지 않는다.

메시지가 유실되는 것이다.

그래서,

메시지가 저장된 건 롤백이 되면 안된다.

라는 결론을 내리게 됐다.

그런데, 트랜잭션을 아예 없애려고 하니 채팅방 데이터를 더티체킹해주는 것이나, 쿼리들을 마지막에 플러시하는 등의 jpa 이점을 쓰지 못하는 게 아쉽다.

차라리 롤백 기능을 끄는 건 어떨까?

noRollBackFor 옵션을 걸어주면 된다.

예외가 발생해서 상대방에게는 메시지가 가지 않았다.

DB에는 잘 저장이 됐다!

다음편에서는 누락된 채팅을 불어오는 api를 만들어보자.

profile
답을 찾기 위해서 노력하는 사람

0개의 댓글