NAND NVMe SSD Analysis
NAND 플래시 및 NVMe SSD 동작 원리 상세 분석
NAND Flash Memory · SSD Controller · FTL · NVMe Protocol · OS I/O Stack
본 문서는 NAND 플래시 메모리의 물리적 동작부터 SSD 컨트롤러의 FTL, 호스트와의 NVMe 프로토콜 통신, 그리고 운영체제(OS)가 SSD를 다루는 방식(파일시스템·블록 I/O 스택·TRIM·I/O 스케줄러)까지 SSD의 전체 동작 스택을 계층적으로 분석합니다.
이 흐름은 셀의 전하 저장 특성, 컨트롤러의 주소 변환, 호스트 큐잉, 커널의 블록 계층이 하나의 파이프라인처럼 이어진다는 점에서 중요합니다. 읽기 지연, 쓰기 증폭, 마모 평준화, TRIM, 오버프로비저닝은 각각 따로 존재하는 기능이 아니라 서로의 부담을 줄이기 위해 맞물려 동작합니다.
1. SSD 전체 아키텍처 개요
SSD는 크게 호스트 인터페이스, SSD 컨트롤러(SoC), 그리고 NAND 플래시 어레이의 세 부분으로 구성됩니다. 호스트는 PCIe 버스 위에서 NVMe 프로토콜로 명령을 전달하고, 컨트롤러 내부의 FTL이 논리 주소를 물리 주소로 변환하며, 멀티 채널을 통해 여러 NAND 패키지에 병렬로 접근합니다.
그림 1. NVMe SSD 전체 아키텍처 — 호스트에서 NAND 셀까지의 데이터 경로 및 NAND 계층 구조
NAND 계층 구조
NAND 플래시는 Package ⊃ Die(LUN) ⊃ Plane ⊃ Block ⊃ Page ⊃ Cell의 계층으로 구성됩니다. 각 계층은 병렬성과 동작 단위를 결정하는 핵심 요소입니다.
2. NAND 셀 동작 원리
NAND 셀은 플로팅 게이트(또는 charge trap) 트랜지스터로, 게이트에 저장된 전하량에 따라 문턱전압(Vth)이 달라지는 원리를 이용해 데이터를 저장합니다. 전하량을 여러 단계로 구분하면 한 셀에 여러 비트를 저장할 수 있습니다.
그림 2. NAND 셀 구조, 셀당 저장 비트(SLC~QLC), 그리고 읽기/쓰기/소거 3대 동작
셀당 저장 비트 수 비교
셀당 비트 수가 늘수록 같은 면적에 더 많은 데이터를 저장하지만, 전압 레벨 간 간격이 좁아져 오류율이 높아지고 P/E 수명이 급감합니다. 이를 보완하기 위해 강력한 ECC(LDPC)와 정교한 FTL이 필수가 됩니다.
읽기 / 쓰기 / 소거의 비대칭성
NAND의 가장 중요한 특성은 동작 단위의 비대칭성입니다. 읽기와 쓰기는 Page 단위로 수행되지만, 소거는 그보다 훨씬 큰 Block 단위로만 가능합니다. 또한 이미 데이터가 쓰인 셀에 곧바로 덮어쓸 수 없고(in-place update 불가), 반드시 소거를 먼저 거쳐야 합니다.
이 비대칭성(Page R/W vs Block Erase)과 'erase-before-write' 제약이 바로 FTL이라는 소프트웨어 계층이 반드시 필요한 근본 원인입니다.
3. FTL (Flash Translation Layer)
FTL은 NAND의 물리적 제약을 호스트로부터 숨기고, 일반 블록 디바이스처럼 보이게 하는 핵심 펌웨어 계층입니다. 네 가지 핵심 기능 — 논리-물리 매핑, 가비지 컬렉션, 마모 평준화, 오버프로비저닝 — 을 수행합니다.
그림 3. FTL의 4대 핵심 동작 — 매핑, 가비지 컬렉션, 마모 평준화, 오버프로비저닝
① 논리-물리 주소 매핑 (L2P)
호스트가 사용하는 논리 주소(LBA)를 NAND의 물리 주소(PPA)로 변환하는 매핑 테이블을 관리합니다. 덮어쓰기가 불가능하므로, 같은 LBA에 대한 쓰기 요청이 와도 매번 새로운 빈 페이지에 기록하고 매핑 테이블만 갱신합니다(out-of-place update). 이 매핑 테이블은 접근 속도를 위해 SSD 내장 DRAM에 저장됩니다.
DRAM-less SSD는 Host Memory Buffer(HMB)나 더 작은 온디바이스 캐시를 함께 사용해 매핑 테이블의 일부를 호스트 메모리에 둡니다.
② 가비지 컬렉션 (Garbage Collection)
out-of-place 쓰기로 인해 무효(invalid) 페이지가 블록 곳곳에 흩어지면, 유효(valid) 페이지만 새 블록으로 모아 옮긴 뒤 원래 블록을 통째로 소거해 빈 공간을 회수합니다. 이 과정에서 호스트가 요청하지 않은 추가 쓰기가 발생하며, 이를 Write Amplification(WAF)이라 합니다. WAF가 높을수록 수명과 성능이 저하됩니다.
③ 마모 평준화 (Wear Leveling)
NAND 블록은 P/E Cycle 한계가 있어, 특정 블록에만 쓰기가 집중되면 그 블록이 먼저 수명을 다해 전체 SSD를 못 쓰게 됩니다. 마모 평준화는 모든 블록의 P/E 횟수를 균등하게 분산시켜 전체 수명을 극대화합니다.
④ 오버프로비저닝 (Over-Provisioning)
사용자에게 노출되지 않는 예비 영역(통상 7~28%)을 두어, 가비지 컬렉션이 항상 충분한 빈 블록을 확보할 수 있게 합니다. OP가 클수록 WAF가 낮아지고 성능과 수명이 향상됩니다.
4. ECC (오류 정정)
미세 공정과 다비트 셀(QLC)로 인해 NAND의 원시 비트 오류율(RBER)은 매우 높습니다. SSD 컨트롤러는 강력한 ECC 엔진으로 이를 정정합니다.
LDPC는 셀의 전압을 여러 번 정밀 측정(soft read)해 확률 기반으로 디코딩하므로, 셀이 마모되어 오류가 늘어나도 데이터를 복구할 수 있어 QLC 같은 고밀도 NAND의 신뢰성을 뒷받침합니다.
5. NVMe 프로토콜
NVMe(Non-Volatile Memory Express)는 PCIe 위에서 동작하도록 처음부터 플래시에 최적화된 프로토콜입니다. 기존 SATA/AHCI가 회전 디스크 시대에 설계되어 단일 큐·32 명령에 그쳤던 것과 달리, NVMe는 대규모 병렬 큐 구조로 SSD의 잠재력을 끌어냅니다.
그림 4. NVMe 큐 기반 I/O 처리 흐름 (SQ/CQ Doorbell 메커니즘)
큐 기반 I/O 처리 흐름
-
① 호스트가 Submission Queue(SQ)에 I/O 명령(Read/Write)을 등록한다.
-
② Doorbell 레지스터에 써서 SSD 컨트롤러에 새 명령을 알린다.
-
③ 컨트롤러가 SQ에서 명령을 페치(fetch)해 처리한다.
-
④ 처리 완료 후 Completion Queue(CQ)에 상태를 기록하고 MSI-X 인터럽트로 호스트에 통지한다.
NVMe vs SATA/AHCI 비교
| 항목 | SATA / AHCI | NVMe |
|---|---|---|
| 인터페이스 | SATA 6 Gbps | PCIe 기반 |
| 큐 구조 | 1개 큐, 명령 32개 | 다중 큐, 큐당 최대 65,535개 명령 |
| 병렬성 | 단일 락/단일 경로 중심 | CPU 코어와 병렬 자원을 전제로 설계 |
| 프로토콜 오버헤드 | 높음 | 낮음 |
| 적합성 | HDD 시대 설계, 레거시 SSD | 플래시/NVM 장치에 최적화 |
이 차이 때문에 NVMe SSD에서는 블록 레이어가 요청을 과하게 정렬하기보다 빠르게 전달하는 편이 유리합니다. Linux에서 none 계열의 가벼운 스케줄러가 자주 권장되는 이유도 여기에 있습니다.
6. 종합 — 읽기/쓰기 전체 흐름
읽기 요청 처리
호스트가 NVMe SQ에 읽기 명령 등록 → 컨트롤러 페치 → FTL이 LBA를 PPA로 변환 → 해당 NAND 페이지 읽기 → ECC 정정 → DRAM 버퍼 경유 → PCIe로 호스트에 전송 → CQ에 완료 기록.
쓰기 요청 처리
호스트가 쓰기 명령 등록 → 컨트롤러 페치 → 데이터를 DRAM/SLC 캐시에 버퍼링 → FTL이 빈 페이지에 기록(out-of-place) → 매핑 테이블 갱신 → 빈 블록 부족 시 가비지 컬렉션 트리거 → 주기적으로 마모 평준화 수행 → CQ에 완료 기록.
7. 운영체제(OS) 관점에서 본 SSD
지금까지는 SSD 내부(NAND·FTL·NVMe)를 살펴봤습니다. 이제 OS가 SSD를 어떻게 바라보고 다루는지, 즉 파일시스템·블록 I/O 스택·캐시·TRIM·I/O 스케줄러의 관점을 분석합니다. OS는 SSD의 물리 구조를 알지 못한 채 LBA(논리 섹터) 단위로만 통신하며, 물리 매핑은 전적으로 SSD 내부 FTL이 담당합니다.
7.1 스토리지 I/O 스택
애플리케이션의 read()/write() 호출은 여러 커널 계층을 거쳐 SSD에 도달합니다. 각 계층은 LBA 단위로 데이터를 주고받으며, 물리 주소 변환은 하드웨어 경계 너머 SSD가 처리합니다.
그림 5. OS 스토리지 I/O 스택 — 애플리케이션에서 NAND까지의 계층 구조
-
VFS — 다양한 파일시스템을 공통 인터페이스로 추상화한다.
-
파일시스템(ext4/F2FS/XFS) — 파일을 논리 블록(LBA)에 매핑하고 저널링으로 일관성을 보장한다. 특히 F2FS는 NAND의 순차 쓰기 특성에 맞춘 로그 구조(log-structured) 파일시스템이다.
-
페이지 캐시 — 읽기/쓰기를 DRAM에 버퍼링하여 실제 I/O를 줄이고, dirty page를 모아 지연 기록(writeback)한다.
-
블록 I/O 레이어 — 인접 요청을 병합·정렬하며, 현대 커널은 멀티큐(blk-mq)로 다중 코어 병렬 처리를 지원한다.
7.2 I/O 스케줄러 — SSD에 맞는 선택
HDD 시대의 I/O 스케줄러는 디스크 헤드 이동을 줄이기 위해 요청을 물리 위치 순으로 정렬했습니다. 그러나 SSD는 탐색 시간(seek time)이 없어 이런 정렬이 불필요하거나 오히려 오버헤드가 됩니다. 따라서 SSD에서는 단순한 스케줄러가 선호됩니다.
SSD는 내부적으로 멀티 채널 병렬성과 자체 큐(NVMe)를 가지므로, OS가 과하게 개입하기보다 요청을 빠르게 전달하는 편이 유리합니다. 이것이 NVMe SSD에서 none 스케줄러가 기본값인 이유입니다.
7.3 TRIM (Discard) — OS-SSD 협력의 핵심
OS가 파일을 삭제해도 그 정보는 SSD에 자동으로 전달되지 않습니다. 파일시스템은 메타데이터만 갱신할 뿐, SSD 입장에서는 해당 LBA가 여전히 유효한 데이터로 보입니다. 이 정보 단절을 해소하는 것이 TRIM(NVMe에서는 Deallocate) 명령입니다.
그림 6. TRIM 유무에 따른 차이와 TRIM(Discard) 발행 경로
TRIM이 없으면 SSD는 삭제된 데이터를 유효한 것으로 오인하여, 가비지 컬렉션 때 불필요하게 복사합니다. 이는 Write Amplification(WAF)을 키우고 성능과 수명을 떨어뜨립니다. TRIM으로 OS가 '이 LBA는 더 이상 쓰지 않는다'고 알려주면, SSD는 해당 매핑을 무효화해 GC 대상에서 제외하고 빈 블록을 효율적으로 확보합니다.
-
실시간 방식 — mount -o discard: 삭제 즉시 TRIM 발행. 잦은 명령으로 오버헤드가 생길 수 있습니다.
-
주기적 방식 — fstrim: cron/타이머로 모아서 batch TRIM. 일반적으로 더 무난하며, 주 1회 정도의 주기가 많이 쓰입니다.
7.4 페이지 캐시와 쓰기 정책
OS의 페이지 캐시는 SSD 접근을 줄이는 1차 완충 역할을 합니다. 읽기는 캐시 히트로 SSD I/O를 건너뛰고, 쓰기는 write-back 정책으로 dirty page를 모아 두었다가 주기적으로(또는 fsync 시) SSD에 기록합니다. 이 버퍼링은 작은 쓰기를 병합해 SSD의 WAF를 줄이는 데에도 기여합니다. 다만 전원 장애 시 데이터 유실을 막으려면 fsync/FUA(Force Unit Access)로 영속성을 보장해야 합니다.
7.5 OS가 SSD 특성을 고려하는 방법 요약
| 계층 | 역할 | 병렬성 / 단위 |
|---|---|---|
| Package | 여러 Die를 적층한 물리 칩 | 채널에 연결 |
| Die (LUN) | 독립적으로 명령 수행 가능한 최소 단위 | Die 간 완전 병렬 |
| Plane | Die 내 병렬 동작 단위 (보통 2~4개) | Plane 간 동시 동작 |
| Block | 소거(Erase)의 최소 단위 (수백~수천 Page) | 소거 단위 |
| Page | 읽기/쓰기(R/W)의 최소 단위 (4~16 KB) | R/W 단위 |
| Cell | 1비트 이상을 저장하는 트랜지스터 | SLC~QLC |
| 종류 | 비트/셀 | 전압 레벨 | P/E Cycle | 특성 |
|---|---|---|---|---|
| SLC | 1 bit | 2 | ~100,000 | 최고 속도·수명, 고가, 엔터프라이즈/캐시 |
| MLC | 2 bit | 4 | ~3,000~10,000 | 속도·수명·비용 균형 |
| TLC | 3 bit | 8 | ~1,000~3,000 | 현재 소비자 주류 |
| QLC | 4 bit | 16 | ~100~1,000 | 최대 용량·최저 비용, 낮은 수명 |
| 동작 | 단위 | 속도(대략) | 특성 |
|---|---|---|---|
| READ (읽기) | Page (4~16KB) | 25~100 µs | 비파괴적, 가장 빠름 |
| PROGRAM (쓰기) | Page | 200~1,500 µs | 전하 주입(FN 터널링), 소거 선행 필요 |
| ERASE (소거) | Block | 2~10 ms | 전하 방출, 셀 마모 발생, 가장 느림 |
| ECC 방식 | 특징 | 적용 |
|---|---|---|
| BCH | 대수적 정정, 구현 단순, 정정 능력 제한 | 구형 SLC/MLC |
| LDPC | 연판정(soft-decision) 디코딩, 높은 정정 능력 | 현재 TLC/QLC 주류 |
| 항목 | SATA / AHCI | NVMe |
|---|---|---|
| 인터페이스 | SATA 6 Gbps | PCIe (Gen5 x4 ≈ 16 GB/s) |
| 큐 개수 | 1개 | 최대 65,535개 |
| 큐당 명령 수 | 32 | 최대 65,535 |
| 프로토콜 오버헤드 | 높음 (HDD 시대 설계) | 낮음 (플래시 최적화) |
| 레이턴시 | 높음 | 낮음 |
| 스케줄러 | 특징 | SSD 적합성 |
|---|---|---|
| none (noop) | 스케줄링 거의 없이 바로 전달 | ★★★ NVMe SSD 기본 권장 |
| mq-deadline | 지연시간 상한 보장, 가벼운 정렬 | ★★ 혼합 워크로드 |
| kyber | 지연시간 목표 기반 적응 제어 | ★★ 고성능 NVMe |
| BFQ | 공정성 중심, 데스크탑 반응성 | ★ 오버헤드 큼 |
| OS 기법 | 목적 | SSD에 미치는 효과 |
|---|---|---|
| TRIM/Discard | 삭제 정보 전달 | WAF↓, GC 효율↑, 수명↑ |
| none I/O 스케줄러 | 불필요한 정렬 제거 | 레이턴시↓, CPU 오버헤드↓ |
| F2FS 등 FS | 순차 쓰기 유도 | GC 부담↓, 성능↑ |
| 페이지 캐시 write-back | 작은 쓰기 병합 | WAF↓, I/O 횟수↓ |
| 정렬(alignment) | 파티션을 페이지 경계 정렬 | 쓰기 분할 방지, WAF↓ |
8. 장단점
장점
-
NVMe와 blk-mq의 조합으로 다중 코어 병렬 I/O를 효율적으로 처리합니다.
-
FTL과 오버프로비저닝 덕분에 호스트는 NAND의 덮어쓰기 불가 제약을 직접 보지 않아도 됩니다.
-
TRIM과 page cache write-back이 작은 쓰기를 병합해 WAF와 지연을 낮춥니다.
한계
-
가비지 컬렉션과 LDPC 재시도로 인해 tail latency가 흔들릴 수 있습니다.
-
셀당 비트 수가 늘수록 수명과 오류 여유가 줄어듭니다.
-
DRAM-less SSD는 HMB에 의존하므로 고부하 랜덤 I/O에서 불리할 수 있습니다.
-
SLC 캐시는 버스트 쓰기에는 유리하지만, 장시간 연속 쓰기에서는 소진될 수 있습니다.
9. 관련 기술
-
nand_0010_nand_flash_internals.html- 셀 구조, Vth 분포, Program/Erase 물리 -
nand_0020_ftl_wearleveling_garbagecollection.html- L2P 매핑, GC, Wear Leveling, OP -
nand_0015_vfs_fs_pagecache_blockio.html- VFS, page cache, blk-mq 경로 -
nand_0025_ssd_internal_parallelism_channel_die_plane.html- 채널, 다이, 플레인 병렬성 -
../system/system_0025_nvme_architecture.html- NVMe 큐 구조와 인터페이스 -
../system/system_0020_ecc_error_correction.html- ECC/LDPC와 데이터 정정 배경 -
https://docs.kernel.org/filesystems/f2fs.html- F2FS의 로그 구조, background GC, discard -
https://docs.kernel.org/block/blk-mq.html- 멀티큐 블록 I/O와 요청 분산 -
https://man7.org/linux/man-pages/man8/fstrim.8.html- 주기적 TRIM과 discard 운영
10. 핵심 정리
NAND SSD는 셀 물리, FTL, NVMe, OS 블록 계층이 서로 부담을 나눠 갖는 구조입니다. NAND의 erase-before-write 제약을 FTL이 숨기고, NVMe와 blk-mq가 다중 큐 병렬성을 제공하며, OS는 page cache와 TRIM으로 내부 증폭을 줄입니다. 성능은 단순한 대역폭보다 GC, ECC, HMB, OP 같은 보조 메커니즘의 균형에 더 크게 좌우됩니다. 결국 좋은 SSD는 빠른 NAND만이 아니라, 그 NAND를 얼마나 안정적으로 관리하느냐에 달려 있습니다.