LabHub
배우기 러닝패스 코스

オブジェクトストレージとS3

なぜフォルダがないのか

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

한 줄 요약

오브젝트 스토리지에 디렉터리는 없다. img/2026/logo.png 는 슬래시가 든 하나의 긴 키일 뿐이고, 그 사실이 확장성의 근거다.

概念マップ: 키가 긴 문자열일 뿐・이름 바꾸기가 없습니다.・키 설계를 처음에 잘해야・빈 디렉터리가 없습니다.

왜 이게 필요했나

파일시스템은 트리입니다. 디렉터리마다 inode 가 있고, 파일 하나를 열려면 경로를 따라 내려가며 각 단계의 권한과 존재를 확인합니다. 이 구조가 로컬 디스크에서는 훌륭합니다. 그런데 노드 100대에 걸쳐 파일 100억 개를 두려고 하면 문제가 됩니다. 트리의 상위 노드가 모든 접근의 경합 지점이 되고, 디렉터리 하나에 파일 100만 개를 넣으면 ls 가 몇 분씩 걸립니다.

오브젝트 스토리지는 트리를 버립니다. 평평한 키-값 공간만 있습니다. 키는 그냥 문자열이고 슬래시는 특별한 의미가 없습니다. mc ls 나 콘솔이 폴더처럼 보여 주는 것은 접두어로 그룹핑한 화면일 뿐입니다.

이 단순화가 무엇을 사 주냐면, 키를 해시해서 어느 노드에 둘지 정할 수 있습니다. 중앙 디렉터리 서버가 필요 없고, 노드를 추가하면 용량과 처리량이 함께 늡니다.

어떻게 동작하나

대신 포기하는 것도 분명합니다.

첫째, 부분 수정이 없습니다. 객체는 통째로 쓰거나 통째로 읽습니다. 1GB 파일의 가운데 1바이트를 바꾸려면 1GB 를 다시 올려야 합니다. 그래서 로그 파일처럼 계속 덧붙이는 데이터에는 맞지 않습니다.

둘째, 이름 바꾸기가 없습니다. 이름 변경은 복사 후 삭제입니다. img/ 접두어를 images/ 로 바꾸려면 그 아래 모든 객체를 복사하고 지워야 합니다. 접두어 설계를 처음에 잘 해야 하는 이유입니다.

셋째, POSIX 의미론이 없습니다. 파일 잠금, 하드링크, 원자적 이름 변경 같은 것이 없습니다. 데이터베이스 파일을 오브젝트 스토리지에 두면 안 되는 이유입니다.

넷째, 목록 조회가 비쌉니다. 접두어 기반 목록은 가능하지만 "크기가 1MB 이상인 것"이나 "어제 수정된 것"을 찾으려면 전부 훑어야 합니다. 메타데이터 검색이 필요하면 별도 색인을 둡니다.

현장에서 만나는 모습

접두어 설계에서 자주 하는 실수가 날짜를 맨 앞에 두는 것입니다. 2026-08-20/user/... 로 하면 그날 들어오는 모든 쓰기가 같은 접두어 범위에 몰립니다. 파티셔닝이 키 순서에 기반한 구현에서는 이것이 핫스팟이 됩니다. 앞자리에 흩어지는 값(사용자 ID 해시 앞 두 글자 등)을 두는 편이 안전합니다.

그리고 오브젝트 스토리지에 진짜로 맞는 워크로드를 기억해 두면 좋습니다 — 한 번 쓰고 여러 번 읽는 크고 불변인 데이터입니다. 이미지, 동영상, 백업, 학습 데이터셋, 빌드 산출물. 반대로 자주 부분 수정되는 작은 데이터는 데이터베이스가 맞습니다.

파일시스템처럼 쓰면 생기는 일

S3 에는 디렉터리가 없고 키가 긴 문자열일 뿐 입니다. / 는 화면이 트리처럼 보여 주려고 쓰는 관례입니다. 이 차이가 실무에서 세 가지로 나타납니다.

이름 바꾸기가 없습니다. mv 는 복사 + 삭제입니다. 100GB 디렉터리의 이름을 바꾸면 100GB 를 복사하고 지웁니다. 그래서 키 설계를 처음에 잘해야 합니다.

빈 디렉터리가 없습니다. 안의 객체를 다 지우면 그 "폴더" 는 사라집니다. s3://bucket/logs/ 를 만들어 두는 것은 0바이트 객체를 만드는 것일 뿐입니다.

목록 조회가 비쌉니다. LIST 는 1,000개씩 페이지로 옵니다. 객체가 100만 개면 1,000번 왕복입니다. 파일시스템의 ls 를 떠올리고 매 요청마다 목록을 부르면 비용과 지연이 함께 오릅니다.

키를 설계하는 법

옛날에는 "앞부분을 무작위로 흩어야 성능이 난다" 고 했지만, 지금은 S3 가 프리픽스 단위로 자동 분할하므로 읽기 쉬운 순서 로 두는 편이 낫습니다.

logs/2026/09/06/api/instance-42.jsonl.gz
  │    └ 시간 계층 — 수명주기 규칙과 부분 조회에 유리
  └ 종류

❌ 2026-09-06-api-instance-42.jsonl.gz    ← 접두로 못 자른다

시간을 계층으로 두면 logs/2026/09/ 만 지우거나 그 달만 값싼 등급으로 옮기는 규칙을 쉽게 씁니다. 반대로 한 줄로 붙이면 접두 조건을 만들 수 없습니다.

언제 파일시스템이 맞나

객체 저장소가 언제나 답은 아닙니다.

객체 저장소 파일시스템(NFS·EFS)
부분 수정 불가(전체 재업로드) 가능
이름 바꾸기 복사+삭제 즉시
잠금 없음 있다
POSIX 의미 없음 있다
확장성 사실상 무한 한계가 있다
단가 싸다 몇 배 비싸다

기존 애플리케이션이 파일을 부분 수정하거나 잠금을 쓴다면 객체 저장소로 그냥 옮길 수 없습니다. s3fs 같은 도구로 마운트할 수는 있지만, 부분 수정이 전체 재업로드가 되고 잠금은 흉내일 뿐이라 성능과 정합성이 모두 나빠집니다.

쓰고 나서 안 바꾸는 것(로그·이미지·백업·모델 가중치)은 객체 저장소가 맞고, 계속 고치는 것(작업 디렉터리·DB 파일)은 아닙니다.

다음 실습에서 할 것

로컬 S3 호환 서버에 별칭을 붙이고 버킷을 만들고 객체를 올리고 접두어로 정리합니다. ETag 가 무엇인지 로컬 md5 와 비교해 확인하고, 서버 사이드 복사와 Content-Type 지정까지 다뤄 봅니다.