본문 바로가기

Server Programming/Spring Boot Full-Stack Programming

[스프링 풀스택 클론 코딩] Open EntityManager (또는 Session) In View 필터

반응형

JPA EntityManager (영속성 컨텍스트)

: 뷰를 랜더링 할 때까지 영속성 컨텍스트를 유지하기 때문에, 

 

회원가입을 하고, 메일 인증까지 완료했음에도, 프로필에서 가입 완료라고 인지를 못하는 버그

 

컨트롤러에서 데이터를 변경했지만, DB에 반영이 되지 않은 상태

-> 트랜재션 범위 밖이기 때문에

 

-> 리파지토리를 직접 사용했기 때문에, 서비스 계층에서 인지를 하지 못한다.

따라서 DB에 반영이 되지 않는다.

 

리파지토리를 직접 사용하는 게 아니라, 서비스 계층의 트랜잭션안에서 처리하도록 수정한다.

->따라서 데이터 조회를 리파지토리 혹은 서비스를 사용하도록 변경


인증메일 처리

AccountController의 checkEmailToken 메서드

: Validation이후 -> account 클래스의 completeSignUp메서드로 처리

 

Account의 completeSignUp 메서드

: emailVerified에 true를 넣고, joinedAt에 LocalDateTime.now()를 넣는다. 

 

-> 객체의 데이터는 변경되었지만, 실제로 읽어올 때 읽어오지 못한 이유

 

 

DB에 적용이 되지 않았기 때문에.

-> 객체의 변경사항이 DB에 반영이 되지 않는데, Open EntityManager In View 필터 때문에

 

영속성 컨텍스트

:  객체들을 관리하는 컨텍스트

-> 객체들의 변경사항을 트랜잭션이 끝나면 DB에 적용하는 역할

따라서, 트랜잭션 안에서 일어난 변경사항을 DB에 반영하는데, 해당 로직에서는 트랜잭션이 존재하지 않는다.

 

왜?

서비스가 아닌 컨트롤러에서 동작하기 때문에,

서비스는 이전의 토큰 오류때문에 트랜잭션 내에서 동작하도록 변경했지만, 컨트롤러는 그렇지 않다.

[해당 이메일에 대한 토큰값과 해당 이메일 정상 여부 확인하기 위해서 @Transactional이용]

 

결론적으로, 데이터의 변경을 위해 DB에 반영하기 위해서는 트랜잭션 내에서 관리하도록 한다.

-> 구조적 완성도를 위해 서비스에 트랜잭션을 위임해서 관리

 

 

 

 

즉, 이전에 트랜잭션으로 묶지 않았을 때 DB에 반영이 안되는 이유는

 

영속성 컨텍스트 상태에서는, 영속성 컨텍스트가 끝나야 반영이 되는데,

 

해당 영속성 컨텍스트는 뷰 렌더링이 끝나야 반영이 되기 때문에,

뷰를 렌더링 할때에도 영속성 컨텍스트를 통해서 조회가 가능해서,

DB에 반영이 되기전에 퍼시스턴트 상태의 객체를 조회했으므로,

변경되기 전의 객체를 리턴해서 발생한 버그이다.

 

 


Open EntityManager를 사용하는 이유는

뷰에 렌더링을 할 때에 뷰에 모든 데이터를 읽어서 모델에 담는 것이 아니라, 

뷰에 도메인 기반으로 필요한 객체들을 로딩을 가능하게 해주기 때문이다. [도메인 주도 개발 DDD]

 

-> 뷰를 랜더링 할때까지 영속성 컨텍스트를 유지하므로, 필요한 데이터를 랜더링하는 시점에 지연로딩을 통해 추가로 읽어온다.

 

-> 때문에, 엔티티의 객체 변경이 트랜잭션 안에서 발생해야, 필요한 시점에 DB에 반영될 수 있다.

 

[스프링 부트는 기본적으로 오픈 엔터티매니저가 활성화 되어있어서, 모든 읽어온 데이터는 퍼시스턴트 상태이다.

또한 모든 리파지토리는 트랜잭션이 적용되어 있으므로, 리파지토리 또는 서비스를 통해서 읽어오면 된다.]


 결론 : 데이터 변경은 서비스 계층에서 트랜잭션안에서 처리 / 데이터 조회는 리파지토리 또는 서비스를 사용

반응형