Engineering Note

[Database] JOIN과 EXIST 차이 본문

Computer Science/Database

[Database] JOIN과 EXIST 차이

Software Engineer Kim 2026. 1. 14. 14:48

1.JOIN과 EXIST 차이

 

JOIN의 핵심: "조건에 맞는 테이블을 이어준다."

 

EXISTS의 핵심: "데이터를 합치지 않는다"

 

보통 JOIN은 두 테이블을 가로로 이어 붙여서 커다란 종이를 만드는 작업입니다. 하지만 EXISTS는 메인 테이블을 한 줄씩 읽으면서, 서브쿼리에 물어만 보는 방식입니다.

 

 

예시

 

검색 조건 필터링에 따라 상품을 조회하는 동적쿼리

 

@Override
public Page<Item> findBySearchOption(ItemSearchDto itemSearchDto, Pageable pageable) {

  // 1. 메인 쿼리 데이터 조회
  List<Item> content =
      jpaQueryFactory
          .selectFrom(item)
          .where(
              itemNameStartsWith(itemSearchDto.getItemName()),
              categoryFilter(itemSearchDto.getCategoryId()), //서브쿼리
              isSellOrSoldOut(ItemSellStatus.SELL))
          .offset(pageable.getOffset())
          .limit(pageable.getPageSize())
          .orderBy(item.regTime.desc())
          .fetch();


  return PageableExecutionUtils.getPage(content, pageable);
}


// 카테고리 필터링 조건 (서브쿼리)
private BooleanExpression categoryFilter(Long categoryId) {
  if (categoryId == null) {
    return null;
  }
  return JPAExpressions.selectFrom(itemCategory)
      .where(
          itemCategory
              .item
              .eq(item) // 외부 쿼리의 item과 연결
              .and(itemCategory.category.id.eq(categoryId)))
      .exists();
}

 

 

 

시나리오: 101번 상품이 '가전' 카테고리인지 확인하기

  1. 메인 쿼리: Item 테이블에서 첫 번째 줄(101번 냉장고)을 딱 집습니다.
  2. 질문 던지기: "야, ItemCategory 테이블! 너네 데이터 중에 item_id가 101이면서 category_id가 **'가전'**인 줄이 하나라도 있어?"
  3. 답변 받기:
    • Yes! (한 줄이라도 찾으면 즉시 중단): 메인 쿼리는 101번 냉장고를 결과창에 포함시킵니다.
    • No!: 101번 냉장고를 결과창에서 버립니다.
  4. 다음 줄로: 이제 102번 상품을 집고 똑같은 짓을 반복합니다.

 

2. EXISTS가 성능상 유리한 이유: "Short-Circuit"

JOIN은 조건에 맞는 모든 데이터를 다 찾아내서 합쳐야 합니다. 하지만 EXISTS는 아주 영리합니다.

 

"하나라도 찾으면 그 즉시 탐색을 종료한다."

 

예를 들어, 어떤 상품이 카테고리를 100개 가지고 있다고 해도, EXISTS는 첫 번째 카테고리만 확인하는 순간 "어, 있네! 통과!" 하고 바로 다음 상품으로 넘어갑니다. 100개를 다 뒤질 필요가 없죠.


3. JOIN vs EXISTS 결과의 차이 (중복 문제)

이게 가장 실무적으로 중요한 차이입니다.

  • JOIN: Item(1) + Category(3개) = 결과 3줄 (상품이 중복되어 보임)
  • EXISTS: Item(1)이 조건에 맞으면 = 결과 딱 1줄 (상품 엔티티 그 자체를 유지)
Comments