[MyBatis] xml 매핑 변수로 ${}를 함부로 쓰면 안 되는 이유

2024. 11. 19. 15:32·편안한코딩생활/오류 해결 일지
  1.  #{}와 ${}의 차이점
  2. 나의 실수 사례
  3. #{}를 ${}로 대체했을 때의 문제점

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이 발생하거나 치환이 실패한다.


안전하게 사용하는 방법

  1. MyBatis에서는 SQL에 사용자 입력값을 받을 때 #{}로 파라미터 바인딩을 사용한다.
    ex ) SELECT * FROM users WHERE name = ${name} 
  2. Spring Framework에서는 ${}를 사용할 때 환경 변수나 설정 값을 명확히 지정한다.
     
    ex) <property name="basePath" value="${app.base.path}" />
  3. 주석으로 ${}로 치환되는 값의 의미와 출처를 명확히 설명한다.

결론

${}는 편리하지만,  잘못 사용할 경우 보안 문제와 유지보수 어려움이 생길 수 있다.
꼭 필요한 경우에만 사용하고, 가능하면 #{} 같은 안전한 대체 방법을 사용하는 것이 좋다.(특히 사용자 입력값)

저작자표시 (새창열림)

'편안한코딩생활 > 오류 해결 일지' 카테고리의 다른 글

apache 아파치 웹 서버 실행 경로 여러 개로 만드는 방법  (0) 2025.03.25
스프링부트 한글 깨짐 오류(jpa data utf-8 encoding)  (1) 2023.08.03
페이징 순서대로 정렬 시 주의할 점(rownum 과 order by)  (1) 2023.06.27
타임리프 문법관련 오류(RFC 7230 and RFC 3986)  (0) 2023.06.21
xml 경로 설정 오류  (1) 2023.06.20
'편안한코딩생활/오류 해결 일지' 카테고리의 다른 글
  • apache 아파치 웹 서버 실행 경로 여러 개로 만드는 방법
  • 스프링부트 한글 깨짐 오류(jpa data utf-8 encoding)
  • 페이징 순서대로 정렬 시 주의할 점(rownum 과 order by)
  • 타임리프 문법관련 오류(RFC 7230 and RFC 3986)
니누고
니누고
주니어 개발괴발자
  • 니누고
    진땡이코딩조림
    니누고
  • 전체
    오늘
    어제
    • 분류 전체보기 (93)
      • 편안한코딩생활 (12)
        • 오류 해결 일지 (6)
        • 기타등등 (6)
      • 백 (23)
        • jsp (1)
        • spring boot (7)
        • spring (7)
        • 전자정부프레임워크 (8)
      • 프로젝트 (13)
        • 블로그 제작(중단) (12)
      • 프론트 (3)
        • javascript (3)
      • 데이터베이스 (6)
        • oracle (5)
        • 그 외 (1)
      • cs (6)
        • java (4)
        • cs (1)
        • C (1)
      • 코테 (26)
        • java (25)
        • sql (1)
      • 앱 (0)
        • flutter (0)
        • dart (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    CRUD
    컴퓨터용량줄이기
    코딩테스트
    티스토리챌린지
    문자열 정렬하기
    JPA
    프로그래머스
    오블완
    2017팁스다운
    가장 큰 수 찾기
    카카오 블라인드 채용
    Oracle
    mod_jk.log
    tomcat
    jpa #springboot
    spring
    egov
    Eclipse
    전자정부프레임워크
    oracle함수
    스프링의 기본 파싱전략
    Java
    배열 회전시키기
    apache
    대문자와소문자
    배열
    함수
    iBatis
    SpringBoot
    중복된 문자 제거
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.1
니누고
[MyBatis] xml 매핑 변수로 ${}를 함부로 쓰면 안 되는 이유
상단으로

티스토리툴바