본문 바로가기

TIL(Today I Learned)

TIL-230829(항해99 실전 프로젝트-행동대장(19))

📝오늘 공부한 것

  • 실전프로젝트 - '행동대장' 트러블 슈팅
  • 실전 프로젝트 - '행동대장'  유저피드백 준비

 

📌 트러블 슈팅

⛔ 문제점 : Dirty Checking이 작동되지 않음

마이페이지에서 이메일, 닉네임, 비밀번호 update기능을 구현하였는데 DB에 반영되지 않는 문제가 발생하였다.

 

[updateNickname메서드]

닉네임 변경에 대한 코드를 작성하고 dirty checking을 기대하며 Transactional을 걸어주었다.

@Transactional을 걸어주면 JPA Entity를 업데이트할 때 Dirty Checking을 지원하여 트랜잭션 안에 save를 명시적으로 호출하지 않아도 commit시에 판단해서 update를 해준다.

 

[Postman]

[User table]

 

그런데 코드를 실행하였을 때, DB에 닉네임이 정상적으로 update되지 않았다.

update메서드에 @Transactional이 동작하지 않는 것이었다!!

 

 

💯 해결

JPA 쓰기지연 기능으로 인해 update 쿼리는 영속성 컨텍스트에 저장되어 있다가 트랜잭션 commit시 한 번에 DB로 요청을 보내게 된다. 따라서 JPA의 Dirty checking을 이용하려면 변경하는 Entity가 영속성 컨텍스트 안에 있어야 한다.

 

그러나, 나는 User를 @AuthenticationPrincipal UserDetailsImpl클래스에서 user정보를 가져와서 사용하였다.

이로 인해, User Entity는 트랜잭션 범위 내의 영속성 컨텍스트안에 존재하지 않는다는 것이었다.

 

스프링컨테이너 환경에서는 영속성 컨텍스트와 트랜잭션의 생명주기가 일치하며, 각 트랜잭션은 서로 다른 Entity Manager가 관리한다. 트랜잭션 종료 후에는 영속성 컨텍스트가 소멸하기 때문에 서로 간의 정보를 공유할 수 없다.

 

[updateNickname메서드]

 

⭐ 그래서!! save매서드를 사용하여 Entity를 영속성 컨텍스트에 저장하고 DB에 반영이 가능하도록 변경하였다.

이렇게 하면 'userRepository.save(user)' 메서드를 호출하여 Entity를 영속성 컨텍스트에 저장하고, 그 후 변경작업을 수행할 수 있다. 

 

save메서드에는 @Transactional이 적용되어 있으므로 트랜잭션 내에서 작업이 수행된다.

 

[SimpleJpaRepository의 save메서드]

롤백기능도 필요없기 때문에 @Transactional을 삭제하기로 하였다!!

 

[User table]

update메서드들에 save메서드를 추가해 주었더니 변경 성공!!