Skip to content
메모장
Go back

DB 3 value logic - 가격 협의 게시글이 필터에서 사라지던 이유

개요

도움 요청 게시글 목록에 가격 범위 필터(minPrice/maxPrice)를 걸었을 때, 가격을 아직 정하지 않은(“협의”) 게시글이 필터 조건과 무관하게 항상 결과에서 빠지는 버그가 있었다.

필터를 걸든 안 걸든 협의 게시글이 안 보이는 게 아니라, “가격 필터를 하나라도 걸면” 사라지는 조건부 버그라 처음엔 원인을 짚기 까다로웠다.


1. 원인 — SQL은 NULL >= x를 참으로도 거짓으로도 안 본다

원래 코드는 이랬다.

criteria.minPrice?.let { helpJpaEntity.priceOffer.price.goe(it) },
criteria.maxPrice?.let { helpJpaEntity.priceOffer.price.loe(it) },

minPrice가 지정되면 price >= minPrice 조건이 붙는다.

문제는 price 컬럼 자체가 “협의”인 게시글은 NULL이라는 것


2. 수정 — 근데 단순히 “OR isNull”만 붙이면 안 됐다

가장 먼저 떠오르는 수정은 모든 가격 비교에 .or(price.isNull())을 붙이는 것이다.

그런데 이렇게 하면 minPricemaxPrice둘 다 지정한 경우에도 협의 게시글이 계속 섞여 나온다

“1만원에서 3만원 사이”로 명시적으로 좁힌 사용자 입장에서는 원하는 결과가 아니다.

그래서 실제 수정은 조건 조합에 따라 분기했다.

when {
    criteria.minPrice != null && criteria.maxPrice != null ->
        helpJpaEntity.priceOffer.price.goe(criteria.minPrice)
            .and(helpJpaEntity.priceOffer.price.loe(criteria.maxPrice))

    criteria.maxPrice != null ->
        helpJpaEntity.priceOffer.price.loe(criteria.maxPrice)
            .or(helpJpaEntity.priceOffer.price.isNull)

    criteria.minPrice != null ->
        helpJpaEntity.priceOffer.price.goe(criteria.minPrice)
            .or(helpJpaEntity.priceOffer.price.isNull)

    else -> null
}

이건 버그를 고치는 것과 별개로, “NULL을 결과에 포함시킬지”가 SQL 문법 문제가 아니라 비즈니스 판단 문제라는 걸 보여주는 지점이다.

3값 논리 자체를 이해하는 것과, 그걸 도메인 요구사항에 맞게 어떻게 다룰지 결정하는 건 다른 층위의 문제다.


Share this post:

Previous Post
인메모리로 STOMP 세션 상태를 추적하다 겪은 두 가지 버그
Next Post
Spring Boot 4 + Jackson 3 — Redis 직렬화가 조용히 어긋나는 지점