@Transactional 은 스프링 프레임워크에서 데이터베이스와의 트랜잭션 관리를 쉽게 하기 위해 제공하는 어노테이션이다. 트랜잭션은 데이터베이스 작업의 논리적인 단위를 의미하며, 원자성을 보장한다.
원자성?:
모든 작업이 성공하거나, 실패 시 모든 변경이 롤백되는 성질
@Transactional 을 사용의 장점
원자성 보장 :
트랜잭션 내의 모든 작업이 성공해야만 데이터베이스에 반영되며, 하나라도 실패하면 모두 롤백된다.
자동 커밋/롤백 :
메소드가 정상적으로 끝나면 자동으로 커밋, 예외가 발생하면 자동으로 롤백한다.
트랜잭션 관리 간소화 :
코드 내에서 명시적으로 커밋, 롤백을 구현하지 않아도 되어 관리가 간편해진다.
예시 코드
UserService.java
@Service
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
private final ProfileRepository profielRepository;
@Transactional
public User registerUser(UserRegisterRequest request) {
if(userRepository.existsByEmailAndStatus(request.getEmail(), "ACTIVE")) {
throw new IllegalArgumentException("이미 사용 중인 이메일입니다.");
}
if (!request.getPassword().equals(request.getConfirmPassword())) {
throw new IllegalArgumentException("비밀번호가 일치하지 않습니다");
}
User user = new User();
user.setEmail(request.getEmail());
user.setPassword(request.getPassword());
user.setUsername(request.getUsername());
User savedUser = userRepository.save(user);
profileService.createProfile(savedUser);
return savedUser;
}
}
ProfileService.java
@Service
@RequiredArgsConstructor
pubic class ProfileService {
private final ProfileRepository profileRepository;
@Transactional
public void createProfile(User user) {
profile profile = Profile.builder()
.user(user)
.bio("자기소개를 입력해주세요.")
.profileImage("/images/basic-profile.png")
.follower(0L)
.following(0L)
.build();
profileRepository.save(profile);
}
}
@Transactional :
위 코드에서 회원가입과 프로필 생성이 동일한 트랜잭션 내에서 처리되므로 원자성을 보장해야 한다. 회원가입 도중에 예외가 발생할 경우, 프로필 생성 작업 역시 롤백되어야 데이터의 무결성을 지킬 수 있게된다.
예를 들어, 사용자가 회원가입을 하다가 예외가 발생하면, 이미 저장된 사용자 정보와 프로필을 자동으로 롤백하게 되는 것이다.
원자성 보장 :
회원가입 과정에서 프로필 생성에 실패하면, 사용자 정보도 저장되지 않도록 전체 작업을 취소할 수 있다.
자동 커밋 및 롤백 :
모든 작업이 정상적으로 수행되었을 경우, 자동으로 데이터베이스에 커밋하고 예외가 발생할 경우 데이터베이스 변경을 자동으로 롤백한다.
@Transactional 옵션
propagation :
트랜잭션의 전파 수준을 지정한다. REQUIRED 는 기존 트랜잭션을 사용할 수 있으면 사용하고 없으면 새로 생성한다.
readOny :
true 로 설정하면 읽기 전용 트랜잭션을 만든다. 이렇게 하면 성능 최적화가 가능하고, 쓰기 작업 시 예외가 발생한다.
rollbackFor :
특정 예외가 발생했을 떄 롤백하도록 설정할 수 있다.