
MyBatis 동적 SQL 완벽 가이드 – if, choose, foreach 실무 활용법
MyBatis는 동적 SQL(Dynamic SQL)을 지원하여 조건에 따라 SQL 구문을 유연하게 생성할 수 있습니다. 이 기능은 검색 조건이 많거나, 쿼리 조건이 상황에 따라 달라지는 경우 실무에서 매우 유용합니다. 이 글에서는 <if>, <choose>, <foreach> 등 핵심 동적 SQL 태그의 사용법과 주의점을 예제 중심으로 정리합니다.
1. 동적 SQL이란?
실행 시점의 조건에 따라 SQL 쿼리를 동적으로 조립할 수 있는 기능입니다. 기존 JDBC로는 복잡한 분기 처리가 필요했던 부분을 XML 태그로 간단하게 구현할 수 있습니다.
2. <if> 태그 – 조건부로 WHERE 절 구성
<select id="searchUser" parameterType="map" resultType="User">
SELECT * FROM users
WHERE 1=1
<if test="name != null and name != ''">
AND name = #{name}
</if>
<if test="age != null">
AND age = #{age}
</if>
</select>
tip: WHERE절에서 WHERE 1=1 패턴은 가독성과 유지보수성을 높입니다.
3. <choose>, <when>, <otherwise> – 조건 분기
Java의 switch-case 구문과 비슷한 역할을 합니다.
<select id="selectUserByStatus" resultType="User">
SELECT * FROM users
WHERE
<choose>
<when test="status == 'ACTIVE'">
status = 'ACTIVE'
</when>
<when test="status == 'INACTIVE'">
status = 'INACTIVE'
</when>
<otherwise>
status IS NOT NULL
</otherwise>
</choose>
</select>
4. <foreach> – 리스트, 배열, 컬렉션 반복
IN 절 같은 쿼리를 처리할 때 자주 사용됩니다.
<select id="selectUsersByIds" resultType="User">
SELECT * FROM users WHERE id IN
<foreach item="id" collection="idList" open="(" separator="," close=")">
#{id}
</foreach>
</select>
collection: 파라미터 이름 or @Param 이름
item: 반복되는 값의 변수명
5. WHERE, SET, TRIM – 조건식 조합 최적화
MyBatis는 <where>, <set>, <trim>으로 SQL 조각의 앞뒤 공백, 접두사 등을 자동 제어합니다.
예: <where>
<where>
<if test="name != null"> AND name = #{name} </if>
<if test="age != null"> AND age = #{age} </if>
</where>
예: <set> (UPDATE 문에서 사용)
<update id="updateUser" parameterType="User">
UPDATE users
<set>
<if test="name != null"> name = #{name}, </if>
<if test="age != null"> age = #{age} </if>
</set>
WHERE id = #{id}
</update>
6. 실무 주의사항
- EL 표현식 사용 시 null 체크, 빈 문자열 체크 필수
- <if> 조건 누락 시 SQL 오류 발생 가능
- <foreach>는 빈 리스트 처리 여부 주의
- 단순한 쿼리는 정적 SQL로 유지하는 것이 유지보수에 좋음
7. 결론
MyBatis의 동적 SQL 기능은 복잡한 조건 분기나 반복이 많은 쿼리를 매우 효율적으로 작성할 수 있게 해줍니다. <if>, <choose>, <foreach>, <where> 등을 상황에 맞게 조합하면 유지보수가 뛰어난 SQL 구성도 가능합니다. 실무에서는 꼭 필요한 기능이므로 패턴을 익혀 두는 것이 중요합니다.