- #{}와 ${}의 차이점
- 나의 실수 사례
- #{}를 ${}로 대체했을 때의 문제점
1) #{}와 ${}의 차이점
둘 다 mybatis에서 동적 sql을 작성하기 위하여, 변수를 매핑하는 방법이다.
#{} : preparedStatement . 변수가 ' ' 형식으로 넘어온다.
ex) A.COL1 = #{COL1}
=> A.COL1 = 'COL1'
${} : statement => 변수가 문자열 그대로 넘어온다.
ex) A.COL1 = ${COL1}
=> A.COL1 = COL1
2)나의 실수 사례
쿼리 where 조건에서 파라미터로 넘어온 값과 컬럼 값을 바로 비교하는 것이 아니라,
파라미터 값에 따라 다른 컬럼 값을 조회해야하는 쿼리를 짜야 하는 경우가 생겼다.
<if test = ' COL1 == "COL1"'>
AND A.COL1 = 'Y'
</if>
<if test = ' COL2 == "COL2"'>
AND A.COL2 = 'Y'
</if>
즉 위와 같이 조건문을 작성해야 했는데, 컬럼 갯수가 너무 많아서 다른 방법이 없나 생각해봤다.
<if teset = ' COL1 != "" and COL1 != null'>
AND A.${COL1} = 'Y'
</if>
그래서 위와 같이 조회하면 파라미터로 넘어온 값이 바로 컬럼이름으로 매핑되니까, 컬럼 갯수만큼 조건문을 작성하지 않아도 되는 좋은 방법이라고 생각했다.
하지만 배포 전 보안 점검에서 이 부분이 지적을 받았고, 다시 원래 쿼리로 수정을 하게 되었다.
3) #{}를 ${}로 대체했을 때의 문제점
1. 문법적 충돌
${}는 템플릿 언어나 설정 파일(Spring, MyBatis, Maven 등)에서 동적으로 값을 치환할 때 사용된다.
XML에서 ${}를 잘못 쓰면 문법 해석 과정에서 오류가 발생하거나, 예상하지 못한 값으로 치환될 수 있다.
특정 프레임워크에서 ${}는 변수 치환이나 예약된 의미로 사용되기 때문에, 충돌하거나 의도와 다른 동작이 발생할 가능성이 높다.
2. 보안 문제
${}를 통해 외부 입력값을 직접 삽입하거나 평가하면 보안 문제가 생길 수 있다.
- SQL 인젝션 위험
MyBatis에서 ${}를 사용하면 SQL 구문이 그대로 삽입되기 때문에, 악의적인 입력값이 들어올 경우 시스템이 공격당할 수 있다.
예를 들어 다음 코드는 SQL 인젝션에 취약하다:
<select id="getUser" resultType="User"> SELECT * FROM users WHERE name = ${name} </select>
사용자가 "' OR '1'='1" 같은 값을 입력하면 모든 데이터가 노출된다.
이를 방지하기 위해 ${} 대신 #{}를 사용해 파라미터 바인딩을 처리해야 한다.
3. 유지보수 어려움
${}를 많이 사용하면 코드 가독성이 떨어진다.
정적인 값과 동적으로 치환되는 값을 구분하기 어려워지고, 설정 파일이 많아질수록 치환 순서와 충돌 문제를 파악하기 어렵다.
4. 의도치 않은 치환
${}는 외부 환경 변수나 시스템 속성을 매핑하려고 시도하는데, 해당 값이 없으면 오류가 발생할 수 있다.
예를 들어 ${env.HOME}을 사용하는 경우, 값이 설정되지 않았다면 NullPointerException이 발생하거나 치환이 실패한다.
안전하게 사용하는 방법
- MyBatis에서는 SQL에 사용자 입력값을 받을 때 #{}로 파라미터 바인딩을 사용한다.
ex ) SELECT * FROM users WHERE name = ${name} - Spring Framework에서는 ${}를 사용할 때 환경 변수나 설정 값을 명확히 지정한다.
ex) <property name="basePath" value="${app.base.path}" />
- 주석으로 ${}로 치환되는 값의 의미와 출처를 명확히 설명한다.
결론
${}는 편리하지만, 잘못 사용할 경우 보안 문제와 유지보수 어려움이 생길 수 있다.
꼭 필요한 경우에만 사용하고, 가능하면 #{} 같은 안전한 대체 방법을 사용하는 것이 좋다.(특히 사용자 입력값)
'편안한코딩생활 > 오류 해결 일지' 카테고리의 다른 글
스프링부트 한글 깨짐 오류(jpa data utf-8 encoding) (0) | 2023.08.03 |
---|---|
페이징 순서대로 정렬 시 주의할 점(rownum 과 order by) (0) | 2023.06.27 |
타임리프 문법관련 오류(RFC 7230 and RFC 3986) (0) | 2023.06.21 |
xml 경로 설정 오류 (0) | 2023.06.20 |