Day 1에서 만난 "모든 것은 파일이다"라는 철학이 실제로 어떻게 구현되는지, 그 첫 축인 공간적 구조부터 본다.
/bin, /etc, /var 같은 배치는 무작위가 아니라 FHS(Filesystem Hierarchy Standard, 파일시스템 계층 표준)라는 공식 규약을 따른다.
덕분에 어떤 배포판을 쓰든 "설정 파일은 /etc에, 로그는 /var/log에 있다"는 약속이 지켜진다. 이 표준이 없다면 배포판마다 위치가 제각각이라 관리가 불가능했을 것이다.
윈도우와 근본적으로 다르다. 윈도우는 드라이브마다 C:, D:처럼 별도의 루트가 있지만, 리눅스는 단 하나의 루트(/)에서 뻗어나가는 단일 계층 트리다.
다른 디스크나 USB는 이 트리의 특정 디렉터리에 "마운트(mount)"되어 가지로 합쳐진다.
디렉터리
역할
핵심 내용
/
루트
전체 트리의 시작점
/bin
필수 명령어
ls, cp, cat 등 모든 사용자용 기본 명령
/sbin
시스템 명령어
fdisk, ip 등 관리자용 명령
/etc
설정 파일
passwd, fstab 등 시스템 전역 설정
/home
사용자 홈
일반 사용자의 개인 디렉터리
/root
관리자 홈
root 계정의 홈 디렉터리
/var
가변 데이터
로그(/var/log), 메일, 캐시
/tmp
임시 파일
재부팅 시 삭제될 수 있는 임시 공간
/usr
사용자 프로그램
추가 설치된 응용 프로그램(/usr/bin)
/dev
장치 파일
디스크·터미널 등 하드웨어 표현
/proc
프로세스 정보
가상 파일시스템, 커널/프로세스 상태
/sys
시스템 정보
가상 파일시스템, 하드웨어/드라이버 정보
/lib
공유 라이브러리
/bin, /sbin이 쓰는 라이브러리
/boot
부팅 파일
커널(vmlinuz), initramfs, GRUB
/mnt, /media
마운트 지점
임시 마운트(/mnt), 자동 마운트(/media)
/opt
선택 패키지
서드파티 대형 응용 프로그램
/bin과 /sbin은 쓰임이 다르다. /bin은 모든 사용자가 쓰는 일반 명령(ls, cp), /sbin은 주로 관리자(root)가 쓰는 시스템 관리 명령(fdisk, reboot)이다. "s"는 system 또는 superuser를 뜻한다. 마찬가지로 /usr/bin, /usr/sbin도 같은 구분을 따른다. 최근 배포판은 /bin을 /usr/bin의 심볼릭링크로 통합(usrmerge)하는 추세다.
/proc와 /sys는 디스크에 실제로 존재하는 파일이 아니라, 커널이 메모리상에서 실시간으로 만들어내는 가상 파일시스템(virtual filesystem)이다.
"모든 것은 파일"이라는 철학이 가장 극적으로 드러나는 곳이다.
프로세스 정보, CPU 정보, 메모리 사용량 같은 커널 내부 상태를 파일을 읽듯이 확인할 수 있다.
# /proc - 커널과 프로세스 정보를 파일처럼 읽기cat /proc/cpuinfo # CPU 상세 정보cat /proc/meminfo # 메모리 사용 현황cat /proc/version # 커널 버전ls /proc/1/ # PID 1번 프로세스의 정보 디렉터리# /sys - 하드웨어와 드라이버 정보cat /sys/class/net/eth0/address # 네트워크 인터페이스 MAC 주소# 직접 쳐보기: 자신의 CPU 코어 수를 파일에서 세어보기grep -c processor /proc/cpuinfo
/proc의 각 숫자 디렉터리(/proc/1234)는 PID 1234 프로세스에 대응한다. 그 안의 status, cmdline, fd/를 읽으면 그 프로세스가 어떤 명령으로 실행됐고 어떤 파일을 열고 있는지 알 수 있다. top, ps 같은 도구들도 사실 내부적으로 /proc를 읽어 정보를 보여주는 것이다. 가상 파일시스템은 0바이트 크기로 보이지만 읽으면 실시간 데이터가 나온다.
ls -l 명령의 맨 앞 글자 하나가 그 파일의 종류를 알려준다. 이 식별 문자는 1급 시험에서 묻는 포인트다.
식별자
종류
설명
-
일반 파일(regular)
텍스트, 실행 바이너리, 이미지 등
d
디렉터리(directory)
다른 파일들을 담는 폴더
l
심볼릭 링크(symbolic link)
다른 파일을 가리키는 바로가기
b
블록 장치(block device)
디스크처럼 블록 단위 I/O (예: /dev/sda)
c
문자 장치(character device)
키보드처럼 문자 단위 I/O (예: /dev/tty)
s
소켓(socket)
프로세스 간 양방향 통신
p
파이프(named pipe, FIFO)
프로세스 간 단방향 통신
# ls -l의 첫 글자로 파일 종류 확인ls -l /dev/sda # b로 시작 → 블록 장치ls -l /dev/tty # c로 시작 → 문자 장치ls -l /etc/passwd # -로 시작 → 일반 파일ls -ld /etc # d로 시작 → 디렉터리# file 명령으로 내용 기반 파일 종류 판별file /etc/passwd # ASCII textfile /bin/ls # ELF 실행 바이너리
블록 장치(b): 데이터를 정해진 크기의 블록 단위로 읽고 쓰며 버퍼링과 임의 접근이 가능하다. 디스크, SSD, USB.
문자 장치(c): 데이터를 한 글자씩 순차적으로 흘려보낸다. 키보드, 마우스, 시리얼 포트, 터미널.
소켓(s)과 파이프(p): 프로세스 간 통신(IPC) 수단. 파이프(FIFO, named pipe)는 한 방향으로만 흐르고, 소켓은 양방향이며 네트워크 통신에도 쓰인다.
⚠️ 함정: 시험에서 "디스크 /dev/sda는 어떤 종류의 장치 파일인가?"라고 물으면 답은 블록 장치(b)다. "키보드나 터미널은?"이라고 물으면 문자 장치(c)다. 블록(랜덤 접근, 버퍼링)과 문자(순차, 스트림)의 구분을 혼동하기 쉽다. /dev/sda의 's'는 SCSI/SATA를 뜻하지 socket의 's'가 아니다.
링크를 이해하려면 먼저 inode(아이노드, index node)를 알아야 한다. 리눅스 파일시스템의 가장 근본적인 개념이다.
흔히 "파일 = 이름 + 내용"이라고 생각하지만, 리눅스에서 파일의 본질은 inode다. inode는 파일에 대한 모든 메타데이터를 담은 자료구조다.
파일 종류와 접근 권한(rwx)
소유자(UID)와 그룹(GID)
파일 크기
타임스탬프(수정·접근·변경 시각)
링크 수(이 inode를 가리키는 이름의 개수)
실제 데이터가 저장된 디스크 블록의 주소
핵심은 파일 이름은 inode에 포함되지 않는다는 점이다. 파일 이름은 디렉터리 안에 "이름 → inode 번호" 매핑으로 저장될 뿐이다.
즉 디렉터리는 사실 "이름과 inode 번호의 짝을 담은 표"다.
# inode 번호 확인ls -i file.txt # 파일의 inode 번호 표시stat file.txt # inode 번호, 크기, 권한, 타임스탬프 등 상세df -i # 파일시스템별 inode 사용량
파일시스템을 만들 때 inode 개수가 정해진다. 디스크 용량이 남아도 inode가 고갈되면 더 이상 파일을 만들 수 없다(df -i로 확인). 작은 파일을 무수히 만드는 메일 서버 등에서 "용량은 남았는데 No space left on device" 오류가 나는 것이 바로 inode 고갈 때문이다. 이것이 inode가 실무에서 중요한 이유다.
새 inode를 만들지 않고, 기존 inode를 가리키는 이름(디렉터리 엔트리)만 하나 더 추가한다.
원본과 하드링크는 inode 번호가 완전히 같고 사실상 동등하다. 둘 중 어느 것이 "원본"인지 구분할 수 없다.
inode의 링크 수가 1 증가하며, 모든 이름을 지워 링크 수가 0이 되어야 실제 데이터가 삭제된다.
심볼릭링크(symbolic link, soft link) = 다른 파일의 경로(이름)를 담고 있는 별도의 파일. 윈도우의 "바로가기"와 같다.
자기만의 새 inode를 가지며, 그 안에 "가리키는 대상의 경로"가 문자열로 저장된다.
원본을 찾아갈 때는 그 경로를 따라간다.
항목
하드링크
심볼릭링크
inode
원본과 동일
자신만의 새 inode
가리키는 대상
inode(데이터) 직접
경로(이름) 문자열
원본 삭제 시
데이터 유지(링크 수만 감소)
깨진 링크(dangling)가 됨
다른 파일시스템
불가능
가능
디렉터리 대상
불가능(일반적으로)
가능
크기
원본과 같음
대상 경로 문자열 길이
# 하드링크 생성 (ln, 옵션 없음)ln original.txt hardlink.txtls -li original.txt hardlink.txt # inode 번호가 동일함을 확인# 심볼릭링크 생성 (ln -s)ln -s original.txt symlink.txtls -li original.txt symlink.txt # inode 번호가 다름, l로 표시# 직접 쳐보기: 원본을 지운 뒤 차이를 관찰echo "hello" > orig.txtln orig.txt hard.txtln -s orig.txt soft.txtrm orig.txtcat hard.txt # 정상 출력 (데이터 유지)cat soft.txt # No such file (깨진 링크)
위 실습이 두 링크의 본질적 차이를 가장 잘 보여준다.
원본 orig.txt를 삭제해도 하드링크 hard.txt는 같은 inode를 직접 가리키므로 데이터가 살아있다(링크 수가 2→1로 줄었을 뿐).
반면 심볼릭링크 soft.txt는 "orig.txt라는 경로"를 저장하고 있는데 그 경로가 사라졌으므로 깨진 링크가 된다.
⚠️ 함정: "심볼릭링크는 다른 파일시스템(파티션)과 디렉터리를 가리킬 수 있지만, 하드링크는 둘 다 불가능하다"가 핵심 출제 포인트다. 이유는 명확하다. 하드링크는 inode 번호를 공유하는데, inode 번호는 각 파일시스템 안에서만 유일하므로 파티션을 넘을 수 없다. 디렉터리 하드링크를 금지하는 이유는 파일시스템 트리에 순환(loop)이 생겨 find 같은 도구가 무한 반복에 빠지는 것을 막기 위함이다.
ls -l로 디렉터리를 보면 권한 옆에 숫자가 있다(예: drwxr-xr-x 2). 이 숫자가 바로 inode의 링크 수다. 새 디렉터리를 만들면 링크 수가 기본 2다. 자기 자신을 가리키는 .과 부모가 자식을 가리키는 이름, 이렇게 2개의 하드링크가 자동 생성되기 때문이다. 하위 디렉터리를 하나 만들 때마다 그 안의 ..이 부모를 가리키므로 부모의 링크 수가 1씩 늘어난다.
"inode"라는 이름의 유래는 데니스 리치도 정확히 기억하지 못한다고 밝힌 바 있다. 가장 유력한 설은 "index node"의 줄임말로, 파일의 정보를 색인(index)하는 노드라는 의미다. 1970년대 초 유닉스 초기 파일시스템 설계에서 탄생한 이 개념은 50년이 지난 지금도 ext4, XFS 등 리눅스 파일시스템의 근간으로 살아있다.