본문 바로가기
개발/리팩토링

엔티티 조회 대신 존재 여부만 확인하기

by nineteen 2025. 3. 7.
반응형

특정 조건의 데이터가 DB 에 존재하는지 알기 위해선 직접 엔티티를 조회해서 그 값을 확인해볼수있고, 존재하는지만 체크할 수 있습니다.
DB에 존재하는지만 알고 싶은데 굳이 엔티티를 조회해와야하나? 싶은 마음에 DB에 존재하는지만 체크해보기로 했습니다.

리팩토링 전

기존에는 알림의 존재 여부를 확인할 때 엔티티를 조회하고 있었습니다:

@Query(value = """
    SELECT *
    FROM notification
    WHERE type = :type
      AND user_id = :userId
      AND is_active = true
      AND created_at >= :timeLimit
    ORDER BY id DESC
    LIMIT 1
""", nativeQuery = true)
Optional<NotificationEntity> findLatestNotification(
    @Param("type") String type,
    @Param("userId") Long userId,
    @Param("timeLimit") Long timeLimit
);

리팩토링 과정

1. 쿼리 메소드 시도

먼저 JPA의 쿼리 메소드를 활용해보았습니다:

boolean existsByTypeAndUserIdAndAndCreatedAtGreaterThanEqual(
    String type,
    Long userId,
    Long timeLimit
);

하지만 메소드명이 지나치게 길어져 가독성이 떨어진다고 판단했습니다.

2. JPQL로 전환

@Query("""
    SELECT COUNT(n) > 0
    FROM NotificationEntity n
    WHERE n.type = :type
      AND n.userId = :userId
      AND n.createdAt >= :timeLimit
""")
boolean existsNotification(
    @Param("type") String type,
    @Param("userId") Long userId,
    @Param("timeLimit") Long timeLimit
);
  • COUNT를 활용하여 존재 여부를 확인하는 방식을 구현하였습니다.

3. EXISTS 검토

@Query(value = """
    SELECT EXISTS (
        SELECT 1
        FROM notification
        WHERE type = :type
          AND user_id = :userId
          AND created_at >= :timeLimit
        LIMIT 1
    )
""", nativeQuery = true)
Integer existsNotification(
    @Param("type") String type,
    @Param("userId") Long userId,
    @Param("timeLimit") Long timeLimit
);
  • 좀 더 좋은 성능을 낼 수 있는, EXISTS 쿼리를 사용하였습니다.
  • JPQL 에서 EXISTS 키워드는 제공되지 않기 때문에, 네이티브 쿼리를 사용해서 처리를 했는데 어째서인지 동작을 하지 않았습니다..ㅜ
  • QueryDSL 로 EXISTS 쿼리를 사용할 수 있지만, 현재 프로젝트의 규모상 과도하다고 판단해 적용하지 않았습니다.

리팩토링 결과

최종 선택: JPQL을 활용한 COUNT 쿼리

선택 이유

 

  1. QueryDSL 도입 비용: EXISTS 사용을 위해 QueryDSL을 도입하는 것은 현재 프로젝트 규모를 고려할 때 과도하다고 판단했습니다.
  2. 데이터 규모: 현재 조건으로 필터링되는 데이터의 규모를 고려했을 때, COUNT 방식으로도 충분한 성능을 확보할 수 있었습니다. -> 그럼 엔티티 조회하는 거랑 큰 차이가 있남?
  3. 네이티브 쿼리로 EXISTS 쿼리를 짰는데 동작을 안 함

이게 리팩토링이야? 이게 더 나아진거야? 싶지만.. EXISTS 를 사용하는 것이 확실한 개선이라는 것을 알아갈 수 있었습니다.
네이티브 쿼리로 할 수 있을 거 같은디ㅜ

참고자료