Foundry
파일 업로드 시스템 설계
심화
핵심

후처리와 전달

올린 뒤에 남는 일. 내려주기와 후처리

요구사항의 기능은 업로드만이 아닙니다. 다운로드와 링크 공유가 함께 있습니다. 올리는 문제를 풀었으면 내려주는 문제가 남고, 모양이 대칭입니다.

비공개 파일 읽기 경로 세 단계. 앱이 읽어 전달, 서명된 읽기 주소, 서명과 캐시를 함께 1 앱이 읽어서 전달 클라이언트 앱 서버 스토리지 2 서명된 읽기 주소 앱 서버 클라이언트 권한 확인 스토리지 3 서명과 캐시를 함께 클라이언트 엣지 스토리지

읽기도 같은 사다리를 오른다

앱이 스토리지에서 읽어 전달하면 업로드에서 본 문제가 그대로 재현됩니다. 대역폭을 앱이 내고 큰 파일이 요청을 오래 붙잡습니다.

그래서 읽기도 서명된 주소를 씁니다. 앱은 권한만 확인하고 짧게 만료되는 읽기 주소를 내려줍니다. 파일은 클라이언트가 스토리지에서 직접 받습니다.

캐시와 서명이 부딪힌다

엣지 캐시를 앞에 두면 같은 파일을 여러 사람이 받을 때 스토리지까지 가지 않습니다. 그런데 서명된 주소는 사람마다 다르고 만료가 있습니다.

문제왜 생기나
캐시 적중률이 0에 가깝다주소가 사람마다 달라 캐시 키가 매번 다르다
만료된 응답이 캐시에 남는다캐시 수명이 서명 만료보다 길다

그래서 공개 파일과 비공개 파일을 다르게 다룹니다. 공개 파일은 서명 없이 캐시하고, 비공개 파일은 서명을 쓰되 캐시 수명을 만료보다 짧게 둡니다. 엣지 전달 자체는 CDN 과 엣지 전달 에서 다룹니다.

후처리는 비동기로

썸네일 생성이나 변환은 업로드 응답 경로에 두지 않습니다. 큰 파일에서 오래 걸리고, 실패하면 업로드 자체가 실패한 것처럼 보입니다.

작업 큐에 넣고 별도 워커가 처리합니다. 여기서 워커가 멱등해야 합니다. 큐는 같은 메시지를 두 번 줄 수 있고, 그때 썸네일을 두 번 만들면 요금이 두 배가 되거나 결과가 어긋납니다.

진행 상태를 알리는 방법

후처리가 끝나기 전에는 목록에 원본만 보입니다. 완료를 알리는 방법이 둘입니다.

방법특징
클라이언트가 주기적으로 물어본다만들기 쉽다. 요청이 늘고 지연이 폴링 간격만큼 생긴다
서버가 밀어준다즉시 반영된다. 연결 관리가 필요하다

요구사항에 실시간 미리보기가 없으므로 폴링으로 충분합니다. 무엇을 안 해도 되는지가 요구사항에서 나옵니다.

면접에서 이렇게 나옵니다

Q.비공개 파일을 어떻게 내려주나요

업로드와 대칭입니다. 앱은 권한만 확인하고 짧게 만료되는 서명된 읽기 주소를 내려줍니다.

앱이 스토리지에서 읽어 전달하면 업로드에서 본 문제가 그대로 재현됩니다. 대역폭을 앱이 내고 큰 파일이 요청을 오래 붙잡습니다.

방식앱의 역할한계
앱이 읽어 전달파일을 통과시킨다대역폭과 요청 점유
서명된 읽기 주소권한 확인만주소가 유출되면 만료까지 유효하다

만료를 짧게 두는 이유가 여기 있습니다. 주소 자체가 접근 권한이므로, 링크가 새면 만료 전까지는 누구나 받을 수 있습니다.

흔한 실수: 스토리지 객체를 공개로 두고 주소를 어렵게 만드는 것. 주소를 모른다는 것은 접근 통제가 아닙니다. 한 번 새면 되돌릴 방법이 없습니다.

Q.서명된 주소와 엣지 캐시를 함께 쓰면 무엇이 문제인가요

캐시 키가 매번 달라져 적중률이 0에 가까워집니다. 서명이 사람마다 다르기 때문입니다.

문제원인
적중률이 낮다주소가 사람마다 다르다
만료된 응답이 남는다캐시 수명이 서명 만료보다 길다

그래서 공개 파일과 비공개 파일을 다르게 다룹니다. 공개 파일은 서명 없이 캐시해 적중률을 얻고, 비공개 파일은 서명을 쓰되 캐시 수명을 만료보다 짧게 둡니다.

절충안도 있습니다. 서명을 쿠키로 옮기면 주소가 같아져 캐시가 동작합니다. 대신 쿠키 범위 관리가 필요해집니다.

흔한 실수: 캐시 적중률만 보고 파일을 공개로 바꾸는 것. 적중률은 오르지만 접근 통제가 사라집니다. 두 목표가 충돌할 때는 무엇이 요구사항인지를 봐야 합니다.

Q.썸네일 생성 같은 후처리를 어디에 두나요

업로드 응답 경로 밖입니다. 작업 큐에 넣고 별도 워커가 처리합니다.

응답 경로에 두면 두 가지가 문제입니다. 큰 파일에서 오래 걸려 업로드가 느려 보이고, 후처리가 실패하면 업로드 자체가 실패한 것처럼 보입니다. 파일은 이미 올라갔는데도 그렇습니다.

여기서 워커가 멱등해야 합니다. 큐는 같은 메시지를 두 번 줄 수 있습니다.

멱등하지 않으면결과
썸네일을 두 번 만든다변환 요금이 두 배가 된다
결과 파일 이름이 매번 다르다어느 것이 최신인지 알 수 없다

결과 경로를 입력에서 결정되는 값으로 정하면 두 번 처리해도 같은 자리에 덮여 안전합니다.

흔한 실수: 후처리 실패를 업로드 실패로 처리하는 것. 원본은 이미 저장됐으므로 업로드는 성공입니다. 후처리는 따로 재시도하고, 실패하면 원본만 보여주는 편이 낫습니다.

Q.후처리 완료를 사용자에게 어떻게 알리나요

폴링과 푸시 중에 고르고, 요구사항이 그 선택을 정합니다.

방법특징
클라이언트가 주기적으로 물어본다만들기 쉽다. 요청이 늘고 폴링 간격만큼 지연
서버가 밀어준다즉시 반영. 연결 관리가 필요하다

이 서비스는 실시간 미리보기가 범위 밖이므로 폴링으로 충분합니다. 몇 초 지연은 사용자가 눈치채지 못하고, 연결을 유지하는 구조를 만들지 않아도 됩니다.

폴링을 고르면 간격과 종료 조건을 정해야 합니다. 끝없이 물어보면 화면을 열어 둔 사용자가 쌓일수록 요청이 늘어납니다. 간격을 점점 늘리고 일정 시간 뒤에는 멈춥니다.

흔한 실수: 즉시성이 더 좋다는 이유로 푸시를 고르는 것. 얻는 것이 몇 초이고 내는 것이 연결 관리와 재연결 처리입니다. 무엇을 안 해도 되는지가 요구사항에서 나옵니다.

먼저 스스로 답해보고 아래 답변과 견줘보세요. 막히는 부분은 문제로 확인할 수 있어요.

읽었으면 문제로 확인해보세요

파일 업로드 시스템 설계 문제를 풀면 틀린 문제가 자동으로 노트에 쌓입니다. 가입 없이 5문제를 먼저 풀어볼 수도 있어요.