aws CLI 로 버킷과 객체 다루기
목표
S3 호환 스토리지의 기본 조작 — 프로필, 버킷, 객체 업로드, 접두어, 목록, ETag, 복사, 메타데이터 — 를 aws CLI 로 손에 익히고 오브젝트 스토리지에 디렉터리가 없다는 사실을 체감한다.
왜 중요한가
S3 API 를 이해하는 것은 특정 벤더를 배우는 일이 아닙니다. AWS S3, SeaweedFS, Garage, Ceph RGW, MinIO 가 전부 같은 API 를 말하기 때문에, 이 API 는 사실상의 이식성 계층입니다. 실제로 2025~2026년 MinIO 커뮤니티 에디션이 배포를 중단했을 때 애플리케이션 쪽 이주 비용이 크지 않았던 이유가 이것입니다 — 엔드포인트와 자격 증명만 바꾸면 코드는 대체로 그대로였습니다. 이 실습 환경도 같은 일을 겪었습니다. 서버가 MinIO 에서 SeaweedFS 의 S3 게이트웨이로 바뀌었지만, 여기서 치는 명령은 AWS 에서도 한 글자 안 바꾸고 돕니다. 이 실습에서 특히 기억할 것은 6번 스텝의 ETag 입니다. 단일 파트 업로드에서 ETag 는 내용의 md5 이고, 그래서 업로드가 온전했는지 클라이언트가 스스로 검증할 수 있습니다. 다음 실습에서 멀티파트 업로드의 ETag 가 이것과 어떻게 달라지는지를 다룰 때, 여기서 본 규칙이 출발점이 됩니다.
단계
aws configure set으로 프로필local에 네 값 —aws_access_key_id,aws_secret_access_key,region,endpoint_url(http://127.0.0.1:9000) — 을 넣는다. 자격 증명은/opt/fixtures/s3/creds.env에 있다.aws --profile local s3 ls가 오류 없이 끝나야 한다.- 버킷
lab-media를 만든다.aws --profile local s3 ls목록에 나타나야 한다. /opt/fixtures/s3/logo.png를s3://lab-media/img/logo.png로 올린다./opt/fixtures/s3/의banner.png를img/banner.png로,readme.txt를doc/readme.txt로,sales.csv를doc/sales.csv로 올린다.aws --profile local s3 ls --recursive s3://lab-media결과를/root/s3/list.txt에 저장한다. 정확히 4줄이어야 한다./root/s3/etag.txt에etag=<값>과md5=<값>두 줄을 적는다.logo.png의 ETag(따옴표 제거)와 로컬 파일 md5 가 같아야 한다.doc/readme.txt를doc/README.txt로 서버 사이드 복사한 뒤 원본을 지운다.aws --profile local s3 ls s3://lab-media/doc/에README.txt만 있고readme.txt는 없어야 한다.sales.csv를text/csvContent-Type 으로 다시 올린다.aws --profile local s3api head-object --bucket lab-media --key doc/sales.csv출력의ContentType이text/csv여야 한다.
참고
- 프로필 확인:
aws configure list --profile local(시크릿은 끝 네 글자만 보인다) - 매번
--profile local을 붙이기 싫으면export AWS_PROFILE=local - 재귀 목록:
aws s3 ls --recursive s3://lab-media - 객체 메타데이터:
aws s3api head-object --bucket lab-media --key img/logo.png - Content-Type 지정:
aws s3 cp 파일 s3://버킷/키 --content-type text/csv aws s3는 파일 복사처럼 쓰는 고수준 명령이고,aws s3api는 S3 API 호출 하나하나에 1:1 로 대응한다. 무엇이 실제로 오가는지 보고 싶을 때는s3api를 쓴다.- 흔한 실수 1: 버킷 이름에 대문자나 밑줄을 쓰는 것 — DNS 규칙을 따릅니다.
- 흔한 실수 2:
img/를 폴더로 착각해 따로 만들려는 것 — 키 이름의 일부일 뿐입니다.
S3 프로필 설정하기
aws configure set 으로 프로필 local 에 aws_access_key_id, aws_secret_access_key, region, endpoint_url(http://127.0.0.1:9000) 네 값을 넣는다. 자격 증명은 /opt/fixtures/s3/creds.env 에 있다. aws --profile local s3 ls 가 오류 없이 끝나야 한다.
엔드포인트와 자격 증명을 프로필 하나로 묶습니다. 자격 증명은 /opt/fixtures/s3/creds.env 에 있고, endpoint_url 을 빼면 CLI 가 진짜 AWS 로 나가려 합니다.
버킷 만들기
버킷 lab-media 를 만든다. aws --profile local s3 ls 목록에 나타나야 한다.
버킷 이름은 DNS 규칙을 따릅니다 — 소문자, 숫자, 하이픈만 쓸 수 있습니다.
객체 하나 올리기
/opt/fixtures/s3/logo.png 를 s3://lab-media/img/logo.png 로 올린다.
로컬 경로와 대상 키를 함께 지정합니다. 대상 키의 슬래시는 폴더가 아니라 이름의 일부입니다.
접두어로 정리하기
/opt/fixtures/s3/ 의 banner.png 를 img/banner.png 로, readme.txt 를 doc/readme.txt 로, sales.csv 를 doc/sales.csv 로 올린다.
img/ 와 doc/ 아래에 나눠 올립니다. 실제로는 폴더가 만들어지는 게 아니라 키 이름이 그렇게 되는 것입니다.
재귀 목록 뽑기
aws --profile local s3 ls --recursive s3://lab-media 결과를 /root/s3/list.txt 에 저장한다. 정확히 4줄이어야 한다.
기본 목록은 접두어 단위로 접혀 보입니다. 전부 펼치는 옵션이 있습니다.
ETag 와 로컬 해시 비교하기
/root/s3/etag.txt 에 etag=<값> 과 md5=<값> 두 줄을 적는다. logo.png 의 ETag(따옴표 제거)와 로컬 파일 md5 가 같아야 한다.
단일 파트 업로드의 ETag 는 내용의 md5 입니다. 두 값을 나란히 적어 비교하세요.
서버 사이드 복사 후 원본 지우기
doc/readme.txt 를 doc/README.txt 로 서버 사이드 복사한 뒤 원본을 지운다. aws --profile local s3 ls s3://lab-media/doc/ 에 README.txt 만 있고 readme.txt 는 없어야 한다.
이름 변경은 없습니다. 복사하고 지우는 것이 이름 변경입니다. 다운로드 없이 서버에서 처리되게 하세요.
Content-Type 지정해 올리고 확인하기
sales.csv 를 text/csv Content-Type 으로 다시 올린다. aws --profile local s3api head-object --bucket lab-media --key doc/sales.csv 출력의 ContentType 이 text/csv 여야 한다.
확장자로 추측되기도 하지만 명시하는 편이 안전합니다. 객체 메타데이터를 조회해 확인하세요.