mybatis 의 mapper.xml 을 작성하면 #{} 혹은 ${} 를 사용한다. 둘의 차이점을 알자. 현재 테스트할 테이블의 상태는 아래와 같다.


1
2
3
4
5
6
SQL> desc USER_TB_APPLE;
 
Name          Null?    Type
------------- -------- -------------
USER_ID       NOT NULL VARCHAR2(10
USER_PW       NOT NULL VARCHAR2(20)

cs


이제 비교 해보자.


#{} 

1
2
3
SELECT count(*FROM 
    USER_TB_APPLE 
WHERE USER_ID = #{id} AND USER_PW = #{pw}
cs



1
2
3
SELECT count(*FROM USER_TB_APPLE 
    WHERE 
USER_ID = ? AND USER_PW = ?
cs


#{}을 사용하면, mybatis 는 PreparedStatement를 생성하고 PreparedStatement 매개변수에 대해서 값을 안전하게 설정한다. PreparedStatement 가 제공하는 set 계열의 메소드를 사용하여 물음표(?)를 대체할 값을 지정한다. #{}의 방법은 안전하고 빠르기 때문에 선호된다. 그리고 들어오는 데이터를 문자열로 취급하기 때문에 자동으로 큰 따옴표가 붙는다.


${}

1
2
3
SELECT count(*FROM 
    USER_TB_APPLE 
WHERE USER_ID = ${id} AND USER_PW = ${pw}
cs



1
2
3
SELECT count(*FROM USER_TB_APPLE 
    WHERE 
USER_ID = apple AND USER_PW = apple1004
cs


${}을 사용하면 해당 테이블에서 VARCHAR2 로 설정했는데 해당 인자 값을 그대로 받는다. 따라서 상수 그대로 값을 받기 때문에 해당 컬럼이 문자열인 경우에는 따옴표로 감싸주는 구문을 추가해주어야 한다. 


USER_ID 와 USER_PW 가 문자열 컬럼인 경우 큰 따옴표로 감쌌다.


1
2
3
SELECT count(*FROM 
    USER_TB_APPLE 
WHERE USER_ID = "${id}" AND USER_PW = "${pw}"
cs


${}을 사용하게 되면 SQL Injection 같은 문제에 취약하다. 왜냐하면 문자열을 직접 삽입하기 때문이다. 하지만 ORDER BY 같은 경우, 아래와 같이 사용할 수 있다.


1
ORDER BY $ {columnName}
cs


필요에 따라 구분해서 사용하면 될 듯 하다.

Posted by doubler
,