간혹 Entity와 Repository를 구현한 코드를 찾아보면,
Member member = new Member();
member.setId("member1");
member.setUsername("회원1");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(member);
위와 같이 EntitiyManager 객체를 사용하여 데이터를 저장하는 코드를 발견할 수 있다.
도데체 여기서 EntitiyManager가 뭘까? 라는 생각이 들었다.
일단 EntitiyManager가 무슨 역할을 하는지 알기 전에, 왜 jpa가 제공하는 repository를 사용하지 않고 위와 같은 코드를 썼는지 부터 알아야 한다.
Entity에 있는 데이터를 조회하거나 저장과 변경 그리고 삭제를 할때 Spring JPA 에서 제공하는 Repository라는 인터페이스를 정의해 해당 Entity의 데이터를 사용할 수 있다. Repository는 내부적으로 EntityManager가 직접 대상 Entity의 데이터를 관리하고 있기 때문에 Repository 인터페이스를 정의하지 않고도 직접 EntityManager를 사용해 Persistance Layer 를 구현 할 수도 있다. 하지만, Spring JPA 에서 Repository 의 내부 구현체를 자동으로 생성시켜 주기 때문에 별도의 구현체를 따로 생성하지 않아도 된다.
쉽게 말해, 이미 repository에서 Entitymanager을 사용하는 코드를 구현해 두었기 때문에, 우리는 이걸 가져다 쓰기만 하면 된다는 것이다. 그리고, repository를 사용하지 않고도, 직접 EntityManger을 사용하여 객체에 영속성을 부여하고, 데이터 처리를 할 수도 있다.
그렇다면 EntityManager가 하는 일은 무엇일까?
JPA에서 엔티티 매니저(Entity Manager)는 엔티티를 저장하고, 수정하고, 삭제하고 조회하는 등 엔티티와 관련된 모든 일을 처리한다. 또한 영속성 컨텍스트를 통해 데이터의 상태 변화를 감지하고 필요한 쿼리를 자동으로 수행한다.
Spring Data JPA에서는 EntityManager를 자동으로 Bean이 등록되기때문에 직접 사용하지는 않는다
여기서 영속성 이라는 말이 뭔가 싶다.
영속성이라는 것은, 영구적으로 저장한다는 뜻이고,
영속성 컨텍스트는, 객체를 영구 저장하는 장소? 라고 보면 된다.
영속성 컨텍스트는 DB와 다르다.
이곳에 먼저 객체를 영구 저장하고, 트랜잭션의 커밋 시점에 영속성 컨텍스트에 있는 정보들이 DB에 쿼리로 날라간다
여기서 또 트랜잭션이란 무엇인지 알아야 한다.
트랜잭션이란, 데이터베이스의 상태를 변화시키기 해서 수행하는 작업의 단위를 뜻한다.
커밋은 관계형 데이터베이스 관리 시스템(RDBMS)에서 트랜잭션을 종료하고 다른 사용자에게 변경된 모든 사항을 보이도록 만드는 것이다.
이렇게 바로 객체의 데이터 변경을 하지 않고 영속성 콘텍스트를 이용하는 이유는 무엇일까?
영속성 콘텍스트의 장점
위와 같은 장점이 있다. 아직 내가 이해하기는 힘든 내용들이 많았다.
내가 이해한 대로 설명하면,
일단 영속성 콘텍스트가 캐시의 역할을 하기 때문에, 데이터 조회시 성능상 이점이 있다.
그리고, 모든 데이터 변경을 이곳에 모아두고, 트랜잭션이 끝난 후에 실제 DB에 쿼리문을 날리기 때문에, 트랜잭션 수행중 문제 발생 시에 처리가 더 쉬워진다.
그리고 이와 관련한 어노테이션 하나가 있다.
@Transactional
전에 했던 프로젝트에서, 서비스에 무슨 역할인지도 모르고 이 어노테이션을 사용했던 것이 기억이 났다. 그 당시에는 했던 생각은 "이거 넣으면 문제 발생하면 롤백이 된대" 하면서 넣었던 것 같다.
하지만 포스팅을 하면서 @Transactional 어노테이션이 이와 관련이 있을 것 같다는 생각이 들었다.
쇼핑앱의 결제 기능으로 예시를 들겠다.
이와 같은 문제가 발생한다면 정말 큰일이다.
@Transactional 어노테이션은 이를 방지해줄 수 있다.
서비스 클래스에서 @Transactional을 사용할 경우, 해당 코드 내의 메서드를 호출할 때 영속성 컨텍스트가 생긴다.
또한 아래와 같은 속성을 가진다.
위의 속성이 보장되기 때문에, 해당 메서드를 실행하는 도중 메서드 값을 수정/삭제하려는 시도가 들어와도 값의 신뢰성이 보장된다. 또한, 연산 도중 오류가 발생해도 rollback해서 DB에 해당 결과가 반영되지 않도록 할 수 있다. 참 편리한 어노테이션이다.
그냥 지나쳤던 EntityManager이었는데, 이와 같이 매우 중요한 내용들을 담고 있었다. 사소한 것도 그냥 지나치지 말자.