[데이터베이스/DB] 관계형 DB에서 JOIN의 개념(Inner join과 Left join)

kindof

·

2021. 10. 26. 10:52

1. JOIN ?

JOIN이란 영어 해석 그대로 두 개 이상의 테이블을 결합하여 데이터를 조회할 때 쓰는 개념입니다.

 

정규화를 통해 여러 테이블로 나누어진 데이터는 서로 연관관계를 가지고 있을 수 있고, A라는 엔티티를 조회할 때 B라는 엔티티의 부분 정보도 같이 조회하고 싶다면 JOIN 개념이 반드시 필요하죠. 

 

어떻게 보면 JOIN이 필요한 이유는 정규화로부터 파생되었다고 볼 수 있기 때문에, 정규화 개념은 JOIN을 공부하기 이전에 반드시 알아야하는 내용이기도 합니다.

 

 

본론으로 돌아와서, JOIN의 예시를 하나 보겠습니다. 

 

게시물 아이디로 조회 쿼리

 

위 내용은 게시물(Post)을 조회할 때 게시물을 작성한 유저의 정보와 해당 게시물에 관련된 '좋아요' 정보를 함께 불러오는 JPQL 쿼리입니다.

 

정규화 과정에 의해 DB 스키마는 User, Post, PostLike 라는 엔티티들로 나뉜 상태인데요. 이 엔티티들은 서로 기본키(Primary Key)와 외래키(Foreign Key)로 매핑이 되어있고, 따라서 이 키 값들을 바탕으로 JOIN이 이루어지는 것을 볼 수 있습니다. 이 상황에서 게시물 하나를 조회하려고 하면, Post 데이터만 가져오는 것이 아니라 게시물을 구성하는 유저 정보와 '좋아요' 정보도 가져와야 하는 것이죠(물론 Fetch 타입에 따라 위 쿼리가 필요없을 수도 있지만, JOIN 개념 설명을 위해 LAZY Fetch를 가정하겠습니다).

 

자, 그런데 위 쿼리문을 잘 보시면 inner join이라는 키워드가 보입니다. 사실 JOIN에는 여러 가지 방법이 존재하는데요. 이번 포스팅에서는 그 중에서도 자주 사용되는 Inner Join, Left (Outer) Join에 대해 집중적으로 알아보겠습니다.

 

 

 

2. Inner Join

Inner Join은 두 테이블에서 "공통되는 데이터"만 조회하는 방법입니다.

 

 

위에 들었던 예시에서는 게시물을 조회할 때 유저 정보도 함께 불러와야 하는데요. 하나의 게시물을 조회할 때는 게시물을 작성한 유저의 정보도 필요하기 때문입니다.

 

따라서 단순히 게시물의 ID만 가지고 조회를 하면 유저의 정보가 나타나지 않기 때문에, 해당 게시물이 매핑된 유저의 아이디와 동일한 아이디를 갖는 유저를 Join해서 같이 가져오는 것입니다. 이해가 되시나요?

 

좀 더 직관적으로 이해하기 위해 아래 테이블을 보겠습니다.

 

게시물 table
유저 테이블

 

위 게시물 테이블을 보면 4개의 게시물을 작성한 user_id가 모두 1입니다. 그리고 게시물은 외래키로 user_id를 가지고 있죠? 따라서 위 게시물들을 조회할 때 user_id를 가지고 Join을 하게 되면 해당 게시물의 제목, 내용과 여러 데이터를 포함해서 1번 유저의 이름 등을 같이 가져오게 되고, 이를 뷰에서 표기할 수 있게 되는 것입니다.

 

 

 

3. Left (Outer) Join

Inner Join이 교집합을 찾는 개념이었다면, LEFT Join은 왼쪽 테이블을 포함하여 교집합을 찾는 방식입니다. 

 

 

 

그림에서 알 수 있듯이, 두 개의 테이블에 대해 왼쪽 테이블은 그대로 모든 데이터를 조회해서 가져오고, 거기에 추가해서 두 테이블의 공통되는 부분을 같이 조회해오는 방식입니다.

 

예를 들어 보겠습니다.

 

유저가 쓴 게시물 조회 쿼리

 

위 쿼리문은 "어떤 유저가 작성한 모든 게시물을 조회"하는 목표를 가지고 있습니다. 그래서 유저의 아이디를 가지고 게시물들을 조회하고, 해당 게시물에 존재하는 '좋아요' 데이터들도 가져와서 보여줘야하죠.

 

참고로 PostLike(좋아요) 테이블은 자신의 Id를 가지고 있으며, Post_id, User_id를 가지고 있어서 각 게시물마다 좋아요를 누른 유저 아이디를 저장하고 있습니다. 26번 게시물에 10명이 좋아요를 눌렀다면 10개의 셀이 생성되는 것이죠.

 

그런데 위 상황에서 PostLike(좋아요) 테이블에 대해 Inner Join을 걸어버리면 어떤 문제가 생길까요?

 

정답은 "해당 유저가 좋아요를 누른 적 없는 게시물은 표시가 안 된다" 입니다. 왜냐하면 Inner Join은 교집합만을 찾고 있기 때문이죠!

 

따라서, 위 쿼리를 위도한대로 동작하게 하기 위해서는 Left Join을 통해 유저가 좋아요를 누른 적 없는 게시물도 모두 표시되게 하고 그 중에서 좋아요를 누른 게시물은 좋아요 데이터도 같이 표시해줘야 하는 것입니다. 이해가 되셨나요?

 


이렇게 이번 시간에는 Inner Join과 Left Join에 대해 공부해봤습니다.

 

이 개념을 제대로 모르고 쿼리문을 짰을 때 원하는대로 데이터가 조회되지 않아서 고통받았던 기억이 있는데요.

 

데이터를 조회할 때 필요없는 데이터를 같이 조회하는 것을 방지하거나, 원하는 데이터를 적절히 조회하기 위해서는 JOIN의 개념을 잘 알아야 할 것 같습니다.

 

감사합니다.