일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- JSONArray 분할
- 스프링 웹플럭스
- 스프링 리액티브 프로그래밍
- spring webflux
- 성능개선
- JSON 분리
- nonblocking
- date_format
- 스테이지에 올리기
- org.json
- multi update
- Meta Table
- 스프링 배치 공식문서
- spring reactive programming
- 날짜형을 문자형으로
- JSON 분해
- jar 소스보기
- 문자형을 날짜형으로
- batchInsert
- 무시하기
- ChainedTransactionManager #분산데이터베이스 #Spring Boot #MyBatis
- str_to_date
- git stage
- JSON 분할
- 마이바티스 트랜잭션
- JSONObject 분할
- 마리아디비
- 스프링 배치 메타 테이블
- JobExecutionAlreadyRunningException
- 폐기하기
- Today
- Total
ebson
[ Spring Framework Transaction, LG CNS DEVON-Framework batch-insert ] 데브온 프레임웍의 배치인서트 사용해 성능 개선하기 본문
[ Spring Framework Transaction, LG CNS DEVON-Framework batch-insert ] 데브온 프레임웍의 배치인서트 사용해 성능 개선하기
ebson 2023. 4. 6. 09:31JPA 개발자들이 스프링 프레임웍을 함께 사용하는 이유 중 하나가 스프링에서는 트랜잭션 관리를 해주기 때문이라고 한다. 내가 실무에서 만난 프로젝트도 스프링 프레임웍 기반의 프로젝트였고 트랜잭션 설정 파일이 있었다. 서비스 메서드를 호출한 후 트랜잭션을 처리하도록 하되 insert, update, delete 으로 시작하는 서비스 메서드에서 예외가 발생하는 경우에 트랜잭션을 롤백하도록 설정할 수 있었다.
트랜잭션 과다 생성으로 인한 성능저하
그런데 서비스 메서드를 호출할 때 적용되는 트랜잭션 설정과 어울리지 않는 일부 소스에서 성능저하를 일으키는 경우가 있었다. 서비스단에서 모아서 처리해야 할 트랜잭션 작업을 컨트롤러에서 for문을 돌면서 개별적으로 요청하고 같은 쿼리를 여러번 호출했기 때문이다.
... (생략)
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="retrieve*" read-only="true" />
<tx:method name="insert*" rollback-for="Exception" />
<tx:method name="update*" rollback-for="Exception" />
<tx:method name="delete*" rollback-for="Exception" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="txPointcut" expression="execution(*.service..impl.*ServiceImpl.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" />
</aop:config>
[소스1] 일부 접두어의 서비스 메서드 호출 이후 트랜잭션을 commit 하거나 rollback 하는 설정의 모습 (*모든 소스는 원본 소스와 세부적으로 다를 수 있음)
// *Controller.java
for(int i=0; i<customerModelArray.length; i++){
... 생략
warrantyService.insertWtysvcingInfoModel(input);
}
[소스2] 컨트롤러에서 반복적으로 서비스단의 INSERT 요청메서드를 호출하고 있는 모습 (*모든 소스는 원본 소스와 세부적으로 다를 수 있음)
트랜잭션 생성 구조 개선 및 배치인서트를 사용해 성능개선
그래서 해당 반복문에 사용되는 파라미터 리스트를 포함한 데이터를 서비스단으로 통째로 넘겨주고, 서비스 단에서도 매퍼의 인자로 VO 대신 List를 넘겨 줌으로서 배치인서트를 할 수 있도록 했다. 이 프로젝트의 경우는 LG CNS에서 스프링 프레임웍을 개량한 데브온 프레임웍이라는 것을 사용 중이었고, 마이바티스 배치인서트를 커스텀한 기능을 지원해서 이것을 사용하기로 했다. PM과 아키텍트의 가이드 메일을 따른 것이었다. 가능한 기 제공되는 메서드를 사용하려는 의도였다.
// *Controller.java
int cnt = warrantyService.insertWtysvcingInfoModelList(input);
mv.addObject("cnt", cnt);
[소스3] 파라미터 리스트를 포함한 데이터를 서비스 메서드로 전달하고 insert 개수를 반환받는 모습 (*모든 소스는 원본 소스와 세부적으로 다를 수 있음)
// *ServiceImpl.java
@Override
public int insertWtysvcingInfoModelList(Map<String, Object> input) {
int count = 0;
try{
... (생략)
count = commonDao.batchInsert("Warranty.insertWtysvcingInfoModel", list, "publ");
} catch(Exception e) {
throw new AjaxException(e);
}
return count;
}
[소스4] 전달받은 데이터에서 파라미터 리스트를 추출하고 반복문을 돌면서 정제 후 배치인서트하는 모습 (*모든 소스는 원본 소스와 세부적으로 다를 수 있음)
이렇게 함으로서 기존에 90초 이상 소요되던 검색 속도가 10초 내외로 단축되었다. 약 900% 속도 향상하는 효과였다. 그래서 프로젝트 전체에서 비슷한 원인으로 검색속도가 느린 페이지들을 모두 찾아서 동일한 작업을 진행했다. 그 결과 비슷한 속도 향상률을 보였다.
피드백
이 작업은 PM과 아키텍트의 가이드 메일을 따라 진행한 작업이었다. 그렇지만 스프링 트랜잭션 설정과 그에 따른 코딩시 주의사항에 대해 생각해 볼 수 있는 기회였다. 앞으로 비슷한 상황이 있을 때에 더 빨리 해결책을 찾을 수 있을 것이라고 생각한다. 아쉬웠던 점은 이와 같은 성능 이슈들을 더 자발적으로 찾아보지 못했다는 점이다.