Unix/Linux 디렉토리 구조 이해하기

Unix/Linux 디렉토리 구조 이해하기

터미널을 열고 ls /를 입력해본 적 있으신가요? bin, etc, usr, home 같은 디렉토리들이 주루룩 나오는데, 처음 보면 이게 다 뭔지 좀 막막하죠. Windows에서는 C:\Program Files, C:\Users 같은 이름만 봐도 대충 뭘 하는 폴더인지 짐작이 가는데, Unix/Linux의 디렉토리 이름들은 /etc/usr니 하는 약어투성이라 직관적이지 않습니다.

사실 이 디렉토리 구조는 1970년대 Unix 시절부터 내려온 것인데요. 수십 년간 다듬어지면서 나름의 논리적인 체계를 갖추고 있습니다. 이 글에서는 Linux 시스템의 주요 디렉토리가 각각 어떤 역할을 하는지 살펴보겠습니다. 서버 관리를 하든, Docker 컨테이너를 다루든, 단순히 개발 환경을 세팅하든, 이 구조를 알아두면 파일을 찾거나 시스템을 이해하는 데 꽤 도움이 됩니다.

FHS (Filesystem Hierarchy Standard)

Linux의 디렉토리 구조는 FHS(Filesystem Hierarchy Standard)라는 표준을 따릅니다. 이 표준은 어떤 종류의 파일이 어디에 위치해야 하는지를 정해놓은 것인데요. 덕분에 Ubuntu든 CentOS든 Arch Linux든 기본적인 디렉토리 배치가 비슷합니다.

터미널에서 루트 디렉토리의 내용을 한번 확인해볼까요?

결과
$ ls /
bin   dev  home  lib    media  opt   root  sbin  sys  usr
boot  etc  lib64 mnt    proc   run   srv   tmp   var

배포판마다 약간의 차이는 있지만, 대부분 이런 구조를 갖고 있습니다. 이제 각 디렉토리가 무슨 역할을 하는지 하나씩 알아보겠습니다.

/ (루트 디렉토리)

모든 디렉토리의 최상위, 파일 시스템의 시작점입니다. Windows의 C:\에 해당한다고 보면 됩니다. Unix/Linux에서는 모든 것이 이 / 아래에 트리 구조로 매달려 있습니다. 별도의 디스크를 연결하더라도 D:\ 같은 드라이브 문자가 생기는 게 아니라, 이 트리의 어딘가에 마운트(mount)되는 방식이죠.

$ pwd
/home/dale/projects

위 경로를 분해하면 루트(/) 아래 home 디렉토리, 그 아래 dale, 그 아래 projects라는 뜻입니다.

/home — 사용자 홈 디렉토리

일반 사용자들의 개인 디렉토리가 모여 있는 곳입니다. 사용자 계정을 만들면 보통 /home/사용자이름 디렉토리가 자동으로 생깁니다.

$ ls /home
dale  guest  deploy

사용자의 문서, 다운로드 파일, 개인 설정 파일(.bashrc, .gitconfig 같은 dotfile), 프로젝트 코드 등 개인적인 파일은 전부 여기에 저장됩니다. ~ 기호가 현재 사용자의 홈 디렉토리를 가리키는 단축키인데요. cd ~cd /home/dale은 같은 곳으로 이동합니다.

참고로 root 사용자(시스템 관리자)의 홈 디렉토리는 /home/root가 아니라 /root입니다. 시스템에 문제가 생겨서 /home이 마운트되지 않는 상황에서도 관리자는 로그인할 수 있어야 하기 때문이죠.

/etc — 시스템 설정 파일

/etc는 시스템 전체에 적용되는 설정 파일들이 모여 있는 디렉토리입니다. 이름의 유래는 “et cetera”(기타 등등)인데, 초기 Unix에서 다른 곳에 넣기 애매한 파일들을 여기에 넣었던 것이 시작이었습니다. 지금은 사실상 “Editable Text Configuration”의 약자처럼 쓰이고 있죠.

실제로 어떤 파일들이 있는지 볼까요?

$ ls /etc
hostname    hosts       passwd      shadow      group
fstab       resolv.conf sudoers     crontab     ssh/
nginx/      systemd/    apt/        environment profile

자주 만지게 되는 설정 파일을 몇 가지 살펴보면…

/etc/hosts 파일은 도메인 이름과 IP 주소의 매핑을 정의합니다. DNS 조회 전에 이 파일을 먼저 확인하기 때문에, 로컬 개발에서 도메인을 테스트할 때 유용합니다.

$ cat /etc/hosts
127.0.0.1   localhost
127.0.0.1   myapp.local
192.168.1.100  db.internal

/etc/passwd 파일은 이름과 달리 비밀번호가 아니라 사용자 계정 정보를 저장합니다. (실제 비밀번호 해시는 /etc/shadow에 있습니다.)

$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
dale:x:1000:1000:Dale Seo:/home/dale:/bin/bash
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin

각 줄은 콜론(:)으로 구분된 필드로 이루어져 있는데, 순서대로 사용자명, 비밀번호 자리(x는 shadow 파일 사용을 의미), UID, GID, 설명, 홈 디렉토리, 로그인 셸입니다.

/etc/ssh/sshd_config는 SSH 서버 설정이고, /etc/nginx/nginx.conf는 Nginx 웹 서버 설정입니다. 이런 식으로 시스템에 설치된 서비스들의 설정 파일이 /etc 아래에 자리잡고 있습니다.

/var — 가변 데이터

/var는 “variable”의 약자로, 시스템이 운영되면서 계속 변하는 데이터를 저장합니다. 로그 파일, 메일 큐, 데이터베이스 파일, 캐시 같은 것들이 여기에 들어갑니다.

$ ls /var
cache  lib  lock  log  mail  opt  run  spool  tmp

개발자가 가장 자주 들여다보게 되는 곳은 /var/log일 겁니다. 시스템과 애플리케이션의 로그 파일들이 여기에 쌓입니다.

$ ls /var/log
syslog      auth.log    kern.log    dpkg.log
nginx/      mysql/      journal/

서버에서 뭔가 잘 안 될 때, 가장 먼저 달려가는 곳이 바로 이 /var/log인데요. 예를 들어 Nginx가 요청을 제대로 처리하지 못하면 /var/log/nginx/error.log를 확인하고, 로그인 실패 기록은 /var/log/auth.log에서 찾을 수 있습니다.

$ tail -f /var/log/syslog

tail -f는 파일의 끝부분을 실시간으로 따라가며 보여주는 명령어라서, 로그 모니터링할 때 정말 많이 씁니다.

웹 서버를 운영한다면 /var/www도 눈에 익을 텐데요. Apache나 Nginx의 기본 웹 루트 디렉토리가 보통 /var/www/html로 설정되어 있습니다.

/usr — 사용자 프로그램과 데이터

/usr은 “Unix System Resources”의 약자입니다. (“user”의 약자라고 오해하기 쉬운데 그건 아닙니다.) 시스템에 설치된 대부분의 프로그램과 라이브러리가 이 디렉토리 아래에 있습니다.

$ ls /usr
bin  include  lib  lib64  local  sbin  share  src

/usr 안에도 bin, lib, sbin 같은 하위 디렉토리가 있어서 처음에는 루트의 /bin, /lib과 뭐가 다른지 헷갈릴 수 있는데요.

원래는 역할이 구분되어 있었습니다. /bin에는 시스템 부팅에 필수적인 기본 명령어(ls, cp, cat 같은)가, /usr/bin에는 부팅 후에 사용하는 일반 프로그램이 들어갔습니다. 하지만 현대 배포판에서는 이 구분이 거의 사라져서, /bin/usr/bin의 심볼릭 링크인 경우가 많습니다.

$ ls -la /bin
lrwxrwxrwx 1 root root 7 Jan  1 00:00 /bin -> usr/bin

/usr/local은 좀 특별한데, 시스템 패키지 관리자가 아닌 사용자가 직접 컴파일하거나 설치한 프로그램이 들어가는 곳입니다. 소스 코드를 직접 빌드해서 make install을 실행하면 기본적으로 /usr/local 아래에 설치됩니다.

$ ls /usr/local
bin  etc  include  lib  sbin  share  src

/usr/share에는 아키텍처에 독립적인 데이터가 들어갑니다. 문서, 매뉴얼 페이지, 아이콘, 폰트 같은 것들이죠.

/bin과 /sbin — 실행 파일

/bin에는 일반 사용자도 사용하는 기본 명령어들이 있습니다.

$ ls /bin
bash  cat   cp    date  echo  grep  ls    mkdir
mv    pwd   rm    sed   sh    tar   touch

ls 쉘 커맨드cp, mv, cat 같은 일상적인 명령어들이 전부 여기에 있죠.

/sbin은 “system binaries”의 약자로, 시스템 관리 명령어가 들어 있습니다. fdisk(디스크 파티션), iptables(방화벽), reboot(재부팅) 같은 명령어는 보통 root 권한이 필요합니다.

$ ls /sbin
fdisk    fsck     halt     ifconfig  init
iptables mkfs     mount    reboot    shutdown

앞서 말했듯이 최근 배포판에서는 /bin/sbin이 각각 /usr/bin/usr/sbin의 심볼릭 링크로 바뀌는 추세입니다. 파일 시스템 구조를 단순화하려는 움직임이죠.

/tmp — 임시 파일

프로그램이 실행 중에 잠깐 쓰고 버리는 임시 파일을 저장하는 공간입니다. 시스템을 재부팅하면 보통 여기 있는 파일들이 자동으로 삭제됩니다. (배포판에 따라 주기적으로 정리하는 경우도 있습니다.)

$ ls /tmp
systemd-private-abc123
ssh-XYZabc123
tmpfile.txt

누구나 쓸 수 있는 디렉토리라서 권한이 1777로 설정되어 있습니다. 맨 앞의 1은 sticky bit인데, 다른 사용자가 만든 파일을 함부로 삭제하지 못하게 막는 역할을 합니다.

$ ls -ld /tmp
drwxrwxrwt 10 root root 4096 Mar 10 12:00 /tmp

권한 표시 끝의 t가 바로 sticky bit가 설정되어 있다는 표시입니다.

개발 중에 임시로 뭔가 테스트하고 싶을 때 /tmp를 활용하면 편리합니다. 어차피 나중에 자동으로 정리되니까요.

/dev — 장치 파일

Unix/Linux의 철학 중 하나가 “모든 것은 파일이다”(Everything is a file)인데요. 하드디스크, USB, 키보드 같은 하드웨어 장치도 /dev 디렉토리에서 파일처럼 다룹니다.

$ ls /dev
sda     sda1    sda2    sdb     null    zero
random  urandom tty     stdin   stdout  stderr

개발자라면 알아둘 만한 특수 장치 파일이 몇 개 있습니다.

/dev/null은 블랙홀 같은 존재입니다. 여기에 쓰는 데이터는 전부 사라지는데, 명령어의 출력을 버리고 싶을 때 유용합니다. 쉘 리다이렉션을 사용해서 불필요한 출력을 /dev/null로 보내는 건 자주 쓰이는 패턴이죠.

$ command_that_prints_a_lot > /dev/null 2>&1

/dev/random/dev/urandom은 난수를 생성합니다. 암호화 키나 토큰을 생성할 때 사용됩니다.

$ head -c 32 /dev/urandom | base64
K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols=

/dev/zero는 무한한 null 바이트(0x00) 스트림을 제공합니다. 특정 크기의 빈 파일을 만들거나 디스크를 초기화할 때 씁니다.

/proc — 프로세스 정보

/proc는 실제로 디스크에 존재하는 디렉토리가 아닙니다. 커널이 메모리상에 만들어내는 가상 파일 시스템(virtual filesystem)인데요. 실행 중인 프로세스와 시스템 정보를 파일 형태로 보여줍니다.

$ ls /proc
1     123   456   cpuinfo    meminfo    version
2     124   789   loadavg    mounts     uptime

숫자로 된 디렉토리는 실행 중인 프로세스의 PID(Process ID)입니다. 그 안에 해당 프로세스의 상세 정보가 들어 있죠.

$ cat /proc/cpuinfo | head -5
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 142
model name      : Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz

시스템 정보를 확인할 때 자주 쓰는 파일들이 있습니다. /proc/cpuinfo는 CPU 정보, /proc/meminfo는 메모리 사용량, /proc/version은 커널 버전을 보여줍니다. Docker 컨테이너 안에서 할당된 리소스를 확인할 때도 /proc를 들여다보게 됩니다.

/sys — 커널과 하드웨어 정보

/proc와 비슷한 가상 파일 시스템인데, 좀 더 체계적으로 하드웨어와 커널 모듈 정보를 제공합니다. /proc가 프로세스 중심이라면 /sys는 장치 중심입니다.

$ ls /sys
block  bus  class  dev  devices  firmware  fs  kernel  module  power

일반 개발자가 직접 건드릴 일은 드물지만, 시스템 프로그래밍이나 임베디드 개발을 한다면 접하게 됩니다.

/boot — 부팅 파일

시스템 부팅에 필요한 파일들이 있습니다. Linux 커널 이미지(vmlinuz), 초기 RAM 디스크(initrd), 부트로더 설정(grub/) 등이 들어 있죠.

$ ls /boot
grub/                        initrd.img-5.15.0-generic
vmlinuz-5.15.0-generic       config-5.15.0-generic
System.map-5.15.0-generic

커널 업데이트를 하면 여기에 새 커널 파일이 추가됩니다. 직접 수정할 일은 거의 없지만, 부팅 문제가 생겼을 때 확인하게 될 수 있습니다.

/lib — 라이브러리

/bin/sbin에 있는 프로그램들이 동작하는 데 필요한 공유 라이브러리(shared library) 파일이 들어 있습니다. Windows의 DLL 파일과 비슷한 .so(shared object) 파일들이죠.

$ ls /lib/x86_64-linux-gnu/libc*
/lib/x86_64-linux-gnu/libc.so.6

/lib64는 64비트 라이브러리를 위한 디렉토리인데, 요즘은 /usr/lib로 통합되는 추세입니다.

/opt — 서드파티 소프트웨어

“optional”의 약자로, 시스템 패키지 관리자를 통하지 않고 별도로 설치하는 서드파티 소프트웨어가 들어가는 곳입니다. 상용 소프트웨어나 자체 디렉토리 구조를 갖는 대형 패키지가 주로 여기에 설치됩니다.

$ ls /opt
google/  microsoft/  containerd/

Google Chrome이나 Visual Studio Code 같은 프로그램을 Linux에 설치하면 /opt/google/chrome이나 /opt/microsoft/vscode 같은 경로에 들어가는 경우가 많습니다.

/mnt와 /media — 마운트 포인트

외부 저장 장치를 연결할 때 사용하는 마운트 포인트입니다.

/mnt는 수동으로 마운트할 때 사용하는 전통적인 마운트 지점입니다. 관리자가 임시로 파일 시스템을 마운트하거나, NFS 같은 네트워크 파일 시스템을 연결할 때 쓰입니다.

$ sudo mount /dev/sdb1 /mnt
$ ls /mnt
documents  photos  backup.tar.gz

/media는 USB, CD-ROM 같은 이동식 미디어가 자동으로 마운트되는 곳입니다. 데스크톱 환경에서 USB를 꽂으면 /media/사용자이름/USB_NAME 같은 경로에 자동으로 연결됩니다.

/srv — 서비스 데이터

“service”의 약자로, 시스템이 제공하는 서비스의 데이터를 저장하기 위한 디렉토리입니다. FTP 서버의 파일이나 웹 서버의 콘텐츠를 여기에 놓기도 합니다.

$ ls /srv
ftp/  www/

실제로는 /var/www에 웹 콘텐츠를 두는 경우가 더 많아서, /srv는 비어 있는 시스템이 많습니다.

/run — 런타임 데이터

부팅 후 실행 중인 시스템의 런타임 데이터를 저장합니다. PID 파일, 소켓 파일, lock 파일 같은 것들이 여기에 들어갑니다. tmpfs로 마운트되어 메모리에만 존재하므로 재부팅하면 사라집니다.

$ ls /run
docker.sock  sshd.pid  systemd/  user/

Docker를 사용한다면 /run/docker.sock 파일이 눈에 익을 겁니다. Docker 데몬과 통신하는 Unix 소켓 파일인데, docker 명령어가 이 소켓을 통해 Docker 데몬에 요청을 보냅니다.

한눈에 보기

지금까지 살펴본 디렉토리를 정리하면 이렇습니다.

디렉토리용도자주 쓰는 상황
/파일 시스템의 루트모든 경로의 시작점
/home사용자 개인 디렉토리프로젝트 코드, dotfile 관리
/etc시스템 설정 파일서버 설정, hosts 파일 수정
/var가변 데이터 (로그, 캐시)로그 확인, 웹 서버 콘텐츠
/usr설치된 프로그램과 라이브러리프로그램 위치 확인
/bin기본 실행 파일일상적인 명령어 사용
/sbin시스템 관리 실행 파일시스템 관리 작업
/tmp임시 파일임시 테스트, 캐시
/dev장치 파일/dev/null, 난수 생성
/proc프로세스/시스템 정보 (가상)CPU, 메모리 정보 확인
/boot부팅 파일커널 업데이트 확인
/lib공유 라이브러리라이브러리 의존성 확인
/opt서드파티 소프트웨어Chrome, VS Code 등
/mnt수동 마운트 지점외부 디스크 연결
/media이동식 미디어 자동 마운트USB, CD 연결

마치며

Unix/Linux의 디렉토리 구조가 처음에는 복잡해 보여도 규칙을 알고 나면 상당히 논리적인 체계라는 걸 알 수 있습니다. 설정은 /etc, 로그는 /var/log, 프로그램은 /usr/bin… 이런 패턴이 머릿속에 자리잡으면 어떤 Linux 시스템에서든 필요한 파일을 금방 찾을 수 있게 됩니다.

특히 서버에 SSH로 접속해서 문제를 해결하거나, Docker 컨테이너의 내부 구조를 파악하거나, CI/CD 환경을 디버깅하는 상황에서 이 지식이 빛을 발합니다. macOS에서 개발하고 계신다면 macOS 디렉토리 구조 이해하기도 함께 읽어보세요.

더 자세한 내용이 궁금하다면 터미널에서 man hier 명령어를 실행해보세요. 시스템에 설치된 파일 시스템 계층 구조의 공식 매뉴얼을 읽을 수 있습니다. FHS 공식 문서는 Linux Foundation의 FHS 페이지에서 확인할 수 있습니다.

This work is licensed under CC BY 4.0 CC BY

개발자를 위한 뉴스레터

달레가 정리한 AI 개발 트렌드와 직접 만든 콘텐츠를 전해드립니다.

Discord