본문 바로가기

삽질

Spring Data Jpa, @Transactional이 붙지않은 메서드에서의 영속성 컨텍스트

나의 무지에서 오는 가벼운 의문이었다. @Transactional이 붙지 않은 메서드에서 영속성 컨텍스트는 어디까지 유지될까?

의문의 시작은 다음과 같다.

조회만 해오는 메서드에는 @Transactional을 붙이지 않았다. 붙일 이유가 없었기 때문이다. 그러다가 문득 조회만 해오는 메서드에서 생긴 영속성 컨텍스트가 어디까지 유지될 지 궁금해졌다.

메서드 끝까지? 컨트롤러 까지? 아무 생각 없이 실험해보기로 했다. 실험 환경은 아래와 같다.

@Entity
public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @ManyToOne(fetch = FetchType.LAZY)
    private Team team;
    ...
}
@Service
public class TempService {
    private final MemberRepository memberRepository;

    public TempService(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

    public Member findById(Long id) {
        Member member = memberRepository.findById(id)
            .orElseThrow(IllegalArgumentException::new);
        member.getTeam();
        return member;
    }
}

TempService의 findById 메서드를 호출해보면 member.getTeam()에서 바로 LazyInitalizationException이 터진다. 디비를 찌를 동안에만 트랜잭션이 열리고 영속성 컨텍스트가 열리는 것 같다.

@Transactional을 안붙이니 한 메서드 안에서도 LazyInitalizationException이 터지는게 신기했다.

영속성 컨텍스트가 트랜잭션 범위에 따라 열리고 닫히고 한다는 것을 알고는 있었지만 트랜잭션이 없을 땐 어떻게 되는지 궁금했는데 해결이 됐다.

영속성 컨텍스트는 왜 트랜잭션 범위에 따라 열리고 닫힐까?

자세히는 검색해봐도 잘 안나온다. 많은 이유가 있겠지만 추측해보면 1차 캐시나 쓰기 지연 SQL 저장소의 데이터 불일치 방지나 DB와의 싱크 때문에 그럴 수 밖에 없을 것 같다.

생각해보면 여러 요청이 들어왔을 때 트랜잭션 범위에 영속성 컨텍스트가 있지 않다면 thread-safe 하지 않은 static 변수를 사용할 때의 문제점과 비슷하게 영속성 컨텍스트의 기능을 할 수가 없는 것 같다.

JPA를 더 많이 사용해보고 열심히 공부해야겠다. 😅