① Inner-Join
② Left-Join
Left-Join의 경우, 기준 테이블의 정보는 모두 가져오고 대상 테이블의 정보는 있으면 가져오고 없으면 NULL을 입력한다.
User테이블에는 user1, user2, user3이 있지만, user1과 user3만 주문한 이력이 있고 user2는 한 번도 주문을 한 적이 없다. 이러한 사실을 Left-Join으로 알 수 있다.
Left-Join이기 때문에 왼쪽에 있는 T1이 기준 테이블이 되어 모든 user_id를 가져온다. 이 때 대상 테이블인 T2에 user_id가 있는 경우에만 order_id를 가져오고 없으면 NULL이 입력된다.
③ Right-Join
④ Full-Outer-Join
ORM은 Object Relational Mapping의 약자로 말그대로 객체와 관계를 매핑한다는 뜻이다. ORM이 필요한 이유를 한 단어로 정리하면 “객체 모델과 관계형 모델 간의 불일치”때문이다.
객체지향 프로그래밍은 클래스를 사용하고, 관계형 데이터베이스는 테이블을 사용하기 때문에 객체 모델과 관계형 모델 간에는 불일치점이 생길 수 밖에 없다. 이 때, ORM을 사용하여 객체 간의 관계를 바탕으로 SQL을 자동 생성하여 불일치를 해결한다. 즉, 객체를 통해 간접적으로 데이터 베이스의 데이터를 컨트롤한다. ORM을 사용할 때의 장점은 아래와 같다.
물론, ORM을 사용함으로 인한 단점도 있다.
ORM이 매핑하는 관계에는 1:1관계, 1:N관계(N:1관계), N:M관계가 있다. 먼저 일대일 관계는 객체가 서로 일대일 관계에 있는 것으로 사람과 주민등록번호가 대표적인 예이다.
일대다 관계는 단방향과 양방향으로 구분된다. 팀과 팀원의 관계를 생각해보자. 단방향의 경우 Member만 Team을 N:1관계로 참조하게 된다. 즉, Member에서는 Team을 조회할 수 있지만, Team에서는 Member를 조회할 수 없다. 이를 코드로 나타내어 보면 아래와 같다.
Team과 Member 클래스를 실제로 구성할 때에는 양방향이 유리하다. 양방향일 경우 Member는 Team을 N:1관계로 참조한다. Team입장에서는 Member가 1:N이기 때문에 List를 갖는다.
마지막으로 다대다의 경우는 예시만 간단히 알아보자. Member와 Role의 관계는 한 명의 Member가 여러 개의 Role을 가질 수 있고 한 개의 Role을 여러 명의 Member가 가질 수도 있다. 단, 실무에서는 거의 사용할 일이 없다. 그 이유는 관계형 데이터베이스는 다대다 관계를 표현할 수 없기 때문이다. 항상 1:N관계로 정규화를 시키는 것이 여러 측면에서 유리하다.
ORM의 대표적인 프레임워크로 전에 소개한 바 있는 JPA가 있다. 그리고 이러한 JPA의 구현체로 Hibernate가 있다. ORM은 크게 두 가지 방식으로 구분된다. 바로 Lazy-Loading과 Eager-Loading이다. JPA의 경우를 기준으로 설명하겠다.
먼저, Lazy-Loading은 JPA를 이용해 데이터를 조회할 때마다 데이터베이스에 접근하여 데이터를 가져오는 것이 아니라, 모든 명령처리가 끝나고 실제 데이터를 불러와야 하는 시점에서 데이터베이스 Query문을 실행하는 방식을 말한다. 아래의 코드에서 Member를 조회했을 때 Team은 불러오지 않는다.
반면, Eager-Loading은 즉시 로딩한다는 뜻으로 Lazy-Loading의 반대 개념이다. Lazy-Loading은 Query문을 하나하나 실행하여 데이터를 가져오는 반면, Eager-Loading은 지금 당장 사용하지 않을 데이터도 포함하여 Query문을 실행한다.
물론 아무 데이터나 다 가져오는 것은 아니고 연관된 정보를 모조리 가져오는 것이다. 위 코드에서 FetchType만 EAGER로 바꿔주면, Member를 조회할 때 Team까지 불러오는 쿼리도 함께 날아가기 때문에 한번에 데이터를 모두 불러오게 된다.
Lazy-Loading이 다소 비효율적으로 보일지는 모르나, 실무에서 자주 사용되는 것은 지연 로딩이다. 그 이유는 즉시 로딩을 자주 사용할 경우 오히려 효율성이 저하될 수 있기 때문이다.
만약, 모든 정보를 즉시 로딩으로 불러온다면, 불필요한 데이터를 불러오는 데에 시간을 낭비하게 될 수 있다. 특별한 경우가 아니라면 지연 로딩의 방법을 사용할 것을 권장한다.