본문 바로가기
[개발] 프레임워크/Spring

MyBatis useGeneratedKeys 조심히 사용하기

by Devsong26 2024. 10. 7.

회사 코드 중에 알림톡을 발송하는 로직이 있었고 로직은 다음과 같이 구현이 되어 있었습니다.

 

 

  • 비즈니스 로직을 수행
  • 알림톡 이벤트 발행
  • 알림톡 이벤트 소비
  • 알림톡 발송

 

이벤트를 발행할 때는 다음과 같이 비즈니스 로직에서 수행된 결과값 중 하나를 사용하고 있었습니다.

이를 컬럼 'happyCallId' 라고 하겠습니다.

 

아래는 이벤트 발행에 사용되는 JSON 객체입니다.

{
	"happyCallId" : 1234567 [Long 타입]
	...
}

 

 

id의 값의 정상적인 범위는 2_000_000 ~ 2_500_000 범위 값이 되어야 합니다.

하지만 간헐적으로 알림톡에 발행될 때 입력되는 id 값이 17_000_000 ~ 18_000_000  범위 값인 경우가 있었습니다.

 

여러가지 로그를 찍으며 의심되는 범위를 좁혀갔고 이상한 코드를 발견하게 되었습니다.

특정 조건에 따라 해피콜 로그 데이터를 생성하는 쿼리인데 다음과 같습니다.

 

<insert id="..." parameterType="HappyCall" useGeneratedKeys="true" keyProperty="srl" keyColumn="srl">
	INSERT INTO happy_call_log (...) values (...)
</insert>

 

useGeneratedKeys, keyProperty, keyColumn은 생성된 쿼리의 결과를 이용하여 key 값을 매핑해줄 때 사용하는 설정입니다.

자세한 설명은 아래와 같습니다.

 

useGeneratedKeys

  • 데이터베이스에서 자동으로 생성되는 키 값(예: Auto Increment ID, 시퀀스 값)을 MyBatis가 자동으로 가져오게 하는 옵션

keyProperty

  • 자동으로 생성된 키 값을 매핑할 Java 객체의 필드를 지정하며, MyBatis는 이 필드에 데이터베이스에서 반환된 키 값을 저장합니다. 

keyColumn

  • 데이터베이스에서 자동 생성된 키 값이 저장되는 컬럼 이름을 지정하며, 주로 키 값이 여러 컬럼에서 생성되는 경우나, 데이터베이스의 키 생성 컬럼이 명시적으로 필요할 때 사용됩니다. 

 

위의 쿼리는 happy_call_log의 로우 데이터가 생성되면 srl 컬럼의 값을 입력된 파라미터 객체에 srl 필드에 매핑시켜버립니다.

 

알림톡 발송 이벤트 발송 전 비즈니스 로직이 수행될 때, 위의 쿼리에서 사용되는 happyCall 객체의 srl이 불변이라는 가정으로 로직이 구현되어 있었습니다. 하지만 쿼리가 실행되고 나서 happy_call_log의 srl로 매핑되어 쓰이다 보니 알림톡에서 예상치 못한 예외가 지속적으로 발송하였습니다. 

 

불필요한 useGeneratedKeys, keyProperty, keyColumn 설정을 제거하였고 이를 통해 문제를 해결하였습니다.

 

레거시 코드를 다루다 보면 의도를 알 수 없는 코드들이 많이 보여 주의가 필요합니다.