문제 발생

원인

**NoSuchFileException**이 발생하는 이유는 **MultipartFile**이 비동기 이벤트 핸들러로 전달되는 과정에서, **MultipartFile**의 입력 스트림이 소비되었기 때문입니다. **MultipartFile**은 한 번만 읽을 수 있는 입력 스트림을 가지고 있으며, 비동기 이벤트 방식으로 처리될 때 그 스트림이 이미 닫혀버릴 수 있습니다.

해결방법

**MultipartFile**의 내용을 직접 사용하기 전에 파일의 내용을 바이트 배열로 변환하여 메모리에 저장합니다. 이를 통해 비동기 처리 중에도 원본 데이터를 유지할 수 있습니다.

@Override
@CacheEvict(cacheNames = "products", allEntries = true)
public void createProduct(Long memberId, RegisterProductDto command) throws Exception {
    ...

    eventPublisher.publishEvent(new ImageUploadEvent(command.productImages());
}

public record ImageUploadEvent(List<byte[]> productImages) {
		public ImageUploadEvent(List<MultipartFile> images, String company, Long productId) {
			  this(
			      images.stream()
			          .map(image -> {
			              try {
			                  return image.getBytes();
			              } catch (IOException e) {
			                  throw new RuntimeException("Error while reading image bytes: " + image.getOriginalFilename(), e);
			              }
			          })
			          .toList()
					  );
		}
}

@Async
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void listenImageUpload(ImageUploadEvent event) {
		imageUploadService.uploadImages(event);
}