URECA 과정을 진행하면서 해당강의를 중심으로 스터디를 진행하고 있다.
spring에 대해 1도 모르는 상태였기 때문에 개념정리를 목표로 시작했고, 현재 Spring과 JPA(1~7강)까지 정리한 상태이다.
복기를 위해 하나의 단원이 끝날 때마다 스터디 진행중에 논란?이 되었던 주제, 정확히 설명하지 못하는 주제에 대해 다시한번 정리하기로 했다.
JPA : Entity 생명주기 관리
영속성 컨텍스트를 통해 데이터 영구저장
: 데이터를 APP(어플리케이션)내에서 영구적으로(휘발X) 보관할 수 있는 상태들의 범위
영속성 컨텍스트(Persistence Context)는 단어 그대로 영구적인 맥락(범위) 이다.
Java에서는 데이터를 저장할 때 JVM에서 관리하는 Heap 이라는 메모리 공간을 이용한다.
heap은 자바 app가 실행될 때 운영체제로 부터 할당받고, 런타임동안 사용되며, app가 종료되면 GC(garbage collector)에 의해 제거된다.
즉, heap은 휘발성 메모리 공간이다.
하지만 데이터가 그렇게 쉽게 휘발되면 안되기 때문에 영속성 컨텍스트를 이용해서 영구적으로 데이터를 저장할 수 있는 DB와 연결할 수 있다.
영속성 컨텍스트를 통해 휘발성 공간인 heap 이외에 영구적 공간인 DB에 데이터를 저장할 수 있다.
Entity의 생명주기
: entity의 생성부터 삭제될 때까지의 모든 상태변화과정
entity를 생성해서 DB에 저장, 새로운 입력으로 인한 업데이트, 마지막 삭제가 될 때까지의 상태를 생명주기라고 한다.
생명주기에는 크게 4가지 상태가 있다.
1. 비영속 상태
: entity가 생성되었지만, 아직 EntityManager에 의해 관리되지 않는 상태.
약간 뜬금없이 EntityManager가 나왔는데 영속성 컨텍스트(범위)를 관리한다. 영속성 컨텍스트 자체는 무슨 특별한 기능을 하는 메소드나, 인터페이스나 이런게 아니다. 그냥 하나의 범위(데이터를 영구적으로 저장할 수 있는 범위)를 네이밍한 것일 뿐이다.
- 아직 EntityManager에 의해 관리되지 않는다. = 영속성 컨텍스트에 포함되지 않는다. = DB에 저장안된다.
User user = new User();
user.setName("Alice"); // 비영속 상태
2. 영속 상태
: entity가 EntityManager에 의해 관리되는 상태
- 영속성 컨텍스트 범위에 포함된다. = DB와 동기화된다(DB에 저장된다.) = 변경사항은 자동으로 DB에 반영된다.
EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
em.persist(user); // 영속 상태
em.getTransaction().commit();
3. 준영속 상태
: 영속성 컨텍스트에 의해 관리되지 않는 상태
- 영속성 컨텍스트 범위에 포함 안된다. = DB와 동기화 안된다. = 변경사항이 저장되지 않는다.
em.detach(user); // 준영속 상태
em.close(); // 영속성 컨텍스트가 닫힘
4. 삭제 상태
: entity가 영속성컨텍스트와 DB에서 삭제된 상태
- 저장된 entity 관련 데이터 모두 삭제
em.getTransaction().begin();
em.remove(user); // 삭제 상태
em.getTransaction().commit();
준영속상태?? 트랜잭션??
: 영속성컨텍스트에 의해 관리되다가 현재는 영속성컨텍스트에 의해 관리되지 않는 상태 = 트랜잭션 종료
위 그림이 준영속 상태와 트랜잭션의 범위를 가장 단순하게 보여주는 그림인 것 같다.
트랜잭션은 entity가 persist() 메소드로 영속상태가 되고
트랜잭션 commit()을 하고 나서부터 detach() 메소드로 준영속 상태가 될 때까지를 의미한다.
트랜잭션 = 영속성 컨텍스트 생존 범위
준영속 상태는 삭제상태와 영속상태와 전혀 다르다.
영속 상태 | 준영속 상태 | 삭제 상태 | |
Entity가 존재하는가? | O | O | X |
영속성 컨텍스트가 관리 하는가? DB에 새로운 내용이 동기화 되는가? |
O | X | X |
DB에 entity 데이터가 저장되어 있는가? | O | O | X |
heap에 데이터가 저장되어 있는가? | O | O / X | O / X |
1차캐시에 데이터가 저장되어 있는가? | O | X | X |
준영속 상태는 한마디로 EntityManager가 관리를 안하는 Entity상태, DB에 업데이트가 안되는 Entity 상태이다.
관리를 안해주고, DB 업데이트가 안되더라도 준영속 상태의 entity데이터는 DB에 존재한다. (삭제를 한건 아니기 때문)
또한, JVM이 관리하는 Heap 메모리에도 준영속 상태의 entity 데이터가 있을 수 있다.
- 왜 "있다." 가 아니라 "있을 수 있다" 인가요? : heap도 메모리 공간이다. 메모리공간이 부족해지면 GC에 의해 삭제될 수 있다.
하지만, 영속성 컨텍스트내에 존재하는 1차캐시 에는 준영속 상태의 entity 데이터가 존재하지 않는다.
먼저 1차 캐시란 EntityManager내에서 같은 entity를 여러번 조회할 경우 DB까지 검색하지 않도록 저장되는 메모리공간이다.
1차 캐시의 생존 범위는 트랜잭션 시작 후 종료까지며, 준영속 상태는 트랜잭션이 종료된 상태이므로 당연히 1차캐시에는 준영속 상태의 데이터가 남아있을 수 없다.
DB에 변경내용 동기화 하기
: flush() 사용
영속상태일 경우 entity관련 데이터는 DB에 동기화된다고 설명했다. 어떻게??
EntityManager내에서 영속성컨텍스트의 범위에 있는(영속상태인) entity는 변경사항이 파악될 경우 flush를 통해 DB에 데이터가 CRUD된다.
flush는
- 트랜잭션 커밋 시:
- 트랜잭션이 커밋되기 직전에 flush가 자동으로 호출
- 데이터베이스에 변경 내용을 반영한 후, 커밋 수행
- JPQL 쿼리 실행 시:
- JPQL 쿼리가 실행되기 전에 flush가 자동으로 호출되어 쿼리의 일관성 보장
- 이는 JPQL 쿼리가 데이터베이스 상태를 기반으로 수행되기 때문입니다.
- JPQL 쿼리가 실행되기 전에 flush가 자동으로 호출되어 쿼리의 일관성 보장
- 명시적인 flush 호출:
- 애플리케이션 코드에서 EntityManager의 flush() 메서드 호출
- 특정 시점에서 변경 내용을 데이터베이스에 반영해야 하는 경우 유용
- 애플리케이션 코드에서 EntityManager의 flush() 메서드 호출
보다시피 flush는 DB를 동기화하는 작업으로 쓸데없이 남발하다간 성능에 큰 영향이 끼칠 것 같다.(DB와의 통신빈도 ↑)
따라서 여러 데이터를 변경 후 한번의 flush 호출로 동기화하는 것이 효율적이다.
그래서, Entity의 생명주기는 어디서부터 어디까지?
Entity가 생성된 후부터 트랜잭션이 종료 + Entity가 삭제상태가 될 때까지
생명주기라는 말을 쉽게 생각하면 탄생부터 소멸까지를 일반적으로 의미한다.
entity도 마찬가지다.
entity가 생성되면 그때부터 생명주기는 시작되고, entity가 소멸되기 위해서는 트랜잭션이 종료되고, 삭제까지 되어야한다.
'하고싶은거 > Springboot' 카테고리의 다른 글
API_정의, 명세 (0) | 2024.08.04 |
---|---|
SpringBoot 동작 원리 (0) | 2024.07.22 |
JPA 상속 (0) | 2024.06.28 |
JPA vs Spring data JPA (0) | 2024.06.28 |
#개발 #게임 #일상
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!