권한을 뺐는데, 예전에 받은 파일 링크는 계속 열려도 될까?
자료실에서 다운로드 권한을 회수했어. 버튼도 없어졌는데, 권한을 빼기 전에 받은 이메일 링크로 파일이 열려. 이걸 버튼 오류로 넘기면 같은 문제가 다른 경로에서 다시 나와. 가상 팀 자료실을 놓고 권한 회수의 범위부터 기존 링크, 생성 작업, 안내 문구와 검수까지 정해볼게.
“다운로드 못 하게 해줘”에서 어디까지 막을 건지부터 정해
처음 요청을 받으면 권한을 지우는 화면부터 그릴 수 있어. 그런데 이 안건의 목적은 권한 목록에서 이름 하나를 빼는 게 아니야. 그 사람이 어느 시점부터 어떤 파일을 받을 수 없어야 하는지 정하는 일이야. 나는 요청서에 현상, 목적, 수정 범위, 배포 뒤 확인할 결과를 먼저 적을 거야.
수정 전 재현 조건을 먼저 고정해. 09:55에 보고서 생성을 요청하고, 완성된 보고서의 직접 링크를 09:59에 발급해. 이 링크는 30분 뒤인 10:29에 만료돼. 관리자는 10:00에 다운로드 권한 회수를 저장·확정하고, 팀원은 로그인한 채 10:01에 링크를 열어. 아직 유효한 링크가 열리는 게 이번에 바꿀 현상이야. 로그인과 다른 업무는 유지해.
확정 전에 허용된 전송과 이미 PC에 저장된 복사본은 따로 물어봐야 해. 이 예제는 진행 중인 전송이 끝날 수 있다는 조건을 선택하고, 저장된 복사본을 회수한다고 약속하지 않아. 진행 중인 전송도 끊어야 하는 서비스라면 전송 세션 관리까지 범위를 바꿔서 다시 설계해야 해.
지금 화면에서 안 보이는 경로부터 적어봐
나는 개발에 “다운로드 API가 어디야?”만 묻지 않을 거야. 목록, 상세 화면, 이전 이메일, 알림, 파일 생성 작업, 이어받기에서 실제로 어떤 주소를 쓰는지 함께 확인해. 주소가 다르면 화면을 고쳐도 다른 입구가 남을 수 있어. 조사표에는 지금 확인한 경로와 아직 확인하지 못한 경로를 나눠 남겨.
AWS의 사전 서명 URL 설명은 링크가 발급자의 자격 증명을 사용한다는 점을 보여줘. 예제처럼 서비스 공용 자격 증명으로 발급했다면, 앱의 팀원 역할을 바꾸는 것과 그 링크의 발급 자격을 없애는 건 같은 작업이 아니야. 이 차이 때문에 역할 변경 화면만으로 끝낼 수 없어.
파일을 주는 곳과 권한을 확인하는 곳을 같은 행에 적어. 아래는 작성 예시야.
| 입구 | 개발에 확인할 내용 | 이번 설계에 남길 조건 |
|---|---|---|
| 자료 목록·상세 | 버튼 표시와 실제 파일 응답이 같은 권한을 보는가 | 화면과 서버 모두 현재 유효 권한 사용 |
| 이전 이메일·알림 | 저장소 직접 주소인지 서비스 주소인지 | 인증된 서비스 경로로 연결 |
| 대기·생성 작업 | 요청 당시 권한을 계속 신뢰하는가 | 실행과 결과 등록 때 다시 확인 |
| 파일 전송·이어받기 | 새 요청이 인증 검사를 건너뛰는가 | 이어받기도 새 권한 검사 |
| 공유 캐시·저장 사본 | 권한 확인 없이 응답을 돌려주는 경로가 있는가 | 캐시 경로 조사와 저장 사본 한계 명시 |
링크 만료 시간만 줄이면 해결될까?
링크 유효 시간을 30분에서 5분으로 줄이는 안부터 비교해봐. 09:59 발급이라면 만료는 각각 10:29와 10:04야. 둘 다 10:00 권한 회수 뒤인 10:01에는 아직 유효해. 이 사례에서 짧은 링크도 즉시 회수라는 목적을 충족하지 못하는 거야. 30분과 5분은 비교 조건이지 권장 보안 기준은 아니야.
그래서 이번 안건에서는 로그인한 서비스가 요청을 받고, 지금 권한을 확인한 뒤 파일을 중계하는 안을 선택해. 권한 검사 뒤에 다시 직접 저장소 주소로 보내면 다음 접근이 서비스 검사를 지나지 않을 수 있어. 중계 방식을 골랐다는 문장과 실제 응답 방식이 맞아야 해. 중계에 필요한 전송량과 용량은 개발이 확인하고, 감당할 수 없다면 즉시 회수라는 요구부터 다시 합의해.
더 강해 보이는 표현 대신, 이번 약속을 지킬 수 있는지 비교해.
| 안 | 얻는 것 | 이번 판단 |
|---|---|---|
| 버튼만 숨김 | 현재 화면에서 클릭을 막음 | 이전 주소가 남아 제외 |
| 직접 링크 유효 기간 단축 | 기존 링크 노출 시간을 줄임 | 남은 유효 시간 동안 즉시 회수 보장이 안 돼 보조안 |
| 서비스가 확인 후 파일 중계 | 매 새 요청에 현재 권한 적용 가능 | 이번 선택. 용량·동시성·캐시 검수 필요 |
| 발급 자격 증명 전체 철회 | 해당 자격으로 발급한 접근에 영향 | 다른 이용자·파일까지 영향이 커 회원별 기본 방식에서 제외 |
버튼보다 먼저 허용 조건을 맞춰
OWASP는 로그인 확인과 권한 확인을 구분하고 요청마다 권한을 검사하라고 설명해. 이 예제의 허용 조건은 유효한 로그인, 현재 팀 소속, 해당 파일에 대한 유효 다운로드 권한, 이용 가능한 파일 상태, 정상적인 권한 조회야. 관리 화면에서 역할 하나를 지웠어도 다른 역할로 같은 권한이 남으면 실제 유효 권한으로 판단해야 해.
기획서에는 “즉시 반영” 한 줄 대신 회수가 저장·확정된 시점과 전송 허용 판정의 순서를 적어. 개발은 두 판단이 일관된 권한 정보를 보도록 해야 해. 오래된 복제본이나 권한 캐시로 허용해 버리면 새 화면이 맞아도 목적은 깨져. 조회가 실패했을 때는 파일을 보내지 않고 확인 실패 상태를 돌려줘.
로그인·팀·파일별 권한·파일 상태·조회 성공을 앞 문단의 조건으로 모두 확인한 결과야.
흐름을 글로 보기
- 현재 이용 조건을 모두 충족해?
- 예: 서비스가 파일 전송을 허용 → 허용·거부 판단과 기준 시각을 기록
- 아니오: 파일을 보내지 않고 이유에 맞는 안내 → 허용·거부 판단과 기준 시각을 기록
같은 “권한 없음”으로 묶으면 처리 순서가 사라져
화면 설계서에는 현재 상태, 보여줄 문구, 할 수 있는 행동, 다시 검사할 시점을 한 묶음으로 남겨. 로그인 만료는 다시 로그인할 입구를 주고, 이미 권한이 회수된 사람에게는 재로그인만 반복하게 하지 않아. 파일 이용 불가 응답에는 보호해야 할 파일명이나 저장소 주소를 덧붙이지 않아.
생성 작업도 봐야 해. 실행 전에 권한이 없어졌으면 시작하지 않고, 생성 도중 회수됐으면 계산이 끝나더라도 이용 가능한 결과로 등록하거나 다운로드 알림을 보내지 않아. 파일 생성이 끝났다는 사실과 지금 사용자가 받아도 된다는 판단을 별도로 저장하는 거야. 다른 권한 있는 이용자에게 필요한 파일까지 일괄 삭제하지는 않아.
전환 완료 후 중계 주소를 사용하는 가상 시연이야. 각 항목은 별도 상황이며 실제 파일을 조회하지 않아.
자료 열어 보기
옛 직접 링크 차단까지 검수된 전환 완료 상태야. 09:59 받은 서비스 중계 주소를 10:01 다시 열면, 10:00 회수 확정 후 남은 유효 권한이 없어 파일을 보내지 않아. “이 자료를 이용할 수 없습니다”와 자료 목록 동선을 제공해.
09:55에 요청했어도 10:00 이후 실행 검사에서 권한이 없으면 생성하지 않아. 대기 작업을 이용 불가 상태로 남기고 다운로드 완료 알림은 보내지 않아.
회수 확정 전에 허용 판정을 받은 전송은 이 예제에서 종료를 보장하지 않아. 연결이 끊겨 이어받으면 새 요청이므로 현재 권한을 확인하고 거부해.
삭제한 역할 외에 허용된 다른 역할과 팀·파일 조건이 모두 유효하면 다운로드가 가능해. 관리자에게 제거한 역할과 최종 접근 결과를 구분해서 보여줘.
새 경로를 만들었다고 예전 링크가 없어지진 않아
이 부분을 배포 계획에 빠뜨리면 새로 만든 버튼만 안전해져. 먼저 직접 링크를 새로 발급하는 곳을 중계 주소로 바꿔. 그다음 이미 발급된 주소의 유효 조건과 최대 남은 시간, 오래된 이메일과 캐시 경로를 조사해. 이전 링크가 더는 파일을 주지 않는지 확인하기 전에는 전체 경로의 회수가 끝났다고 표시하면 안 돼.
즉시 전환이 필요하다면 보안·저장소 담당자와 기존 링크를 무효화할 방법과 다른 사용자에게 미치는 영향을 정해야 해. 일정 기간 만료를 기다리는 안을 택한다면 그 기간에는 기존 링크가 남는다는 제약을 운영 문구에 반영해. 둘을 같은 완료 상태로 묶지 않는 거야.
MDN의 캐시 설명처럼 새 응답에 no-store를 붙여도 이미 저장된 응답이 지워지는 건 아니야. 이번 다운로드 응답의 저장 방침, 앞단 캐시의 처리, 이미 저장된 복사본에 대한 안내를 분리해서 확인해. 감사 기록에는 판단 시각·대상 파일의 내부 참조·허용 여부·정책 버전을 남기되 직접 링크의 토큰이나 파일 내용까지 남기지 않아.
AI에는 “보안적으로 검토해줘” 대신 빠진 경로를 맡겨
AI에 맡길 건 아직 정하지 않은 회사 정책을 만들어내는 일이 아니야. 확정한 조건과 공개 자료를 주고, 어느 입구가 빠졌는지 찾게 할 거야. 아래는 그때 쓸 질문 예시야. 답을 받으면 요청서의 목적, 상태 설계표, QA 기대 결과와 한 줄씩 대조해.
가령 “모든 세션을 종료하면 해결된다”는 제안이 오면 이번 범위와 맞지 않아. 다운로드만 회수하고 다른 업무는 유지한다는 조건으로 다시 검토하게 해. “캐시를 지우면 저장 파일도 회수된다”는 문장이 오면 채택하지 않아. 최종 기록에는 채택한 조건, 고친 문장, 보류 이유, 개발 확인 담당을 남겨. 이 가정형 답변들은 실제 AI 실행 결과가 아니야.
회사 자료 없이 가상 조건으로 바꿔 쓸 예시 질문이야.
가상 팀 자료실의 다운로드 권한 회수 설계를 검토해줘. 조건: 09:55에 파일 생성 요청, 10:00에 권한 회수가 저장·확정됨, 10:01에 이전 링크로 접근함. 회원 로그인과 다른 업무 권한은 유지함. 브라우저에는 저장소 직접 링크를 전달하지 않는 서비스 중계 방식을 선택함. 맡길 범위: 목록, 이전 이메일, 생성 작업, 전송, 재시도에서 빠진 조건을 찾아줘. 실제 DB 필드나 미확인 API는 만들지 마. 판정 기준: 회수 확정 후 유효 권한이 없는 새 요청은 차단. 회수 전에 허용 판정을 받은 진행 중 전송은 끝날 수 있고, 이어받기는 새 요청으로 검사함. 다른 역할로 같은 권한이 남아 있다면 그 유효 권한으로 판단함. 이미 저장된 파일의 회수는 보장하지 않음. 출력: 누락 조건 / 영향을 받는 화면·동작 / 바꿀 문장 / 재현 순서와 기대 결과. 개발이 확인해야 할 항목은 확정된 사실과 나눠줘. 시험 전제: 수정 전 직접 링크는09:59 발급,30분이면10:29·5분이면10:04 만료로10:01에 모두 유효함. 전환 완료 후 중계 주소와 무효화된 옛 직접 주소는 별개로 검수함. 대기 작업은 별도 대체 상황임.
검수는 권한을 뺀 뒤 새로고침하는 데서 끝내지 않아
수정 전과 전환 완료 후를 다른 시험으로 기록해. 수정 전에는 09:59에 발급한 직접 링크가 10:01에도 열리는지 재현해. 전환 완료 후에는 같은 상대 시각 조건으로 서비스 중계 주소가 다시 권한을 검사하는지, 따로 보관한 옛 직접 주소는 더는 파일을 주지 않는지 각각 확인해. 전환 중 남아 있는 직접 링크를 새 중계 경로의 통과 결과로 덮으면 안 돼.
QA에는 테스트 계정 두 개와 서로 다른 팀의 예제 파일을 준비하게 할 거야. 파일 내용은 가상 자료로 만들고, 권한 회수가 저장·확정된 시각과 다운로드 허용 판정 시각을 각각 기록해. 버튼 상태만 보지 말고 파일 응답이 실제로 나갔는지 확인해야 해.
아래 기대 결과는 설계 기준이야. 이 글에서 서비스나 저장소를 직접 연동해 통합 검수를 마친 결과는 아니야. 출시 전에는 회수와 허용 판정이 겹치는 조건, 다른 노드로 접속하는 조건, 캐시와 이어받기를 실제 구현에서 재현해야 해. 통과 여부와 증거 위치를 QA 문서에 채워서 개발에 다시 넘겨.
권한 회수의 확정 시점을 기준으로 비교해.
| 재현 조건 | 기대 결과 | 확인할 증거 |
|---|---|---|
| 수정 전:09:59 직접 링크 발급 →10:01 접근 | 30분 만료10:29·5분 만료10:04로 둘 다 유효 | 발급·만료 시각과 실제 파일 응답 |
| 전환 완료 후:10:00 회수 →10:01 중계 주소 | 유효 권한 없으면 파일 본문 미전송 | 현재 권한 판정과 중계 응답 |
| 다른 팀 파일 주소로 새 요청 | 파일 본문·보호 파일명 미노출 | 팀·파일 범위 검사 |
| 10:00 전에 전송 허용 → 이후 회수 | 기존 전송은 끝날 수 있음 | 허용 판정 시각 |
| 회수 후 끊긴 전송 이어받기 | 새 요청 거부 | 이어받기 요청의 권한 검사 |
| 생성 직전 또는 완료 직전 회수 | 이용 가능 결과·다운로드 알림 없음 | 작업 상태와 결과 등록·발송 검사 |
| 역할 하나 삭제, 다른 역할은 유효 | 유효 권한과 파일 조건에 따라 허용 | 최종 권한 계산 |
| 권한 조회 장애 | 파일 미전송, 확인 실패 안내 | 장애 응답과 재시도 동선 |
| 새 경로 적용 후 옛 직접 링크 재접속 | 옛 경로 차단 확인 전 전체 전환 미완료 | 발급 중지·잔여 링크·캐시 검수 |
| 전환 완료 후:보관한 옛 직접 주소 접근 | 파일 본문 미전송 | 해당 주소 만료·무효화 또는 경로 차단 결과 |
개발에 넘길 때는 완료 조건도 같이 넘겨
기획자는 이번 회수의 의미와 예외를 결정 기록에 남겨. 개발자는 실제 권한 저장소와 파일 경로를 확인해 설계서의 동작으로 연결하고, QA는 예전 주소와 동시 요청까지 검수해. 운영 담당자는 “권한을 회수했습니다”라는 안내가 보장하는 범위를 확인해. 보관 기간, 중계 용량, 진행 중 전송 정책이 미정이면 담당자와 확정할 시점을 적어 두고 관련 범위를 완료 처리하지 않아.
나는 효과도 “안전해졌다”로 끝내지 않을 거야. 회수 확정 후 유효 권한이 없는 새 요청에 파일이 전달된 건수, 조회 장애로 막힌 정상 이용, 권한 안내 뒤 재문의, 중계 전송 실패를 따로 볼 거야. 개인정보를 늘려 수집하지 않고 필요한 판정 기록으로 확인해. 차단 건수가 많다는 것만으로 좋은 결과라고 판단하지는 않아.
자기 서비스의 확정 조건과 담당자를 채워 쓰는 작성 예시야.
안건: 팀 자료실 다운로드 권한 회수 현상: 목록에서 버튼을 숨겨도 이전 이메일·직접 링크·생성 작업이 남을 수 있다. 목적: 회수가 저장·확정된 뒤 들어온 새 다운로드 요청은 현재 유효 권한으로 판단한다. 로그인과 다른 업무는 유지한다. 범위: 가상 팀 자료실과 새 중계 다운로드 경로. 이미 저장된 복사본을 회수하는 기능은 포함하지 않는다. 선택: 요청마다 회원·팀·파일·현재 유효 다운로드 권한·파일 상태를 확인한 뒤 서비스가 파일을 중계한다. 브라우저에 저장소 직접 링크를 전달하지 않는다. 동시성: 권한 회수의 확정과 전송 허용 판정의 순서를 일관된 권한 저장소로 정한다. 회수 뒤의 신규 판정에서 유효 권한이 없으면 거부한다. 확정 전에 허용된 진행 중 전송은 끝날 수 있다. 재시도·이어받기는 새 판정이다. 확인 장애는 허용으로 처리하지 않는다. 생성/알림: 실행 전·결과 등록 전·알림 발송 전 권한을 다시 확인한다. 권한이 없으면 이용 가능한 결과나 다운로드 알림을 노출하지 않는다. 생성 완료와 이용 허용은 별도 상태다. 기존 경로 전환: 신규 직접 링크 발급을 중지하고 기존 링크의 유효 조건·최대 잔여시간·캐시를 조사한다. 이전 경로가 더는 파일을 주지 않는 검수까지 끝낸 뒤 전체 회수 완료를 표시한다. 화면: 로그인 필요 / 이용 불가 / 권한 확인 실패를 구분한다. 미권한 응답에 파일명·저장소 주소를 넣지 않는다. 권한 회수가 파일 삭제를 뜻하지는 않는다. 담당: 기획은 회수 시점·예외·문구 결정, 개발은 모든 다운로드 경로와 권한 일관성·캐시 확인, QA는 이전 링크와 동시 요청 재현, 운영은 안내 및 감사 기록 확인. 출시 전: 직접 접근 우회, 다른 팀 파일, 복수 역할, 대기 작업, 생성 완료 직전 회수, 이어받기, 권한 조회 장애를 시험한다. 보관 기간·중계 용량·진행 중 전송 허용은 각 담당자가 승인한 값을 명세에 채운다. 완료 증거: 설계표, 결정 이유, API/화면 검수 결과, 이전 경로 차단 결과, 운영 인계 기록. 이 문서는 가상 설계의 작성 예시다. 시간·전환 검수: 수정 전 직접 링크09:59 발급→30분 만료10:29 또는5분 만료10:04→10:01 접근은 유효하다. 전환 후 같은 상대 시각으로 중계 주소 재인가 거부와 보관한 옛 직접 주소의 본문 차단을 각각 확인한다. 전환 중 상태를 전체 완료로 기록하지 않는다.
출처와 예제 조건
공개 AWS·OWASP·MDN 문서를 2026-09-26 확인하고 만든 가상 팀 자료실 설계안이야. 시각·링크 유효 시간·중계 방식·진행 중 전송 처리는 이 예제의 조건이야. 회사 자료나 실제 사용자 업무 경험·성과를 사용하지 않았고, AI 질문과 가정형 답변은 실행 기록이 아닌 예시야. 문서의 조건 일치와 페이지 동작 검수는 실제 서비스의 권한·저장소 통합 검수와 구분해. 영어·중국어는 같은 한국어 안건의 현지화야.
AWS — Download and upload objects with presigned URLs