[개발일지] 230504 IN절 안의 foreach문

오늘 새로 배운 내용

foreach문을 이용해 반복해서 쿼리를 날릴 때, 전체적인 쿼리를 날리는 것보다 IN절 안에서 foreach문을 이용해 반복하는 게 효율이 더 좋다.

아래쿼리처럼 foreach문을 작성하면 전달받은 list의 크기만큼 전체 쿼리가 발생하기 때문에 비효율적이다.

<foreach collection="list" item="userId" separator="UNION ALL">
	SELECT *
	FROM users
	WHERE user_id = #{userId}
</foreach>

예를 들어 userId가 들은 list의 사이즈가 10이면 "SELECT * FROM users WHERE user_id = #{userId}" 전체 쿼리가 10번이 날아간다.

 

하지만 전체 쿼리를 10번 반복할 필요 없이 IN절 안에 foreach문을 작성해 주면 전체쿼리 발생수가 한 번으로 줄어들어 쿼리 발생 비용을 줄일 수 있어 더 효율적이다.

 

아래 쿼리처럼 IN절 안에 foreach문을 작성할 수 있다.

SELECT *
FROM users
WHERE user_id IN 
<foreach collection="list" item="userId" separator="," open="(" close=")">
  #{userId}
</foreach>

 

 

사실 foreach문을 저렇게 작성하면 전체 쿼리가 반복해서 날라가는줄 몰랐었다.

 

 

고민한 내용

컨트롤러에서 서비스의 메서드를 호출할때 파라미터로 객체 전체를 전달할 것인지, 객체 안의 필드값 하나만 전달할 것인지? 

-> 서비스에서 필요한 필드 값이 객체가 갖고있는 2개의 필드값이 필요했기 때문에 전체를 전달해도 되고, 객체 안의 필드값 하나만 전달해서 그 필드값을 이용해 db에서 전체 객체를 조회할 수 있었기 때문에 하나만 전달해도 되는 상황이다. (db는 최소한 1번은 조회해야 했기 때문에 join쿼리를 이용해 객체를 가져올 수 있다.)

 

그런데 파라미터로 객체 전체를 전달하는 것보다 필드값 하나만 전달하는 방식이 더 컨트롤러에서 호출하는 메서드의 의미가 더 잘 드러난다고 생각했고, 계층간 전송되는 데이터의 양도 줄일 수 있다.

 

그리고 테스트 코드 작성시 전체 객체를 생성할 필요가 없기 때문에 테스트하기도 더 수월해진다고 생각을 했었다.