[mybatis] 파라메터 ${}, #{} 차이점 정리
${}
, #{}
mybatis mapper에서 parameter를 받아서 사용할때 크게 2가지 방법이 있다.${}
, #{}
두가지 방법은 동작이 다르고 경우에따라서는 보안상으로 좋지 않으므로 차이점을 명확히 알고 사용해야한다.
${}
: 원문 그대로 -> 잠재적 sql injection 취약점 - 주의해서 사용#{}
:' '
를 씌워줌, sql injection 방지
파라메터 - Parameters
Parameters는 마이바티스에서 매우 중요한 엘리먼트이다. 대략 90%이상은 간단한 경우 이러한 형태로 설정한다.
1 | <select id="selectUsers" resultType="User"> |
#{}
문법은 마이바티스로 하여금 PreparedStatement프로퍼티를 만들어서 PreparedStatement파라미터(예를들면 ?)에 값을 셋팅하도록 할 것이다. 위의 쿼리로 예를 들면
1 | select id, username, password |
이후 ?
에 값을 대입한다. ( '
도 같이 추가해준다. )
이때 ?
에 들어올 데이터가 달라지더라도 mysql같은 rdb에서 동일한 쿼리로 인식한다
따라서 1,2,3,4, 값이 바뀌어도 새로 파싱을 하지 않는다
.
아래와같은 문법으로 type을 지정해줄수도 있다
1 | #{age,javaType=int,jdbcType=NUMERIC,typeHandler=MyTypeHandler} |
문자열 대체 String Substitution
가끔은 SQL 구문에 변하지 않는 값으로 삽입하길 원하기도 한다. 예를들면 ORDER BY와 같은 구문들이다. 이럴때는 #{}
을 사용하면 string 에 따옴표를 추가하므로 문법 오류가 발생 할 수 있다.
이런경우 ${}
를 사용할 수 있다.
1 | ORDER BY ${columnName} |
마이바티스는 문자열을 변경하거나 이스케이프 처리하지 않는다.
사용자 입력값에 대해서는 언제나 자체적으로 이스케이프 처리하고 체크해야 한다.
정적 바인딩
1 | <select id="selectUsers" resultType="User"> |
${} 로 바인딩을 하게되면 정적으로 쿼리에 값이 들어가게 되는데
1 | select id, username, password |
1 | select id, username, password |
이경우 값이 바뀌면 쿼리가 여러개 생성된다. 그리고 파싱도 여러번 하게되므로 성능상 #{} 보다 불리하다
위험성
사용자 입력값에 대해서는 이 방법을 사용하면 안된다.
만약 이 값이 사용자의 입력을 통해 전달된다면 위험 할 수 있다.
사용자가 입력한 값이 그대로 쿼리에 적용되기 때문이다. 잠재적인 SQL 주입 공격에 노출된다.