Database
[Mybatis] 마이바티스 #{} ${} 차이
08genie
2023. 9. 10. 20:14
반응형
회사에서는 Mybatis를 이용하여 파라미터를 받을 때 #{}를 사용 하지만 ${}로도 파라미터를 받을 수 있다는 걸 알게되었습니다. 저에겐 #이 익숙하지만 $로도 받을 수 있다고 생각하니 두개의 차이점이 궁금해졌습니다.
${}
사용 과정
- ${} 사용 시 Statement 생성 합니다.
- Statement의 Parameter 값을 그대로 전달합니다.
- Parameter를 그대로 전달하기 때문에 문자열에 따옴표가 붙지 않습니다.
특징
- Parameter가 바로 출력됩니다.
- 해당 컬럼의 자료형에 맞춰 Parameter의 자료형이 변경됩니다.
- Parameter 값이 넣어진 채로 Query문이 수행됩니다.(parameter 값이 바뀌면 다른 query로 인식)
- 그러므로 Parameter의 값이 바뀔 때마다 항상 Query문에 대한 파싱을 진행해야 한다는 성능상의 단점을 내재하고 있어 속도가 저하될 수 있습니다.
- SQL Injection을 예방할 수 없어 보안 측면에서 불리합니다. 그렇기 때문에 사용자의 입력을 받아 사용할 경우에는 사용하지 않는 것이 좋습니다.
- Table이나 Column명을 전달하고 싶을 때 사용합니다. ( #{}는 자동으로 따옴표가 붙어 이 경우에는 사용할 수 없음)
-- Mybatis
SELECT num FROM sample WHERE num = ${num}
-- mysql로 넘어온 Query
SELECT num FROM sample WHERE num = 11
-- 실제 수행 Query
SELECT num FROM sample WHERE num = 11
#{}
사용 과정
- #{} 사용 시 PreparedStatement 생성합니다.
- PreparedStatement Parameter 값을 안전하게 생성합니다.
- PreparedStatement가 제공하는 set 계열의 메소드를 사용하여 물음표(?)를 대체할 값을 지정합니다.
- 들어오는 데이터를 String으로 인식하기 때문에 자동으로 따옴표가 붙습니다.
특징
- Parameter가 String 형태로 들어와 자동으로 'parameter' 형식이 됩니다.
- SQL Injection을 예방할 수 있어 보안 측면에서 유리합니다.
- Query 작성 시 #{}을 사용하는 경우 PreparedStatement가 생성되어 ?에 Parameter가 바인딩되어 수행(Parameter 값이 바뀌어도 같은 query로 인식) 됩니다. 이렇게 파싱된 Query문은 재활용(캐싱)되기 때문에 효율적입니다.
-- Mybatis
SELECT id FROM sample WHERE id = #{id}
-- mysql로 넘어온 Query
SELECT id FROM sample WHERE id = ?
-- 실제 수행 Query
SELECT id FROM sample 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에 취약하기 때문에 #{}를 사용하는 것이 좋습니다.
Reference : https://logical-code.tistory.com/25
https://developing-move.tistory.com/4
반응형