티스토리 뷰

Backend/Spring

#27 영속성 컨텍스트

RadderNepa 2023. 9. 28. 20:19

- Service 계층의 주요 역할 중 하나가 트랜잭션을 관리하는 것이다.

@Transactional
- Spring에서 트랜잭션을 적용하는 방법
- 메소드에 @Transactional Annotation이 붙으면 메소드가 시작될 때 트랜잭션을 시작(start transaction)해주고 메소드가 종료되면 Exception 발생 여부에 따라 commit 혹은 rollback을 적용한다.

org.springframework.transaction.annotation.Transactional를 import 해야한다.
메소드에 @Transactional annotation을 붙여주면 된다.

cf1)

- SELECT 쿼리만 사용한다면 readOnly 옵션을 쓸 수 있다.

- readOnly 옵션이 붙으면 저장, 수정, 삭제와 같은 데이터 변경을 일으키는 기능을 수행하지 않는다.(약간의 성능 향상과 혹시 모를 데이터 변경 방지)

 

cf2)

- IOException과 같은 Checked Exception은 rollback이 일어나지 않는다.

- IllegalArgumentException은 unchecked Exception이다.


● 영속성 컨텍스트

- Table과 매핑된 Entity 객체를 관리&보관하는 역할

- 관리&보관? 이게 뭔 말이냐?? 뭔 말인지 아직 모르겠으니 우선 아래의 문장부터 알아두자

- Spring에서는 트랜잭션을 사용(트랜잭션이 시작)하면 영속성 컨텍스트가 생겨나고 트랜잭션이 종료되면 영속성 컨텍스트가 종료된다.

인프런 - 자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지!(최태현)


[영속성 컨텍스트의 기능 3가지]

1. 변경 감지(Dirty Check)
영속성 컨텍스트 안으로 불러와진 Entity는 명시적으로 save 하지 않더라도 변경을 감지해 자동으로 저장된다.
- 여기서 Entity는 Table과 매핑된 객체이다.  /  save는 userRepository.save(user)를 의미한다.

인프런 - 자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지!(최태현)

 

- 즉, 위 사진 왼쪽 코드의 userRepository.save(user) 부분 없이 오른쪽 사진처럼만 코드를 구성해도 DB에 아서 update되는 것이다.

- 이것이 가능한 이유는 영속성 컨텍스트가 트랜잭션이 시작하면서 생겨나고 트랜잭션이 종료되면서 영속성 컨텍스트도 종료되었기 때문이다.(update 자체가 영속성 컨텍스트 범위 안에서 일어났다.)

- 그리고 이러한  영속성 컨텍스트가 가능한 이유는 @Transactional annotation이 붙었기 때문이다.

 

2. 쓰기 지연

- DB 한테 INSERT, UPDATE, DELETE SQL을 바로 날리는 것이 아니라 트랜잭션이 commit 될 때 모아서 한 번만 날린다.

인프런 - 자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지!(최태현)

- 위와 같은 코드가 있다고 했을 때 @Transactional annotation이 없으면 A, B, C를 각각 저장할 때마다 Spring과 DB가 통신을 하므로 총 3번의 통신이 발생한다.

- 만약 @Transactional annotation 붙어 영속성 컨텍스트가 생성된다면 아래 사진과 같이 영속성 컨텍스트가 각각의 작업을 기억해놨다가 DB에 한 번에 저장한다. 즉, 3번의 통신 횟수가 1번으로 줄어든다.(시간 절약 가능)

인프런 - 자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지!(최태현)

 

3. 1차 캐싱

- ID를 기준으로 Entity를 기억한다.

인프런 - 자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지!(최태현)

- (id = 1)인 유저를 3개 가져오는 상황이다.

- 만약 영속성 컨텍스트가 없다면 DB에는 (SELECT * FROM USER WHERE ID = 1) 쿼리가 총 3번 날라갈 것이다.

- 하지만 영속성 컨텍스트의 1차 캐싱 기능으로 인해 아래와 같은 일이 발생한다.

 

1. 맨 처음에는 DB에 (SELECT * FROM USER WHERE ID = 1) 쿼리를 날려 해당 user의 정보를 가져온 후 영속성 컨텍스트가 그것을 기억한다.

2. 다시 한 번 (id = 1)인 유저를 가져올 때 이번엔 DB와 통신을 하는 것이 아니라 영속성 컨텍스트가 기억하고 있는 (id = 1)인 유저의 정보를 넘겨준다.(마지막 3번째 줄도 마찬가지)

인프런 - 자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지!(최태현)

- 이렇게 캐싱된 객체는 완전이 동일하다.

- 캐싱 기능으로 인해 DB와 계속해서 통신을 할 필요가 없으므로 시간&자원을 절약할 수 있다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함