4주차 - 3) RDS 접속 및 SQL 쿼리

변현섭·2023년 6월 10일
1

4th UMC Server-Spring Study

목록 보기
14/30
post-thumbnail

5) Join문 실습

① Inner-Join

  • Inner-Join의 경우는 형태만 낯설지 사실 위에서 사용한 WHERE문이 Inner-Join에 해당한다. 아래의 예시를 보면 이해가 쉬울 것이다.
  • Inner-Join의 인자로 오는 두 테이블의 순서는 바뀌어도 결과는 같다. 또 위에서 설명한 바 있듯 on 대신 where을 사용해도 된다.

② 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

  • Right-Join의 경우도 마찬가지로 기준 테이블의 정보는 모두 가져오고 대상 테이블의 정보는 있으면 가져오고 없으면 NULL을 입력한다. 단 기준테이블이 우측 테이블이 된다는 것만 다르다. 위 예제를 그대로 가져와서 Left Join만 Right Join으로 바꾸면 어떻게 될까?

  • 기준 테이블인 Place_Order테이블에 있는 모든 order_id를 가져오고 이에 해당하는 user_id가 있는 경우 가져온다. 당연한 이야기지만, 만약 User테이블과 Place_Order테이블의 위치까지 바꾼다면, 위 Left-Join 실습에서와 동일한 결과가 나올 것이다.

④ Full-Outer-Join

  • Full-Outer-Join은 사실 mysql에서는 지원하지 않는 기능이다. mysql에서 Full-Outer-Join을 사용하는 방법은 Left-Join과 Right-Join의 결과를 합집합시키는 것이다. 아래의 예시를 보자.

  • 기준 테이블은 from 뒤에 있는 Place_Order테이블이기 때문에 Place_Order테이블의 order_id에 맞는 user_id가 먼저 출력되고 User테이블에 남은 나머지 user_id가 뒤이어 출력된다.

Ⅲ. 보충 설명

1. ORM

ORM은 Object Relational Mapping의 약자로 말그대로 객체와 관계를 매핑한다는 뜻이다. ORM이 필요한 이유를 한 단어로 정리하면 “객체 모델과 관계형 모델 간의 불일치”때문이다.

객체지향 프로그래밍은 클래스를 사용하고, 관계형 데이터베이스는 테이블을 사용하기 때문에 객체 모델과 관계형 모델 간에는 불일치점이 생길 수 밖에 없다. 이 때, ORM을 사용하여 객체 간의 관계를 바탕으로 SQL을 자동 생성하여 불일치를 해결한다. 즉, 객체를 통해 간접적으로 데이터 베이스의 데이터를 컨트롤한다. ORM을 사용할 때의 장점은 아래와 같다.

  • 객체 지향적인 코드로 인해 더 직관적이고, 개발자가 로직에 집중할 수 있다.
  • 클래스의 메서드를 통해 데이터베이스를 조작할 수 있어 객체모델만으로 프로그래밍이 가능하다.
  • 객체마다 코드를 별도로 작성하므로 코드의 가독성이 높아진다.
  • 재사용 및 유지보수에 용이하다.
  • ERD에 대한 의존도나 DBMS에 대한 종속성이 줄어든다.

물론, ORM을 사용함으로 인한 단점도 있다.

  • 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이 다소 비효율적으로 보일지는 모르나, 실무에서 자주 사용되는 것은 지연 로딩이다. 그 이유는 즉시 로딩을 자주 사용할 경우 오히려 효율성이 저하될 수 있기 때문이다.

만약, 모든 정보를 즉시 로딩으로 불러온다면, 불필요한 데이터를 불러오는 데에 시간을 낭비하게 될 수 있다. 특별한 경우가 아니라면 지연 로딩의 방법을 사용할 것을 권장한다.

profile
Java Spring, Android Kotlin, Node.js, ML/DL 개발을 공부하는 인하대학교 정보통신공학과 학생입니다.

0개의 댓글