얼쑤의 녹음 다시 듣기 API에 기존 저장소의 읽기 주소 발급 기능을 연결했습니다. 로컬 저장소에서는 분석 컨테이너가 쓰는 내부 주소가 HTTP 200 응답에 들어왔습니다. 테스트는 그 주소의 호스트를 테스트 프로세스가 접근할 수 있는 주소로 바꿔 읽었기 때문에 성공했습니다. 휴대폰은 응답에 들어 있는 주소 그대로 접속하므로 같은 결과를 기대할 수 없었습니다.

앱이 접근할 주소만 발급

DB의 recording_url에는 녹음 원본을 찾는 객체 키를 저장합니다. 앱에 넘길 임시 주소는 그 키로 다시 듣기를 요청할 때 따로 만듭니다. 그래서 같은 세션의 객체 키를 읽어도 연결한 저장소에 따라 앱이 사용할 주소를 발급할 수 있는지가 달랐습니다.

앱이 도달할 수 있는 주소를 발급하는 저장소에만 재생용 서명기를 연결했습니다. 로컬 저장소에서는 HTTP 503으로 응답하고, S3 호환 저장소에서는 15분짜리 서명 읽기 주소를 돌려주게 했습니다.

응답에 담는 만료 시각은 서명하기 직전에 읽은 시각을 초 단위로 내려 TTL을 더했습니다. 밀리초를 그대로 남기면 저장소의 초 단위 서명보다 만료를 늦게 안내할 수 있기 때문입니다. 시계를 04:00:00.700Z로 고정한 단위 검사에서 응답의 만료 시각이 04:15:00Z인지 확인했습니다.

SDK 단위 검사에서는 읽기용 GET 주소를 만든 뒤 버킷과 객체 경로, SigV4 서명 형식, 유효기간을 대조했습니다. 주소의 X-Amz-Expires는 900초였고 테스트용 비밀 키는 주소에 포함되지 않았습니다. HTTP 대역이 받은 요청은 0건이었습니다. 이 단계의 서명은 로컬에서 계산됩니다.

실제 JAR에서 두 저장소 설정 검증

빌드한 JAR을 일회용 MySQL에 붙여 검증했습니다. 로컬 저장소 설정에서 20개 확인이 통과했고, 다시 듣기는 503을 반환했습니다. S3 호환 설정에서는 16개 확인이 통과했고, 같은 API에서 15분짜리 서명 주소가 나왔습니다. S3 호환 검증은 접속할 수 없는 로컬 주소를 설정하고 URL 발급까지 확인했습니다. 실제 R2 객체를 휴대폰에서 재생하는 과정은 별도 검증 범위입니다.