25/05/01
내용
영속성
영속성 -> 프로그램이 종료된 이후에도 데이터가 사라지지 않고 저장되는 성질
- 즉 메모리(휘발성 공간)가 아닌 디스크(비휘발성 저장소)에 데이터를 영구히 보존하겠다라는 강력한 의지를 나타내기 위한 것
영속성은 JPA의 개념이 아니다.
JPA로 이해하시는 분들이 계시다. Java 프로그래밍에서 생긴 개념이 아님
데이터베이스의 개념 데이터베이스 전반에 데이터를 저장한다면 데이터는 프로그램이 종료되더라도 저장 데이터베이스에 저장되어 영속한다 라고 함
JPA에서의 영속은 자바 객체나 컬렉션에만 데이터를 담는경우 프로그램이 종료되면 사라짐.
용어는 같지만 의미가 다름
JPA에서 '영속성'이란?
한명의 유치원 선생님이 여러 유치원생을 관리하려면 유치원이라는 환경이 필요하듯 여러 객체를 관리하기 위한 환경
JPA에서의 영속은 영속성 컨텍스트에 객체를 등록된 상태를 뜻함
영속
- 영속성 컨텍스트에 등록된 상태
- find(),save()시
비영속
- 영속성 컨텍스트에 등록 되지 않은 상태
준영속
- 영속성 컨텍스트에 저장되었다가 분리된 상태
- 준영속 상태의 엔티티는 영속성 컨텍스트가 제공하는 기능을 사용 할 수 없음
- clear(), refresh()시
삭제
- 영속성 컨텍스트에서 제외되며 SQL 저장소에 delete문을 저장
- delete() 시
반영
- 현재 영속성 컨텍스트에 상태를 확인하여 SQL 생성 후 데이터베이스에 query를 전송
- 단, commit 전이기 때문에 데이터베이스에 실제로 저장되지 않은 상태
- flush()시
그럼 영속성 컨텍스트에서 객체는 누가 관리 할까?
- 유치원생인 객체를 관리하는 선생님이 바로
EntityManager 에요.
- 선생님을 배출하는 곳은
EntityManagerFactory 이며 선생님을 배출하는 시점은 transaction이 시작
- 생성된
EntityManager 는 스프링은 내부적으로 발행된 TransactionThread에 바인딩되기 때문에 해당 트랜잭션 동안 동일한 EntityManager 인스턴스를 재사용 가능
영속성 컨텍스트의 특징
1차 캐시&동등성 보장
- 영속성 컨텍스트 내부에는 캐시라는 이름의 Map<@Id, Entity>형태의 자료구조가 존재
- 이 캐시는 동일 트랜잭션 내에서만 유효한 로컬 캐시
- 같은 엔티티를 반복 조회할 때 DB 접근 횟수를 줄여줌
- 1차 캐시를 사용한다는것 = 동등성을 보장 받을 수 있다.
- 실무 고려사항 : 대량의 데이터를 처리하는 배치 작업에서는 주기적으로 영속성 컨텍스트를 초기화 clear()해주는것이 좋음 -> 너무많은 것을 찾으면 메모리 사용량이 너무많다. but clear()를 해준다고해서 stack memory에서 없어지는 것은 아니여서 OutOfMemory를 조심
쓰기 지연 (일괄로 전송한다)
- JPA는 SQL을 즉시 실행하지않고 영속성 컨텍스트 내의 쓰기 지연 SQL 저장소에 모아둠
- 그러다 transaction.commit()시점에 모아둔 SQL을 한 번에 DB에 전송 (일괄 처리)
- 상세 작동 과정
- em.persist(entity) 호출 : 엔티티를 1차 캐시에 저장 + INSERT SQL 생성 후 쓰기 지연 SQL 저장소에 보관
- transaction.commit() 호출 :
배치관점 : JDBC 배치 기능과 결합하면 성능이 크게 향상
commit 전 flush()를 통해 DB에 반영되는 경우
- repository.flush() 직접 호출 시
- JPQL 쿼리 실행 전 (자동)
- 식별자 생성 전략이 GenerationType.IDENTITY인 경우 save() 호출 시 즉시 INSERT SQL 실행
변경 감지 (Dirty Checking)
- 트랜잭션 내에서 엔티티 값이 변경되면, 커밋 시점에 자동으로 UPDATE SQL이 생성
- 별도의 update() 메소드 호출이 필요 없는 것이 JPA의 큰 특징
변경 감지 동작 원리 :
- 트랜잭션 시작 시 엔티티의 최초 상태 스냅샷을 저장
- 플러시 시점에 현재 엔티티와 스냅샷을 비교하여 변경된 엔티티 감지
- 변경된 엔티티가 있으면 UPDATE SQL 생성 후 DB에 전송
변경 감지 최적화 관점 :
- JPA는 기본적으로 엔티티의 모든 필드를 업데이트하는 SQL을 생성
- 필드가 많은 엔티티의 경우 변경 필드만 업데이트하도록 설정 가능
영속성 컨텍스트의 범위와 OSIV 패턴 ?
- OSIV는 영속성 컨텍스트를 Controller, filter, View 등이 끝날 때까지 개방된 상태로 유지하는 방식
- 사실 스프링에서는 @Transactional을 붙여주지 않아도 지연로딩을 사용할 수 있는데 OSIV 기능이 기본적으로 활성화 되어있기 때문
OSIV 동작 순서
- 요청이 들어옴과 동시에 그때부터 영속성 콘텍스트를 만들어주고 그만큼 요청의 길이가 길어짐 따라서 커넥션의 길이가 길어지고 서버에서 제공해주는 커넥션은 한계가 있어 기본적으로 false로 해두는 것이 좋다
- 클라이언트의 요청이 들어오면 영속성 컨텍스트 생성
- 트랜잭션의 범위에 진입할때 미리 생성해둔 영속성 컨텍스트를 찾아와 트랜잭션을 시작
- 트랜잭션이 종료되면 커밋을 하고 영속성 컨텍스트를 Flush함. 영속성 컨텍스트는 유지
- 영속성 컨텍스트가 유지되므로 Entity는 영속상태로 관리
- 요청이 종료될때, Flush(DB와 동기화)를 호출 하지 않고 종료
Transaction은 도대체 무엇일까?
Transaction도 데이터베이스에서 나온 개념
데이터가 영구적으로 저장되려면, 그 과정이 정확하고 안정적이여야하는데, 그것을 보장해주기 위한 기술
Transaction은 모든 작업의 성공 시에만 commit, 하나라도 실패하면 rollback하여 일관성을 유지
기술면접 단골 질문 트랜잭션의 핵심 4대 속성 (ACID)
- Atomicity (원자성) - 전부 성공 or 전부 실패
- Consistency (일관성) - 트랜잭션 전/후의 데이터 일관성 유지
- Isolation (격리성) - 동시에 실행되는 트랜잭션 간 간섭 방지
- Durability (지속성) - 트랜잭션이 완료된 내용은 반드시 저장
로그인을 위해서 Session을 활용했듯이 데이터베이스 서버에도 session이 존재
transaction 동작 순서
- 웹 서버는 데이터베이스 서버 연경을 요청 후 연결
- 데이터베이스 서버는 세션을 만들어 전달
- 웹서버는 커넥션을 통해 SQL을 전달하면 세션 SQL을 실행
- 세션은 데이터베이스 서버 내에서 트랜잭션을 시작하고 커밋, 롤백으로 트랜잭션을 종료
- 이때 한 세션은 여러 트랜잭션을 가질 수 있으며 트랜잭션은 세션 안에서 수행
- 사용자가 커넥션을 닫거나 DB 관리자가 세션을 종료하면 세션이 종료 후 커넥션 해제
Spring에서 어떻게 transaction을 관리하는가?
스프링에서는 트랜잭션과 영속성 컨텍스트의 생명주기가 동일하게 관리,
Spring 에서 transaction 이 없다면?
변경된 자바 객체는 영속성 컨텍스트 메모리에만 존재 (비영속 상태로 끝날 수 있음)
여러 쿼리가 실행 중 하나 실패라도 실패했을 때 데이터 불일치 발생
Spring 에서 transaction 을 어떻게 지정?
TransactionManager가 실제로 트랜잭션의 시작, 커밋, 롤백을 처리하는 반면, @Transactional은 개발자가 간편하게 트랜잭션 범위를 정의 가능
@Transactional이 선언된 메서드가 호출될 때 자동으로 트랜잭션 관련 작업 수행하게 AOP가 동작하도록 구현
실무 주의 사항 :
- 트랜잭션은 가능한 짧게 유지하는 것이 좋음, 트랜잭션 범위가 넓으면 DB 락(lock)으로 인해 동시성 문제, 무한 대기와 같은 이슈가 발생
transaction에 어떤 특징 ?
transaction의 주요 특징은 기술면접에서 중요! 실무에서도 중요!
transaction 주요 특징은 전파, 격리, 락 등이있음..
그중 옵션으로 선별하여 구현 가능
propagation (전파 속성)
- 기본값은 Propagation.REQUIRED 으로 해당 값은 상위 transaction이 transaction을 포함하여 하나의 트랜잭션으로 간주
isolation (격리 수준)
- 격리 수준은 동시에 여러 트랜잭션이 실행 될 때 트랜잭션 간의 간섭 정도를 조절하는 설정
- 기본 값은 REPEATABLE_READ
rollbackFor/noRollbackFor
- 특정 예외에 대해 롤백 여부를 지정
- 업무 흐름상 예외가 발생해도 그대로 처리되어야 하는가 ?
noRollbackFor
- 예외 발생 시 재시도하거나 되돌려야 하는가 ?
rollbackFor
timeout
너무 디테일한 정리입니다