픽블엽 서비스를 운영하면서 처음으로 Prometheus + Grafana 조합을 활용해 로그/지표 환경을 구성했다. 이 과정에서 HTTP 응답 속도가 최대 18초까지 지연되는 현상을 발견했는데, 비동기(Async) 처리를 적용하여 이를 500ms 수준으로 단축했다.
아래 그래프를 보면, 특정 구간에서 응답이 최대 18초까지 지연되는 스파이크를 확인 할 수 있다.
해당 시간대의 로그를 추적해보니 엽서 등록 신청 API에서 발생한 문제였다. 구체적인 처리 흐름은 다음과 같았다.
모든 작업이 동기적으로 처리되면서, 이메일 발송이 끝날 때까지 클라이언트가 응답을 받지 못하는 문제가 있었다.
사실 관리자 메일 발송은 성공/실패 여부와 상관없이 엽서 등록 자체에는 영향이 없는 부가 기능이다.
즉, 유저 입장에서는 메일 발송이 완료되기를 기다릴 필요가 전혀 없다.
→ 그런데도 동기 흐름에 묶여 있어 응답 지연을 초래했던 것.
메일 발송을 비동기(Async) 처리로 분리하자!
@Configuration
@EnableAsync //<< 필수
public class AsyncConfig {
@Bean
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(50);
executor.setThreadNamePrefix("Async_Tread-");
executor.setTaskDecorator(new MdcTaskDecorator());
executor.initialize();
return executor;
}
}
@Async
public void sendRegisterMail(RegisterPrePost event) {
...
}
설정은 간단하지만, ExecutorThreadPool을 직접 정의하면 로깅/모니터링, 스레드 풀 사이즈 조정 등 운영 측면에서 더 유연하게 대응할 수 있으니 꼭 커스텀해서 사용하길 추천한다.
단순히 비동기를 도입했을 뿐인데 응답속도를 획기적으로 개선할 수 있었다.
이번 경험을 통해 다시금 느낀 점은,
👉 “중요한 것은 코드를 잘 짜는 것뿐만 아니라, 로직을 어떻게 분리하고 책임을 어디까지 둘 것인지 추상화하는 것” 이다.