@Column(updatable = false)와 @Immutable

Sechan Beak·2023년 10월 1일
0

읽기 전용 엔티티

다른 도메인의 엔티티를 가져와 사용하는 것이 비효율적이고 보안적으로도 문제가 있는 경우가 있다.
예를 들어 사용자의 기본정보 엔티티인 Account에는 비밀번호, spring security 스펙인 role, OAuth2 사용자인 경우 provider 정보등이 함께 있다. 그러나 article 도메인에서 참조해야하는 사용자 엔티티에는 이러한 필드들이 거의 참조되지 않을 것이다.

때문에 article엔티티가 모든 사용자의 정보를 들고다니는 것은 오버헤드가 클뿐만 아니라 보안적으로도 비밀번호등의 유출가능성을 높일 수 있다.

때문에 같은 테이블을 참조하면서, 필요한 필드들만을 가지고있는 엔티티를 정의해서 사용하는 것이 좋은 방법이 될 수 있다.

엔티티 동기화

문제가 되는 것은 동기화이다. 하나의 테이블과 매핑되는 엔티티가 2개가 된다는 것은, 데이터 입출력의 창구가 하나 더 생긴다는 의미이다. 이렇게 되면 데이터가 어디서 입력되고 변경되는지 추적하기가 매우 어려워질 수 있고, 여러 엔티티에서 하나의 자원에 접근하기 때문에, 테이블에 락을 걸어야 할 수도 있고, 트랜젝션 설계가 매우 복잡해질수있다. 이를 위해서 루트 어그리게이트는 그대로 놔두고 해당 엔티티를 참조하는 엔티티는 읽기전용으로 만드는 방법을 고려해 볼 수 있다.

읽기 전용 엔티티 구현

2가지 구현 방법이 있겠다.
1. 모든 필드에 @Column(updatable = false, insertable = false) 달기
2. 엔티티 클래스에 @Immutable 달기

1. @Column(updatable = false, insertable = false)

변경감지를 통해 해당 필드에 대한 updata 쿼리와 insert쿼리가 생성되는 것을 막는다. 변경 감지를 통해서 해당 필드가 변경된 것을 ORM이 파악해도 쿼리를 날리지 않는다는 것이다.

2. import org.hibernate.annotations:@Immutable

보다보면 해당 어노테이션이 2개 있다.
org.springframework.data.annotation.Immutable 이것도 있긴한데, ORM에게 직접적으로 제약을 거는 것은 없고 단순히 주석기능이다. 다른 개발자들이 immutable 엔티티라는 것을 알리는 기능을 수행한다. (그냥 껍데기라는 뜻)

반면, org.hibernate.annotations 패키지의 @Immutable은 실제로 ORM에게 해당 엔티티의 변경감지 수행을 하지 않을 것을 지시하는 역할을 한다.
위의 @Column(~) 설정과 다른점은 @Column 설정은 변경 감지는 허용하지만 설정한 필드에 대한 updata, insert 쿼리가 발생하지 않도록 한다. 그러나 @Immutable은 에초에 hibernate에게 엔티티를 대상으로한 변경감지가 작동하지 않도록한다.

강제로 쿼리 전달

근데 둘 다 강제로 SQL, JPQL등을 작성하여 전달하면 변경된다.

결론: 읽기 전용이면 @Immutable 쓰고, 만약 어떤 필드'만' 읽기 전용으로 해야한다면 @Column(~) 쓰면 되겠다

profile
거사 하나 치르면 올림

0개의 댓글