본문 바로가기
Programming

[Mybatis] #{}과 ${}의 차이

by BTC_아리 2023. 10. 5.

안녕하세요 여러분 일단고입니다!

지난번에 이어서 Mybatis에 대해 좀 더 알아보는 시간을 갖겠습니다.

저번 시간에 쿼리문의 결과 값을 객체로 반환받는 방법에 대해 알았다면, 이번엔 쿼리문에 파라미터를 전달할 때 사용되는 설정 : 플레이스 홀더 #{}와 ${}의 차이에 대해서 알아보겠습니다.


MyBatis는 데이터베이스와의 상호 작용을 쉽게 만들어주는 자바 퍼시스턴스 프레임워크 중 하나입니다. MyBatis를 사용하면 SQL 쿼리를 정의하고 실행할 때 플레이스 홀더로 #{} 또는 ${}를 사용할 수 있습니다. 이 글에서는 #{}와 ${}의 차이점과 언제 어떤 것을 사용해야 하는지에 대해 알아보겠습니다.

 

#{}: Prepared Statements

#{}은 MyBatis의 Prepared Statements 기능을 사용할 때 주로 쓰입니다. Prepared Statements는 SQL 쿼리를 미리 컴파일하여 쿼리에 전달되는 데이터를 파라미터화할 수 있는 방법을 제공합니다. #{}을 사용하면 MyBatis는 입력된 값에 대한 타입 변환과 SQL 인젝션 방지를 자동으로 처리합니다.

 

예를 들어, 다음과 같은 쿼리가 있다고 가정해봅시다.

# mapper
<select id="selectUserById" parameterType="int" resultType="User">
  SELECT * FROM users WHERE id = #{userId}
</select>

 

# mysql에서 받는 쿼리문 및 컴파일 결과
SELECT * FROM users WHERE id = ?

 

# 실제 실행 : 파라미터 값으로 변경되어 실행됨
SELECT * FROM users WHERE id = '100'

위의 예제에서 #{userId}는 사용자로부터 입력받은 userId 값을 안전하게 쿼리에 매핑해줍니다.

 

${}: String Substitution

${}은 SQL 문자열 대체를 수행할 때 사용됩니다. MyBatis는 ${} 안의 내용을 그대로 SQL 쿼리에 삽입합니다. 이는 동적인 SQL을 작성할 때 유용합니다. 하지만 주의해야 할 점은 ${}을 사용할 때 사용자 입력을 그대로 삽입하기 때문에 SQL 인젝션 공격에 취약할 수 있습니다.

 

예를 들어, 다음과 같은 쿼리가 있다고 가정해봅시다.

# mapper
<select id="selectUserByName" parameterType="string" resultType="User">
  SELECT * FROM users WHERE username = '${username}'
</select>

 

# mysql에서 받는 쿼리문 및 컴파일 결과
SELECT * FROM users WHERE id = '100'

 

# mysql에서 받는 쿼리문 및 컴파일 결과
SELECT * FROM users WHERE id = '100'

위의 예제에서 ${username}은 사용자로부터 입력받은 username 값을 그대로 쿼리에 삽입합니다. 이 경우, 사용자가 악의적인 SQL 코드를 입력하면 SQL 인젝션 공격에 노출될 수 있습니다.

 

언제 어떤 것을 사용해야 할까?

  • #{}
    • 대부분의 경우에는 #{}을 사용하는 것이 안전하며, SQL 인젝션을 방지하는 데 도움이 됩니다. 즉, 악의적인 쿼리 주입을 예방할 수 있습니다. 특히 사용자 입력을 쿼리에 바인딩할 때 사용하세요.
  • ${}
    • 동적인 SQL을 작성하거나, 쿼리의 테이블 명, 컬럼 명 등을 동적으로 바꿔야 하는 경우에만 ${}을 사용하세요. 그러나 주의해야 하며, 사용자로부터 입력 값을 ${}으로 직접 삽입하는 경우에는 반드시 입력 값의 유효성을 검증하고 방어적으로 대처해야 합니다.

 


#{}${}은 MyBatis에서 SQL 작성 시의 유연성과 안전성을 제공하는 중요한 기능입니다. 올바르게 사용하면 SQL 쿼리를 보다 효과적으로 작성하고 실행할 수 있습니다.

그럼 다음시간에 만나요 안녕!

댓글