-
Notifications
You must be signed in to change notification settings - Fork 0
N 1문제 해결(One To One 관계)
JPA를 사용하던중 OneToOne관계를 설정할 일이 있엇는데 OneToOne관계에서 주인이 아닌 엔티티에 지연로딩을 설정했으나
즉시로딩으로 조회해서 필요없는 쿼리가 발생됨을 확인하고 그것을 해결하는 것을 기록했습니다.
현 프로젝트는 JWT 토큰을 사용해서 토큰 기반 인증으로 동작되게 설계하고
보안등을 위해 RefreshToken이 필요하므로 RefreshToken
엔티티를 User
엔티티와 OneToOne(일대일)양방향 연관관계를
설정했습니다.
그리고 연관관계 주인을 RefreshToken
으로 지정해둬서 User
테이블의 복잡도를 줄일려고 하였으나.
여기서 예상하지못한 문제점이 발생했습니다.
User
엔티티에서 RefreshToken
엔티티를 지연로딩 설정을 했으나 User
엔티티를 조회가 필요할떄
계속 RefreshToken
이 즉시로딩되는 문제점이였습니다.
이렇게 문제가 생길시 User
엔티티를 조회하는 경우가 많이있는데 User
엔티티를 조회할때마다 무조건
RefreshToken
을 즉시로딩해서 불필요한 쿼리가 나가게 되었습니다.
이 문제점을 확인해본 결과 OneToOne N+1문제 인걸 확인했습니다.
OneToOne N+1문제란 연관관계의 주인이 아닌 User
테이블에서 RefreshToken
필드를 DB에 가지고 있지 않으므로
무조건 RefreshToken
필드를 조회해서 NULL인지 또는 값이 있는지 확인해야 하므로 지연로딩의 의미가 사라지고
즉시로딩으로 조회된다는 점 이였습니다.
해결방법으로는
1,양방향 관계를 제거한다. 2, OneToOne 관계를 다른 ManyToOne 등으로 변환한다.
이렇게 두가지 해결방법을 가지고 고민하였습니다.
하지만 하나의 User
테이블 레코드에 하나의 RefreshToken
테이블 레코드가 맵핑되어야 한다는점.
그리고 User
엔티티 에서 RefreshToken
을 직접적으로 조작하지 않는다는점에서
1,양방향 관계를 제거한다. 이 방법으로 해결을 하였습니다.
그래서 User
엔티티 에서 RefreshToken
엔티티의 연관관계를 제거하고
RefreshToken
엔티티에서만 단방향으로 User
엔티티와 OneToOne 단방향 연관관계를 설정했습니다.
그리고 테스트결과
이렇게 OneToOne N+1문제를 해결 할수있엇습니다.
JPA를 사용할때 연관관계 설정이 필요하면 양방향으로 설정을 하는것을 선호하였으나,
양방향 연관관계에서 생길수있는 문제점들이 많다는점을 알게되었습니다.
특히 이번에 문제생긴 OneToOne N+1문제 뿐만아니라
다른 N+1 문제, 순환참조 예외, 유지보수의 어려움등
이번에 배운점을 기반으로 양방향관계를 설정할떄 꼭 필요한경우에서만 사용하고
연관관계 설정에서 많은 고민을하고 설계를 하는게 중요하다는 것 을 알게되었습니다.