배경
이미지(신분증, 범죄이력조회서, 픽업/배달 인증 사진 등) 업로드 방식을 정할 때, "클라이언트가 서버를 거쳐 S3에 올리는 방식(서버 경유)"과 "서버가 presigned URL만 발급하고 클라이언트가 S3에 직접 올리는 방식(Presigned URL)" 중 하나를 골라야 했습니다. Discussion #56에서 이 논의가 이뤄졌습니다.
검토한 선택지
1. 서버 경유
클라이언트가 파일을 서버로 보내고, 서버가 그 파일을 다시 S3로 업로드하는 방식입니다.
장점:
- 업로드 전 파일을 검증할 수 있습니다(바이러스 스캔, 리사이징, 확장자 검증 등).
- 성공·실패를 서버가 그 자리에서 바로 압니다.
단점:
- 파일 바이트가 서버를 두 번 통과합니다(클라이언트→서버, 서버→S3). 100MB 파일 기준 클라이언트→서버 10초 + 서버→S3 1초로, 워커 스레드 하나를 11초간 붙잡습니다. 스레드 풀이 200개라면 동시성 천장은 대략 200 ÷ 11 ≈ 18 uploads/s에 그칩니다.
- 같은 바이트가 서버를 두 번 통과하므로 파일당 실질 트래픽도(100MB 파일 기준) 200MB로 늘어납니다.
- 동시 업로드가 몰리면 임시 파일로 디스크·메모리 압박도 생깁니다(100MB × 동시 100건이면 순간 temp 10GB).
- 대안으로 MVC 대신 WebFlux를 쓰는 방법도 검토했습니다 — 업로드 조각이 도착할 때만 짧게 처리하고 스레드를 즉시 반납해 동시성 천장을 올릴 수 있습니다. 다만 이건 스레드 고갈이라는 증상을 기술로 관리하는 것일 뿐, "파일 바이트가 서버를 거친다"는 근본 구조 자체를 없애지는 못합니다.
2. Presigned URL
서버는 업로드 가능한 URL만 서명해서 발급하고, 실제 파일 전송은 클라이언트가 S3와 직접 주고받는 방식입니다.
장점:
- 파일 바이트가 서버를 아예 거치지 않아 서버 트래픽이 사실상 0이고, 스레드도 URL을 발급하는 짧은 순간(~5ms)만 점유합니다. 동시성 천장이 수만/s 단위로 올라갑니다.
- AWS 자격 증명을 클라이언트에 노출하지 않고도 직접 업로드를 허용할 수 있습니다.
- 만료 시간을 짧게 설정해 URL 남용 범위를 통제할 수 있습니다.
단점: