[MyBatis] #{}와 ${} 차이?

2023. 1. 26. 16:44Dev.Program/USELESS:<

728x90
	<select id="emailCheck" parameterType="String" resultType="Integer">
		SELECT COUNT(*)
		FROM ZOOM_ACCOUNT_INFO
		WHERE EMAIL = ${email};
	</select>

parameterType 을 map으로만 받아오다가

String 으로 받아오려고 하는데 처음엔 그냥 ${변수명} 을 넣어주었다.

뭔가 #{}에는 map의 key값을 적는다고 생각해서...

그러고 실행하니까

### SQL: SELECT COUNT(*)   FROM ZOOM_ACCOUNT_INFO   WHERE EMAIL = test@test.com;
### Cause: com.microsoft.sqlserver.jdbc.SQLServerException: 여러 부분으로 구성된 식별자 "test@test.com"은(는) 바인딩할 수 없습니다.
; uncategorized SQLException; SQL state [S0001]; error code [4104]; 여러 부분으로 구성된 식별자 "test@test.com"은(는) 바인딩할 수 없습니다.; nested exception is com.microsoft.sqlserver.jdbc.SQLServerException: 여러 부분으로 구성된 식별자 "test@test.com"은(는) 바인딩할 수 없습니다.] with root cause
com.microsoft.sqlserver.jdbc.SQLServerException: 여러 부분으로 구성된 식별자 "test@test.com"은(는) 바인딩할 수 없습니다.

String 으로 들어간 곳에 '' 따옴표가 없이 들어간다. 그래서 바로 에러로그 빡!

이런 기본적이고 간단한 거부터 애먹고 있다^.^

 

	<select id="emailCheck" parameterType="String" resultType="Integer">
		SELECT COUNT(*)
		FROM ZOOM_ACCOUNT_INFO
		WHERE EMAIL = #{email};
	</select>

다시 #{변수명} 으로 바꿔주고 돌려본다.

INFO  j.sqlonly - SELECT COUNT(*) FROM ZOOM_ACCOUNT_INFO WHERE EMAIL = 'test@test.com'

이제 따옴표까지 잘 달고 들어간다! 성공!

진짜 별 거 아닌데 이렇게 시간 쓸 일이냐고.... 부들부들

 

보통 #은 값에 $는 컬럼명이나 테이블 명에 사용한다.

좀 더 정리하자면

${}
Statement로 매개변수 값 그대로 전달
값 그대로 보내기 때문에 들어오는 데이터에 따옴표가 붙지 않는 거 였다.

#{}
PreparedStatement 를 생성하여 매개 변수 값을 안전하게 설정
PreparedStatement 가 제공하는 set 계열 메소드를 사용하여 매개변수 ?를 대체할 값을 지정
들어오는 데이터를 문자열로 인식하기 때문에 자동으로 따옴표 붙음

몰랐는데 ${} 는 SQL Injection에 취약해서 보안 문제가 있다고 한다.
아무래도 값을 그대로 전달하다보니 #{}보다 보안적인 측면에서 별로인 듯.
그러나 테이블명이나 컬럼명에 따옴표가 붙으면 인식을 못하기 때문에
ORDER BY, GROUP BY 등에서 사용할 때엔 ${} 사용을 해야한다.

아무튼 데이터 주고받을 때에는 되도록이면 #{} 사용하기!
훨씬 더 안전하고 빠르다!

728x90