본문 바로가기
BackEnd-Study/DB

[MyBatis] WHERE 1=1

by ChaeLOTUS 2024. 4. 3.
728x90

 

 

SELECT id, username, nickname
FROM member_test
WHERE
    1=1
    <if test="username != null">
        AND username = #{username}
    </if>
    <if test="nickname != null">
        AND nickname = #{nickname}
    </if>

 

위의 쿼리에서 username과 nickname에 null이 들어오면 전체 데이터를 조회한다.

전체 조회가 된다는 사실을 의도하지 않거나 예상하지 못한다면 데이터 양에 따라 어플리케이션 응답 지연 문제 등이 발생할 수 있다.

 

만약 쿼리가 DELETE 혹은 UPDATE였다면 전체 데이터가 변하는 상황이 발생할 수도 있다.

 

 

WHERE 1=1 피하기

구글링을 해본 결과 위와 같은 이유로 여러 블로그에서 WHERE 1=1을 사용하는 것에 대해 피하자는 글들이 많았다.

 

WHERE 1=1 대신 대체할 수 있는 방법이 무엇이 있을까?

TRIM  사용하기

 

 

1. TRIM 사용(1)

 

TRIM 태그를 사용하면 태그 내부에서 실행할 쿼리를 생성해준다.

prefix=WHERE 은 해당 블록 안의 쿼리에 where쿼리를 추가해준다.

 

SELECT id, username, nickname
FROM member
<trim prefix="WHERE" prefixOverrides="AND">
    <if test="username != null">
        AND username = #{username}
    </if>
    <if test="nickname != null">
        AND nickname = #{nickname}
    </if>
</trim>

prefixOverrides 태그 안에서 실행될 쿼리의 가장 앞 쿼리가 속성값에 설정해둔 문자와 동일할 경우 문자를 제거해준다.

즉, FROM member WHERE AND username=#{username} 이런 문법이 되지 않도록 WHERE 다음에 AND를 제거해준다.

 

 

여기서 username, nickname이 전부 null 이면?

SELECT id, username, nickname
FROM member_test

 where 1=1과 마찬가지로 전체 조회쿼리가 실행된다.

where 1=1을 사용하지 않을 순 있지만, 여전히 인자값을 검증하지 않는다면 전체 조회가 발생할 가능성이 있다.

 

 

 

2. TRIM 사용(2)

 

SELECT id, username, nickname
FROM member_test
WHERE
<trim prefixOverrides="AND">
    <if test="username != null">
        AND username = #{username}
    </if>
    <if test="nickname != null">
        AND nickname = #{nickname}
    </if>
</trim>

prefix="WHERE" 을 제거하였다.

위의 방법과 동일하게 동작할 것 같지만 username, nickname을 전부 null로 넘어오면 큰 차이가 생긴다.

 

SELECT id, username, nickname
FROM member_test WHERE

WHERE 다음에 어떤 조건이 걸리지 않기 때문에 BadSqlGrammarException이 발생한다.

검증 로직이 부족하여 username, nickname이 전부 null로 넘어온다면 Exception이 발생하기에 데이터 전체 조회가 일어나는 것을 막을 수 있다.

728x90

댓글