SSD, 키보드, 네트워크 카드를 같은 방식으로 다룬다 — 장치 추상화와 LVM
서버에 디스크를 하나 더 꽂았다. 이제 공간이 모자라니 LVM으로 볼륨을 늘리고 싶다. 그런데 스크립트가 /dev/sda1을 찾는데 실제는 /dev/nvme0n1p1이라 실패한다 — 왜 이름이 다르지? 또 모든 드라이버를 커널에 넣지 않고도 필요할 때만 쓸 수 있는데, 어떻게?
이 글은 리눅스가 수십~수백 종의 하드웨어를 일관되게 다루는 방식(장치 파일 추상화)과, 고정된 물리 디스크를 유연하게 쪼개고 합치는 방식(LVM)을 다룬다. 서버 운영 일상 — 디스크 추가, LVM 확장, 드라이버 적재 — 의 기반을 잡는다.
하드웨어도 파일이다 — 장치 파일과 major/minor
리눅스는 "모든 것은 파일" 원칙에 따라 하드웨어를 /dev 아래 파일로 노출한다. 그래서 디스크는 cat으로, 키보드는 read로 접근할 수 있다(물론 권한이 있어야). 각 장치는 major:minor 번호로 식별된다:
- major: 장치 종류/드라이버(예: 8 = SCSI/SATA 디스크)
- minor: 같은 드라이버 내 개별 장치(예: 0 = 첫 디스크, 1 = 첫 파티션)
ls -l /dev/sda1
# brw-rw---- 1 root disk 8, 1 ... ← 'b'=블록, major=8, minor=1
블록 장치 vs 문자 장치
| 구분 | 블록 장치(b) |
문자 장치(c) |
|---|---|---|
| 접근 | 랜덤 접근(임의 블록) | 순차 스트림 |
| 단위 | 블록(512B/4KiB) | 바이트 |
| 예 | 디스크(/dev/sda, NVMe), 램디스크 |
직렬 포트(/dev/tty), /dev/null, /dev/random |
자주 쓰는 /dev 노드
| 노드 | 용도 |
|---|---|
/dev/null |
읽으면 EOF, 쓰면 버림(출력 폐기) |
/dev/zero |
읽으면 0x00 무한 제공 |
/dev/random |
엔트로피 기반 난수 |
/dev/urandom |
의사난수(블록 안 됨, 빠름) |
/dev/sda, /dev/nvme0n1 |
디스크 전체 |
/dev/sda1, /dev/nvme0n1p1 |
디스크 파티션 |
/dev/mapper/rl-root |
LVM 논리 볼륨 |
LVM — 레고 블록으로 조립하는 유연한 디스크
물리 디스크는 고정되어 있다. 디스크 2개(각 1TB)를 합쳐 2TB 하나처럼 못 쓰면 공간이 비효율적이고, 공간이 모자랄 때 파티션을 옮기지 않고는 확장할 수도 없다. LVM(Logical Volume Manager)이 이를 푼다.
| LVM | 레고 블록 | |
|---|---|---|
| 기본 단위 | PV(물리 디스크) | 레고 베이스판 |
| 모으기 | VG(볼륨 그룹) | 베이스판 여러 개 연결 → 큰 작업판 |
| 잘라 쓰기 | LV(논리 볼륨) | 작업판에서 원하는 크기로 조립 |
레고 비유는 "작은 것을 모아 크고 유연하게"만 잡는다. LVM은 PE(Physical Extent, 보통 4 MiB) 단위의 논리 매핑이고, LV는 데이터를 유지하며 확장된다(축소는 위험).
flowchart LR
PV1[PV<br/>/dev/sda] --> VG[VG<br/>volgroup]
PV2[PV<br/>/dev/sdb] --> VG
VG --> LV1[LV<br/>root]
VG --> LV2[LV<br/>swap]
VG --> LV3[LV<br/>data]
- PV(Physical Volume): LVM용으로 초기화한 디스크/파티션(
pvcreate). - VG(Volume Group): PV들의 풀. 여러 PV를 묶어 하나의 가상 디스크처럼(
vgcreate). - LV(Logical Volume): VG에서 잘라낸 논리 볼륨. 파일 시스템을 올리는 단위(
lvcreate). - PE/LE: PV의 최소 할당 단위 = LV의 최소 단위. 보통 4 MiB.
LVM이 주는 것: 여러 물리 디스크를 하나의 거대 볼륨으로, 온라인 크기 조정(fs 언마운트 불필요), 스냅샷·thin provisioning·mirroring.
RHEL 9+/Rocky 10의 LVM은 devices file(
/etc/lvm/devices/system.devices)로 사용 디스크를 추적한다.lvmdevices로 관리. 기존 filter 방식보다 명시적이다.
Rocky 10 기본 설치 구조:
sda
├─sda1 → /boot (파티션)
└─sda2 → rl VG
├─rl-root LV (17G) → /
└─rl-swap LV (2G) → [SWAP]
파티션 — MBR vs GPT, 그리고 NVMe 이름의 비밀
| 항목 | MBR(MSDOS) | GPT(GUID) |
|---|---|---|
| 최대 디스크 | 2 TiB | 사실상 무제한 |
| 최대 파티션 | 4개 주(확장 시 더) | 128개(기본) |
| 부팅 | BIOS/Legacy | UEFI |
| 권장 | 구 시스템 | 현대(Rocky 10 기본) |
디스크가 2 TiB 이상이거나 UEFI면 GPT가 필수다.
NVMe vs SATA 이름 — 자주 걸리는 함정
초보자는 디스크 파티션을 무조건 /dev/sda1로 생각한다. 하지만 NVMe는 /dev/nvme0n1(컨트롤러0 네임스페이스1), 파티션은 /dev/nvme0n1p1(p가 붙는다). SATA/SCSI는 /dev/sda1. 이 차이를 모르면 스크립트가 NVMe 시스템에서 실패한다.
커널 모듈 — 런타임에 드라이버를 끼웠다 뺐다
모든 드라이버를 커널에 넣으면 커널이 비대해지고 메모리가 낭비된다. 해법은 필요할 때만 로드하는 것이다. 커널 기능/드라이버는 런타임에 동적 적재 가능한 코드(.ko)로, /lib/modules/<커널버전>/에 있다. 재부팅 없이 기능을 추가·제거할 수 있어 메모리를 절약한다.
insmod vs modprobe — 왜 modprobe를 써야 하나
초보자가 자주 insmod를 쓴다. modprobe가 낫다. insmod는 의존성을 무시한다 — 단일 파일을 강제 로드하며, 의존 모듈이 빠지면 실패. 반면 modprobe는 의존 모듈까지 자동으로 처리한다(depmod가 만든 modules.dep 기반). 항상 modprobe를 써라.
udev — 장치를 자동으로 인식한다
systemd-udevd가 장치 이벤트(핫플러그)를 감지해 /dev 노드를 자동 생성하고 이름을 붙인다. 디스크를 꽂으면 자동으로 /dev/sdb가 생기고, 영구 이름도 만든다: /dev/disk/by-uuid/, /dev/disk/by-id/.
fstab/GRUB에 UUID를 쓰는 이유:
/dev/sdb는 부팅마다 바뀔 수 있다. UUID나 by-id는 고정되어 마운트 실패를 막는다.lsblk는 sysfs + udev DB를 읽어 정보를 표시한다.
Rocky 10에서 직접 확인하기
미검증(출처 인용). Rocky 10 VM에서 실행 권장.
lsblk # 트리 형태
lsblk -f # 파일시스템/UUID 포함
blkid # UUID/타입/라벨
findmnt # 마운트 트리
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 20G 0 disk
├─sda1 8:1 0 1G 0 part /boot
└─sda2 8:2 0 19G 0 part
├─rl-root 253:0 0 17G 0 lvm /
└─rl-swap 253:1 0 2G 0 lvm [SWAP]
# Rocky 10 — 파티션 관리
sudo fdisk -l # 전체 디스크/파티션
sudo parted /dev/sdb print # GPT/MBR 무관 범용
sudo fdisk /dev/sdb # 파티션 생성(대화형)
# Rocky 10 — LVM 확장(자주 쓰는 절차)
sudo pvcreate /dev/sdb # 1. 새 디스크를 PV로
sudo vgextend rl /dev/sdb # 2. 기존 VG에 추가
sudo lvextend -L +10G /dev/rl/root # 3. LV 확장(+10G)
sudo xfs_growfs / # 4. 파일 시스템까지 확장(XFS)
# sudo resize2fs /dev/rl/root # (ext4)
pvs && vgs && lvs # 상태 확인
# Rocky 10 — 커널 모듈
lsmod # 적재된 모듈
modinfo xfs # 모듈 정보
sudo modprobe zram num_devices=1 # 모듈 로드(의존성 자동)
sudo modprobe -r zram # 제거
ls /lib/modules/$(uname -r)/ # 모듈 디렉토리
# Rocky 10 — 영구 식별자: fstab에 안전하게 쓰려면
ls -l /dev/disk/by-uuid/ | grep sda1
ls -l /dev/disk/by-id/
sudo udevadm monitor # 실시간 장치 이벤트
흔히 묻는 것, 흔히 틀리는 것
| 오해 | 정정 |
|---|---|
"NVMe 파티션은 /dev/nvme0n11" |
/dev/nvme0n1p1(p 붙음). SATA는 /dev/sda1 |
"insmod와 modprobe는 같다" |
insmod는 의존성 무시. 항상 modprobe |
| "LVM 축소는 확장처럼 쉽다" | 데이터 손실 위험. fs 먼저 축소 후 LV 축소. XFS는 축소 자체 불가 |
| "파티션 생성하면 바로 쓴다" | 아니다. 위에 파일 시스템 생성(mkfs.xfs) 별도, 마운트도 별도 |
"/dev/sdb는 항상 같은 디스크" |
부팅마다 바뀔 수 있음. fstab엔 UUID/by-id 사용 |
| "LVM은 예전 기술이다" | 현대 RHEL/Rocky 기본. thin pool, 스냅샷, vdo 등 계속 진화 |
| "커널 모듈은 재부팅해야 로드된다" | modprobe로 런타임 로드 가능. /etc/modules-load.d/로 영구화 |
더 깊이
- LVM thin provisioning: 일반 LV는 할당 즉시 공간을 예약하지만, thin pool은 실제 쓰는 만큼만 할당한다(over-provisioning 가능). 가상화·컨테이너 환경에 유리. 단, over-provision 시 풀 고갈에 주의.
- device mapper: LVM은 커널 device mapper(DM) 계층 위에 구현된다. DM은 블록 장치를 매핑·재조합하는 범용 계층(LVM, multipath, dm-crypt가 모두 DM 사용).
dmsetup으로 저수준 확인. - VDO(Virtual Data Optimizer): 중복 제거·압축으로 디스크 공간을 절약. 백업 스토리지에 유리.
요약 — 이 글의 결론
- 장치 파일: 하드웨어를
/dev아래 파일로. major:minor 번호로 식별. 블록(랜덤, 디스크) vs 문자(스트림, 터미널/null). - LVM: PV → VG → LV. 레고 블록처럼 모으고 자른다. 온라인 확장 가능(축소는 위험). Rocky 10은 devices file로 디스크 추적.
- 파티션: MBR(2 TiB 한계, BIOS) vs GPT(대용량, UEFI, Rocky 10 기본).
- NVMe 명명 함정:
/dev/nvme0n1, 파티션은nvme0n1p1(p 붙음). SATA는/dev/sda1. 스크립트가 여기서 자주 실패. - 커널 모듈: 런타임 적재.
modprobe(의존성 자동) >insmod. - udev: 핫플러그 자동 인식,
/dev노드 생성. 영구 이름(by-uuid/by-id) 제공 — fstab엔/dev/sdX말고 UUID를 써라(부팅마다 이름이 바뀔 수 있으니).
생각해 볼 문제
- 블록 장치와 문자 장치의 차이와 각각 예를 말하라.
/dev/null,/dev/zero,/dev/random의 용도를 말하라.- LVM에서 PV, VG, LV의 관계를 그려보라. 왜 LVM이 일반 파티션보다 유연한가?
- NVMe 디스크의 첫 파티션 장치 이름은? SATA와 왜 다른가?
- MBR과 GPT의 주요 차이. 언제 GPT가 필수인가?
insmod대신modprobe를 써야 하는 이유는?/dev/sdb대신 fstab에 UUID를 써야 하는 이유는?- LVM LV를 축소할 때 주의할 점은? XFS는 왜 축소 불능인가?
참고
- Linux allocated devices — Kernel docs - 접근 2026-07-09 (장치 major/minor)
- lvm(8) manual - 접근 2026-07-09 (PV/VG/LV)
- lvmdevices(8) — man7 - 접근 2026-07-09
- man page:
man lsblk,man blkid,man fdisk,man parted,man lvcreate,man modprobe,man udev(7)
'Tech Artifacts > Linux' 카테고리의 다른 글
| Linux - 08. package (0) | 2026.07.09 |
|---|---|
| Linux - 07. shell script (0) | 2026.07.09 |
| Linux - 05. filesystem (0) | 2026.07.09 |
| Linux - 04. memory (0) | 2026.07.09 |
| Linux - 03. process (0) | 2026.07.09 |
