2025. 12. 29. 19:20ㆍ개념 공부
Flash-based SSDs 한 방에 정리
SSD는 “움직이는 부품이 없는” 영구 저장장치이고, 핵심 기술은 NAND Flash다. 단, DRAM처럼 마음대로 덮어쓰기(rewrite)가 되지 않아 내부가 훨씬 복잡해진다.
1) 용어부터 정확히: Flash의 Block/Page는 디스크의 Block과 다르다
- Flash Block(=erase block): 보통 128KB~256KB 같은 큰 단위. Erase는 블록 단위.
- Flash Page: 보통 4KB 정도. Read/Program은 페이지 단위.
현장에서 “블록”이란 단어가 레이어마다 의미가 달라 헷갈리기 쉽다. 디스크/RAID/파일시스템/플래시에서 블록이 다르니, 대화할 때 “erase block”, “flash page”처럼 명시해라.
2) Flash의 3대 연산: Read / Erase / Program
- Read (page): 페이지를 읽음. 수십 μs 수준으로 빠르고 랜덤 접근도 일정하게 빠름.
- Erase (block): 쓰기 전에 해당 블록 전체를 먼저 지움. ms 단위로 비쌈. (모든 비트를 1로 리셋)
- Program (page): 지워진(ERASED) 페이지를 실제 데이터로 채움. 읽기보단 느리고 erase보단 빠름(수백 μs).
페이지 상태 머신(시험/면접 단골)
Initial: i i i i (INVALID)
Erase() -> E E E E (ERASED, 프로그램 가능)
Prog(p0)-> V E E E (VALID)
Prog(p0)-> ERROR (한 번 프로그램한 페이지는 다시 프로그램 불가)
Erase() -> E E E E (블록 전체 지워야 다시 쓸 수 있음)
핵심 직관: Flash는 “페이지 덮어쓰기”가 아니라 “블록 지우고 → 페이지 순차로 다시 채우기”에 가깝다. 그래서 SSD는 내부적으로 쓰기 요청을 ‘재배치’할 수밖에 없다.
3) 성능/신뢰성 특징: 왜 쓰기가 문제인가?
대략적인 지연 시간(감 잡기)
- Read: 수십 μs
- Program: 수백 μs
- Erase: 수 ms (제일 비쌈)
신뢰성 이슈 2개
- Wear-out(수명): 한 블록을 너무 많이 P/E(Program/Erase)하면 결국 못 씀. (MLC는 대략 1만 P/E 같은 식으로 “등급”이 있음)
- Disturbance: 한 페이지를 읽거나 프로그램할 때 주변 페이지 비트가 뒤집히는 현상(읽기/프로그램 디스터브).
SSD 성능은 “평상시(새 드라이브/GC 없음)”보다 steady-state(오래 사용, GC 진행 중)에서 갈린다. 그리고 수명은 “어떤 워크로드가 얼마나 덮어쓰는지”에 달려서, 소프트웨어 설계가 하드웨어 수명을 좌우한다.
4) SSD가 디스크처럼 보이게 만드는 핵심: FTL(Flash Translation Layer)
운영체제/파일시스템은 보통 “논리 블록 주소(LBA)에 read/write”하는 디스크 인터페이스를 기대한다. 하지만 Flash는 erase/program 제약이 있으니, SSD 내부의 FTL이 요청을 read/erase/program으로 번역한다.
- FTL은 논리 주소(LBA) → 물리 페이지 주소(PPA)를 연결하는 매핑 테이블을 관리한다.
- 목표: (1) 성능 좋게 (2) write amplification 줄이고 (3) wear leveling으로 수명 확보
5) FTL의 “나쁜 설계” (Direct-mapped): 왜 망하는가?
가장 단순한 생각: 논리 페이지 N을 물리 페이지 N에 그대로 매핑하자. 문제는 overwrite가 발생할 때마다:
- 해당 페이지가 속한 블록 전체를 읽고(live 데이터 보존하려면 필요)
- 블록을 erase하고
- 기존 페이지들 + 변경된 페이지를 모두 다시 program해야 한다
결과: 블록에 페이지가 많을수록 write amplification이 폭증하고, 특정 논리 주소만 자주 덮어쓰면 같은 물리 블록만 혹사되어 수명도 급락.
6) 정답에 가까운 방식: Log-structured FTL
덮어쓰지 말고, 새 데이터는 항상 “다음 빈 페이지”에 append한다. 그리고 “논리 주소가 실제 어디에 있는지”를 매핑 테이블로 추적한다.
왜 빠른가?
- overwrite 때마다 블록 erase를 강제하지 않고, 빈 곳에 순차적으로 program → 쓰기 지연을 줄임
- 쓰기들이 내부적으로 “연속적인 로그”처럼 쌓여서 랜덤 write를 순차 write로 바꾸는 효과
- 전체 블록에 골고루 쓰기 쉬워 wear leveling에 유리
하지만 대가가 있다: Garbage Collection(GC)
overwrite의 “옛 버전”은 남아서 garbage(죽은 데이터)가 된다. 공간을 회수하려면 GC가:
- garbage가 많은 블록을 고르고
- 그 블록 안의 live 페이지들을 읽어서
- 로그 끝으로 다시 써주고
- 블록을 erase해서 재사용 가능하게 만든다
이 과정이 바로 write amplification의 주된 원인이다.
“SSD는 write가 빠르다”가 항상 참이 아니다. 많은 SSD가 평소엔 로그처럼 잘 쓰다가, GC가 몰리면 순간적으로 지연이 튀는 현상이 나타난다. 서비스에서는 p99/p999 지연이 문제라서, GC/WA를 줄이는 설계가 중요해진다.
7) TRIM(삭제 힌트)과 Overprovisioning(여유 공간)의 의미
- TRIM: “이 논리 블록은 삭제됐으니 더 이상 필요 없다”를 SSD에 알려 GC가 더 효율적으로 하도록 돕는다.
- Overprovisioning: 실제 용량보다 내부 여유 공간을 둬서 GC를 덜 급하게/더 백그라운드로 돌리게 함 → 성능 안정화에 도움.
8) 매핑 테이블의 딜레마: Page mapping은 좋지만 메모리가 터진다
이상적인 성능을 위해서는 “논리 4KB 페이지마다” 물리 위치를 기록하는 page-level mapping이 좋다. 하지만 SSD가 커지면 매핑 테이블이 엄청 커진다(메모리 비용 폭발).
대안 1) Block-level mapping (메모리는 줄지만 작은 write가 지옥)
블록 단위로만 매핑하면, 블록 안의 일부(예: 4KB)만 수정해도 나머지 live 페이지들을 함께 모아 블록 단위로 다시 써야 해서 write amplification이 커진다.
대안 2) Hybrid mapping (현실적인 타협)
- Data table: 큰 덩어리는 block-level로 매핑(메모리 절약)
- Log table: 일부 “로그 블록”만 page-level로 매핑(작은 write 흡수)
- 주기적으로 log 블록을 정리/병합(merge)해서 다시 block-level로 돌아가게 함
병합에는 대표적으로 switch merge(이상적), partial merge, full merge(가장 비쌈) 같은 케이스가 있고, full merge가 잦으면 성능이 크게 떨어진다.
SSD 성능이 워크로드(쓰기 패턴)에 민감한 이유가 여기 있다. “작고 흩어진 덮어쓰기”가 많으면 log table/merge/GC가 바빠지고, write amplification이 커진다.
9) Wear Leveling: 수명을 맞추는 ‘백그라운드 이사’
어떤 블록은 자주 덮어써서 빨리 닳고, 어떤 블록은 오래 살아남는 “불균형”이 생길 수 있다. FTL은 주기적으로 “오래 안 바뀐 데이터(장수 데이터)”도 다른 곳으로 옮겨, 모든 블록이 비슷한 속도로 닳게 만드는 wear leveling을 수행한다. 이 역시 추가 I/O를 유발해 write amplification을 늘릴 수 있다.
10) SSD vs HDD: 어디서 차이가 극적이냐?
- 랜덤 I/O: SSD가 HDD를 압도(기계적 seek/rotation이 없기 때문).
- 순차 I/O: HDD도 꽤 잘함. 차이는 랜덤만큼 극적이지 않다.
- 비용(GB당): SSD가 더 비싸서, 대규모 저장은 여전히 HDD가 매력적일 수 있다.
11) “실무 감각”으로 가져가야 할 6줄
- Flash는 page write 전에 block erase가 필요하고, 그게 느리다.
- SSD는 FTL로 “디스크처럼 보이게” 만들고, 내부는 로그 구조가 많다.
- 로그 구조의 대가는 GC + write amplification이다.
- 매핑 테이블은 성능/메모리의 핵심 트레이드오프라서 hybrid/caching 같은 타협을 쓴다.
- 수명 문제 때문에 wear leveling이 필수고, 이것도 추가 I/O 비용을 만든다.
- SSD 성능은 평균보다 GC가 몰릴 때의 tail latency를 봐야 한다.
12) 복습용 질문 3개
- Q1. Direct-mapped FTL에서 “작은 overwrite”가 왜 (읽기+erase+대량 program)로 이어지고 write amplification이 폭증하는가?
- Q2. Log-structured FTL에서 GC가 하는 “live page 이동”이 왜 성능(특히 tail latency)에 영향을 주는가?
- Q3. Page-level mapping vs Block-level mapping vs Hybrid mapping의 trade-off를 “메모리 vs 작은 write 성능” 관점에서 비교해보라.
'개념 공부' 카테고리의 다른 글
| 운영체제 아주 쉬운 세가지 이야기 18주차(Sun 사의 네트워크 파일 시스템(NFS) (1) | 2026.01.06 |
|---|---|
| 운영체제 아주 쉬운 세가지 이야기 18주차(분산 시스템) (0) | 2026.01.06 |
| 운영체제 아주 쉬운 세가지 이야기 17주차(RAID) (0) | 2025.12.29 |
| 운영체제 아주 쉬운 세가지 이야기 16주차(데이터 무결성과 보호) (0) | 2025.12.23 |
| 운영체제 아주 쉬운 세가지 이야기 15주차(크래시 일관성: FSCK와 저널링) (1) | 2025.12.16 |