본문으로 바로가기

[MyBatis] #{}, ${} 변수 차이

category FrameWork/mybatis 2020. 4. 22. 17:57

여태까지 #{}과 ${}의 #{}를 주로 사용하며 '' 유무, 보안상의 이점 정도로만 인식하고 지냈었는데,

이번과 같은 문제점이 발생하면서 주의하면서 사용해야할 일이 생긴 것 같다.

 

문제점

SSMS에서 쿼리 실행시 1초대에서 실행되던 결과가 웹에서 실행시 7분 걸리는 현상 발생

 
1
2
3
4
        SELECT *
          FROM 테이블펑션(CONVERT(VARCHAR(10),DATEADD(M,-12, DATEADD(D,-DAY(GETDATE())+1,GETDATE())),112), 
                         CONVERT(VARCHAR(10),DATEADD(D,-DAY(GETDATE()),GETDATE()),112),  #{PARAMETER}) 
         ORDER BY MM
 

원인

#{} 변수의 경우 PreparedStatement 로써 실행결과시 Index기반을 먼저 탐색하게 되며, 상황에 따른 FullScan을 처리하지 않는다. (특정상황에서는 Index가 우선이 아닌 FullScan이 우선시 되어야할때가 문제가 된다.)

 

해결

1. ${}를 사용하여, 상황에 따라 실행계획이 바뀌어 처리되도록 한다.

2. 해당 쿼리에서 힌트를 사용한다.

   빠른시간에 처리가 최우선이라 ${}를 사용하였으나 Injection 문제가 있으니 주의할것.

 

* #{}과 ${}의 차이점

 

#{}  - PreparedStatement (데이터베이스 옵티마이저에 대한 수행 계획은 항상 동일하다)

      - 들어오는 데이터를 문자열로 인식 함(따옴표가 붙는다. ex: #{asdf} -> 'asdf')

 

${}  - Statement(옵티마이저 수행 계획에 이점을 주는 경우도 존재)

      - 매개변수값을 그대로 전달한다.(따옴표 안붙음 ex: ${asdf} -> asdf)

      - SQL Injection 취약

        (ex: ${asdf}데이터에 --과 같은 주석등 임의로 값을 변경 할 시 쿼리 자체의 결과가 달라지므로

             보안상 취약할 수 있음, 비슷한 예로는 html injection과 같이 심각한 결과를 초래할수도 있음 )

 

 

* PreparedStatement와 Statement에 대하여

데이터의 분포도가 일정하지 않을 경우, 예를 들어 X가 100건있고 Y가 10000만건이 있는 경우의 데이터를 조회한다고 가정 하였을때, 분포도가 좁은 X라는 데이터를 조회할때는 INDEX가 유리하게 작용할것이나 ,

분포도가 넓은 Y라는 데이터를 조회시에는 FULLSCAN이 유리할것이다.

 

PreparedStatement의 경우에는 분포도에 따른 실행계획이 획일화 되어있다.

애초에 미리 준비된 문법을 가지고 하나의 실행계획만 주구장창 사용한다.

static sql의 활용으로 파싱 타임을 절약, 매번 실행계획을 작성하는것을 피하는것이 목적이다.

 

Statement의 경우에는 분포도에 따른 실행결과가 달라진다.

재사용성이 떨어져 파싱 타임을 절약할수는 없지만 매번 실행계획을 작성하여, 위와같은 문제에서는 해결책이 될수도 있다.

 

이처럼 충분한 히스토그램(통계정보)이 없어서 실행계획이 잘못 수립이 되는 경우에는

HINT를 사용하여 올바른 실행계획을 수립하게 하거나, Statement를 사용하면 해결 할수있다.

하지만 애초에 쿼리 생성 단계에서 이런 문제가 생기지 않도록 하는것이 제일 좋은 해결 방안 일것이다.

 

 

참고: https://helols.tistory.com/13

 

Statement vs. PreparedStatement

펌 : http://cafe.naver.com/jspworld.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=31 Statement vs. PreparedStatement PreparedStatement를 사용하는 경우 분포도 이 부분은 preparedStatement를 사용하는 경..

helols.tistory.com

https://sas-study.tistory.com/96

 

Spring mybatis에서 #{ }문법과 ${ }문법의 차이점(feat. SQL Injection)

안녕하세요. 오늘 공유할 내용은 Spring mybatis에서 사용하는 #{} 문법과 ${} 문법의 차이와 ${}문법을 사용했을때 발생할 수 있는 SQL Injection이라는 해킹 방법에 대하여 내용을 공유하고자 합니다. 먼저 Spri..

sas-study.tistory.com