개요
최근 사이드 프로젝트에서 PR을 진행하며 팀원에게 @Transaction 애너테이션을 사용 이유에 대해 질문을 받았다. 당시 명확한 답변을 하지 못했기에 애너테이션을 삭제하기로 했다. 하지만 이 과정에서, findBy와 save 메서드의 흐름에서 트랜잭션이 필요한 상황에 대해 다시 고민하게 되었다. 특히, findBy로 조회한 데이터가 다른 트랜잭션에서 삭제되는 경우에 대한 고민이 생겼고, 이를 해결하기 위한 방법을 찾고자 테스트를 진행했다. 결국 무결성 유지를 위해 테이블 분리 방법을 선택했다. 이런 결론을 내린 과정을 서술하고자 한다.
특정 상황에서의 트랜잭션?
기존에 findBy 메서드를 사용하여 데이터를 조회하고, sace 메서드를 사용해 데이터를 삽입하는 흐름에서 문제가 발생할 수 있는 상황을 고려했다. 예를 들어, findBy로 조회한 데이터가 삭제된 후, save 메서드를 통해 그 데이터를 다시 저장하려고 한다면 다른 트랜잭션에서 해당 데이터가 이미 삭제된 상태일 수 있다. 이때, 트랜잭션을 사용했을 때와 그렇지 않았을 때의 동작 차이를 확인하고자 했다.
테스트 환경은 테스트하려는 api에 thread.sleep을 걸어서 진행했다. 테이블 삭제는 실제 api가 진행되는 과정에서 테이블을 삭제했다.
- 트랜잭션을 사용한 경우 : 예외가 발생할 것으로 예상
- 트랜잭션을 사용하지 않은 경우 : 정상적으로 저장될 것으로 예상
그러나 테스트 도중, 외래키가 없다는 점을 간과한 채 진행했음을 깨달았다. 그로 인해, 외래키를 통한 데이터 무결성 관리에 대해 다시 한 번 고민하게 되었다.
트랜잭션 격리 수준
이 문제를 해결하기 위해, 팀원 중 한 명이 트랜잭션 격리 수준에 대해 설명해주셨다. PostgreSQL에서는 기본적으로 READ COMMITTED 격리 수준을 사용하고 있었다. 이 설정에서는 다른 트랜잭션에서 데이터가 변경될 경우, 그 변경을 읽지 않도록 보장해주지만, 삭제된 데이터를 다시 저장하려고 할 때 발생할 수 있는 문제를 완전히 해결하지는 못한다.
두 개의 외래키 nullable vs 테이블 분리
이 문제를 해결하려면 외래키를 활용하여 데이터 무결성을 보장해야 한다는 결론에 도달했다. 외래키를 통해 데이터 관계를 명확하게 하고, 이를 관리할 방법을 고민했다. 두 가지 해결 방안이 제시되었다.
- 하나의 테이블에 두 개의 외래키를 nullable로 둔다. → 이 방법은 가능하지만, 데이터 무결성이 제대로 유지되지 않을 위험이 있다.
- 테이블을 두 개로 나누어 관리한다. → 데이터 관계를 명확히 하고, 무결성을 유지할 수 있는 더 안전한 방법으로 보였다.
결국, 테이블을 두 개로 나누는 바법이 더 나은 선택이라는 결론에 이르게 되었다. 이는 무결성을 지키는 데 유리하며, 데이터를 명확히 구분할 수 있기 때문이다.
마무리
내 의견은 테이블을 두 개로 나누는 것이 더 바람직하다고 생각했다. 외래키를 nullable로 두는 방법은 가능하지만, 무결성이 지켜지지 않을 수 있기 때문에 피하는 것이 좋다고 본다. 외래키를 nullable로 두는 방식은 해당 테이블에 대해 CRD가 일어나기 때문에 데이터 무결성을 보장하지 못할 수 있어 다른 방향을 선택했다.
함께 본 자료
https://mangkyu.tistory.com/299
[MySQL] 트랜잭션의 격리 수준(Isolation Level)에 대해 쉽고 완벽하게 이해하기
이번에는 트랜잭션 격리 수준(Isolation Level)에 대해 알아보도록 하겠습니다. 아래의 내용은 RealMySQL과 MySQL 공식 문서 등을 참고하여 작성하였으며, 모든 내용은 InnoDB를 기준으로 설명합니다. 해
mangkyu.tistory.com
https://www.youtube.com/watch?v=XJo5O6GrFC0
https://resilient-923.tistory.com/415
[Spring/JPA] @Transactional을 사용하는 이유에 대하여 (부제. JPA Dirty Checking)
이번 포스팅에서는 JPA를 사용한다면 한 번쯤은 사용해 봤을 법한 @Transactional 어노테이션에 대해서 알아보려고 합니다. 0. Transaction이란? 그럼 먼저 Transaction에 대해서 간단하게 짚고 넘어가 보겠
resilient-923.tistory.com
'🌃 TIL' 카테고리의 다른 글
[TIL] 도메인 기반 3-Tier 구조에서 SRP 고민(feat. Facade 개념 적용) (0) | 2025.03.11 |
---|---|
[TIL] 3계층 구조의 단일 책임 원칙(SRP) 위배 (0) | 2025.02.16 |
[TIL] REST API 설계 (feat. 계층형 vs 필터링 구조) (0) | 2025.02.09 |
[TIL] 검색+필터 기능 설계 시 고려할 점 (feat. DB, API) (0) | 2025.01.21 |
윈도우 환경에서 Python 크롤링 작업 자동화 (feat. PowerShell, 작업 스케줄러) (2) | 2024.12.27 |