튜토리얼

대용량 파일 업로드, 어떤 전략이 현명할까요? Pre-signed URL vs. 백엔드 프록시 비교

강코의 코딩 일기 2026. 7. 19. 13:14
반응형

대용량 파일 업로드 고민이신가요? Pre-signed URL과 백엔드 프록시 방식의 장단점을 비교 분석하여, 여러분의 프로젝트에 최적화된 파일 처리 전략을 쉽고 자세하게 알려드립니다.

안녕하세요, 개발 입문자 여러분! 여러분이 만드는 웹 서비스에 사용자들이 사진이나 동영상 같은 큰 파일을 업로드해야 하는 기능이 필요하다고 상상해 봅시다. 처음에는 간단하게 만들 수 있을 것 같지만, 막상 구현하려고 하면 생각보다 쉽지 않다는 것을 깨닫게 될 거예요.

대용량 파일 업로드 처리 전략 비교: Pre-signed URL을 이용한 클라이언트 직접 업로드와 백엔드 프록시를 통한 안정적인 업로드 방식 비교 분석 - proxy, proxy server, free proxy, online proxy, proxy site, proxy list, web proxy, web scraping, scraping, data scraping, instagram proxy, sneaker proxy, twitter proxy, facebook proxy, supreme bot proxy, residential proxy, residential ip, datacenter ip, web crawler, ip rotation, laptop, computer, internet, notebook, network, gray data, gray facebook, gray online, gray network, gray internet, gray web, gray social, gray media, gray server, proxy, proxy, proxy, proxy, proxy

Image by kevinandthepup on Pixabay

대용량 파일 업로드, 왜 이렇게 어려울까요? (문제 발생)

사용자가 100MB 이상의 동영상 파일이나 고해상도 이미지를 여러분의 서비스에 업로드한다고 가정해 봅시다. 가장 기본적인 방법은 사용자의 웹 브라우저 (클라이언트)가 파일을 여러분의 백엔드 서버로 직접 보내고, 백엔드 서버는 이 파일을 받아서 어딘가에 저장하는 방식입니다. 그런데 이런 방식에는 다음과 같은 문제들이 발생할 수 있습니다.

  • 느린 업로드 속도: 파일이 크면 클수록 서버로 전송하는 데 시간이 오래 걸립니다. 사용자는 답답함을 느끼겠죠.
  • 서버 과부하: 수십, 수백 명의 사용자가 동시에 대용량 파일을 업로드하려고 하면, 여러분의 백엔드 서버는 모든 파일을 처리하느라 매우 바빠질 겁니다. 마치 좁은 도로에 많은 차가 한꺼번에 몰리는 것처럼 서버에 트래픽(데이터 이동량)이 몰려 병목 현상이 발생하고, 결국 서버가 느려지거나 멈춰버릴 수도 있습니다.
  • 타임아웃 문제: 파일 업로드가 너무 오래 걸리면, 서버와의 연결이 중간에 끊어져버리는 타임아웃 현상이 발생할 수 있습니다.
  • 확장성 부족: 서비스 규모가 커져서 더 많은 사용자가 파일을 업로드해야 할 때, 서버를 늘리는 것만으로는 한계가 있습니다.

이러한 문제들은 사용자 경험을 나쁘게 만들고, 서비스 운영에 큰 어려움을 초래할 수 있습니다. 그렇다면 왜 이런 문제가 발생하는 걸까요?

파일 업로드 방식, 무엇이 문제일까요? (원인 분석)

가장 흔한 파일 업로드 방식은 클라이언트가 파일을 백엔드 서버로 전송하고, 백엔드 서버가 다시 이 파일을 클라우드 스토리지(예: AWS S3, Google Cloud Storage) 같은 영구 저장소에 저장하는 방식입니다. 이 과정에서 백엔드 서버는 단순히 파일을 전달하는 '중간 다리' 역할만 할 뿐인데도, 모든 파일 데이터를 직접 받아야 합니다.

이것이 문제의 핵심입니다.

  • 불필요한 서버 자원 소모: 백엔드 서버는 파일 데이터를 처리하기 위해 CPU, 메모리, 네트워크 대역폭 등 귀중한 자원을 소모합니다. 이는 실제 서비스 로직을 처리해야 할 서버의 부담을 가중시킵니다.
  • 네트워크 지연 (Latency): 파일이 클라이언트 -> 백엔드 서버 -> 클라우드 스토리지로 두 번의 네트워크 구간을 거치게 됩니다. 이로 인해 파일 업로드에 걸리는 네트워크 지연(데이터가 오가는 데 걸리는 시간)이 증가합니다.
  • 비용 증가: 백엔드 서버의 트래픽이 많아지면 서버를 더 많이 늘려야 하거나, 더 좋은 사양의 서버를 사용해야 합니다. 이는 곧 운영 비용 증가로 이어집니다.

결국, 대용량 파일 업로드에서는 백엔드 서버가 파일 데이터를 직접 처리하는 것이 비효율적이며, 서비스의 성능과 안정성을 저해하는 주요 원인이 됩니다. 이러한 문제를 해결하기 위해 두 가지 주요 전략이 있습니다. 바로 Pre-signed URL을 이용한 클라이언트 직접 업로드백엔드 프록시를 통한 안정적인 업로드 방식입니다.

대용량 파일 업로드 처리 전략 비교: Pre-signed URL을 이용한 클라이언트 직접 업로드와 백엔드 프록시를 통한 안정적인 업로드 방식 비교 분석 - giraffes, heads, ossicones, giraffe heads, artiodactyl, ruminant, large ruminant, large animals, large mammals, animals, mammals, nature, spotted, large, giraffes, giraffes, giraffes, giraffes, giraffes, animals

Image by birder62 on Pixabay

대용량 파일 업로드 전략 비교: Pre-signed URL vs. 백엔드 프록시 (해결 과정)

이제 대용량 파일 업로드 문제를 해결하기 위한 두 가지 핵심 전략을 자세히 살펴보겠습니다. 각각의 장단점을 비교 분석하여 여러분의 프로젝트에 어떤 방식이 더 적합할지 판단하는 데 도움을 드리겠습니다.

1. Pre-signed URL을 이용한 클라이언트 직접 업로드

이 방식은 백엔드 서버의 부담을 획기적으로 줄여주는 똑똑한 방법입니다. 'Pre-signed URL'은 미리 서명된(Pre-signed) URL이라는 뜻으로, 클라우드 스토리지 서비스(예: AWS S3)에서 특정 파일에 일정 시간 동안만 접근할 수 있는 임시 URL을 발급해 주는 기능입니다.

작동 방식:

  1. 클라이언트가 백엔드 서버에 "나 파일을 업로드하고 싶어!"라고 요청합니다.
  2. 백엔드 서버는 클라우드 스토리지에 "이 파일명으로 파일을 올릴 수 있는 임시 URL을 줘"라고 요청하고, 클라우드 스토리지는 Pre-signed URL을 생성하여 백엔드에 전달합니다.
  3. 백엔드 서버는 이 Pre-signed URL을 클라이언트에 돌려줍니다.
  4. 클라이언트는 백엔드를 거치지 않고, 전달받은 Pre-signed URL을 이용해 클라우드 스토리지에 파일을 직접 업로드합니다.
  5. 업로드가 완료되면 클라이언트는 백엔드에 "파일 업로드 완료했어!"라고 알려줍니다.

이 그림을 상상해 보세요: 백엔드는 택시 운전사가 아니라, 택시를 탈 수 있는 쿠폰(Pre-signed URL)을 주는 역할만 하고, 실제 택시(클라우드 스토리지)를 타고 목적지(파일 업로드)까지 가는 건 클라이언트가 직접 하는 방식입니다.

장점:

  • 백엔드 부담 감소 및 확장성: 백엔드 서버는 URL만 생성할 뿐, 실제 대용량 파일 데이터를 직접 처리하지 않습니다. 덕분에 서버 자원을 아낄 수 있고, 동시에 많은 사용자가 파일을 업로드해도 서버가 과부하될 걱정이 줄어들어 확장성이 매우 좋습니다.
  • 빠른 업로드 속도: 파일이 클라이언트에서 클라우드 스토리지로 바로 전송되므로, 중간에 백엔드 서버를 거치는 과정이 생략되어 네트워크 지연이 감소하고 업로드 속도가 빨라집니다.
  • 비용 효율적: 백엔드 서버의 트래픽이 줄어들기 때문에 서버 운영 비용을 절감할 수 있습니다.

단점:

  • 보안 고려 사항: Pre-signed URL이 외부에 노출될 경우, 해당 URL을 아는 누구나 파일을 업로드하거나 다운로드할 수 있는 문제가 발생할 수 있습니다. 따라서 유효 기간을 짧게 설정하고, 반드시 필요한 사용자에게만 발급하는 등의 보안 대책이 중요합니다.
  • 클라이언트 책임 증가: 업로드 진행 상황 표시, 에러 처리, 재시도 로직 등 파일 업로드와 관련된 복잡한 로직을 클라이언트(프론트엔드)에서 직접 구현해야 하는 부분이 많아집니다.
  • CORS 문제: 웹 브라우저에서 다른 도메인의 클라우드 스토리지로 직접 요청을 보낼 때 발생하는 CORS(Cross-Origin Resource Sharing) 보안 정책 문제를 해결하기 위해 클라우드 스토리지 버킷에 적절한 CORS 설정을 해주어야 합니다. (CORS는 웹 브라우저가 보안을 위해 다른 출처(도메인)의 리소스에 접근하는 것을 제한하는 정책입니다.)
  • 파일 검증의 복잡성: 파일 내용 검증(예: 바이러스 검사, 유해성 검사)을 업로드 전에 백엔드에서 미리 하거나, 업로드 후 별도의 후처리 과정을 거쳐야 합니다.

코드 예시 (Python Flask + AWS S3 Pre-signed URL 생성):

from flask import Flask, jsonify, request
import boto3 # AWS SDK for Python

app = Flask(__name__)
s3 = boto3.client('s3', region_name='ap-northeast-2') # S3 클라이언트 초기화

@app.route('/generate-presigned-url', methods=['POST'])
def generate_presigned_url():
    filename = request.json.get('filename')
    filetype = request.json.get('filetype')
    
    # S3에 저장될 파일 경로와 이름
    object_name = f"uploads/{filename}" 

    try:
        # Pre-signed URL 생성 (HTTP PUT 메서드, 5분 유효)
        response = s3.generate_presigned_url(
            'put_object', # 파일을 업로드하는 작업
            Params={
                'Bucket': 'your-s3-bucket-name', # 여러분의 S3 버킷 이름
                'Key': object_name,
                'ContentType': filetype
            },
            ExpiresIn=300 # URL 유효 시간 (초 단위, 여기서는 5분)
        )
        return jsonify({'presignedUrl': response, 'objectKey': object_name})
    except Exception as e:
        return jsonify({'error': str(e)}), 500

if __name__ == '__main__':
    app.run(debug=True)

이 코드는 클라이언트가 파일명과 파일 타입을 백엔드에 보내면, 백엔드가 AWS S3에서 파일을 업로드할 수 있는 Pre-signed URL을 생성하여 돌려주는 간단한 예시입니다. `boto3`는 AWS 서비스를 파이썬에서 사용할 수 있게 해주는 라이브러리이고, `put_object`는 S3에 파일을 업로드하는 작업을 의미합니다. `ExpiresIn`은 이 URL이 유효한 시간을 설정합니다.

2. 백엔드 프록시를 통한 안정적인 업로드

이 방식은 기존의 클라이언트 -> 백엔드 -> 스토리지 방식과 유사하지만, 백엔드 서버가 파일 업로드 과정에서 단순한 전달자 이상의 역할을 하는 것에 초점을 맞춥니다. 여기서는 백엔드 서버가 프록시(Proxy, 대리인) 역할을 하여 파일 업로드를 대신 처리해 줍니다.

작동 방식:

  1. 클라이언트가 백엔드 서버에 파일을 전송합니다.
  2. 백엔드 서버는 파일을 받아 자체적으로 유효성 검사(예: 파일 확장자, 크기, 악성 코드 검사 등)를 수행하고, 필요한 경우 파일 이름을 변경하거나 메타데이터를 추가하는 등의 후처리를 합니다.
  3. 검증이 완료된 파일을 백엔드 서버가 클라우드 스토리지에 대신 업로드합니다.
  4. 업로드가 완료되면 백엔드 서버가 클라이언트에 성공 여부를 알려줍니다.

이 방식은 마치 클라이언트가 비서(백엔드 프록시)에게 중요한 서류(파일)를 건네주면, 비서가 서류를 꼼꼼히 확인(검증)하고 안전하게 보관함(클라우드 스토리지)에 넣어주는 것과 비슷합니다.

장점:

  • 강력한 보안 및 검증: 모든 파일이 백엔드 서버를 거치기 때문에, 업로드 전에 악성 파일 검사, 파일 타입 및 크기 제한, 사용자 권한 확인 등 강력한 보안 로직과 유효성 검사를 적용하기 매우 용이합니다.
  • 간편한 클라이언트 구현: 클라이언트는 단순히 백엔드 API를 호출하여 파일을 보내기만 하면 되므로, 프론트엔드 개발이 비교적 간단합니다.
  • 세밀한 제어 및 로깅: 업로드 과정 전반(진행 상황, 에러 처리, 파일 저장 경로 등)을 백엔드에서 통합적으로 관리하고 모니터링하며 상세한 로깅(기록)을 남기기 좋습니다.

단점:

  • 백엔드 서버 부담: 대용량 파일 업로드 시 백엔드 서버가 모든 파일 데이터를 직접 처리해야 하므로, 서버 자원 소모가 크고 트래픽 증가로 인한 병목 현상이 발생할 수 있습니다.
  • 느린 업로드 속도: 파일이 백엔드 서버를 한 번 더 거쳐야 하므로, 네트워크 지연이 발생하여 Pre-signed URL 방식보다 업로드 속도가 느릴 수 있습니다.
  • 확장성 문제 및 비용 증가: 서버 부하 증가에 따라 서버를 수직 확장(서버 성능 업그레이드)하거나 수평 확장(서버 대수 늘리기)해야 할 필요성이 커지며, 이는 운영 비용 증가로 이어집니다.
  • 타임아웃 문제: 파일 크기가 매우 큰 경우, 백엔드 서버에서 파일 처리 중 연결 타임아웃이 발생할 위험이 있습니다.

코드 예시 (Python Flask + AWS S3 프록시 업로드):

from flask import Flask, request, jsonify
import boto3
from werkzeug.utils import secure_filename # 안전한 파일명 처리를 위한 유틸리티

app = Flask(__name__)
s3 = boto3.client('s3', region_name='ap-northeast-2')

# 허용된 파일 확장자 목록
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif', 'mp4', 'mov'}

def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@app.route('/upload-proxy', methods=['POST'])
def upload_via_proxy():
    if 'file' not in request.files:
        return jsonify({'error': 'No file part'}), 400
    
    file = request.files['file']
    if file.filename == '':
        return jsonify({'error': 'No selected file'}), 400

    # 파일 유효성 검사
    if not allowed_file(file.filename):
        return jsonify({'error': 'Invalid file type'}), 400

    try:
        # 파일명을 안전하게 처리하여 S3에 저장할 이름 생성
        object_name = f"uploads/{secure_filename(file.filename)}"

        # 백엔드 서버에서 S3로 파일 직접 업로드
        s3.upload_fileobj(file.stream, 'your-s3-bucket-name', object_name)
        return jsonify({'message': 'File uploaded successfully', 'objectKey': object_name}), 200
    except Exception as e:
        return jsonify({'error': str(e)}), 500

if __name__ == '__main__':
    app.run(debug=True)

이 코드는 클라이언트가 보낸 파일을 백엔드 서버가 받아서 파일 유효성 검사(`allowed_file`)를 하고, `secure_filename`으로 파일명을 안전하게 처리한 후 S3에 업로드하는 예시입니다. `upload_fileobj`는 파일 객체를 직접 S3에 업로드하는 AWS SDK 함수입니다.

두 가지 방식 비교 요약

두 가지 방식의 주요 특징을 한눈에 비교해 봅시다.

특징 Pre-signed URL 방식 (클라이언트 직접 업로드) 백엔드 프록시 방식
백엔드 부하 매우 낮음 (URL 생성만 담당) 높음 (모든 파일 데이터를 처리)
업로드 속도 빠름 (클라이언트 → 스토리지 직접 연결) 느림 (클라이언트 → 백엔드 → 스토리지)
보안 및 검증 URL 유효기간 관리, 업로드 후처리 검증 필요. 클라이언트 측 CORS 설정 필요. 백엔드에서 강력한 파일 검증 및 보안 로직 적용 용이.
클라이언트 복잡성 업로드 진행, 에러 처리 등 클라이언트에서 더 많은 로직 구현 필요. 간단 (백엔드 API 호출만 하면 됨).
확장성 매우 우수 (백엔드 서버 확장에 대한 부담 적음) 낮음 (서버 부하 증가로 수직/수평 확장 필요)
비용 효율성 높음 (백엔드 서버 트래픽 감소) 낮음 (서버 자원 및 트래픽 증가로 비용 증가 가능성)
주요 사용 사례 대용량 파일, 고성능/고확장성 요구 서비스 (예: 비디오 스트리밍, 클라우드 스토리지) 중요한 보안 검증이 필요한 서비스, 파일 크기가 비교적 작거나 트래픽이 적은 경우

우리 프로젝트에 맞는 최적의 전략은? (교훈)

지금까지 대용량 파일 업로드를 위한 두 가지 주요 전략, Pre-signed URL 방식과 백엔드 프록시 방식을 비교 분석해 보았습니다. 각각의 방식은 뚜렷한 장단점을 가지고 있으며, 어떤 방식이 '더 좋다'고 단정하기보다는 여러분의 프로젝트 특성과 요구사항에 따라 적절한 선택을 하는 것이 중요합니다.

  • Pre-signed URL 방식은 이런 경우에 적합합니다:
    • 성능과 확장성이 최우선인 경우 (예: 수백 MB에서 GB 단위의 대용량 파일을 처리해야 하는 비디오 플랫폼, 클라우드 스토리지 서비스).
    • 백엔드 서버의 부담을 최소화하고 운영 비용을 절감하고 싶을 때.
    • 클라이언트 측 개발 복잡성을 감수하고서라도 최대한 빠른 업로드 속도를 제공하고 싶을 때.
  • 백엔드 프록시 방식은 이런 경우에 적합합니다:
    • 보안과 파일 검증이 매우 중요하여 모든 파일을 백엔드에서 꼼꼼하게 검사해야 할 때 (예: 민감한 문서 업로드, 악성 코드 필터링이 필수인 경우).
    • 파일 업로드 과정에 백엔드에서 복잡한 로직이나 후처리가 필요한 경우.
    • 클라이언트 개발을 최대한 단순하게 유지하고 싶을 때.
    • 업로드되는 파일의 크기가 비교적 작고, 트래픽이 아주 폭발적이지 않은 경우.

때로는 이 두 가지 방식을 혼합하여 사용하는 전략도 고려해 볼 수 있습니다. 예를 들어, Pre-signed URL을 통해 파일을 클라우드 스토리지에 직접 업로드하게 한 후, 백엔드에 업로드 완료 알림을 보내서 백엔드가 해당 파일에 대한 후처리(바이러스 검사, 이미지 리사이징, 메타데이터 업데이트 등)를 수행하는 방식입니다. 이는 성능과 보안을 모두 잡을 수 있는 현명한 접근법이 될 수 있습니다.

핵심은 여러분의 서비스가 어떤 문제를 해결하고 싶은지, 어떤 자원(개발 시간, 비용, 서버 성능)을 가지고 있는지 명확히 이해하는 것입니다. 이 글을 통해 대용량 파일 업로드 전략을 선택하는 데 도움이 되셨기를 바랍니다. 여러분의 프로젝트는 어떤 전략을 사용해 보셨나요? 또는 어떤 전략이 더 끌리시나요? 댓글로 여러분의 경험과 생각을 공유해 주세요!

📌 함께 읽으면 좋은 글

  • [튜토리얼] 서비스 중단 없는 배포, 어떻게 가능할까요? 블루/그린 배포와 카나리 배포 개념 살펴보기
  • [튜토리얼] 복잡한 웹 UI, 게임 개발 ECS 패턴으로 50% 이상 관리 효율 높이는 3가지 방법
  • [튜토리얼] 분산 캐시 일관성: MSI, MESI, MOESI 프로토콜 심층 비교 분석

이 글이 도움이 되셨다면 공감(♥)댓글로 응원해 주세요!
궁금한 점이나 다루었으면 하는 주제가 있다면 댓글로 남겨주세요.

반응형