반응형
특정 조건의 데이터가 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 쿼리
선택 이유
- QueryDSL 도입 비용: EXISTS 사용을 위해 QueryDSL을 도입하는 것은 현재 프로젝트 규모를 고려할 때 과도하다고 판단했습니다.
- 데이터 규모: 현재 조건으로 필터링되는 데이터의 규모를 고려했을 때, COUNT 방식으로도 충분한 성능을 확보할 수 있었습니다. ->
그럼 엔티티 조회하는 거랑 큰 차이가 있남? 네이티브 쿼리로 EXISTS 쿼리를 짰는데 동작을 안 함
이게 리팩토링이야? 이게 더 나아진거야? 싶지만.. EXISTS 를 사용하는 것이 확실한 개선이라는 것을 알아갈 수 있었습니다.
네이티브 쿼리로 할 수 있을 거 같은디ㅜ
참고자료
'개발 > 리팩토링' 카테고리의 다른 글
일급 컬렉션 (First-Class Collection)으로 코드 품질 향상 도전하기 (0) | 2025.04.23 |
---|