inode 완전 해부: 파일 시스템의 심장

inode가 무엇인지, 어떤 메타데이터를 담는지, 파일 이름과의 관계, inode 고갈 문제를 stat·ls·df 명령으로 실제 확인하는 방법을 익힌다.

· 6 min read · PALDYN Team

지난 글에서 read로 입력을 처리하는 방법을 익혔다. 이번에는 리눅스 파일 시스템의 핵심 개념인 inode를 해부한다. “파일을 어떻게 저장하는가?”를 이해하려면 inode를 피해갈 수 없다. inode를 알면 하드 링크, 파일 이름 변경, 권한 변경, 디스크 “파일 생성 불가” 오류의 원인까지 한 번에 이해된다.

inode란 무엇인가

파일 시스템은 각 파일에 고유한 번호(inode 번호)를 부여하고, 그 번호에 해당하는 inode 자료구조에 파일의 모든 메타데이터를 저장한다.

inode에 담기는 정보:

  • 파일 유형 (일반 파일, 디렉터리, 심볼릭 링크, …)
  • 권한 (rwxrwxrwx)
  • 소유자 UID/GID
  • 파일 크기 (bytes)
  • 하드 링크 수
  • 접근/수정/변경 시간 (atime/mtime/ctime)
  • 데이터 블록 포인터

inode에 없는 것: 파일 이름. 파일 이름은 디렉터리가 관리한다. 디렉터리는 {파일 이름 → inode 번호} 매핑 테이블이다.

파일 이름과 inode의 분리

ls -li     # -i: inode 번호 함께 출력
# 42381 -rw-r--r-- 2 user user 2048 May 10 hello.txt
# 42381 -rw-r--r-- 2 user user 2048 May 10 link.txt

hello.txtlink.txt가 같은 inode 번호(42381)를 가리키는 것을 확인할 수 있다. 이것이 하드 링크다. 두 이름은 완전히 동등하며 어느 쪽으로 수정해도 동일한 데이터를 변경한다.

inode 구조

stat — inode 전체 정보 조회

stat hello.txt

stat 출력에서 중요한 필드:

필드의미
Inodeinode 번호
Links하드 링크 수
Accessatime — 마지막으로 읽은 시각
Modifymtime — 내용을 마지막으로 수정한 시각
Changectime — inode 메타데이터(권한·소유자 등)를 마지막으로 변경한 시각

ctime과 mtime은 다르다. chmod로 권한을 바꾸면 ctime은 갱신되지만 mtime은 변하지 않는다. 반대로 내용을 수정하면 둘 다 갱신된다.

세 가지 시간 타임스탬프

# 파일 읽기 → atime 갱신 (noatime 마운트 옵션으로 비활성화 가능)
cat hello.txt

# 파일 내용 수정 → mtime, ctime 갱신
echo "data" >> hello.txt

# 권한 변경 → ctime 갱신 (mtime은 유지)
chmod 644 hello.txt

# find: 수정 시각 기준 검색
find /var/log -mtime -7        # 7일 이내에 수정된 파일
find /tmp -newer /etc/fstab    # /etc/fstab보다 최근 파일

성능이 중요한 서버에서는 /etc/fstabnoatime 옵션을 붙여 불필요한 atime 기록을 생략하는 경우가 많다.

inode 번호 확인

ls -i file.txt          # 42381 file.txt
stat file.txt           # Inode: 42381 출력
find . -inum 42381      # inode 번호로 파일 찾기

파일 이름을 모르지만 inode 번호를 알고 있을 때 find -inum으로 해당 파일을 찾을 수 있다.

inode 고갈 — 파일 크기 여유가 있는데 생성 불가

df -h /      # 디스크 용량: 30% 사용 중
touch newfile.txt
# touch: cannot touch 'newfile.txt': No space left on device

용량이 충분한데 파일을 못 만든다면 inode가 고갈된 것이다.

df -i /      # inode 사용률 확인
# IUse% 100% → inode 고갈

inode 조회 명령어

inode 고갈은 소규모 파일이 극단적으로 많을 때 발생한다. 메일 서버의 스풀 디렉터리, 임시 파일 누적, npm/pip 캐시 등이 대표적인 원인이다. 해결책은 불필요한 파일을 삭제해 inode를 회수하거나, 파일 시스템 생성 시 더 많은 inode를 할당하는 것이다.

# inode 가장 많이 쓰는 디렉터리 찾기
find / -xdev -printf '%h\n' | sort | uniq -c | sort -rn | head -20

inode와 파일 삭제

파일을 rm으로 삭제하면 디렉터리에서 {파일명 → inode} 항목이 제거되고, inode의 링크 수가 1 줄어든다. 링크 수가 0이 되면 그때 비로소 inode와 데이터 블록이 해제된다. 따라서 파일이 열려 있는 동안 rm으로 삭제해도 해당 프로세스는 계속 파일에 접근할 수 있다.

# 열린 파일이 삭제됐는지 확인
lsof | grep deleted

지난 글: read: 스크립트에서 사용자 입력 받기

다음 글: 하드 링크 vs 심볼릭 링크: 연결의 두 가지 방식


읽어주셔서 감사합니다. 😊