Linux가 부팅되는 순간부터 서비스가 요청을 처리하는 순간까지 — 커널·유저스페이스 구조, 부팅 과정, 파일 시스템 계층(FHS), 권한 모델, 프로세스 생명주기, systemd, 네트워크 스택, 스토리지·메모리, 로깅, 보안 하드닝, 성능 진단, 컨테이너의 커널 기반(namespace·cgroups)까지 — 다이어그램과 함께 Linux를 하나의 시스템으로 이해하는 완전 가이드입니다.
Linux가 부팅되는 순간부터 서비스가 요청을 처리하는 순간까지 — 커널·유저스페이스 구조, 부팅 과정, 파일 시스템 계층(FHS), 권한 모델, 프로세스 생명주기, systemd, 네트워크 스택, 스토리지·메모리, 로깅, 보안 하드닝, 성능 진단, 컨테이너의 커널 기반(namespace·cgroups)까지 — 다이어그램과 함께 Linux를 하나의 시스템으로 이해하는 완전 가이드입니다. 이 가이드는 개념을 나열하기보다, 실제 프로젝트에서 판단해야 하는 순서대로 내용을 따라갈 수 있게 구성했습니다.
핵심 관점
인프라 / 운영
설치 명령을 외우기보다 트래픽, 런타임, 관측, 장애 대응이 어떤 순서로 이어지는지 파악합니다.
시스템 아키텍처 이해systemd & 프로세스 운영네트워크·스토리지 구조 설계보안 하드닝 & 성능 트러블슈팅
구조 다이어그램
글로 읽은 내용을 머릿속에 오래 남기려면 먼저 흐름을 그림으로 잡는 편이 좋습니다. 아래 두 그림은 Linux를 학습할 때 계속 되돌아볼 수 있는 기준 지도입니다.
학습 흐름
다이어그램 렌더링 중…
아키텍처 관점
다이어그램 렌더링 중…
아키텍처 & 부팅 과정
Linux를 처음 펼칠 때는 세부 명령보다 큰 그림이 먼저입니다. 이 섹션에서는 앞으로 배울 개념들이 어떤 문제를 풀기 위해 등장했는지부터 잡아봅니다.
Linux는 하드웨어를 직접 통제하는 커널(Kernel)과, 그 위에서 커널이 제공하는 시스템 콜을 통해서만 하드웨어에 접근하는 유저스페이스(User space)로 나뉩니다. 애플리케이션이 파일을 열거나 소켓을 만들 때 실제로 디스크·NIC를 조작하는 주체는 항상 커널이며, 애플리케이션은 그 결과만 시스템 콜을 통해 돌려받습니다. 이 경계를 이해하면 "명령어 하나가 커널의 어느 부분을 건드리는지"가 보이기 시작하고, 뒤에 나올 프로세스·파일시스템·네트워크 섹션이 서로 어떻게 연결되는지 훨씬 쉽게 이해할 수 있습니다.
다이어그램 렌더링 중…
다이어그램 렌더링 중…
구성 요소
역할
펌웨어 (BIOS/UEFI)
전원이 켜지면 가장 먼저 실행되어 하드웨어를 초기 진단하고 부트로더를 찾음
부트로더 (GRUB)
어떤 커널을 어떤 옵션으로 부팅할지 선택 — 멀티 부팅, 커널 파라미터 전달 담당
커널
프로세스 스케줄링, 메모리 관리, 파일시스템, 네트워크 등 모든 하드웨어 자원을 중재
init (PID 1)
커널이 최초로 실행하는 유저스페이스 프로세스 — 이후 모든 프로세스의 조상
파일 시스템 계층 구조(FHS)
여기서는 파일 시스템 계층 구조(FHS)을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.
Linux는 배포판이 달라도 "이 파일은 이 디렉토리 아래 있어야 한다"는 공통 규칙인 FHS(Filesystem Hierarchy Standard)를 따릅니다. 이 규칙 덕분에 Ubuntu에서 배운 경로 감각이 CentOS나 Alpine에서도 거의 그대로 통하고, 설정 파일·로그·실행 파일이 뒤섞이지 않아 자동화 스크립트를 배포판에 상관없이 재사용할 수 있습니다.
다이어그램 렌더링 중…
디렉토리
용도
실무 팁
/etc
데몬·시스템 설정 파일
설정 변경 전 반드시 .bak로 백업하거나 Git으로 버전 관리
/var/log
애플리케이션·시스템 로그
디스크 풀 방지를 위해 logrotate 설정 필수
/proc
실행 중인 프로세스·커널 파라미터를 파일처럼 노출
/proc/[PID]/status로 특정 프로세스 상태 직접 확인 가능
/sys
커널이 인식한 디바이스·드라이버 정보
sysfs 값을 바꿔 런타임에 커널 파라미터를 조정할 수 있음
/opt
FHS 표준 경로를 따르지 않는 독립 실행형 소프트웨어
패키지 매니저가 관리하지 않는 수동 설치 소프트웨어의 정석 위치
권한 & 소유권 모델
여기서는 권한 & 소유권 모델을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.
Linux의 모든 파일은 소유자(owner)·소유 그룹(group)·나머지(other) 세 주체에 대해 각각 읽기(r)·쓰기(w)·실행(x) 권한을 가집니다. 어떤 프로세스가 파일에 접근하려 할 때 커널은 이 세 그룹 중 프로세스가 "가장 먼저 해당하는" 하나만 적용합니다 — 소유자 본인이면 그룹·전체 권한이 아무리 넓어도 소유자 권한만 적용된다는 점이 실무에서 자주 놓치는 부분입니다.
다이어그램 렌더링 중…
BASH
# 소유자/그룹 변경chown deploy:deploy /var/www/myappchgrp developers shared-folder/# 권한 변경 — 숫자(절대) 표기chmod 755 script.sh # rwxr-xr-xchmod 644 config.yml # rw-r--r--chmod -R 750 /var/www/myapp # 디렉토리 전체에 재귀 적용# 새 파일의 기본 권한을 결정하는 umaskumask # 현재 값 확인 (예: 0022)umask 0027 # 이후 생성되는 파일은 그룹 쓰기·전체 접근이 기본 차단# 세밀한 접근 제어가 필요할 때 — 표준 rwx로는 부족한 경우setfacl -m u:alice:rx /var/www/myappgetfacl /var/www/myapp
기호
숫자
의미 (파일)
의미 (디렉토리)
r
4
파일 내용 읽기
디렉토리 안의 파일 목록 조회(ls)
w
2
파일 내용 수정
디렉토리 안에서 파일 생성·삭제
x
1
파일을 프로그램으로 실행
디렉토리로 진입(cd) 가능
setuid (4000)
-
실행 시 소유자 권한으로 동작 (예: passwd)
해당 없음
setgid (2000)
-
실행 시 소유 그룹 권한으로 동작
디렉토리 안에서 새 파일이 같은 그룹을 상속
sticky bit (1000)
-
해당 없음
자기 파일만 자신이 삭제 가능 (예: /tmp)
필수 명령어
여기서는 필수 명령어을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.
서버 장애의 상당수는 로그와 디스크 용량을 얼마나 빨리 들여다보는지에서 갈립니다. find/du로 오래되거나 용량이 큰 파일을 먼저 찾아내고, grep/awk/sed로 로그를 실시간 필터링하는 습관을 들이면 원인 파악 시간이 크게 줄어듭니다.
BASH
# 파일 & 디렉토리ls -lah # 상세 목록find / -name "*.log" -mtime +7 # 7일 넘은 로그du -sh /var/log/* | sort -hr # 용량 순 정렬tail -f /var/log/nginx/access.log# 텍스트 처리grep -r "ERROR" /var/log --include="*.log"awk '{print $1}' access.log | sort | uniq -c | sort -rnsed -i 's/old/new/g' config.txt# 여러 파일에 명령을 일괄 적용find . -name "*.tmp" | xargs rm -f
프로세스 관리 & 생명주기
여기서는 프로세스 관리 & 생명주기을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.
모든 프로세스는 이미 실행 중인 부모 프로세스가 fork()로 자신을 복제하고, 그 복제본이 exec()로 실제 실행할 프로그램으로 교체되면서 태어납니다. 그래서 모든 프로세스는 PID(자신의 번호)와 PPID(부모의 번호)를 가지며, 이 계보를 따라가면 최종적으로 PID 1(systemd)에 도달합니다. 어떤 프로세스가 포트를 점유하고 얼마나 많은 CPU/메모리를 쓰는지 확인하는 것이 장애 대응의 첫 단계입니다.
다이어그램 렌더링 중…
BASH
# 모니터링top / htopps aux | grep nginxps -o pid,ppid,cmd -p 1234 # PID/PPID 계보 확인lsof -i :8080 # 포트 사용 프로세스# 신호 보내기kill -TERM 1234 # 정상 종료 요청 (기본값)kill -9 1234 # 강제 종료 (SIGKILL)pkill -f "node server.js"# 우선순위 조정nice -n 10 ./batch-job.sh # 낮은 우선순위로 시작renice -n 5 -p 1234 # 실행 중인 프로세스 우선순위 변경
시그널
기본 동작
용도
SIGHUP (1)
종료 (데몬은 종종 재로드로 재정의)
터미널 종료 알림 — nginx 등은 이 신호로 설정 파일 리로드
SIGINT (2)
종료
Ctrl+C — 사용자가 포그라운드 프로세스를 중단
SIGTERM (15)
종료 (프로세스가 가로채서 정리 작업 가능)
kill의 기본 신호 — "정상적으로 종료해라"는 요청
SIGKILL (9)
즉시 강제 종료 (가로챌 수 없음)
프로세스가 응답 없을 때의 최후 수단
SIGSTOP (19)
일시 정지 (가로챌 수 없음)
Ctrl+Z와 유사하게 프로세스를 멈춤
systemd & 서비스 관리
여기서는 systemd & 서비스 관리을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.
systemd는 PID 1로 실행되며 부팅 과정 전체와 이후의 서비스 생명주기를 관리합니다. 서비스 하나하나는 "유닛(unit)"이라는 단위로 선언되고, 유닛 파일에 "무엇이 준비된 뒤에 시작해야 하는지(After)"와 "어떤 타겟에 속하는지(WantedBy)"를 적어두면 systemd가 의존성 그래프를 계산해 병렬로 최대한 빠르게 부팅을 진행합니다.
# 유닛 파일 작성 후 반영systemctl daemon-reload# 부팅 시 자동 시작 등록 + 즉시 실행systemctl enable --now myapp# 상태 확인 & 로그 확인systemctl status myappjournalctl -u myapp -f --since "1 hour ago"# 백그라운드 실행 (임시 디버깅용 — 운영 서비스에는 부적합)nohup ./server &tmux new -s work
디렉티브
의미
After=
이 유닛보다 먼저 시작되어야 할 유닛 (실패해도 이 유닛은 시작 시도함)
Requires=
이 유닛이 의존하는 유닛 — 의존 유닛이 실패하면 이 유닛도 중단
Restart=on-failure
비정상 종료 시 자동 재시작
WantedBy=multi-user.target
이 타겟이 활성화될 때 함께 시작되도록 등록 (enable 시 심볼릭 링크 생성)
네트워크 스택 & 방화벽
여기서는 네트워크 스택 & 방화벽을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.
서비스가 응답하지 않을 때는 포트가 실제로 열려 있는지, 방화벽이 트래픽을 막고 있는지를 먼저 확인해야 합니다. 커널로 들어온 패킷은 netfilter의 여러 체인(chain)을 순서대로 통과하며, iptables는 그 체인마다 규칙을 걸어 패킷을 허용(ACCEPT)·차단(DROP)·변환(NAT)할 수 있게 해주는 도구입니다.
다이어그램 렌더링 중…
BASH
# 연결 확인ss -tlnp # 리스닝 포트 목록curl -v https://api.example.comnc -zv host 443 # 포트 연결 테스트# iptables (방화벽) — 위에서부터 순서대로 매칭iptables -A INPUT -p tcp --dport 80 -j ACCEPTiptables -A INPUT -p tcp --dport 443 -j ACCEPTiptables -A INPUT -p tcp --dport 22 -j ACCEPTiptables -A INPUT -j DROP # 명시한 것 외 전부 차단 (반드시 SSH 허용 뒤에 추가)# 트래픽 분석tcpdump -i eth0 port 80 -w capture.pcap
체인
패킷이 지나는 시점
PREROUTING
패킷이 도착해 라우팅 결정을 내리기 전 (포트 포워딩용 DNAT에 사용)
INPUT
이 호스트 자신을 목적지로 하는 패킷
FORWARD
이 호스트를 거쳐 다른 호스트로 전달되는 패킷 (라우터·NAT 게이트웨이 역할일 때)
OUTPUT
이 호스트에서 만들어져 나가는 패킷
POSTROUTING
패킷이 실제로 나가기 직전 (SNAT/MASQUERADE에 사용)
스토리지(LVM) & 메모리·스왑
여기서는 스토리지(LVM) & 메모리·스왑을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.
물리 디스크는 파티션으로 나뉘고, 그 위에 LVM(Logical Volume Manager)을 얹으면 여러 디스크를 하나의 저장소 풀로 묶어 파티션 크기를 마운트된 상태에서도 유연하게 늘릴 수 있습니다. 메모리 역시 프로세스가 보는 "가상 메모리"와 실제 "물리 메모리(RAM)"가 분리되어 있어, RAM이 부족해지면 커널이 자동으로 대응합니다.
다이어그램 렌더링 중…
다이어그램 렌더링 중…
BASH
# 디스크 & 마운트 현황lsblk # 블록 디바이스 트리 확인df -h # 마운트된 파일시스템 사용량# LVM — PV/VG/LV 생성부터 온라인 확장까지pvcreate /dev/sdbvgcreate data-vg /dev/sdblvcreate -L 50G -n data-lv data-vgmkfs.ext4 /dev/data-vg/data-lvmount /dev/data-vg/data-lv /data# 서비스 중단 없이 용량 확장lvextend -L +20G /dev/data-vg/data-lvresize2fs /dev/data-vg/data-lv# 메모리 & 스왑 확인free -hswapon --showvmstat 1 5 # 1초 간격 5회 — si/so 컬럼이 계속 0이 아니면 스왑 과다 사용
free -h 항목
의미
available
실제로 새 프로세스가 즉시 쓸 수 있는 메모리 (캐시 회수분 포함) — 여유 메모리 판단은 이 값 기준
buff/cache
커널이 파일 I/O 속도를 높이려고 임시로 쓰는 캐시 — 필요하면 즉시 회수되므로 "사용 중"으로 오해하지 말 것
swap used
물리 메모리가 부족해 디스크로 밀려난 페이지 총량 — 지속적으로 늘어나면 메모리 증설 신호
로깅 시스템 (journald)
여기서는 로깅 시스템 (journald)을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.
systemd 기반 배포판에서는 서비스의 표준 출력(stdout/stderr)과 커널 메시지가 모두 journald로 모여 바이너리 형식으로 저장됩니다. 텍스트 로그 파일과 달리 journald는 유닛 이름, 우선순위, 타임스탬프 같은 메타데이터로 구조화되어 있어 grep 대신 journalctl의 필터 옵션으로 원하는 로그만 정확히 뽑아낼 수 있습니다.
다이어그램 렌더링 중…
BASH
# 특정 서비스 로그만 실시간 확인journalctl -u myapp -f# 최근 1시간, ERROR 이상만journalctl -u myapp --since "1 hour ago" -p err# 부팅 이후 커널 메시지journalctl -k -b# journald가 쓰는 디스크 용량 상한 설정# /etc/systemd/journald.conf# SystemMaxUse=500M
여기서는 보안 하드닝을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.
기본 설치 상태의 Linux 서버는 root 비밀번호 로그인이 열려 있고 불필요한 서비스가 떠 있는 경우가 많습니다. SSH·sudo·방화벽 세 가지만 제대로 잠가도 자동화된 스캐너의 무차별 대입 공격 대부분을 막을 수 있고, fail2ban 같은 도구로 반복 실패를 자동 차단하면 사람이 매번 로그를 지켜볼 필요가 없어집니다.
/etc/ssh/sshd_config (발췌)TEXT
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AllowUsers deploy admin
Port 22
# sudoers에 명령 단위로 최소 권한 부여echo 'deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart myapp' \ > /etc/sudoers.d/deploy-myappvisudo -c # 문법 검증 후 반영# SELinux 상태 확인 (RHEL 계열)getenforcesestatus
항목
기본 상태의 위험
권장 조치
SSH root 로그인
비밀번호만 알면 누구나 root로 직접 접속 가능
PermitRootLogin no + 키 기반 인증만 허용
SSH 비밀번호 인증
무차별 대입(brute-force) 공격에 노출
PasswordAuthentication no, 공개키 인증으로 전환
sudo 권한
사용자가 모든 명령을 root 권한으로 실행 가능
/etc/sudoers.d/에 필요한 명령만 최소 권한으로 부여
반복 로그인 실패
자동화된 봇이 무한정 시도 가능
fail2ban으로 일정 횟수 실패 시 IP 자동 차단
DAC 권한 모델의 한계
root로 뚫리면 시스템 전체에 무제한 접근
SELinux/AppArmor로 프로세스별 접근 범위를 추가로 제한(MAC)
성능 진단 & 트러블슈팅
여기서는 성능 진단 & 트러블슈팅을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.
"서버가 느리다"는 증상 하나로 원인을 바로 찾을 수는 없습니다. CPU·메모리·디스크 I/O 세 가지 자원을 순서대로 확인해 병목이 어디에 있는지 좁혀나가는 체계적인 접근이 감으로 이것저것 확인하는 것보다 훨씬 빠릅니다.
다이어그램 렌더링 중…
BASH
uptime # load average 확인vmstat 1 5 # 1초 간격 5회 — r, si/so 컬럼 주시iostat -x 1 5 # 디스크별 %util, awaitsar -n DEV 1 5 # 네트워크 인터페이스 트래픽mpstat -P ALL 1 5 # 코어별 CPU 사용률 (특정 코어만 100%인 경우 발견 가능)
도구
핵심으로 볼 값
해석
uptime
load average (1/5/15분)
CPU 코어 수보다 지속적으로 높으면 CPU 자원 부족 신호
vmstat 1
r(실행 대기), si/so(스왑 in/out)
r이 코어 수보다 크거나 si/so가 0이 아니면 각각 CPU/메모리 압박
iostat -x 1
%util, await
%util이 100%에 가깝고 await가 높으면 디스크가 병목
sar -n DEV 1
rxkB/s, txkB/s
NIC 대역폭 포화 여부 확인
컨테이너의 커널 기반
여기서는 컨테이너의 커널 기반을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.
Docker나 Kubernetes가 컨테이너를 만드는 마법처럼 보이지만, 실제로는 Linux 커널의 두 기능을 조합한 것입니다 — namespace는 프로세스가 보는 PID·네트워크·마운트 목록을 서로 격리하고, cgroups는 프로세스(그룹)가 쓸 수 있는 CPU·메모리·I/O 총량을 제한합니다. 이 둘을 이해하면 docker run --memory나 Kubernetes의 리소스 limits가 내부적으로 무엇을 설정하는 것인지 명확해집니다.
다이어그램 렌더링 중…
BASH
# 새 PID/네트워크/마운트 namespace에서 셸 실행 — 컨테이너 격리를 직접 체험unshare --pid --net --mount --fork /bin/bashps aux # 이 셸 안에서는 자신만 PID 1 근처로 보임# cgroup v2로 프로세스 그룹의 메모리 상한 직접 설정mkdir /sys/fs/cgroup/mygroupecho $$ > /sys/fs/cgroup/mygroup/cgroup.procs # 현재 셸을 이 그룹에 편입echo 100M > /sys/fs/cgroup/mygroup/memory.max # 이 그룹 전체 메모리 상한 100MB# docker run --memory=100m 도 내부적으로는 위와 동일하게# 컨테이너 프로세스를 cgroup에 넣고 memory.max를 설정하는 것입니다.
Shell 스크립팅
여기서는 Shell 스크립팅을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.
반복되는 배포·백업 작업은 셸 스크립트로 만들어 사람이 수동으로 실행하며 실수할 여지를 없애야 합니다. set -euo pipefail은 오류 발생 시 즉시 스크립트를 중단시켜, 실패한 단계 이후의 명령이 잘못된 상태로 계속 실행되는 것을 막아줍니다.
deploy.shBASH
#!/bin/bashset -euo pipefail # 에러 시 즉시 종료APP_DIR="/var/www/myapp"BACKUP_DIR="/var/backups"log() { echo "[$(date +%F %T)] $*"; }cleanup() { log "정리 작업 실행 (성공/실패와 무관하게 항상 실행)"}trap cleanup EXIT# 배포 스크립트main() { log "Starting deployment..." cp -r "$APP_DIR" "$BACKUP_DIR/$(date +%Y%m%d%H%M%S)" git -C "$APP_DIR" pull origin main systemctl restart myapp log "Deployment complete"}main "$@"
Linux 실무 설계
Linux 실무 설계은 선택지가 갈리는 지점입니다. 표를 기준으로 각 방법의 쓰임새와 운영상의 차이를 비교해두면 이후 판단이 훨씬 쉬워집니다.
Linux 운영은 명령어 암기보다 process, file, network, permission 모델을 이해하는 것이 핵심입니다.
결정 지점
확인 질문
실무 기준
경계
Linux 코드에서 바뀌기 쉬운 부분은 어디인가?
입출력, 설정, 외부 연동, 핵심 규칙을 분리합니다.
상태
상태가 어디서 생성되고 어디서 사라지는가?
상태 소유자와 수명 주기를 코드로 드러냅니다.
장애
실패했을 때 호출자는 무엇을 받는가?
timeout, fallback, error contract를 먼저 정합니다.
Linux 운영 기준
이 섹션은 Linux 운영 기준을 실무 관점에서 정리합니다. 개념을 외우기보다, 어떤 상황에서 이 기준을 꺼내 쓸지에 초점을 맞춰보세요.
CPU load, memory pressure, disk I/O, network socket, systemd service 상태를 함께 봐야 합니다.
Linux 검증 전략
Linux 검증 전략은 선택지가 갈리는 지점입니다. 표를 기준으로 각 방법의 쓰임새와 운영상의 차이를 비교해두면 이후 판단이 훨씬 쉬워집니다.
운영 작업은 runbook, rollback command, dry-run, audit log를 포함해야 합니다.