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
"insmodmodprobe는 같다" 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를 써라(부팅마다 이름이 바뀔 수 있으니).

생각해 볼 문제

  1. 블록 장치와 문자 장치의 차이와 각각 예를 말하라.
  2. /dev/null, /dev/zero, /dev/random의 용도를 말하라.
  3. LVM에서 PV, VG, LV의 관계를 그려보라. 왜 LVM이 일반 파티션보다 유연한가?
  4. NVMe 디스크의 첫 파티션 장치 이름은? SATA와 왜 다른가?
  5. MBR과 GPT의 주요 차이. 언제 GPT가 필수인가?
  6. insmod 대신 modprobe를 써야 하는 이유는?
  7. /dev/sdb 대신 fstab에 UUID를 써야 하는 이유는?
  8. LVM LV를 축소할 때 주의할 점은? XFS는 왜 축소 불능인가?

참고

'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