771 words in content
8 minutes for read
사용자 경험을 위해 Event와 Async를 사용한 API 개선

인식한 상황#

약사 사용자가 글을 수정할 때, 작성 과정보다 약 10~20% 정도 느리게 느껴진다는 피드백을 받았다. Postman과 관리자 도구를 통해 실제 응답 시간을 비교한 결과, 수정 시에 약간의 지연이 발생하고 있음을 확인했다.

기존 수정 로직에서는 다음과 같은 과정들이 즉각적으로 처리되고 있었다.

  1. 임시 이미지 처리

    • 이미 Object Storage에 존재하는 임시 이미지는 실제 Article 경로로 옮기는 작업 수행

    • 외부 경로의 이미지는 다운로드 후 Object Storage에 저장하는 작업 수행

  2. 삭제된 이미지 처리

    • 더 이상 필요 없는 이미지는 즉시 Object Storage에서 삭제

이러한 이미지 처리 로직이 모두 수정 API 응답 전에 처리되면서 응답 지연을 발생하고 있었다.

해결 과정#

막상 생각해 보니 굳이 삭제가 보여주기 전에 모두 되어야 하나? 라는 생각을 했다.

즉, 게시글 수정 후 변경된 게시글을 즉시 보여줄 필요가 있으므로 이미지 이동이나 다운로드는 응답 전에 처리해야 한다. 그러나 이미지 삭제 로직은 응답에 즉각적 영향을 미치지 않는다. 따라서 삭제 로직을 이벤트 기반 비동기 처리로 분리하기로 했다.

게시글 수정 완료 후, 삭제해야 할 이미지 목록을 이벤트로 발행하고, 리스너에서 비동기적으로 처리하도록 했다. 이렇게 하면 메인 처리 로직에서는 불필요한 대기 시간을 줄이고, 사용자 응답 시간을 개선할 수 있다고 생각되었다.

이렇게 이벤트 기반으로 삭제 로직을 처리하면, 메인 스레드(요청 처리 흐름)가 이미지 삭제 작업으로 블로킹 되지 않는다. 결과적으로 사용자 응답 시간이 단축된다.

@Service    
@RequiredArgsConstructor
public class ArticleService {
    
    private final ApplicationEventPublisher eventPublisher;
    private final ObjectStorageService objectStorageService;
    
    public Article updateArticle(ArticleRequest request) {
        // ...

        eventPublisher.publishEvent(new UpdateArticleEvent(articleId, willDeleteImageList));
        
        // ...
    }
}
@Component
@RequiredArgsConstructor
public class ImageListener {
    
    private final ObjectStorageService objectStorageService;
    
    @Async
    @EventListener
    public void handleUpdateArticleEvent(UpdateArticleEvent event) {
        // 비동기적으로 이미지 삭제 처리
        objectStorageService.deleteImages(event.getWillDeleteImageList());
    }
}

이렇게 이벤트 기반으로 삭제 로직을 처리하면, 메인 스레드(요청 처리 흐름)가 이미지 삭제 작업으로 블로킹되지 않는다. 결과적으로 사용자 응답 시간이 단축된다.

결과#

  • 개선 전: 작성 대비 약 10~20% 응답 시간 지연 발생

  • 개선 후: 삭제 로직을 이벤트 비동기 처리로 전환한 이후, 수정 시에도 작성 시와 유사한 응답 속도를 확보할 수 있었다.

이를 통해 사용자가 글을 수정하는 과정에서 느끼던 성능 저하 문제를 해소하고, 전반적인 사용자 경험을 개선할 수 있었다.