마이바티스를 이용하면 SQL문에 파라미터를 쓸 수 있다.
myBatis 공식문서에 Parameters 섹션에 기술된 #{} 과 String substitution의 ${} 이 그것들이다. 예를들어,
<select id="search" resultType="ArticleVO">
SELECT *
FROM article
WHERE article_id = #{articleId}
</select>
위와 같이 사용하거나 WHERE article_id = '${articleId}'
와 같이 사용하면 파라미터를 전달해줄 수 있다.
@Mapper
public interface ArticleMapper {
public List<ArticleVO> selectSearchArticles(@Param("articleId") String articleId);
}
위 매퍼인터페이스의 selectSearchArticles
메서드를 통해 스트링 형태의 파라미터를 전달하는 것이다.
그렇다면 #{}, ${} 의 차이는 무엇일까?
#{} 을 사용하게 되면 PreparedStatement를 생성한다.
SELECT *
FROM article
WHERE article_id = ?
위와 같이 물음표에 파라미터가 바인딩되어 수행된다.
이렇게 파싱된 쿼리문은 캐싱되어 효율적이다.
작은 따옴표가 붙어 파싱되기에 SQL 인젝션으로부터 ${}에 비해 안전하다.
${}을 사용하면 값이 입력된 상태로 쿼리문이 수행된다.
따라서 파라미터가 변경될때마다 항상 쿼리문 파싱이 진행되며 성능상 불리하며, 작은 따옴표가 붙지 않기 때문에 스트링을 쿼리로 인식할 수 있어 SQL 인젝션에 취약하다.
그러나 요녀석은 sql문의 메타데이터, 즉 테이블, 컬럼명에 쓸 수 있다는 장점(?)이 있다.
그러나 결국 테이블, 컬럼명에 쓰는것도 아래와 같은 SQL 인젝션의 위험이 있지 않을까한다.
SELECT * FROM ${tableParam}
->
SELECT * FROM user_data; DROP TABLE users;
보안과 성능상 차이는 알고있었지만 SQL 파라미터(#{})가 테이블명에 사용되지 않아 새롭게 찾아본 내용인데, 안전한 쿼리문을 위해서는
1. 테이블명을 분리해 매퍼를 만들어주던지
2. 클라이언트가 테이블명을 임의로 줄 수 없도록 만들어야할 것 같다.
'개발 > 자바' 카테고리의 다른 글
서블릿이 static resouces 들을 처리하지 못하는 경우(css, js, 이미지 로딩 실패) (0) | 2023.02.13 |
---|---|
myBatis 3) 쿼리에 파라미터에 객체 전달 시 프로퍼티 찾지 못할 때 (0) | 2023.02.10 |
자바의 데이터 타입과 메모리 영역 (0) | 2023.01.03 |
자바 클래스패스(classpath)란? (0) | 2022.12.19 |