Skip to content

이미지 업로드 분리 및 비동기화

오주은 edited this page Feb 12, 2025 · 1 revision

문제점

채팅 데이터에는 이미지를 첨부할 수 있으며, 이 이미지는 AWS S3에 저장됩니다. 하지만 기존 방식에서는 채팅 저장과 이미지 업로드가 동시에 진행되어 다음과 같은 문제가 발생했습니다.

DB 커넥션 자원 낭비

S3에 이미지가 업로드되는 동안 DB 커넥션이 유지되면서 불필요하게 자원이 점유됩니다. DB 커넥션 수는 제한적이므로, 다수의 요청이 발생하면 성능 저하나 커넥션 부족 문제가 발생할 수 있습니다.

처리 지연

여러 개의 이미지 업로드가 순차적으로 진행될 경우, 전체 요청 시간이 길어질 수 있습니다. 대용량 이미지가 포함되면 이 문제는 더욱 심각해집니다.

트랜잭션 지속 문제

트랜잭션이 불필요하게 길어지면서 DB 잠금(lock)이 길어지고 성능 저하를 초래할 수 있습니다.

위 문제를 해결하기 위해 이미지 업로드를 채팅 저장과 분리하는 방식으로 개선하였습니다. 이를 통해 시스템의 효율성을 극대화할 수 있도록 설계하였습니다.

1️⃣ 이미지 업로드 API 분리 이미지 업로드를 채팅 저장과 독립적으로 처리하기 위해 별도의 이미지 업로드 API를 구축하였습니다.

동작방식

  1. 클라이언트는 이미지 파일을 업로드 API로 전송
  2. 서버는 이미지를 AWS S3에 업로드 후, 해당 이미지의 S3 경로를 반환
  3. 클라이언트는 받은 이미지 URL을 채팅 저장 요청과 함께 전송
@PostMapping
public ResponseEntity<ImageResponse> uploadImages(@RequestPart List<MultipartFile> images) {
    return ResponseEntity.ok(imageService.save(images));
}

2️⃣ 채팅 저장 시 이미지 리스트 전달 클라이언트는 S3에 저장된 이미지 URL 리스트를 받아 이를 채팅 저장 요청에 포함하여 전송합니다.

public record ChatMessageRequest(
    ...
    @Size(max = 5, message = "이미지는 최대 5개까지 첨부할 수 있습니다.")
    List<String> imageUrls
)

3️⃣ DB 저장: 이미지 업로드 분리로 커넥션 사용 최적화 서버는 클라이언트로부터 받은 메시지 정보와 이미지 URL 리스트만 저장하며, 실제 이미지 업로드 과정은 DB와 무관하게 처리됩니다. 이를 통해 DB 커넥션 점유 시간을 줄이고, 트랜잭션 유지 시간을 단축할 수 있습니다.

성능 최적화를 위한 비동기 이미지 업로드 적용 이미지 업로드 성능을 개선하기 위해 비동기 처리(Async) 를 적용하여 AWS S3 업로드를 최적화하였습니다. 이를 통해 여러 이미지를 병렬로 업로드하여 시스템의 처리 속도를 높이고, 서버 리소스를 효율적으로 활용할 수 있습니다.

public List<String> uploadImages(List<ImageFile> images) {
    List<CompletableFuture<String>> imageUploadFutures = images.stream()
            .map(image -> CompletableFuture.supplyAsync(() -> uploadImage(image)))
            .toList();
    return getUploadedImageNamesFromFutures(imageUploadFutures);
}
private List<String> getUploadedImageNamesFromFutures(List<CompletableFuture<String>> futures) {
    List<String> imageNames = new ArrayList<>();
    futures.forEach(future -> {
        try {
            imageNames.add(future.join());
        } catch (final CompletionException ignored) {
        }
    });
    return imageNames;
}

💡 결과 : 이미지 업로드 시간 70% 이상 단축

동기 업로드 vs. 비동기 업로드 비교

기존 방식(동기 업로드) → 10개 이미지 업로드: 759ms 개선 방식(비동기 업로드) → 10개 이미지 업로드: 228ms ➡ 처리 속도 약 3배 향상되었습니다.

image

개선 전

image

개선 후

on:u

docs

Rules

프론트 개발일지

백엔드 개발일지

Clone this wiki locally