이글은 프로젝트에서 mybatis를 사용하는데 ${} 과 #{}차이점에 대해서 적었습니다
Statement와 Prepared Statement
jdbc를사용할때 db connection에서 statement를 얻게되어서 이것을 통해 sql문을 실행시킨다
- SQL문을 실행할 수 있는 객체
- 가장 큰 차이점은 캐시 사용 여부
SQL에서도 실행단계가있습니다.
1) 쿼리 문장 분석
2) 컴파일
3) 실행
📕Statement
- 쿼리문을 수행할 때마다 SQL 실행단계 1~3 단계를 거침
- SQL 문을 수행하는 과정에서 매번 컴파일을 하기 때문에 성능상 이슈 발생
- 실행되는 SQL문을 확인 가능
📘Prepared Statement
- 컴파일이 미리 되어있기 때문에 Statement에 비해 좋은 성능
- 특수문자를 자동으로 파싱해주기 때문에 SQL injection 같은 공격을 막을 수 있음 Prepared Statement에서 바인딩 변수를 사용하였을 때 쿼리의 문법 처리과정이 미리 선 수행되기 때문에 바인딩 데이터는 SQL문법적인 의미를 가질 수 없다.
- "?" 부분에만 변화를 주어 쿼리문을 수행하므로 실행되는 SQL문을 파악하기 어려움
📌Prepared Statement를 사용해야 하는 경우
1) 사용자 입력값으로 쿼리문을 실행하는 경우
- 특수 기호가 들어오더라도 알아서 파싱해주므로 이로 인한 에러를 막을 우 있음
- SQL Injection은 방지가능
2) 쿼리 반복 수행 작업일 경우
왜냐하면 캐시 사용으로 성능이 더 빠르기떄문이다. Statement를사용하면 매번 첫번째 단계부터 이루어지기때문에 성능이 느려집니다.
Statement와 PreparedStatement의 아주 큰 차이는 바로 캐시 사용여부입니다.
Statement를 사용하면 매번 쿼리를 수행할 때마다 계속적으로 단계를 거치면서 수행하지만 PreparedStatement는 처음 한 번만 세 단계를 거친 후 캐시에 담아 재사용을 한다.
만약 동일한 쿼리를 반복적으로 수행한다면 PrepardStatement가 DB에 훨씬 적은 부하를 주며, 성능도 좋다.
#{}을 사용하면
- MyBatis에서 위와 같은 #{}이 사용된 쿼리문이 실행되면 아래와 같이 쿼리문에 ?가 생기며 파싱된다.
쿼리문을 작성할 때 #{}을 사용하는 경우 PreparedStatement를 생성하게 되는데 위의 ?에 파라미터가 바인딩되어 수행된다. 이렇게 파싱된 쿼리문은 재활용(캐싱)되기 때문에 효율적이다.
- 그리고 변수에 작은 따옴표(‘)가 자동으로 붙여 쿼리가 수행되기 때문에 '#{id}'와 같은 식으로 쿼리문을 작성하지 않아도 된다, 이로인해 SQLSyntaxErrorException 오류가 발생을 방지할 수 있다
${} 를 사용하면
값이 넣어진 채로 쿼리문이 수행된다.(즉 ?로 컴파일한게 아니라 ${}값을 넣어서 쿼리문을 실행합니다 반면에 ?로는 처음에만 파싱하고 그다음부터는 파라미터 바인딩만 하기때문이다 )
그렇기 때문에 파라미터의 값이 바뀔 때마다 항상 쿼리문 파싱을 진행해야 한다. 즉, 성능상의 단점이 존재한다.
그리고 쿼리문에 #{}을 사용한 것과 다르게 작은 따옴표(‘)가 붙지 않기 때문에 아래처럼 테이블 이름이나 컬럼 이름을 동적으로 결정할 때 사용할 수 있다.
그래서 SQL Injection이 발생 Prepared는 따옴표를붙여주기때문에 쿼리문을 바꿀수가없다 -> 문법에러 발생시켜버림
https://webstone.tistory.com/50
'Delivery' 카테고리의 다른 글
Mybatis batch처리 성능과 트랜잭션 (0) | 2022.08.01 |
---|---|
테스트코드의 MockMvc utf-8 성능측정 (0) | 2022.07.19 |
피드백 반영 리펙토링 후기 (0) | 2022.07.16 |
코드리팩토링 - (CheckStyle, AccessLevel, Builder, final) (0) | 2022.07.13 |
Home-Delivery 개념 모델링 (0) | 2022.06.28 |