공지

transactional

4건

체크 예외를 던졌는데 회원 데이터가 롤백되지 않았다 - @Transactional 기본 롤백 정책과 rollbackFor

@Transactional을 붙여두면 메서드 안에서 예외가 터졌을 때 알아서 롤백해줄 거라고 막연히 믿고 있었다. 그런데 회원가입 로직에 정책 위반을 알리는 예외를 체크 예외(checked exception)로 만들어 던졌더니, 분명히 예외가 터졌는데도 회원 데이터가 그대로 커밋되어 있는 걸 발견했다.결론부터 말하면 @Transactional의 기본 롤백 규칙은 "예외가 터지면 무조건 롤백"이 아니라 "RuntimeException이나 Error가 터지면 롤백, 체크 예외는 롤백 안 함"이다. 이 글에서는 같은 회원가입 로직을 언체크 예외/체크 예외/rollbackFor 지정/rollbackFor 타입을 잘못 지정한 경우 네 가지로 나눠서 실제로 DB에 데이터가 남는지 직접 확인하고 왜 이렇게 동작하는지..

2026.07.10 · 댓글

@Transactional(readOnly = true)를 붙였더니 분명히 바꾼 값이 그대로 사라졌다 - 읽기 전용 트랜잭션과 Dirty Checking

조회 전용 메서드에는 @Transactional(readOnly = true)를 붙이라는 이야기를 많이 듣는다. 그런데 막상 이유를 물으면 "성능에 좋다더라" 정도로만 알고 넘어가는 경우가 많다. 나도 그랬다. 그래서 조회한 엔티티의 값을 실수로 바꿔놓고 저장까지 시켜버리는 버그가 있는 메서드에 readOnly = true를 붙이면 어떻게 되는지 직접 실험해봤다.결과부터 말하면, readOnly = true는 단순히 "이 메서드는 읽기만 한다"는 의미의 주석이 아니었다. 트랜잭션 안에서 조회한 엔티티의 필드를 바꿔도 커밋 시점에 저장이 안 됐고 save()를 명시적으로 다시 호출해도 마찬가지로 반영이 안 됐다. 반대로 새 엔티티를 저장하는 건 readOnly = true여도 정상으로 처리됐다. 여기서는 ..

2026.07.09 · 댓글

회원가입은 됐는데 포인트가 안 쌓였다 - 서비스 계층 분리와 @Transactional 트랜잭션 경계

지금까지 만든 MemberController는 MemberRepository를 직접 호출하는 구조였다. 회원 하나 저장하는 정도는 이렇게 해도 문제가 없다. 그런데 "회원가입하면 웰컴 포인트 1000점을 같이 적립해준다"처럼 저장할 게 두 개로 늘어나면 이야기가 달라진다.결론만 이야기하면 이렇다. 컨트롤러에서 리포지토리 두 개를 순서대로 호출하면, 둘 중 하나가 실패해도 앞서 실행된 저장은 이미 커밋돼버릴 수 있다. 서비스 계층을 분리하고 @Transactional을 붙여야 "회원 저장 + 포인트 적립"이 하나의 단위로 묶여서 하나라도 실패하면 전부 롤백된다.말로만 하면 감이 잘 안 와서 일부러 실수 하나를 코드에 심어놓고 @Transactional 없이 실행해서 정말로 회원은 저장되고 포인트만 실패하는..

2026.07.07 · 댓글

Spring Data JPA findBy 쿼리 메서드로 조건 검색 만들기 — 메서드 이름만으로 SQL이 만들어지는 원리

JDK 21 LTS Spring Boot 3.3.4 MariaDB 10.11 MariaDB Connector/J 3.4.1 메서드 이름을 findByNameContaining처럼 정해진 규칙대로 지으면 Spring Data JPA가 SQL을 직접 만들어준다. 정확 일치·부분 일치·범위·정렬·조합·개수·존재 확인까지 6명의 실제 데이터로 검증했다. MariaDB의 LIKE는 기본적으로 대소문자를 구분하지 않는다는 것도 직접 확인했다.들어가며지난 글에서 JpaRepository를 상속하는 것만으로 저장·조회·수정·삭제가 전부 됐다. 그런데 "이름에 '길'이 들어간 회원만 찾고 싶다"거나 "나이가 25살 이상인 회원만 뽑고 싶다" 같은 조건은 JpaRepository가 기본으로 주는 메서드에 없다. f..

2026.07.06 · 댓글