User가 있고 Profile이 있다고 해보자.
이때 User가 주 테이블이고 Profile이 대상 테이블이다.
일대일 관계에서는 주 테이블과 대상 테이블 모두가 외래키를 가질 수 있다.
두 가지 상황을 비교해보자.
profile에 외래키를 넣는다고 해보자. 한명의 회원이 프로필을 여러개 쓰는 걸로 요구사항이 바뀐다면? profile에 외래키가 있다면 변경할 때 테이블 구조에 변경이 크게 일어나지 않는다.
user에 외래키를 넣는다고 해보자. user가 profile을 가지고 있는지 여부에 대해서 null 체크만 하면 된다.
이 상황을 생각해보면 우리의 경우는 User에 외래키를 넣는 게 맞는 것으로 보인다.
프로필은 모든 유저가 반드시 가져야 하는데, 만약 프로필 설정을 안한 유저가 있으면 프로필 설정을 하게끔 해야 한다. User에 Profile이 있으면 이 작업을 쉽게 할 수 있다.
참고:onetoone에서 lazy관련해서 질문드립니다~!
테이블 구조가 member와 phone이 일대일 관계로 있다고 해보자.
phone에 외래키가 있고, member는 없다.
jpa 입장에서는 일대일 관계에서 프록시 객체를 생성할 수 없어서 lazy 로딩이 안된다고 한다.
1. 외래키가 Phone에 있을 때
외래키가 Phone에 있다면, Member 엔티티를 가져올 때 Member 클래스에 정의된 Locker가 존재하는지 확인해야 한다.
이때 Member 테이블에는 외래키가 존재하지 않기 때문에, 지연 로딩 설정 여부와 상관없이 Locker 테이블을 조회하여 Member와 연결된 Locker가 있는지 확인하는 추가 쿼리가 발생한다.
2. 외래키가 Member에 있을 때
외래키가 Member에 있다면, Member 테이블의 조회만으로도 Member와 연결된 Phone가 있는지 여부를 판단할 수 있다. 따라서 이 경우에는 지연 로딩(lazy loading) 또는 즉시 로딩(eager loading) 설정이 가능하다.
참고:JPA 도입 — OneToOne 관계에서의 LazyLoading 이슈 #1
JPA는 객체의 참조가 프록시 기반으로 동작하는데, 연관관계가 있는 객체는 참조를 할때 기본적으로 null이 아닌 프록시 객체를 반환한다. 1:1관계에서는 null이 허용되는 경우, 프록시형태로 null객체를 반환할 수가 없기 때문이다. 1:N관계는 이미 배열의 형태로 이미 참조할 프록시 객체를 싸고 있기 때문에 그 객체가 null이라도 참조할때는 문제가 되지 않는다.
따라서 JPA 구현체는 기본적으로 1:1관계에서는 지연로딩 를 허용하지 않고, 즉시 값을 읽어 들인다. 물론 Lazy를 설정할 수 있지만 특정조건을 모두 만족하지 않는다면 동작하지 않는다.
개인적인 생각으로는 OneToMany로 변경될 가능성이 있는지를 판단하고 변경이 될 가능성이 있다고 판단되면 Many가 될 엔티티가 관계의 주인이 되는 것이 좋다고 봅니다. 또 애초에 OneToMany를 고려해서 초기 관계 설정을 OneToMany로 가져가는 것도 좋다고 생각합니다. 출처
이런 의견도 있다.
프로필이 여러개로 늘어날 것 같진 않아서 멤버를 주인으로 설정하기로 했다.
근데 또 이렇게 하니까 Profile을 유저 정보로 Select할 수가 없었다..?...
생각해보니 User 테이블에서 조회를 하면 되는 문제긴 하다!