web developer

[ibatis/Mybatis] ibatis/Mybatis에서 #{}, ${} 차이 본문

Persistence Framework/iBatis, MyBatis

[ibatis/Mybatis] ibatis/Mybatis에서 #{}, ${} 차이

trueman 2022. 1. 5. 14:01
728x90
728x90

1. ibatis #값# | Mybatis #{값}


<select id="select" resultType="String" parameterType="Map">
    SELECT NAME, ID
    FROM  USER
    WHERE ID = #{id}
</select>

위와 같이 MyBatis에서 #{}이 사용된 쿼리문이 있다고 가정한다.

 

SELECT NAME, ID
FROM  USER
WHERE ID = ?

쿼리문을 작성할 때 #{}을 사용하는 경우 PreparedStatement를 생성하게 되는데 위의 '?'파라미터 바인딩되어 수행된다.

  1.  #{id}의 값이 abcde이라면 쿼리문에는 id= 'abcde'의 형태가 된다.
    * 변수 자료형이 String이면, 자동으로 작은 따옴표를 붙여 쿼리가 수행되기 떄문에'#{id}'와 같은 식으로 쿼리문을 작성하지 않아도 된다.
  2. 쿼리 주입을 예방할 수 있어 보안측면에서 유리하다.

 

* MyBatis의 해시(#)를 사용한 파라미터는 PreparedStatement의 파리미터와 대응한다. 
* PreparedStatement는 한번 수행한 쿼리를 캐싱하는 객체


2. ibatis $값$ | Mybatis ${값}


<select id="exam_select" parameterType="HashMap" resultType="HashMap">
    SELECT  ${COLUMN}
    FROM    USER
</select>

값이 넣어진 채로 쿼리문이 수행된다. 그렇기 때문에 파라미터의 값이 바뀔 때마다 항상 쿼리문 파싱을 진행해야 한다.

  1. 해당 컬럼의 자료형에 맞추어 Parameter 자료형이 변경된다.
  2. 쿼리 주입을 예방할 수 없어 보안측면에서 불리하다. 그러므로, 사용자의 입력을 전달할 때는 사용하지 않는 편이 낫다.
  3. 테이블이나 컬럼명을 Parameter로 전달하고싶을 때 사용한다.

* 변수의 자료형과 관계없이 작은 따옴표(' ')를 parameter에 감싸지 않기 때문에, Parameter$ 및 ${Parameter}를 사용할 때 작은 따옴표로 처리를 하지 않으면 Column이나 이름을 찾지 못한다는 Error가 발생합니다.


3. 차이점


#Parameter# 및 #{Parameter} 같은 경우에는 PreparedStatement를 사용하게 되면서, 변수를 Bind를 하게 됩니다. 이 경우에는 바인딩한 것들을 계속해서 바꿔줄 수 있기 때문에 코드의 재사용성이라는 장점이 있고, 변수를 Bind하면서, SQL Injection을 예방을 할 수 있습니다.

$Parameter$ 및 ${Parameter}는 변수에 저장된 값을 Bind하지 않고 Statement를 사용하게 되면서 쿼리문에 들어가는 값을 수정할 수 있고, 이 경우에는 우리가 흔히 알고 있는 SQL Injection의 공격을 받을 수 있습니다. 또한, 쿼리문이 변경되면 쿼리문을 다시 파싱하는 작업을 진행하기 때문에 속도가 저하된다는 단점이 있습니다. 
* DB입장에서는 $$은 이미 문자열로 치환되어서 쿼리가 수행되기 때문에 $$값이 달라지면 하드파싱하게 된다. 


그래서 대부분 Query 문을 짤 때, $ 방식보다는 # 방식을 사용하라고 권장을 하고 있습니다.


출처 : https://dev-milk.tistory.com/4
출처 : https://logical-code.tistory.com/25
출처 : https://madplay.github.io/post/difference-between-dollar-sign-and-sharp-sign-in-mybatis

728x90
728x90