Mybatis에서 #{}와 ${}의 차이

2020. 8. 9. 19:02Java/Spring

 

  • ${}

사용 과정

  1. ${} 사용 시 Statement 생성.
  2. Statement의 Parameter 값을 그대로 전달.
  3. arameter를 그대로 전달하기 때문에 문자열에 따옴표가 붙지 않음.

 

특징

  1. Parameter가 바로 출력됨.
  2. 해당 컬럼의 자료형에 맞춰 Parameter의 자료형이 변경됨.
  3. Parameter 값이 넣어진 채로 Query문이 수행됨(parameter 값이 바뀌면 다른 query로 인식). 그러므로 Parameter의 값이 바뀔 때마다 항상 Query문에 대한 파싱을 진행해야 한다는 성능상의 단점을 내재하고 있어 속도가 저하될 수 있음.
  4. SQL Injection을 예방할 수 없어 보안 측면에서 불리함. 그러므로 사용자의 입력을 전달할 경우에는 사용하지 않는 편이 좋음.
  5. Table이나 Column명을 전달하고 싶을 때 사용( #{}는 자동으로 따옴표가 붙어 이 경우에는 사용할 수 없음).

예시

-- Mybatis Mapper
SELECT num FROM test WHERE num = ${num}

-- Oracle로 넘어온 Query
SELECT num FROM test WHERE num = 77

-- 실제 수행 Query
SELECT num FROM test WHERE num = 77

 


  • #{}

 

사용 과정

  1. #{} 사용 시 PreparedStatement 생성.
  2. PreparedStatement Parameter 값 안전하게 생성.
  3. PreparedStatement가 제공하는 set 계열의 메소드를 사용하여 물음표(?)를 대체할 값을 지정.
  4. 들어오는 데이터를 String으로 인식하기 때문에 자동으로 따옴표가 붙음.

특징

  1. Parameter가 String 형태로 들어와 자동으로 'parameter' 형식이 됨.
  2. SQL Injection을 예방할 수 있어 보안 측면에서 유리함.
  3. Query 작성 시 #{}을 사용하는 경우 PreparedStatement가 생성되는데, ?에 Parameter가 바인딩되어 수행(Parameter 값이 바뀌어도 같은 query로 인식). 이렇게 파싱된 Query문은 재활용(캐싱)되기 때문에 효율적임.

예시

-- Mybatis Mapper
SELECT id FROM test WHERE id = #{id}

-- Oracle로 넘어온 Query
SELECT id FROM test WHERE id = ?

-- 실제 수행 Query
SELECT id FROM test WHERE id = 'admin'

 

 


 

  • SQL Injection

  보안을 고려한다면 #{}을 사용해야 함.

 

SELECT * FROM user WHERE id = '${id}' AND password = '${password}'

  위와 같은 쿼리문이 있다고 가정했을 때 id의 parameter 값으로 admin' --이 입력되면 실제 파싱되는 쿼리문은 아래와 같음.

 

 SELECT * FROM user WHERE id = 'admin' -- 'AND password = ''

  즉 WHERE절에서 비밀번호에 대한 조건은 사라지게 되어 id만 입력해도 관리자 계정에 대한 정보를 조회할 수 있게 됨. 이처럼 ${}의 사용은 #{}보다 SQL Injection에 취약하다고 할 수 있음.

 

 

 

 

참고 자료

https://rh-cp.tistory.com/71

https://java119.tistory.com/39

https://logical-code.tistory.com/25

 

'Java > Spring' 카테고리의 다른 글

Mybatis에서의 Like문 사용  (0) 2020.08.09