스토리지
고친 사람 github-actions[bot]
스토리지는 데이터를 전원이 꺼져도 사라지지 않게 맡아 두는 일을 합니다. 서버가 받은 파일과 데이터베이스에 쌓인 기록이 모두 스토리지에 남습니다. 브라우저나 그래픽 프로그래밍에도 스토리지라는 이름이 붙은 것이 따로 있습니다. 이 편은 서버가 데이터를 보관하는 쪽의 뜻을 다룹니다.
쉽고 빠른 이해
스토리지는 데이터를 오래 보관하는 곳입니다. 사용자가 올린 프로필 사진은 서버를 껐다 켜도 남아 있어야 합니다. 그 사진이 놓이는 곳이 스토리지입니다.
메모리는 빠르지만 전원이 꺼지면 비워집니다. 스토리지가 없으면 서버를 다시 켤 때마다 주문 기록과 회원 정보가 사라집니다.
어떻게 도는가:
대가도 있습니다. 메모리보다 훨씬 느립니다. 장치는 언젠가 고장 나므로 같은 데이터를 여러 벌 두어야 합니다. 그만큼 공간과 비용이 더 듭니다.
상세
스토리지(storage)는 데이터를 오래 보관하는 자원입니다. 서버를 굴리는 데 드는 자원은 흔히 셋으로 나눕니다. 계산은 컴퓨팅이, 서버끼리의 연결은 네트워크가, 보관은 스토리지가 맡습니다.
이 절은 먼저 메모리와 무엇이 다른지를 봅니다. 그다음 데이터를 담는 장치, 데이터를 꺼내 쓰는 세 방식, 스토리지가 서버 안에 있느냐 밖에 있느냐를 차례로 봅니다. 마지막으로 쓴 데이터가 언제 안전해지는지, 성능은 무엇으로 재는지, 고장에 어떻게 대비하는지를 다룹니다.
메모리와 스토리지
프로그램이 돌아가는 동안 쓰는 데이터는 메모리에 있습니다. 메모리는 전원이 끊기면 내용을 잃습니다. 이런 성질을 휘발성이라고 부릅니다.
스토리지는 그 반대입니다. 전원이 끊겨도 내용이 남습니다. 이 성질은 비휘발성이라고 부릅니다. 휘발성과 비휘발성은 장치가 지닌 성질입니다.
책상과 서류 캐비닛을 떠올리면 됩니다. 책상이 메모리이고 캐비닛이 스토리지입니다. 일하는 동안 서류는 책상 위에 펼쳐 둡니다. 책상은 좁습니다. 퇴근할 때는 치워집니다. 오래 둘 서류는 캐비닛에 넣습니다. 다음 날 거기서 다시 꺼냅니다.
장치가 아니라 데이터 쪽에서 보는 성질도 있습니다. 데이터가 프로그램이 끝난 뒤에도 살아남는 것을 영속성이라고 합니다. 주문 기록을 프로그램의 변수에만 두면 프로그램이 끝날 때 함께 사라지므로 영속성이 없습니다. 영속성은 데이터를 스토리지에 적어야 얻습니다.
둘은 속도와 크기에서도 갈립니다. 같은 돈을 들이면 스토리지가 훨씬 많이 담습니다. 대신 한 번 읽고 쓰는 데 걸리는 시간은 메모리보다 훨씬 깁니다.
| 메모리 | 스토리지 | |
|---|---|---|
| 전원이 꺼지면 | 내용이 사라진다 | 내용이 남는다 |
| 한 번 읽고 쓰는 데 걸리는 시간 | 짧다 | 길다 |
| 같은 비용으로 담는 양 | 적다 | 많다 |
| 주로 담는 것 | 지금 처리 중인 데이터 | 오래 둘 데이터 |
이 표가 서버 설계의 출발점입니다. 자주 읽는 데이터를 메모리에 복사해 두는 캐싱은 스토리지가 느려서 생긴 기법입니다. 반대로 메모리에만 둔 데이터는 서버가 죽으면 사라진다고 보고 설계합니다.
데이터를 담는 장치
서버의 스토리지 장치는 크게 둘입니다. 원반을 돌려 읽는 HDD(Hard Disk Drive, 하드 디스크 드라이브)와 반도체 칩에 적는 SSD(Solid State Drive, 솔리드 스테이트 드라이브)입니다. 둘을 함께 디스크라고 부르기도 합니다.
HDD 는 자석을 입힌 원반을 돌립니다. 그리고 팔 끝의 헤드를 원하는 위치로 옮겨 읽습니다. 그래서 흩어진 곳을 차례로 읽으면 헤드가 매번 움직이느라 오래 걸립니다. 이어진 곳을 쭉 읽을 때는 빠릅니다.
데이터를 흩어진 위치에서 하나씩 골라 읽는 것을 임의 접근이라고 합니다. 앞에서부터 이어서 읽는 것은 순차 접근입니다. HDD 는 순차 접근에 강하고 임의 접근에 약합니다.
SSD 는 움직이는 부품 없이 플래시 메모리 칩에 데이터를 적습니다. 헤드를 옮길 일이 없어서 임의 접근도 빠릅니다. 대신 칩의 한 칸에 다시 쓸 수 있는 횟수에 한도가 있어서, 오래 쓰면 닳습니다.
블록 · 파일 · 오브젝트
같은 장치라도 프로그램이 데이터를 꺼내 쓰는 방식은 셋으로 갈립니다. 이 소절은 세 방식이 데이터를 무엇으로 부르고 어떻게 고치는지를 견줍니다.
블록 스토리지는 장치를 같은 크기의 칸이 줄지어 선 것으로 봅니다. 이 칸 하나를 블록이라고 하고, 프로그램은 「몇 번 블록을 읽어라」처럼 번호로 가리킵니다. 블록에는 이름이 없습니다. 어느 블록에 무엇이 들었는지는 그 위에 올라탄 쪽이 기억합니다.
그 위에 올라타는 대표가 파일 시스템입니다. 파일 시스템은 블록 위에 이름과 디렉터리 트리를 세웁니다. 프로그램은 /data/orders.log 같은 경로로 파일을 엽니다. 파일 시스템이 그 경로를 블록 번호로 바꿉니다.
이렇게 데이터를 파일 단위로 내주고 경로로 가리키게 하는 방식을 파일 스토리지라고 부릅니다. 서버 안의 파일 시스템도 이 방식입니다. 다만 스토리지를 고를 때 「파일 스토리지」라고 하면 대개 여러 서버가 네트워크로 함께 붙는 파일 공간을 가리킵니다. 이 편의 표도 그 뜻으로 씁니다.
오브젝트 스토리지는 데이터 한 덩어리에 키라는 이름을 하나 붙여 통째로 올리고 통째로 받습니다. 이 덩어리를 오브젝트라고 합니다. 키는 photos/42.jpg 같은 문자열입니다. 요청은 HTTP(HyperText Transfer Protocol, 하이퍼텍스트 전송 프로토콜)로 보냅니다. 오브젝트의 가운데 일부만 고쳐 쓸 수는 없어서, 고치려면 새 덩어리를 다시 올립니다.
일부만 고칠 수 없는 대신 얻는 것이 있습니다. 오브젝트 스토리지에는 디렉터리 트리가 없고 키만 늘어서 있습니다. 오브젝트끼리 얽힌 구조가 없으니 키를 기준으로 여러 서버에 나눠 담으면 됩니다. 서버를 늘리면 담는 양도 그만큼 늘어서 거의 끝없이 담을 수 있습니다. 사진 · 동영상 · 백업 파일처럼 한 번 쓰고 여러 번 읽는 데이터가 여기에 잘 맞습니다.
| 블록 | 파일 | 오브젝트 | |
|---|---|---|---|
| 무엇으로 가리키나 | 블록 번호 | 경로 | 키 |
| 고치는 단위 | 블록 하나 | 파일의 아무 부분 | 오브젝트 전체 |
| 무엇으로 부르나 | 운영체제의 장치 입출력 | 파일 열기 · 읽기 · 쓰기 | HTTP 요청 |
| 흔한 쓰임 | 데이터베이스의 데이터 파일 · 서버의 부팅 디스크 | 여러 서버가 함께 보는 폴더 | 업로드 파일 · 백업 · 로그 보관 |
아래 그림은 셋이 서로 어떻게 얹히는지를 보입니다. 파일 시스템은 블록 위에 얹히지만, 오브젝트 스토리지는 애플리케이션이 네트워크 너머로 직접 부릅니다.
flowchart TD
subgraph 서버["서버 안"]
APP["애플리케이션"] --> FS["파일 시스템 · 경로를 블록 번호로"]
FS --> BLK["블록 스토리지 · 번호 붙은 칸"]
end
APP -->|"HTTP 요청 · 키로 통째로"| OBJ["오브젝트 스토리지"]
로컬 스토리지와 네트워크 스토리지
스토리지가 놓이는 곳도 둘로 갈립니다. 서버에 직접 꽂힌 디스크를 로컬 스토리지라고 합니다. 서버 밖에 따로 두고 네트워크로 붙는 것을 네트워크 스토리지라고 합니다.
로컬 스토리지는 네트워크를 거치지 않으니 빠릅니다. 대신 그 서버가 죽으면 디스크 안의 데이터도 같이 못 씁니다. 다른 서버가 그 데이터를 이어받으려면 디스크를 뽑아 옮겨야 합니다.
네트워크 스토리지는 이 문제를 풉니다. 데이터가 서버 밖에 있으니, 서버 하나가 죽어도 다른 서버가 같은 스토리지에 붙어 일을 이어 갑니다. 여러 서버가 한 데이터를 함께 볼 수도 있습니다.
flowchart TD
subgraph 로컬["로컬 스토리지"]
A1["서버 A"] --> D1["A 에 꽂힌 디스크"]
end
subgraph 원격["네트워크 스토리지"]
B1["서버 B"] --> NET["네트워크"]
B2["서버 C"] --> NET
NET --> D2["따로 선 스토리지"]
end
그림 위쪽에서 서버 A 가 죽으면 A 의 디스크도 함께 닿을 수 없게 됩니다. 아래쪽에서는 서버 B 가 죽어도 서버 C 가 같은 스토리지를 계속 씁니다.
네트워크 스토리지도 내주는 단위에 따라 이름이 다릅니다. 파일 단위로 내주면 NAS(Network-Attached Storage, 네트워크 연결 스토리지)라고 부릅니다. 여러 서버가 한 폴더를 함께 볼 때 쓰는 것이 이쪽입니다.
서버가 NAS 에 붙을 때는 약속된 프로토콜로 말을 주고받습니다. 대표가 NFS(Network File System, 네트워크 파일 시스템)입니다. NFS 로 붙이면 다른 컴퓨터의 폴더를 내 폴더처럼 경로로 열 수 있습니다.
블록 단위로 내주는 쪽은 SAN(Storage Area Network, 스토리지 영역 네트워크)이라고 부릅니다. 스토리지만 오가는 전용 네트워크입니다. 서버는 SAN 너머의 스토리지를 자기 디스크처럼 블록 번호로 읽고 씁니다.
네트워크 스토리지의 대가는 거리입니다. 읽고 쓸 때마다 네트워크를 오가므로 로컬보다 느립니다. 네트워크가 끊기면 데이터가 멀쩡해도 서버가 그 데이터를 못 씁니다.
클라우드는 블록 · 파일 · 오브젝트 세 방식을 모두 서비스로 빌려줍니다. 가상 서버에 붙이는 블록 볼륨, 여러 서버가 함께 붙는 파일 공유, HTTP 로 부르는 오브젝트 버킷입니다. 이름은 클라우드마다 다르지만 나누는 기준은 앞에서 본 세 방식과 같습니다.
서버를 갈아엎어도 남는 데이터
요즘 서버는 쉽게 지우고 다시 만듭니다. 배포할 때마다 새 컨테이너를 띄우고 옛 컨테이너는 지우는 식입니다. 이렇게 지워도 되는 것은 서버가 데이터를 안에 들고 있지 않을 때뿐입니다.
컨테이너 안에 쓴 파일은 컨테이너를 지우면 같이 사라집니다. 그래서 남아야 할 데이터는 컨테이너 밖의 스토리지에 둡니다. 컨테이너에 바깥 스토리지를 붙이는 방법을 볼륨이라고 부릅니다.
이렇게 나누면 서버는 상태(남아야 할 데이터)를 안 들고 계산만 하게 됩니다. 이런 서버를 무상태 서버라고 부릅니다. 상태는 스토리지와 그 위의 데이터베이스가 몰아서 맡습니다. 컴퓨팅과 스토리지를 떼어 관리하는 까닭이 이것입니다.
쓴 데이터가 장치에 닿는 때
프로그램이 파일에 쓰라고 해도 데이터가 곧바로 장치로 가지는 않습니다. 장치가 느리기 때문에 운영체제가 쓰기를 메모리에 잠시 모았다가 한꺼번에 내려보냅니다. 이 메모리 공간을 페이지 캐시라고 합니다.
모으는 동안 전원이 나가면 페이지 캐시에 있던 데이터는 사라집니다. 프로그램은 「썼다」는 답을 이미 받았는데도 그렇습니다. 주문 기록처럼 잃으면 안 되는 데이터에는 이 틈이 문제가 됩니다.
그래서 운영체제는 「지금까지 쓴 것을 장치까지 내려보내라」는 호출을 따로 둡니다. 유닉스 계열에서는 fsync가 그 호출입니다. 아래 파이썬 코드는 한 줄을 쓴 뒤 데이터가 어디까지 갔는지를 단계마다 보입니다.
import os
f = open("orders.log", "a")
f.write("주문 42\n") # 프로그램 버퍼까지
f.flush() # 페이지 캐시까지
os.fsync(f.fileno()) # 장치까지
write 는 파이썬이 쥔 버퍼에 쌓는 데서 끝납니다. flush 는 그 버퍼를 운영체제에 넘겨 페이지 캐시에 올립니다. fsync 가 돌아온 뒤에야 데이터가 장치에 적혔다고 믿을 수 있습니다.
fsync 는 장치가 기록을 끝낼 때까지 기다리므로 느립니다. 그래서 데이터베이스는 쓰기를 모아 두었다가 한 번에 fsync 를 부릅니다. 이렇게 부르는 횟수를 줄입니다.
데이터베이스가 fsync 를 꼭 부르는 곳이 로그 선행 기록입니다. 데이터를 고치기 전에 무엇을 고칠지를 로그 파일 끝에 먼저 적어 두는 방식입니다. 커밋은 이 로그가 장치에 닿은 뒤에야 끝납니다. 그래야 전원이 나가도 로그를 다시 읽어 하던 일을 마저 할 수 있습니다.
성능을 재는 세 값
스토리지 성능은 셋 가운데 무엇을 재느냐에 따라 다른 값이 나옵니다. 이 소절은 세 값이 각각 무엇을 재고 어느 작업이 그 값을 따지는지를 봅니다.
첫째 값은 IOPS(Input/Output Operations Per Second, 초당 입출력 횟수)입니다. 요청을 1초에 몇 번 처리하는지를 셉니다. 나머지 둘은 1초에 옮기는 양과 요청 하나를 기다리는 시간입니다.
| 값 | 무엇을 재나 | 따지는 작업 |
|---|---|---|
| IOPS | 1초에 읽기 · 쓰기 요청을 몇 번 처리하나 | 작은 데이터를 흩어진 위치에서 자주 읽고 쓰는 데이터베이스 |
| 처리량 | 1초에 몇 바이트를 옮기나 | 큰 파일을 이어서 읽고 쓰는 백업 · 동영상 · 로그 |
| 지연 시간 | 요청 하나가 답을 받기까지 얼마나 걸리나 | 사용자 요청마다 스토리지를 기다리는 서비스 |
요청 하나가 작으면 IOPS 가 먼저 한도에 닿습니다. 요청 하나가 크면 처리량이 먼저 한도에 닿습니다.
같은 스토리지라도 작업 모양에 따라 버티는 정도가 다릅니다. 앞에서 본 임의 접근과 순차 접근의 차이가 여기서 드러납니다. HDD 는 순차 접근의 처리량은 넉넉해도 임의 접근의 IOPS 가 낮습니다.
장치가 고장 날 때를 대비하는 법
스토리지 장치는 언젠가 고장 납니다. 장치 하나에만 둔 데이터는 그 장치와 함께 사라집니다. 데이터가 이런 고장을 견디고 남는 정도를 내구성이라고 부릅니다.
내구성을 높이는 기본 방법은 같은 데이터를 여러 곳에 두는 것입니다. 한 서버 안에서 하는 방법이 RAID(Redundant Array of Independent Disks, 독립 디스크 중복 배열)입니다. 디스크 여러 장에 데이터를 나눠 적어서 디스크 한 장이 고장 나도 데이터가 남게 합니다.
서버째 고장 나면 RAID 로는 못 버팁니다. 그래서 서로 다른 서버나 장소에 사본을 둡니다. 이 일을 복제라고 합니다.
복제는 백업을 대신하지 못합니다. 누가 실수로 테이블을 지우면 그 삭제도 사본으로 복제되어 사본까지 지워집니다. 백업은 지난 시점의 모습을 떼어 둔 것이라 그 시점으로 되돌릴 수 있습니다.
| 복제 | 백업 | |
|---|---|---|
| 막는 것 | 장치 · 서버 고장 | 실수로 지움 · 잘못 고침 |
| 사본의 시점 | 지금과 같다 | 지난 어느 시점 |
| 원본이 지워지면 | 사본도 지워진다 | 사본은 남는다 |
사본을 늘릴수록 담는 데 드는 공간과 비용도 그 배수로 늡니다. 그래서 자주 안 꺼내는 오래된 데이터는 느리지만 싼 스토리지로 옮겨 둡니다. 데이터를 자주 쓰는 정도에 따라 다른 스토리지로 나눠 두는 일을 스토리지 티어링이라고 합니다.
쓰임새에 맞는 스토리지
앞의 소절들이 보인 성질을 쓰임새로 옮기면 다음과 같습니다.
| 상황 | 맞는 방식 | 까닭 |
|---|---|---|
| 데이터베이스의 데이터 파일 | 블록 스토리지 | 작은 부분을 자주 고쳐 쓰고 지연 시간을 따진다 |
| 여러 서버가 같은 폴더를 경로로 본다 | 파일 스토리지 | 코드를 안 고치고 같은 파일을 함께 본다 |
| 사용자가 올린 사진 · 백업 · 오래된 로그 | 오브젝트 스토리지 | 통째로 쓰고 여러 번 읽으며 양이 끝없이 는다 |
| 지워져도 다시 만들 수 있는 임시 계산 결과 | 블록 스토리지(로컬 디스크) | 네트워크를 안 거쳐 빠르고 잃어도 된다 |
관련 항목
스토리지와 함께 서버를 이루는 자원
컴퓨팅 · 네트워크 · 메모리 · CPU · 인프라 · 플랫폼 엔지니어링
스토리지에 데이터를 담는 장치
디스크 · HDD · SSD · NVMe · 플래시 메모리 · 자기 테이프
데이터를 꺼내 쓰는 방식으로 나눈 스토리지의 하위 종류
블록 스토리지 · 파일 스토리지 · 오브젝트 스토리지 · 파일 시스템 · 블록 장치 · 블록 계층
스토리지를 서버 밖에 두고 붙이는 방식
로컬 디스크 · 네트워크 스토리지 · NAS · SAN · NFS · SMB · iSCSI · 분산 파일 시스템
스토리지를 빌려 쓰는 클라우드 서비스
클라우드 스토리지 · Amazon S3 · Amazon EBS · Amazon EFS · Google Cloud Storage · Azure Blob Storage · 스토리지 클래스
스토리지를 컨테이너에 붙이는 방법
컨테이너 · 볼륨 · 퍼시스턴트 볼륨 · Kubernetes · Docker · 무상태
쓴 데이터가 장치에 닿기까지 거치는 단계
페이지 캐시 · 버퍼 · fsync · 로그 선행 기록 · 디스크 입출력 · 스토리지 엔진
스토리지 성능을 재는 지표
IOPS · 처리량 · 지연 시간 · 임의 접근 · 순차 접근 · 스토리지 고갈
스토리지가 지키려는 성질과 그 방법
영속성 · 내구성 · 복제 · 백업 · RAID · 스냅숏 · 이레이저 코딩
스토리지 비용을 줄이는 계층 나누기
스토리지 티어링 · 계층형 스토리지 · 핫 데이터 · 콜드 스토리지 · 아카이브 스토리지 · 캐싱
이름에 스토리지가 붙었지만 뜻이 다른 용어
웹 스토리지 · 스토리지 버퍼 · 스토리지 이미지 · 스토리지 텍스처 · 스토리지 모드
다른 이름: storage · 데이터 스토리지 · 저장 장치