Java

Spring JPA - Maria DB 트랜잭션 로컬 테스트

Kaden Sungbin Cho 2025. 1. 14. 01:45
반응형

신규로 사용하게 되는 Spring JPA와 Maria DB 간에 트랜잭션이 정확히 어떤 형태로 처리되는지 확인해보기로 하였습니다.

 

  • 애플리케이션은 어떤 요구사항이 트랜잭션에서 처리되길 원하는가?
  • 로컬 Docker 환경에서의 Maria DB 동작 체크
  • 테스트 컨테이너 기반 테스트 케이스 추가

 

(아래의 코드는 git에 올려두었습니다: https://github.com/kadensungbincho/txtest)


애플리케이션은 어떤 요구사항이 트랜잭션에서 처리되길 원하는가?

유저가 가입하는 기능만 있는 간단한 애플리케이션을 가정했습니다. 가입에는 동일한 닉네임과 이메일을 사용하지 못하는 제약이 있는데요. 그 부분을 위해 아래와 같이 코드를 작성했습니다.

 

    @Transactional
    public void signup(SignupRequestDTO request) {
        if (memberRepository.existsByNickname(request.getNickname())) {
            throw new IllegalArgumentException("이미 사용 중인 닉네임입니다.");
        }

        if (memberRepository.existsByEmail(request.getEmail())) {
            throw new IllegalArgumentException("이미 사용 중인 이메일입니다.");
        }

        Thread.sleep(request.getSleepInMs());
        
        Member member = Member.builder()
                .nickname(request.getNickname())
                .email(request.getEmail())
                .build();

        memberRepository.save(member);
    }

 

다수의 유저가 동시에 가입하여 같은 닉네임이나 이메일에 대한 가입 요청이 들어오는 상황을 가정하기 위해, 위 코드에서 Thread.sleep을 넣어두었습니다. 

 

기대하는 바는, 트랜잭션에 의해 잘 처리가 되어서(?) 동시에 요청이 들어오더라도 DB에 유니크한 닉네임과 이메일의 유저가 존재하는 것입니다. 

 

과연 어떻게 동작할까요?

 

로컬 Docker 환경에서의 Maria DB 동작 체크

서버를 띄우고, 아래의 curl 커맨드를 로컬에서 연속적으로 2번 실행해주었습니다:

curl -v -X POST "http://localhost:8080/signup" \
-H "Content-Type: application/json" \
-d '{
    "nickname":"kaden", 
    "email":"kaden@gmail.com",
    "sleepInMs": 60000
}'

 

첫 번째는 성공, 두 번째는 실패했는데요. 두 번째 요청에 대한 로그는 아래와 같습니다:

2025-01-14T01:54:25.334+09:00 ERROR 3218 --- [txtest] [nio-8080-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper   : (conn=14) Duplicate entry 'kaden@gmail.com' for key 'UKmbmcqelty0fbrvxp1q58dn57t'

 

음.. 컬럼 상의 unique 제약으로 인해 다행히 중복 INSERT가 진행되지 않았네요. 

 

그렇다면 유저의 탈퇴를 고려해야해서 (탈퇴 시, 해당 이메일을 사용할 수 있게 됨), 컬럼에 unique 제약이 없다면 어떻게 될까요?

 

이번에는 예상대로(?) 2번의 호출이 모두 성공해, DB 상에 동일한 닉네임과 이메일을 가진 유저가 2명이 되었네요!

 

유저 가입 플로우가 길어지고, 동시에 가입하는 수가 많아진다면 이런 경우에는 유일성이 안전하게 보장받지 못하는데요. 현재 상황은 왜 그렇고, 어떻게 해결할 수 있을까요?

 

 

 

Reference

(1) https://mariadb.com/kb/en/mariadb-transactions-and-isolation-levels-for-sql-server-users/

반응형