이 게시글은 비동기 프로그래밍에 대해 공부하고 적용한 경험에 대한 회고록을 작성했습니다.
⇒ Async 한 통신 으로 Main Thread가 Task를 처리하는 것이 아니라 Sub Thread에게 Task를 위임하는 행위
=> Spring에서 비동기 프로그래밍을 하기 위해서는 ThreadPool을 정의할 필요가 있다.
- CorePoolSize 만큼 쓰레드를 생성
- Queue에 Task를 담고, Queue가 다 차면
- MaximumPoolSize만큼 새로운 쓰레드를 생성
- CorePoolSize를 너무 크게 설정할 경우 ⇒ 사용되지 않는 쓰레드들이 있을 수 있어서 자원이 낭비됨
- 2가지 Exception
- IllegalArgumentException
- corePoolSize<0
- keepAliveTime<0
- maximumPoolSize ≤0
- maximumPoolSize < corePoolSize
- NullPointerException
- WorkQueue가 null인 경우
if ( Thread 수 < CorePoolSize )
new Thread 생성
if ( Thread 수 > CorePoolSize )
Queue 요청 추가
if ( Queue Full && Thread 수 < MaxPoolSize )
new Thread 생성
if ( Queue Full && Thread 수 > MaxPoolSize )
요청 거절
Spring 프레임워크 에서 비동기 프로그래밍을 하기 위해서는 Spring 프레임워크가 필요함
Async하게 동작하기 위해서 빈을 프록시 객채로 맵핑하고 프록시 객체를 리턴해줌
현재 개발하는 어플리케이션에서 사용자가 새로고침을 눌렀을 때, 깃허브 커밋 수를 갱신해주고, 해당 유저의 커밋수가 목표치에 도달했는지를 확인하고 다른 캐릭터를 부여해주는 API를 개발했다.
어플리케이션 특정상 여러 사용자가 동시에 누를 경우에도 대비를 해야하는데, 많은 유저들이 새로고침을 동시에 누른다면 동기 프로그래밍으로는 처리하는데 시간이 많이 걸릴꺼 같다는 생각이 들었다.
그래서 이번에 해당 로직들에 비동기 프로그래밍을 하는 방식으로 리팩토링을 해보고 성능이 얼마나 달라질까 궁금점이 생겨 Apache Jmeter을 사용하여 동기 프로그래밍과 비동기 프로그래밍의 성능테스트를 진행했다. 결과는 놀라웠다.
먼저 비동기 프로그래밍을 하기위해서 @Async 어노테이션을 사용했다. @Async을 사용하면 매우 간단하게 비동기 프로그래밍을 구현할 수 있었다.
@Async
@Async Annotation은 Spring에서 제공하는 Thread Pool을 활용하는 비동기 메소드 지원 Annotation이다.
Async을 사용하기 위해서는 @EnableAsync 설정을 해줘야 한다.
@EnableAsync
@Configuration
public class AsyncConfig {
}
그 다음 ThreadPool 설정을 해주고
@Configuration
public class AppConfig {
@Bean(name = "defaultTaskExecutor",destroyMethod = "shutdown")
public ThreadPoolTaskExecutor defaultTaskExecutor(){
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(200);
executor.setMaxPoolSize(300);
return executor;
}
}
이렇게 원하는 메서드에 @Async 어노테이션을 설정해주면 끝난다!
각 메서드에 Thread 이름을 출력하게 하고
해당 API를 호출하게 되면
이런식으로 비동기 처리가 되게 된다!
Apache Jmeter 성능테스트를 이용해서 간단하게 성능테스트를 진행해봤다.
결과는
동기 프로그래밍 했을 때
비동기 프로그래밍 했을 떄
처리량은 일정 시간 동안 처리한 요청의 수로 동기 프로그래밍을 했을 때보다 비동기 프로그래밍을 했을 때 약 2배 정도 차이 나는 것을 볼 수 있다!
이번에 기존에 있던 코드를 리팩토링하면서 비동기 프로그래밍의 효과를 직접 체감할 수 있었다. @Async 어노테이션을 이용해 코드를 비동기적으로 실행시키는 것으로 처리량이 2배 가까이 증가한 결과를 확인할 수 있었다. 이를 통해 비동기 프로그래밍의 중요성과 활용 가능성에 대해 새롭게 깨닫게 되다. 하지만 비동기 프로그래밍 자체가 자원이 들기 때문에 무조건적인 비동기 프로그래밍은 피해야 한다고 한다. 특정 상황에서 적절하게 사용을 또 해봐야 겠다.
처음으로 Jmeter를 이용해서 성능테스트도 진행했는데, 바로바로 직관적으로 볼 수 있다는 점이 좋았고, 앞으로 성능 개선시켜 유의미한 결과를 얻어 낼 수 있게 하고 싶다.
Reference
패스트캠퍼스 10개 프로젝트로 완성하는 백엔드 웹개발(Java/Spring) 초격차 패키지 Online. - IT 서비스 회사에서 사용하는 진짜 프로젝트 맛보기 강의