요구사항의 기능은 업로드만이 아닙니다. 다운로드와 링크 공유가 함께 있습니다. 올리는 문제를 풀었으면 내려주는 문제가 남고, 모양이 대칭입니다.
읽기도 같은 사다리를 오른다
앱이 스토리지에서 읽어 전달하면 업로드에서 본 문제가 그대로 재현됩니다. 대역폭을 앱이 내고 큰 파일이 요청을 오래 붙잡습니다.
그래서 읽기도 서명된 주소를 씁니다. 앱은 권한만 확인하고 짧게 만료되는 읽기 주소를 내려줍니다. 파일은 클라이언트가 스토리지에서 직접 받습니다.
캐시와 서명이 부딪힌다
엣지 캐시를 앞에 두면 같은 파일을 여러 사람이 받을 때 스토리지까지 가지 않습니다. 그런데 서명된 주소는 사람마다 다르고 만료가 있습니다.
| 문제 | 왜 생기나 |
|---|---|
| 캐시 적중률이 0에 가깝다 | 주소가 사람마다 달라 캐시 키가 매번 다르다 |
| 만료된 응답이 캐시에 남는다 | 캐시 수명이 서명 만료보다 길다 |
그래서 공개 파일과 비공개 파일을 다르게 다룹니다. 공개 파일은 서명 없이 캐시하고, 비공개 파일은 서명을 쓰되 캐시 수명을 만료보다 짧게 둡니다. 엣지 전달 자체는 CDN 과 엣지 전달 에서 다룹니다.
후처리는 비동기로
썸네일 생성이나 변환은 업로드 응답 경로에 두지 않습니다. 큰 파일에서 오래 걸리고, 실패하면 업로드 자체가 실패한 것처럼 보입니다.
작업 큐에 넣고 별도 워커가 처리합니다. 여기서 워커가 멱등해야 합니다. 큐는 같은 메시지를 두 번 줄 수 있고, 그때 썸네일을 두 번 만들면 요금이 두 배가 되거나 결과가 어긋납니다.
진행 상태를 알리는 방법
후처리가 끝나기 전에는 목록에 원본만 보입니다. 완료를 알리는 방법이 둘입니다.
| 방법 | 특징 |
|---|---|
| 클라이언트가 주기적으로 물어본다 | 만들기 쉽다. 요청이 늘고 지연이 폴링 간격만큼 생긴다 |
| 서버가 밀어준다 | 즉시 반영된다. 연결 관리가 필요하다 |
요구사항에 실시간 미리보기가 없으므로 폴링으로 충분합니다. 무엇을 안 해도 되는지가 요구사항에서 나옵니다.