13년차의 서버실

서버, 인프라, 홈랩 기술 블로그

[카테고리:] linux

  • [Linux] 커널 튜닝 ext4 파일 시스템 성능 최적화 실전 사례

    [Linux] 커널 튜닝 ext4 파일 시스템 성능 최적화 실전 사례

    [Linux] 커널 튜닝 ext4 파일 시스템 성능 최적화 실전 사례

    리눅스 서버를 오래 보다 보면 CPU나 메모리보다도 디스크 I/O가 먼저 발목을 잡는 순간이 꼭 옵니다. 특히 로그가 많이 쌓이거나 작은 파일이 계속 생성되는 워크로드에서는 커널 튜닝 ext4 한 번으로 체감이 확 달라지기도 하거든요. 저도 홈랩과 운영 환경에서 비슷한 문제를 몇 번 겪었는데, 처음엔 애플리케이션 문제인 줄 알고 한참 돌아갔었습니다. 근데 막상 뜯어보니 ext4 마운트 옵션과 writeback(라이트백, 커널의 지연 쓰기) 동작이 핵심이더라고요. 이번 글에서는 Linux 성능 최적화 관점에서 ext4 파일 시스템을 어떻게 점검하고, 어떤 순서로 조정해야 덜 위험하게 성능을 끌어올릴 수 있는지 실제 사례 흐름으로 정리해보겠습니다.

    특히 이 글은 벤치마크 숫자를 과장해서 보여주는 방식이 아니라, 제가 실제로 자주 쓰는 확인 절차와 안전한 튜닝 기준 위주로 풀어갑니다. 혹시 디스크 사용률은 높지 않은데 응답이 한 번씩 뚝 끊기는 경험 있으신가요? 여기서 중요한 포인트가 바로 파일 시스템 자체보다도 파일 시스템 튜닝과 커널 writeback 정책을 같이 봐야 한다는 점입니다.

    커널 튜닝 ext4와 I/O 경로를 설명하는 개요 다이어그램

    애플리케이션 쓰기 요청이 페이지 캐시와 ext4 저널을 거쳐 블록 디바이스로 내려가는 흐름을 보여주는 개요 이미지입니다.

    왜 ext4 성능 개선이 생각보다 큰 차이를 만들까

    쉽게 말해 ext4는 그냥 디스크에 바로 쓰는 시스템이 아닙니다. 애플리케이션이 파일을 쓰면 먼저 page cache(페이지 캐시, 메모리 기반 캐시)에 반영되고, 이후 커널이 적절한 시점에 실제 저장 장치로 내립니다. 여기에 journaling(저널링, 메타데이터 일관성을 위한 기록)까지 얹히니까, 같은 SSD를 써도 마운트 옵션과 커널 파라미터에 따라 체감이 꽤 달라질 수 있어요.

    제가 처음 이걸 제대로 체감한 건 로그 수집 서버였습니다. 디스크는 NVMe였고 CPU도 여유가 있었는데, 특정 시간대만 되면 flush(플러시, 메모리의 변경 내용을 디스크로 밀어내는 작업)가 몰리면서 응답이 출렁이더라고요. 처음엔 “스토리지가 느린가?” 싶었는데 사실 스토리지보다는 쓰기 패턴과 ext4 기본 동작이 workload(워크로드, 실제 작업 특성)과 안 맞았던 겁니다.

    ext4와 커널 튜닝 개념 먼저 정리해보겠습니다

    ext4에서 먼저 봐야 할 핵심 포인트

    • atime: 파일 읽기 때 접근 시간(access time)을 갱신할지 여부입니다.
    • commit: 저널 커밋 주기 관련 옵션입니다. 너무 공격적으로 늘리면 장애 시 최근 변경 유실 범위가 커질 수 있습니다.
    • journaling mode: <code>data=ordered, data=writeback, data=journal 같은 모드가 있습니다.
    • discard: SSD/TRIM 처리 방식입니다. 연속 discard가 편할 때도 있지만, 주기적 fstrim이 더 나은 경우가 많습니다.
    • dirty page: 커널이 메모리에 쌓아두는 더티 페이지 비율입니다. 이게 높아지면 한 번에 밀어내는 양이 커질 수 있어요.

    자주 쓰는 옵션 비교

    항목 의미 장점 주의할 점
    noatime 읽기 시 access time 갱신 비활성화 불필요한 메타데이터 쓰기 감소 atime 의존 프로그램이 있으면 영향 확인 필요
    lazytime 시간 정보 갱신을 지연 반영 메타데이터 쓰기 감소 일부 운영 정책과 충돌 없는지 확인 필요
    commit=30 저널 커밋 간격 증가 잦은 커밋 부담 완화 가능 장애 시 최근 변경 유실 범위 증가 가능
    data=ordered 일반적인 기본 저널링 모드 안정성과 성능 균형 쓰기 특성에 따라 병목 가능
    data=writeback 데이터 기록 순서 보장 완화 일부 쓰기 성능 유리 가능 일관성 측면 주의, 무조건 권장 아님

    여기서 제가 강조하고 싶은 건, ext4 성능 개선은 옵션 몇 개 붙인다고 끝나는 작업이 아니라는 점이에요. 파일 생성이 많은지, 순차 쓰기가 많은지, fsync(에프싱크, 즉시 디스크 반영 요청)가 잦은지에 따라 접근이 달라져야 하거든요.

    실전 사례: 로그 적재 서버에서 지연 스파이크를 줄인 과정

    상황은 이랬습니다. 작은 로그 파일이 자주 쓰이고, 1분 단위 배치 작업이 돌 때 응답 지연이 크게 튀었습니다. 시스템을 보면 CPU는 넉넉했고 메모리도 부족하지 않았습니다. 그런데 iostat와 vmstat를 같이 보니 특정 시점마다 writeback이 몰리더라고요. 저도 처음엔 애플리케이션 쓰레드 문제인 줄 알고 삽질 좀 했습니다 ㅎㅎ 결국 원인은 “작은 쓰기 + 메타데이터 갱신 + flush 집중” 조합이었습니다.

    1. 현재 ext4 마운트 상태부터 확인

    1. 대상 파일 시스템의 마운트 옵션을 확인합니다.
    2. 저널링 모드와 예약 블록, 파일 시스템 특성을 확인합니다.
    3. 실제 장치의 readahead와 I/O 패턴을 함께 봅니다.
    findmnt -no TARGET,SOURCE,FSTYPE,OPTIONS /data
    mount | grep ' /data '
    sudo tune2fs -l /dev/nvme0n1p1 | egrep 'Filesystem features|Reserved block count|Block size|Journal'
    sudo dumpe2fs -h /dev/nvme0n1p1 2>/dev/null | egrep 'Filesystem state|Errors behavior|Journal mode'

    이 단계에서 중요한 건 “이미 어떤 옵션이 걸려 있는지”예요. 의외로 relatime 기본값으로 충분한 환경도 있고, 반대로 불필요한 discard가 항상 켜져 있어서 쓰기 경로를 괜히 복잡하게 만드는 경우도 있었습니다.

    2. 병목이 파일 시스템인지, 블록 계층인지 분리

    iostat -xz 1
    vmstat 1
    pidstat -d 1
    sar -b 1

    제가 실제로 자주 보는 건 이 네 가지입니다. iostat로 디바이스 지연과 큐를 보고, vmstat로 dirty page와 writeback 타이밍 감을 잡고, pidstat로 어떤 프로세스가 얼마나 쓰는지 확인합니다. 여기서 애플리케이션 fsync 호출이 잦으면 ext4 튜닝보다 앱 설정 조정이 먼저일 수 있어요. 그러니까 커널 튜닝 ext4는 언제나 계층 분리를 먼저 해야 합니다.

    3. 안전한 범위의 1차 조정

    제가 처음부터 무리하게 건드리지 않는 항목은 대체로 아래 정도입니다.

    sudo cp /etc/fstab /etc/fstab.bak
    sudo editor /etc/fstab
    UUID=xxxx-xxxx  /data  ext4  defaults,noatime,lazytime,commit=30  0  2

    noatime은 읽기 위주의 접근에서도 불필요한 메타데이터 갱신을 줄이는 데 꽤 도움이 돼요. lazytime은 시간 정보 반영을 지연시켜서 메타데이터 쓰기 부담을 줄일 수 있고요. commit=30은 저널 커밋 빈도를 낮춰 writeback이 너무 자주 발생하는 상황을 완화하는 데 써볼 만합니다. 다만 이 값은 서비스 특성에 따라 보수적으로 잡아야 합니다. 데이터 안전성이 아주 민감하면 함부로 늘리면 안 돼요.

    커널 튜닝 ext4 설정 변경 과정을 보여주는 시스템 점검 이미지

    fstab 편집, findmnt 확인, sysctl 조정 흐름을 한눈에 보여주는 구성 이미지입니다.

    4. 커널 writeback 파라미터도 함께 조정

    파일 시스템 옵션만 바꾸고 끝내면 절반만 본 셈입니다. 실제로 써보니까 flush가 몰리는 서버에서는 이쪽 영향도 꽤 크더라고요.

    sysctl vm.dirty_background_ratio
    sysctl vm.dirty_ratio
    sysctl vm.dirty_expire_centisecs
    sysctl vm.dirty_writeback_centisecs
    sudo tee /etc/sysctl.d/99-ext4-tuning.conf >/dev/null <<'EOF'
    vm.dirty_background_ratio = 5
    vm.dirty_ratio = 20
    vm.dirty_expire_centisecs = 3000
    vm.dirty_writeback_centisecs = 500
    EOF
    sudo sysctl --system

    이 수치는 만능 정답이 아닙니다. 다만 dirty page가 너무 많이 쌓였다가 한꺼번에 내려가는 패턴을 줄이는 출발점으로는 꽤 무난했어요. 저는 메모리가 큰 서버에서 기본값 그대로 두었다가 writeback 몰림이 생긴 적이 있었는데, 이 값을 조정하고 나서 지연 스파이크가 훨씬 덜해졌습니다.

    5. SSD라면 discard 운영 방식 점검

    여기서 한 번 더 많이 헷갈립니다. SSD니까 discard를 무조건 마운트 옵션에 넣어야 할 것 같죠? 저도 예전엔 그렇게 했었는데, 실제론 주기적 TRIM이 더 나은 경우가 적지 않아요.

    systemctl status fstrim.timer
    sudo systemctl enable --now fstrim.timer
    systemctl list-timers | grep fstrim

    즉시 discard보다 주기적 fstrim을 선호하는 이유는, 연속 discard가 쓰기 경로에 부담을 줄 수 있기 때문입니다. 물론 환경에 따라 다르니 확인은 꼭 필요해요.

    ⚠️ 실무에서 자주 만나는 트러블슈팅

    문제 1: noatime 넣었더니 일부 프로그램 동작이 달라졌습니다

    아주 드문 편이긴 하지만 atime을 실제로 참조하는 도구가 있을 수 있습니다. 이런 경우 noatime 대신 기본 relatime 유지가 더 안전해요. 무조건 성능만 보고 밀어붙이면 안 됩니다.

    문제 2: commit 값을 늘렸더니 찜찜합니다

    이건 정상적인 감각입니다. commit 간격을 늘리면 메타데이터 커밋 빈도는 줄 수 있지만, 장애 발생 시 최근 변경이 디스크에 완전히 반영되지 않았을 가능성은 커집니다. 그래서 데이터 무결성이 중요한 DB 데이터 디렉터리에는 저는 보수적으로 접근해요. 로그, 캐시, 재생성 가능한 데이터인지 먼저 구분하세요.

    문제 3: data=writeback으로 바꾸면 더 빠른가요?

    경우에 따라 다를 수는 있어도, 이걸 기본 추천으로 보시면 안 돼요. data=writeback은 데이터 기록 순서 보장이 더 약하므로 장애 시 예상 못 한 상태를 만날 수 있습니다. 제가 운영 서버에서는 대부분 data=ordered를 유지합니다. 성능 때문에 일관성을 희생하는 선택은 언제나 마지막이어야 하거든요.

    문제 4: reserved block이 너무 크게 잡혀 있습니다

    대용량 데이터 볼륨이라면 예약 블록(reserved block) 비율이 과한 경우가 있습니다. 루트 파일 시스템이 아니라 일반 데이터 파티션이면 점검해볼 만해요.

    sudo tune2fs -m 1 /dev/nvme0n1p1

    다만 이것도 서비스 성격을 봐야 합니다. 시스템 영역과 일반 데이터 볼륨은 판단 기준이 다르니까요.

    검증: 바꿨으면 반드시 재현 테스트를 해봐야 합니다

    튜닝은 느낌으로 하면 안 돼요. 저도 처음엔 “체감상 좋아진 것 같은데?” 하고 넘어가려다가 다시 문제를 만난 적이 있습니다. 그래서 지금은 꼭 동일한 패턴의 테스트를 다시 돌립니다.

    fio로 쓰기 패턴 재현

    fio --name=ext4-logtest \
        --directory=/data/fiotest \
        --size=2G \
        --bs=4k \
        --rw=randwrite \
        --iodepth=16 \
        --ioengine=libaio \
        --direct=0 \
        --numjobs=4 \
        --runtime=60 \
        --time_based \
        --group_reporting

    여기서 포인트는 숫자 한 줄만 보지 않는 거예요. IOPS만 보고 “성공!” 하면 나중에 다시 당합니다. 저는 아래 항목을 같이 확인합니다.

    • 지연(latency) 분포가 덜 튀는지
    • 테스트 중 writeback 몰림이 줄었는지
    • 애플리케이션 응답이 실제로 안정적인지
    • 마운트 옵션 변경 후 오류 로그가 없는지
    dmesg -T | tail -n 50
    journalctl -k -n 50
    findmnt -no OPTIONS /data
    ext4 성능 개선 결과를 검증하는 대시보드 이미지

    튜닝 전후의 지연 분포, 쓰기 대기열, writeback 패턴을 비교하는 성능 검증 이미지입니다.

    실제로 해보니까 단순 최고 성능보다 최악 구간이 얼마나 줄었는지가 훨씬 중요했어요. 운영 환경은 평균값보다 꼬리 지연(tail latency, 최악 구간 지연)이 문제를 만들거든요. 이 부분은 다음 글에서 XFS와 ext4를 워크로드별로 비교하면서 더 자세히 다뤄볼 예정입니다.

    정리: 제가 ext4 튜닝할 때 지키는 순서

    1. 현재 마운트 옵션과 저널 상태를 확인합니다.
    2. 디스크 병목인지, 앱의 fsync 패턴인지 먼저 분리합니다.
    3. noatime, lazytime, commit 같은 안전한 범위부터 조정합니다.
    4. 커널 dirty page 정책을 함께 봅니다.
    5. SSD라면 discard 대신 fstrim.timer 운영도 검토합니다.
    6. 반드시 재현 테스트와 커널 로그 확인으로 검증합니다.
    튜닝 대상 먼저 볼 상황 제가 보통 취하는 액션
    메타데이터 쓰기 많음 작은 파일, 잦은 읽기/쓰기 noatime, lazytime 검토
    주기적 지연 스파이크 writeback 몰림 dirty page 관련 sysctl 점검
    SSD 지속 쓰기 부담 discard 상시 사용 fstrim.timer 전환 검토
    데이터 안정성 민감 DB, 중요 서비스 공격적 journaling 변경 지양

    자주 묻는 질문

    ext4보다 다른 파일 시스템이 항상 더 빠른가요?

    항상 그렇진 않아요. 워크로드에 따라 다릅니다. ext4는 여전히 범용성과 안정성 면에서 아주 강한 선택지입니다.

    모든 서버에 noatime을 넣어도 되나요?

    대부분 문제 없지만, atime 의존 프로그램이 아예 없는지 확인은 필요합니다. 운영 표준으로 넣기 전에는 테스트 서버에서 먼저 검증하세요.

    커널 튜닝 ext4는 어느 정도까지 해야 하나요?

    제 기준은 간단해요. 관찰 가능한 병목이 있을 때만, 그리고 되돌릴 수 있는 범위부터입니다. 근거 없는 튜닝은 그냥 리스크죠.

    커널 튜닝 ext4 적용 전후를 요약한 비교 인포그래픽

    운영 반영 전 점검 항목과 튜닝 우선순위를 한 장으로 정리한 요약 이미지입니다.

    마무리

    커널 튜닝 ext4는 화려한 작업은 아닙니다. 그런데 운영 서버에서 한 번 병목이 터졌을 때 가장 현실적으로 효과를 보는 지점이기도 합니다. 제가 직접 해보니 핵심은 “옵션 많이 넣기”가 아니라 “현재 쓰기 패턴을 이해하고, 안전한 범위부터 검증하는 것”이었어요. 드디어 됐다 싶을 때도 로그와 지연 분포를 꼭 다시 보셔야 합니다. 진짜 편하더라고요.

    이번 글에서는 ext4 기준으로 정리했지만, 다음 글에서는 Linux 성능 최적화 관점에서 XFS와 ext4를 어떤 워크로드에서 나눠서 볼지 이어서 다뤄보겠습니다. 이전 글에서 다룬 I/O 스케줄링과 블록 디바이스 점검 내용도 함께 보시면 흐름이 더 잘 잡히실 겁니다. 혹시 지금 운영 중인 서버에서 파일 시스템 튜닝을 고민하고 계시다면, 먼저 현재 마운트 옵션과 iostat 출력부터 확인해보세요. 거기서 절반은 이미 답이 보입니다.

  • [Linux] openSUSE 비교: Leap 15 vs Tumbleweed 1년 운영 후기

    [Linux] openSUSE 비교: Leap 15 vs Tumbleweed 1년 운영 후기

    [Linux] openSUSE 비교: Leap 15 vs Tumbleweed 1년 운영 후기

    홈랩을 오래 굴리다 보면 결국 한 번쯤은 openSUSE 비교를 진지하게 하게 됩니다. 저도 처음엔 “Leap으로 갈까, Tumbleweed로 갈까” 이 고민을 꽤 오래 했거든요. 특히 서버처럼 오래 켜두는 장비와, 이것저것 빨리 테스트해야 하는 실험용 장비를 같이 운영하면 더 헷갈립니다. 실제로 써보니까 둘 다 좋은데, 좋은 방향이 다르더라고요. 그래서 이번 글은 제목상 openSUSE Leap vs Tumbleweed 비교를 다루되, 특정 마이너 버전 숫자에 매달리기보다 Leap 15 계열의 안정성(stable release)과 Tumbleweed의 롤링 릴리스(rolling release) 성격 차이를 1년 사용 관점으로 풀어보겠습니다.

    여기서 중요한 포인트가 하나 있어요. 배포판 비교는 벤치마크 숫자 몇 개로 끝나는 일이 아니더라고요. 업데이트 습관, 드라이버 민감도, 커널(Kernel, 운영체제 핵심 구성요소) 변화에 대한 내성, 그리고 장애 났을 때 복구 난이도까지 다 같이 봐야 합니다. 저도 처음엔 최신 패키지가 무조건 좋다고 생각했었는데, 서버 쪽은 또 이야기가 다르더군요.

    openSUSE 비교를 보여주는 Leap 계열과 Tumbleweed 운영 개요 이미지

    Leap 계열의 안정성 중심 운영과 Tumbleweed의 최신 패키지 중심 운영을 비교한 개요 이미지입니다.

    openSUSE 비교: Leap과 Tumbleweed의 핵심 차이

    쉽게 말해 openSUSE Leap은 “검증된 구성으로 오래 안정적으로 가는 쪽”이고, openSUSE Tumbleweed는 “최신 커널과 최신 패키지를 계속 받아가며 빠르게 움직이는 쪽”입니다. 둘 다 같은 openSUSE 생태계 안에 있지만, 운영 철학이 꽤 다릅니다.

    • Leap 계열: 운영 서버, NAS, 장기 유지가 중요한 장비에 잘 맞습니다.
    • Tumbleweed: 개발 워크스테이션, 데스크톱, 신기능 테스트 장비에 잘 맞습니다.
    • 공통 장점: YaST(야스트, 통합 시스템 관리 도구), zypper(지퍼, 패키지 관리자), Snapper(스내퍼, 스냅샷 기반 롤백 도구) 조합이 강력합니다.

    사실 이 차이를 몸으로 느끼는 시점은 업데이트할 때입니다. Leap은 “업데이트해도 큰 그림이 흔들리지 않는다”는 인상이 있고, Tumbleweed는 “업데이트하면 바로 최신 흐름을 따라간다”는 느낌이 강합니다. 저는 서버는 심리적 안정감이 중요해서 Leap 계열이 편했고, 실험 머신은 Tumbleweed가 진짜 재밌더라고요.

    1년 운영 기준으로 본 리눅스 배포판 비교 포인트

    아래 표는 제가 실제 운영하면서 중요하게 봤던 항목들입니다. 숫자 점수로 억지 비교하는 것보다, 어떤 워크로드에 맞는지 보는 게 훨씬 현실적이었습니다.

    항목 openSUSE Leap 계열 openSUSE Tumbleweed
    업데이트 성격 보수적이고 예측 가능 지속적이고 빠름
    패키지 최신성 상대적으로 보수적 상대적으로 최신
    서버 적합성 매우 높음 운영 가능하지만 관리 습관 필요
    데스크톱 적합성 무난함 매우 좋음
    드라이버/커널 변화 대응 변화 폭이 작음 변화 폭이 큼
    문제 발생 시 체감 드물지만 보수적으로 접근 업데이트 직후 체크 필요
    추천 대상 홈서버, NAS, VM 호스트 개발용 PC, 테스트 장비, 최신 하드웨어

    혹시 이런 경험 있으신가요? 주말에 잠깐 커널만 올린다고 했다가 부트로더(Bootloader, 부팅 관리자)나 그래픽 드라이버 때문에 예상보다 일이 커지는 경우요. 저는 Tumbleweed 쪽에서 그런 긴장감을 몇 번 느꼈고, 반대로 Leap 계열은 “조용히 자기 할 일 하는 장비” 느낌이 강했습니다.

    제가 실제로 운영했던 방식: 역할을 나눠서 쓰는 게 답이었습니다

    처음엔 한 배포판으로 다 통일하려고 했습니다. 관리 포인트를 줄이고 싶었거든요. 근데 실제로 써보니까 역할 분리가 훨씬 낫더라고요.

    1. Leap 계열은 장기 가동이 필요한 홈서버에 배치했습니다.
    2. Tumbleweed는 컨테이너(Container, 격리 실행 환경) 테스트나 개발 툴 검증용 데스크톱에 올렸습니다.
    3. 두 환경 모두 zypper와 Snapper 습관을 들여서 업데이트 전후 상태를 확인했습니다.

    이 조합이 왜 좋았냐면, 장애 허용 범위가 다르기 때문입니다. 서버는 “안 멈추는 것”이 우선이고, 테스트 머신은 “빨리 변화를 받아보는 것”이 우선입니다. 같은 Linux distribution(리눅스 배포판)이라도 목적이 다르면 정답도 달라집니다.

    기본 점검 명령어

    sudo zypper refresh
    sudo zypper list-updates
    sudo zypper patches

    Leap 계열에서는 이런 식으로 패치 성격을 먼저 보는 습관이 좋았습니다. 갑자기 큰 변화를 넣기보다, 보안 업데이트와 일반 패키지 변화를 구분해서 보는 거죠.

    Tumbleweed에서 자주 쓰는 업데이트 방식

    sudo zypper refresh
    sudo zypper dup
    sudo reboot

    여기서 dup(dist-upgrade, 배포판 전체 업그레이드 방식)이 중요합니다. Tumbleweed는 rolling release라서 일반적인 up보다 dup 흐름을 이해하는 게 운영 안정성에 더 도움이 되더라고요. 저도 초반엔 이 차이를 가볍게 봤다가 패키지 정합성(package consistency) 때문에 삽질 좀 했습니다 ㅎㅎ

    openSUSE Leap과 openSUSE Tumbleweed를 관리하는 홈랩 운영 이미지

    패키지 업데이트와 시스템 관리를 진행하는 흐름을 보여주는 이미지입니다.

    실전 구현: openSUSE 비교 기반 업데이트 루틴

    제가 1년 정도 굴리면서 정착한 루틴은 단순합니다. 대단한 자동화보다, 장애를 줄이는 기본기가 더 효과 있었어요.

    1. 업데이트 전 현재 상태 확인
    2. 커널, 저장소(repository, 패키지 저장소), 서드파티 패키지 여부 점검
    3. 업데이트 실행
    4. 재부팅 후 서비스 상태 검증
    5. 이상 있으면 스냅샷 확인 및 롤백 검토

    업데이트 전 정보 확인

    uname -r
    cat /etc/os-release
    zypper lr -u

    별거 아닌 것 같죠? 근데 이거 정말 중요합니다. 특히 저장소가 섞여 있으면 문제가 생겼을 때 원인 추적이 어려워집니다. openSUSE 비교를 할 때도 결국 “기본 저장소 위주로 깔끔하게 운영했는가”가 체감 품질을 크게 좌우하더라고요.

    스냅샷 확인

    sudo snapper list
    sudo snapper status

    Snapper는 openSUSE의 숨은 강점입니다. 물론 파일시스템 구성과 설치 옵션에 따라 체감은 다를 수 있습니다. 그래도 업데이트 전후 상태를 눈으로 비교할 수 있다는 것만으로도 심리적 압박이 많이 줄어요. 드디어 됐다! 싶은 순간이 이런 데서 옵니다.

    서비스 상태 검증

    systemctl --failed
    systemctl status nginx
    systemctl status docker

    서버라면 여기가 핵심입니다. 패키지 업데이트가 끝났다고 끝이 아니거든요. 실제 서비스가 살아 있는지 확인해야 합니다. 저는 예전에 웹 서비스는 떠 있는데 리버스 프록시(reverse proxy, 앞단 중계 서버) 설정이 꼬여서 외부 접근이 안 됐던 적이 있었습니다. 그 뒤로는 꼭 서비스 단위로 확인합니다.

    openSUSE 비교에서 업데이트 검증과 스냅샷 점검을 표현한 이미지

    업데이트 이후 스냅샷과 서비스 상태를 점검하는 검증 과정을 시각화한 이미지입니다.

    ⚠️ 실제로 겪었던 문제와 해결법

    이 섹션은 조금 현실적으로 가보겠습니다. 배포판 비교 글은 장점만 쓰면 재미도 없고, 실제 도움도 덜 되거든요.

    1. Tumbleweed에서 업데이트 직후 예상치 못한 변화

    최신 패키지가 빨리 들어오는 건 장점이지만, 그만큼 변화량이 큽니다. 데스크톱 환경이나 드라이버 쪽은 생각보다 민감할 때가 있어요. 특히 실험 머신에서 그래픽 스택(graphics stack, 그래픽 관련 구성 요소) 변화가 들어오면 체감이 큽니다.

    • 증상: 업데이트 후 일부 툴 동작 변화, 드라이버 재인식, 설정 재점검 필요
    • 대응: 무작정 매일 업데이트하지 않고, 작업 없는 시간대에 반영
    • 팁: 커널과 핵심 라이브러리 변경이 보이면 재부팅 계획까지 같이 잡기

    2. Leap 계열은 조용하지만, 저장소 혼합은 조심

    Leap은 안정적이라 방심하기 쉽습니다. 근데 외부 저장소를 섞기 시작하면 얘기가 달라집니다. 저도 한 번은 편의상 패키지를 여기저기서 가져왔다가 의존성(dependency, 패키지 간 요구 관계) 정리가 꼬였던 적이 있습니다.

    • 증상: 패키지 충돌, 예상 밖 버전 선택
    • 대응: 기본 저장소 우선, 외부 저장소는 목적 명확할 때만 사용
    • 팁: 문제 생기면 먼저 저장소 목록부터 확인

    3. 둘 다 공통으로 중요한 건 롤백 시나리오

    문제가 생겼을 때 가장 위험한 건 당황해서 이것저것 더 건드리는 겁니다. 저도 처음엔 로그를 보기 전에 패키지를 다시 깔아버리는 실수를 했었는데, 오히려 원인 파악이 더 어려워지더라고요.

    journalctl -b
    sudo snapper list
    sudo zypper verify

    journalctl(저널ctl, 시스템 로그 조회)부터 보고, 그다음 스냅샷과 패키지 상태를 보는 순서가 훨씬 낫습니다. 침착하게 가야 합니다.

    검증 결과: 어떤 사용자에게 뭐가 더 맞았나

    1년 정도 운영하면서 결론은 꽤 선명했습니다. openSUSE 비교 관점에서 보면, Leap 계열은 “운영 안정성”에 점수를 주고 싶고, Tumbleweed는 “변화 대응력과 최신성”에 점수를 주고 싶습니다. 절대 우위라기보다 목적 적합성 차이입니다.

    사용 시나리오 추천 이유
    홈서버, NAS, 항상 켜두는 장비 Leap 계열 업데이트 예측 가능성이 높고 운영이 편함
    개발 워크스테이션 Tumbleweed 최신 툴체인(toolchain, 개발 도구 묶음) 반영이 빠름
    리눅스 학습용 메인 PC Tumbleweed 또는 Leap 최신성 우선이면 Tumbleweed, 안정성 우선이면 Leap
    가족이 같이 쓰는 안정성 우선 PC Leap 계열 예상치 못한 변화가 적은 편

    제가 직접 해보니, openSUSE Leap은 “믿고 맡기는 운영체제” 느낌이었고, openSUSE Tumbleweed는 “변화를 빨리 경험하게 해주는 플랫폼” 느낌이었습니다. 둘 다 잘 만든 배포판인데, 사용자의 성향과 운영 방식이 선택을 갈라놓습니다.

    openSUSE 비교 결과를 보여주는 Leap 계열과 Tumbleweed 사용 시나리오 이미지

    서버 안정성과 데스크톱 최신성을 각각 보여주는 결과 비교 이미지입니다.

    정리: 이런 분이라면 이렇게 고르시면 됩니다

    • 안정성이 최우선이라면 Leap 계열이 편합니다.
    • 최신 커널과 패키지가 중요하면 Tumbleweed가 만족도가 높습니다.
    • 하나로 통일하려고 애쓰기보다, 역할별 분리가 실전에서는 더 효율적입니다.
    • Snapper와 zypper 습관을 들이면 두 배포판 모두 훨씬 편해집니다.

    개인적으로는 서버는 Leap 계열, 실험용 데스크톱은 Tumbleweed 조합을 계속 유지할 생각입니다. 이 구성이 운영 피로도가 제일 낮았거든요. 혹시 지금 리눅스 배포판 비교를 두고 고민 중이시라면, 내 장비가 “안정성 중심인지”, 아니면 “최신성 중심인지”부터 정리해보시면 선택이 훨씬 쉬워집니다.

    그리고 이전 글에서 다뤘던 홈랩 백업 전략이나, 다음 글에서 다룰 예정인 Btrfs(비트알에프에스, 스냅샷 지원 파일시스템) 운영 팁과 같이 보시면 더 연결이 잘 되실 겁니다. openSUSE는 한 번 감 잡으면 진짜 편하더라고요.

    FAQ: 자주 받는 질문

    Q1. 처음 입문이면 openSUSE Leap과 Tumbleweed 중 뭐가 더 쉬운가요?

    처음이면 보통 Leap 계열이 덜 부담스럽습니다. 변화량이 상대적으로 적어서 문제를 좁혀 보기 쉽거든요.

    Q2. Tumbleweed를 서버에 쓰면 안 되나요?

    못 쓰는 건 아닙니다. 다만 업데이트 관리와 검증 루틴이 더 중요해집니다. 운영 철학이 맞아야 합니다.

    Q3. openSUSE 비교에서 정말 중요한 한 가지는 뭔가요?

    업데이트 후 장애를 내가 얼마나 감당할 수 있는가입니다. 이 질문에 답이 나오면 선택도 거의 끝납니다.

    openSUSE 비교 선택 기준을 정리한 Leap 계열과 Tumbleweed 요약 이미지

    어떤 사용자에게 어떤 배포판이 더 맞는지 요약한 선택 가이드 이미지입니다.

  • [Linux 보안] SELinux vs AppArmor: 선택 가이드와 실전 비교

    [Linux 보안] SELinux vs AppArmor: 선택 가이드와 실전 비교

    [Linux 보안] SELinux vs AppArmor: 선택 가이드와 실전 비교

    리눅스 서버를 운영하다 보면 결국 한 번은 붙잡게 되는 주제가 있습니다. 바로 SELinux AppArmor 비교입니다. 방화벽만 잘 열고 닫는다고 끝나는 게 아니더라고요. 실제 운영 환경에서는 프로세스가 어디까지 접근할 수 있는지, 침해 사고가 났을 때 피해 범위를 얼마나 좁힐 수 있는지가 정말 중요합니다. 저도 홈랩에서 웹 서버, 컨테이너, 파일 공유 서비스를 이것저것 올려보면서 Linux 보안을 강화하려다가 SELinux(Security-Enhanced Linux)와 AppArmor(Application Armor)를 번갈아 만져봤습니다. 처음엔 둘 다 비슷해 보였는데, 직접 써보니까 운영 철학부터 관리 포인트까지 꽤 다르더라고요.

    혹시 이런 경험 있으신가요? 서비스는 분명 정상인데 권한 거부 때문에 접속이 안 되고, 로그를 보면 더 헷갈리는 상황 말입니다. 저도 처음엔 이게 뭔가 싶었는데, 기준만 잡고 보면 선택이 꽤 쉬워집니다. 이번 글에서는 SELinux vs AppArmor를 비교하면서, 어떤 환경에서 무엇을 선택하면 좋은지 경험 기준으로 풀어보겠습니다.

    SELinux AppArmor 비교를 보여주는 리눅스 보안 개요 다이어그램

    SELinux와 AppArmor가 커널 보안 계층에서 어떻게 동작하는지 보여주는 개요 이미지입니다.

    1. 왜 SELinux와 AppArmor가 중요한가

    쉽게 말해 둘 다 MAC(Mandatory Access Control, 강제 접근 통제) 계열입니다. 일반적인 파일 권한처럼 사용자가 알아서 결정하는 DAC(Discretionary Access Control, 임의 접근 통제)보다 훨씬 강하게 제어하는 방식이거든요. 프로세스가 root 권한을 가졌다고 해도, 보안 정책이 막고 있으면 파일을 읽거나 네트워크 동작을 하지 못하게 되는 겁니다.

    이게 왜 중요하냐면, 서비스 하나가 뚫렸을 때 전체 서버로 번지는 걸 줄여주기 때문이에요. 예를 들어 웹 서버 프로세스가 취약점으로 악용되더라도, 원래 접근하면 안 되는 디렉터리나 소켓을 막아두면 피해 확산을 줄일 수 있습니다. 제가 홈랩에서 리버스 프록시, 파일 서버, 테스트용 앱을 굴릴 때도 결국 마지막 안전장치 역할은 이런 보안 정책이 하더라고요. 평소엔 귀찮아 보여도, 문제 생기면 존재감이 정말 확실합니다.

    2. SELinux와 AppArmor 개념 설명

    2-1. SELinux는 라벨 기반입니다

    SELinux는 객체와 프로세스에 보안 컨텍스트(context, 보안 문맥) 라벨을 붙여서 제어합니다. 파일, 포트, 프로세스가 각각 어떤 타입인지 보고 허용 여부를 판단하는 방식이죠. 처음엔 정말 어렵습니다. 저도 파일 권한만 보다가 갑자기 컨텍스트를 보라니까 삽질 좀 했어요. 그런데 익숙해지면 정책이 꽤 정교하고 체계적이더라고요.

    • 파일과 디렉터리에 보안 라벨을 부여합니다.
    • 프로세스도 특정 도메인(domain, 실행 문맥)으로 실행됩니다.
    • 정책이 세밀해서 대규모 운영 환경에 잘 맞는 편입니다.

    2-2. AppArmor는 경로 기반입니다

    AppArmor는 파일 경로(path, 경로)를 기준으로 제어합니다. 그래서 사람이 읽고 이해하기가 상대적으로 훨씬 쉽습니다. 특정 실행 파일이 어느 경로를 읽고 쓸 수 있는지 프로파일(profile, 정책 파일)로 정의하는 방식이거든요. Ubuntu 계열에서 처음 보안 강화 기능을 접할 때 부담이 덜한 이유가 바로 여기에 있습니다.

    • 실행 파일별 프로파일을 적용합니다.
    • 경로 기반이라 정책을 읽기 쉽습니다.
    • 처음 도입할 때 학습 곡선이 비교적 완만합니다.

    3. SELinux와 AppArmor 비교: 무엇이 다른가

    여기서 중요한 포인트! SELinux AppArmor 비교를 할 때 단순히 “누가 더 강한가”로 보면 답이 잘 안 나옵니다. 실제로는 운영 방식에 맞는지가 훨씬 더 중요하거든요.

    항목 SELinux AppArmor
    정책 기준 라벨 기반 경로 기반
    학습 난이도 상대적으로 높음 상대적으로 낮음
    정책 세밀도 매우 세밀함 직관적이고 단순한 편
    대표 사용 환경 RHEL 계열에서 자주 사용 Ubuntu 계열에서 자주 사용
    초기 운영 체감 로그 분석이 중요 프로파일 관리가 중요
    적합한 상황 엄격한 통제, 장기 운영 빠른 도입, 단순한 서비스 보호

    제 경험상 정리하면 이렇습니다.

    • SELinux: 처음엔 어렵지만, 표준화된 운영과 세밀한 정책이 필요한 환경에서 정말 강합니다.
    • AppArmor: 빠르게 적용하고 이해하기 쉬워서 소규모 서비스나 초기 구축에 부담이 훨씬 적습니다.
    • 보안 강도만 볼 게 아니라, 팀이 정책을 유지할 수 있는지가 더 중요한 선택 기준이 됩니다.

    4. 실전 구현: SELinux 기본 확인과 적용

    이제 실전으로 가보겠습니다. 제가 직접 해보니 무조건 정책부터 건드리기보다, 현재 상태를 먼저 보는 게 훨씬 낫습니다. SELinux는 특히 더 그렇습니다. 상태 확인 없이 파일만 만지면 나중에 왜 막혔는지 추적이 훨씬 어려워지거든요.

    1. SELinux 상태를 확인합니다.
    2. 서비스 파일 컨텍스트를 점검합니다.
    3. 필요하면 적절한 컨텍스트를 다시 지정합니다.
    4. 로그를 보고 실제 차단 원인을 확인합니다.
    getenforce
    seststatus
    ls -Z /var/www
    ps -eZ | grep httpd

    getenforce는 현재 모드를 빠르게 보여줍니다. Enforcing이면 정책이 실제로 강제 적용 중이고, Permissive면 차단 대신 로그만 남깁니다. 처음 테스트할 땐 Permissive 모드에서 원인부터 보는 게 훨씬 편하더라고요.

    sudo semanage fcontext -a -t httpd_sys_content_t "/srv/myweb(/.*)?"  
    sudo restorecon -Rv /srv/myweb

    이 명령은 웹 서버 콘텐츠 디렉터리에 적절한 타입을 지정하는 예시입니다. 여기서 정말 중요한 건 chmod로 해결하려고 하지 말고 컨텍스트를 봐야 한다는 점이에요. 저도 예전에 권한은 맞는데 계속 403이 떠서 한참 헤맸는데, 알고 보니 파일 라벨이 안 맞았던 경우가 정말 많았거든요.

    sudo ausearch -m avc -ts recent
    sudo journalctl -t setroubleshoot --since today

    SELinux는 로그를 보는 습관이 정말 핵심입니다. 거부 로그를 보면 무엇이 막혔는지 힌트를 얻을 수 있어요. 드디어 됐다! 하는 순간이 대부분 여기서 옵니다.

    SELinux AppArmor 비교 글의 SELinux 컨텍스트 적용 흐름 이미지

    SELinux에서 컨텍스트를 확인하고 복구하는 흐름을 단계별로 보여주는 이미지입니다.

    5. 실전 구현: AppArmor 기본 확인과 프로파일 적용

    AppArmor는 상대적으로 진입 장벽이 훨씬 낮습니다. 실제로 써보니까 정책 파일이 사람이 읽기 쉬워서, 빠르게 감을 잡기 정말 좋더라고요. 특히 단일 서비스 보호 용도로는 꽤 편했습니다.

    1. AppArmor가 활성화되어 있는지 확인합니다.
    2. 현재 로드된 프로파일과 적용 상태를 봅니다.
    3. 필요한 프로파일을 enforce 모드로 전환합니다.
    4. 로그를 보고 누락된 권한을 보완합니다.
    sudo aa-status
    sudo apparmor_status

    배포판에 따라 둘 중 하나를 쓰게 되는 경우가 있습니다. 출력에서 어떤 프로파일이 enforce 모드인지, complain 모드인지 확인하면 됩니다. complain은 차단 대신 기록만 남기는 모드라서 테스트할 때 정말 유용해요.

    sudo aa-complain /etc/apparmor.d/usr.sbin.nginx
    sudo aa-enforce /etc/apparmor.d/usr.sbin.nginx

    AppArmor는 이렇게 프로파일 단위로 전환하는 방식이 직관적입니다. 경로 기반이라 “이 서비스가 이 디렉터리를 왜 못 읽지?”를 추적할 때 상대적으로 수월했어요. 다만 경로 변경이 잦은 환경에서는 프로파일 관리가 생각보다 귀찮을 수 있습니다.

    sudo journalctl -k | grep DENIED
    sudo dmesg | grep apparmor

    차단 로그도 꼭 봐야 합니다. AppArmor는 쉬워 보이지만, 결국 로그를 안 보면 감으로 수정하게 되거든요. 그럼 나중에 정책이 지저분해져서 관리가 힘들어집니다.

    6. 어떤 환경에서 무엇을 선택할까

    SELinux AppArmor 비교의 결론은 기술 우열보다 운영 적합성에 있습니다. 제가 홈랩과 실무성 테스트 환경에서 느낀 기준을 정리해보면 이렇습니다.

    • SELinux를 권하고 싶은 경우: RHEL 계열을 쓰고 있고, 정책 일관성과 세밀한 제어가 중요할 때
    • AppArmor를 권하고 싶은 경우: Ubuntu 계열을 쓰고 있고, 빠르게 프로파일을 읽고 조정해야 할 때
    • 팀 운영 관점: 로그 분석과 정책 유지에 익숙한 팀이면 SELinux도 충분히 잘 굴릴 수 있습니다.
    • 개인 홈랩 관점: 처음 시작할 땐 AppArmor가 덜 부담스러울 수 있어요.

    사실 제가 직접 써봤을 때 느낀 체감은 이랬습니다. SELinux는 한 번 체계가 잡히면 든든하고, AppArmor는 처음 붙을 때 편하다는 거죠. 둘 다 좋은 도구인데, 도구보다 운영자의 숙련도가 더 크게 작용하더라고요.

    SELinux AppArmor 비교 선택 가이드를 위한 의사결정 이미지

    배포판, 운영 인력, 정책 복잡도에 따라 어떤 선택이 맞는지 보여주는 결정 흐름도입니다.

    7. ⚠️ 주의사항과 트러블슈팅

    이 섹션은 정말 중요합니다. 저도 처음엔 보안 기능을 꺼버리고 끝내고 싶었던 순간이 정말 많았거든요. 근데 그 습관 들이면 나중에 훨씬 더 힘들어집니다.

    7-1. 서비스가 안 되면 바로 비활성화하지 마세요

    가장 흔한 실수가 “일단 꺼서 되게 만들자”라는 생각입니다. 테스트 중 잠깐 상태를 완화하는 건 가능하지만, 영구 비활성화는 정말 신중해야 합니다. 문제 원인을 안 보고 끄면 이후에 보안 사고 대응력이 확 떨어지거든요.

    7-2. 파일 권한과 보안 정책을 혼동하지 마세요

    SELinux에서는 파일 권한이 맞아도 컨텍스트가 틀리면 접근이 막힙니다. AppArmor에서는 프로세스가 파일 경로 접근 권한을 갖고 있는지 별도로 봐야 합니다. 즉, chmod와 chown만으로는 완벽하게 해결되는 게 아닙니다.

    7-3. 로그 없는 수정은 거의 실패합니다

    • SELinux: AVC 거부 로그 확인
    • AppArmor: DENIED 로그 확인
    • 정책 변경 전후로 무엇이 달라졌는지 기록

    제가 실무 비슷한 환경에서 자주 하는 방식은 간단합니다. 먼저 로그를 보고, 그다음 가장 좁은 범위로 수정합니다. 한 번에 크게 열어버리면 편하긴 한데, 나중에 왜 열었는지 기억이 안 나더라고요.

    8. 검증과 결과 확인

    설정을 끝냈다면 반드시 검증해야 합니다. 적용했다고 믿는 것과 실제로 동작하는 건 정말 다르거든요. 여기서 확인할 건 세 가지입니다.

    1. 서비스가 정상 동작하는지 확인합니다.
    2. 보안 정책이 실제로 enforce 중인지 확인합니다.
    3. 거부 로그가 불필요하게 반복되지 않는지 봅니다.
    curl -I http://localhost
    getenforce
    sudo aa-status
    sudo journalctl -k --since "10 minutes ago"

    정상 응답이 오고, 보안 모드가 의도한 상태이며, 로그에 반복적인 거부가 없다면 1차 검증은 통과입니다. ✅ 여기까지 오면 운영 가능한 상태에 꽤 가까워진 겁니다. 저도 이 단계까지 정리해두면 이후 서비스 추가가 훨씬 수월했어요.

    SELinux AppArmor 비교 적용 후 검증 결과를 보여주는 대시보드 이미지

    서비스 정상 응답, 정책 적용 상태, 로그 감소 여부를 한눈에 확인하는 결과 이미지입니다.

    9. 정리와 FAQ

    SELinux vs AppArmor를 한 줄로 요약하면 이렇습니다. 세밀한 통제와 표준 운영이면 SELinux, 빠른 이해와 간결한 관리면 AppArmor를 선택하는 게 맞습니다. 물론 현실에선 배포판 기본값과 팀 경험이 선택에 큰 영향을 줍니다. 그래서 제 추천은 무조건 하나를 고집하기보다, 현재 운영 체계와 문제 해결 방식에 맞추는 거예요.

    다음 단계로는 컨테이너 환경에서의 보안 프로파일, systemd 서비스 하드닝, seccomp(시스템 콜 필터링) 같은 주제까지 이어가면 좋습니다. 이 부분은 다음 글에서 다룰 예정입니다. 이전 글에서 다뤘던 리눅스 권한 구조와 함께 보시면 흐름이 더 잘 잡히실 거예요.

    자주 묻는 질문

    • Q. 둘 중 하나만 꼭 써야 하나요?
      A. 보통은 배포판과 운영 표준에 맞춰 하나를 중심으로 관리하는 편이 현실적입니다.
    • Q. 초보자에게는 뭐가 더 쉬운가요?
      A. 대체로 AppArmor가 더 직관적입니다. 다만 장기 운영 기준에선 SELinux를 배워둘 가치가 정말 큽니다.
    • Q. 보안 기능이 성능을 크게 떨어뜨리나요?
      A. 일반적인 서버 운영에서 체감보다 정책 정확성이 더 큰 이슈인 경우가 많았습니다.
    SELinux AppArmor 비교 장단점을 정리한 인포그래픽

    선택 기준, 장단점, 추천 시나리오를 한 장으로 정리한 요약 인포그래픽입니다.

    마지막으로, SELinux AppArmor 비교를 하다 보면 자꾸 정답 하나를 찾게 되는데요. 실제로 써보니까 정답은 환경마다 달랐습니다. 중요한 건 꺼두는 게 아니라 이해하고 운영하는 거예요. 처음엔 헷갈려도, 로그를 읽고 정책을 조금씩 줄여가다 보면 감이 옵니다. 그 과정이 조금 번거롭긴 해도, 서버를 오래 안정적으로 굴리려면 결국 한 번은 넘어야 할 산이더라고요. 이거 정말 중요합니다.

  • [Linux] journald 로그 관리: systemd 실전 트러블슈팅 5가지

    [Linux] journald 로그 관리: systemd 실전 트러블슈팅 5가지

    [Linux] journald 로그 관리: systemd 실전 트러블슈팅 5가지

    서버 장애는 꼭 바쁜 시간에 터지더라고요. 특히 journald 로그 관리가 제대로 안 되어 있으면, 분명 에러는 났는데 로그가 어디 갔는지부터 찾게 됩니다. 저도 홈랩에서 Rocky Linux, Ubuntu 계열 서버를 굴리면서 처음엔 /var/log만 뒤지다가 시간을 꽤 날렸습니다. 근데 systemd 기반 배포판에서는 journalctl 하나만 제대로 익혀도 장애 대응 속도가 확 달라지거든요. 이번 글에서는 제가 실제로 자주 쓰는 Linux 트러블슈팅 방식 기준으로, 운영 중 바로 써먹을 수 있는 로그 분석 팁 5가지를 정리해보겠습니다.

    journald 로그 관리 개요와 systemd 로그 수집 구조 이미지

    systemd와 journald가 서비스 로그를 수집하고 조회하는 전체 흐름을 보여주는 개요 이미지입니다.

    1. journald가 중요한 이유: 파일 로그만 보던 습관에서 벗어나야 합니다

    쉽게 말해 journald는 systemd 환경에서 로그를 모아두는 중앙 저장소 역할을 합니다. 전통적인 텍스트 로그 파일처럼 보이는 방식과는 조금 다르죠. 서비스별 로그, 부팅 세션별 로그, 우선순위(priority), 커널 메시지까지 한 번에 엮어서 볼 수 있다는 게 핵심입니다.

    처음엔 이게 뭔가 싶었는데, 실제로 써보니까 특정 서비스가 언제 죽었는지, 재시작되기 직전에 어떤 에러가 있었는지 추적하기가 훨씬 편했습니다. 특히 컨테이너 호스트나 작은 홈서버처럼 서비스 수가 늘어나는 환경에서는 로그가 여기저기 흩어져 있으면 진짜 피곤하거든요.

    • journalctl: journald 로그 조회 도구
    • persistent logging(영구 저장): 재부팅 후에도 로그 유지
    • priority(우선순위): error, warning 같은 중요도 기준 필터링
    • boot scope(부팅 범위): 특정 부팅 시점 로그만 추적

    2. 기본 개념 먼저: journalctl은 어떻게 봐야 덜 헷갈릴까

    저도 처음엔 journalctl 치고 로그가 너무 많이 나와서 바로 닫았습니다. 그래서 저는 아래 순서로 익히는 걸 추천합니다.

    1. 전체 로그보다 서비스 단위로 보기
    2. 시간 범위를 자르기
    3. 우선순위를 걸어서 에러만 보기
    4. 부팅 단위로 사고 시점을 좁히기

    가장 먼저 익혀둘 명령은 이 정도입니다.

    # 전체 로그 최근 부분 보기
    journalctl -e
    
    # 특정 서비스 로그 보기
    journalctl -u nginx.service
    
    # 최근 부팅 기준 로그 보기
    journalctl -b
    
    # 에러 레벨만 보기
    journalctl -p err
    
    # 실시간 추적
    journalctl -f

    여기서 중요한 포인트! -u, -b, -p, --since만 익혀도 현장에서 체감이 큽니다. 쓸데없이 로그 바다에 빠지지 않게 해주거든요.

    3. 실전 트러블슈팅 1: 로그가 너무 많아서 원인을 못 찾을 때

    이건 정말 흔합니다. 로그는 있는데 너무 많아요. 특히 장시간 운영한 서버에서 전체 로그를 그냥 열면 필요한 줄 찾다가 집중력이 먼저 떨어집니다. 제가 직접 해보니 이럴 땐 시간 범위 + 서비스명 + 우선순위를 같이 거는 게 제일 효율적이었습니다.

    3-1. 시간 범위로 자르기

    journalctl --since "2026-07-15 09:00:00" --until "2026-07-15 10:00:00"
    
    journalctl --since "30 min ago"
    
    journalctl --since today

    장애가 9시 20분쯤 났다는 제보가 있으면, 굳이 하루치 전체를 볼 필요가 없죠. 이 범위를 먼저 줄이는 것만으로도 노이즈가 꽤 사라집니다.

    3-2. 서비스 단위로 좁히기

    journalctl -u docker.service --since "30 min ago"
    journalctl -u ssh.service -e
    journalctl -u NetworkManager.service -b

    예를 들어 SSH 접속 장애면 ssh.service, 컨테이너 이슈면 docker.service부터 보시면 됩니다. 서비스 이름이 헷갈릴 때는 아래처럼 확인해두면 편합니다.

    systemctl list-units --type=service
    systemctl status nginx.service

    3-3. 에러 우선순위만 보기

    journalctl -p warning
    journalctl -p err
    journalctl -p crit..alert

    저는 급할 때 journalctl -p err -b부터 봅니다. 큰 줄기부터 잡고, 그다음 상세 로그로 내려가는 방식이 훨씬 빠르더라고요.

    journald 로그 관리에서 시간 범위와 서비스 필터를 적용하는 로그 분석 이미지

    시간 범위, 서비스, 우선순위 필터를 조합해 로그를 줄여나가는 과정을 보여주는 이미지입니다.

    4. 실전 트러블슈팅 2: 재부팅 후 로그가 사라지는 문제

    처음 홈랩을 꾸렸을 때 이걸로 꽤 삽질했습니다. 분명 어젯밤에 장애가 있었는데, 아침에 다시 보니 로그가 안 남아 있는 거예요. 이유는 간단했습니다. persistent logging(영구 저장)이 꺼져 있었던 겁니다.

    4-1. 현재 저장소 상태 확인

    journalctl --disk-usage
    ls -ld /var/log/journal

    /var/log/journal 디렉터리가 없으면 메모리 기반 저장만 되는 경우가 있습니다. 배포판 설정에 따라 동작이 다를 수 있어서, 실제 상태를 먼저 확인하는 게 안전합니다.

    4-2. 영구 저장 활성화

    sudo mkdir -p /var/log/journal
    sudo systemd-tmpfiles --create --prefix /var/log/journal
    sudo systemctl restart systemd-journald

    환경에 따라 /etc/systemd/journald.conf에서 저장 정책을 명시하는 게 더 깔끔할 때도 있습니다.

    sudo editor /etc/systemd/journald.conf
    [Journal]
    Storage=persistent
    SystemMaxUse=1G
    RuntimeMaxUse=200M
    MaxRetentionSec=1month

    설정 후에는 데몬을 다시 읽혀줍니다.

    sudo systemctl restart systemd-journald
    journalctl -b -1

    -b -1이 보이면 이전 부팅 로그까지 남고 있다는 뜻입니다. 드디어 됐다! 싶은 순간이 여기서 나오죠.

    5. 실전 트러블슈팅 3: 디스크가 차오르는 원인이 journald일 때

    로그는 남겨야 하지만, 무한정 쌓아두면 결국 디스크를 압박합니다. 특히 작은 SSD나 VM 디스크에서는 이게 꽤 치명적이거든요. journald 로그 관리에서 운영자가 가장 먼저 챙겨야 할 부분 중 하나가 용량 정책입니다.

    5-1. 현재 사용량 확인

    journalctl --disk-usage

    5-2. 즉시 정리하기

    # 7일보다 오래된 로그 삭제
    sudo journalctl --vacuum-time=7d
    
    # 총 사용량을 500M 이하로 줄이기
    sudo journalctl --vacuum-size=500M
    
    # 파일 개수 기준 정리
    sudo journalctl --vacuum-files=10

    운영 중 급하게 용량을 비워야 할 때 정말 유용합니다. 다만 무작정 지우기 전에 꼭 필요한 장애 분석이 끝났는지는 확인하셔야 합니다.

    5-3. 아예 정책으로 제한하기

    [Journal]
    SystemMaxUse=1G
    SystemKeepFree=500M
    SystemMaxFileSize=100M
    MaxRetentionSec=1month

    저는 홈랩에서는 과하게 크게 잡지 않습니다. 분석 가능한 기간은 유지하되, 디스크 여유 공간도 남겨야 하니까요. 여기서 중요한 건 숫자 자체보다 정책을 명시해두는 습관입니다.

    옵션 의미 언제 유용한가
    SystemMaxUse journal 전체 최대 사용량 디스크 점유 상한을 명확히 두고 싶을 때
    SystemKeepFree 남겨둘 최소 여유 공간 서비스 디스크 고갈을 예방할 때
    MaxRetentionSec 로그 보관 기간 기간 기준으로 운영 정책을 맞출 때
    –vacuum-size 즉시 용량 기준 정리 긴급 대응 시
    journald 로그 관리의 디스크 사용량 점검과 정리 전후 비교 이미지

    journald 로그 용량을 확인하고 정리하기 전후 차이를 보여주는 시각 자료입니다.

    6. 실전 트러블슈팅 4: 서비스는 죽었는데 원인이 안 보일 때

    이럴 때는 서비스 상태만 보지 말고, 이전 부팅 기록과 실시간 추적을 같이 봐야 합니다. 특히 재시작이 반복되는 서비스는 순간적으로 죽었다 살아나서 놓치기 쉽습니다.

    6-1. 특정 부팅 세션 기준으로 보기

    journalctl --list-boots
    journalctl -b -1
    journalctl -b -2 -u nginx.service

    배포 후 재부팅이 있었는지, 장애가 이전 부팅부터 이어진 건지 확인할 때 굉장히 유용합니다. 저도 커널 업데이트 이후 네트워크 서비스가 꼬인 적이 있었는데, 부팅별로 나눠보니 원인이 바로 보이더라고요.

    6-2. 서비스 실시간 추적

    journalctl -u myapp.service -f

    애플리케이션 재시작 테스트를 하면서 한쪽 터미널에서는 이 명령을 띄워두면 편합니다. 장애 재현과 동시에 로그를 보게 되니까, 놓치는 줄이 확 줄어듭니다.

    6-3. 상세 상태 확인과 묶어서 보기

    systemctl status myapp.service
    journalctl -u myapp.service -n 100 -o short-iso

    systemctl status는 현재 상태 요약, journalctl은 상세 로그 본문이라고 생각하시면 이해가 쉽습니다.

    7. 실전 트러블슈팅 5: 로그 형식이 불편하거나 파이프라인 연동이 필요할 때

    운영하다 보면 사람 눈으로만 보는 로그보다, 다른 도구로 넘기기 좋은 형식이 필요할 때가 있습니다. 예를 들어 자동화 스크립트, 간단한 grep 처리, 또는 JSON 수집 파이프라인 같은 경우죠.

    7-1. 출력 형식 바꾸기

    journalctl -u nginx.service -o short-iso
    journalctl -u nginx.service -o json
    journalctl -u nginx.service -o cat

    개인적으로 사람 눈으로 볼 땐 short-iso를 자주 씁니다. 타임스탬프가 읽기 편해서요. 반면 후처리나 수집 연계가 필요하면 json 출력이 꽤 쓸만합니다.

    7-2. 최근 로그 일부만 빠르게 확인

    journalctl -u nginx.service -n 50
    journalctl -k -n 100

    -k는 커널 로그를 보는 옵션입니다. 디스크 I/O나 네트워크 드라이버 문제처럼 시스템 하단 이슈를 의심할 때 먼저 보는 편입니다.

    7-3. grep과 함께 써서 빠르게 패턴 찾기

    journalctl -u docker.service --since "1 hour ago" | grep -i error
    journalctl -b | grep -Ei "timeout|failed|denied"

    엄밀히 말하면 structured log(구조화 로그)의 장점을 다 살리는 방식은 아니지만, 현장에선 이렇게 빠르게 감 잡는 경우도 많습니다. 급할 때는 일단 보이는 게 중요하거든요.

    journald 로그 관리에서 서비스 로그 실시간 추적과 구조화 출력 예시 이미지

    서비스 로그를 실시간으로 추적하고 다양한 출력 형식으로 확인하는 예시 이미지입니다.

    8. 운영 중 자주 겪는 주의사항: 제가 삽질했던 포인트들

    여기부터는 진짜 실무형 메모입니다. 문서만 보면 안 보이는데, 실제로는 아래 포인트에서 많이 막히더라고요.

    • ⚠️ 권한 문제: 일반 사용자로는 일부 시스템 로그가 제한될 수 있습니다. 안 보이면 sudo로 다시 확인해보세요.
    • ⚠️ 로그가 없다고 장애가 없는 건 아닙니다: 애플리케이션이 stdout/stderr로 안 남기면 journald에도 부족하게 남을 수 있습니다.
    • ⚠️ 영구 저장 설정 후 재시작 필요: 설정 파일만 바꾸고 journald 재시작을 안 해서 헷갈리는 경우가 많습니다.
    • ⚠️ 너무 aggressive한 vacuum: 로그를 급하게 지웠다가, 나중에 RCA(Root Cause Analysis, 근본 원인 분석) 못 하는 상황이 생깁니다.
    • ⚠️ 시간 동기화 확인: NTP가 어긋나면 로그 해석이 꼬입니다. 사건 순서가 뒤집혀 보이기도 하거든요.

    여기서 중요한 포인트! journald 로그 관리는 단순히 용량 정리만 의미하지 않습니다. 남겨야 할 로그를 남기고, 필요한 순간에 바로 찾을 수 있게 만드는 운영 습관에 가깝습니다.

    FAQ: 많이 받는 질문

    Q. rsyslog가 있으면 journald는 안 써도 되나요?
    아닙니다. 둘은 배타적이라기보다 함께 쓰는 경우가 많습니다. journald로 빠르게 조회하고, 필요하면 다른 로그 시스템으로 전달하는 식이죠.

    Q. journalctl이 너무 느릴 때는요?
    시간 범위, 서비스명, 부팅 범위를 먼저 줄여보세요. 전체 검색부터 하면 당연히 체감이 무겁습니다.

    Q. Linux 트러블슈팅에서 가장 먼저 볼 명령 하나만 고르라면?
    저는 journalctl -p err -b를 자주 씁니다. 현재 부팅의 에러를 먼저 보고 큰 줄기를 잡기 좋거든요.

    9. 검증과 마무리: 제대로 설정됐는지 이렇게 확인하면 됩니다

    설정은 했는데 정말 잘 적용됐는지 확인하는 단계가 중요합니다. 아래 순서대로 보면 웬만한 건 검증됩니다.

    1. journalctl --disk-usage로 저장량 확인
    2. journalctl --list-boots로 이전 부팅 로그 유지 여부 확인
    3. journalctl -u 서비스명 -f로 실시간 수집 확인
    4. journalctl -p err -b로 에러 필터 확인
    5. systemctl restart systemd-journald 이후 동작 재확인
    journalctl --disk-usage
    journalctl --list-boots
    journalctl -b -1
    journalctl -u ssh.service -n 20 -o short-iso
    journalctl -p err -b

    이 다섯 줄만 점검해도 현재 서버의 journald 상태를 꽤 명확하게 파악할 수 있습니다. 저도 처음엔 파일 로그만 찾다가 돌아왔는데, 이제는 장애가 나면 거의 반사적으로 journalctl부터 엽니다. 이거 진짜 편하더라고요.

    정리하자면, 이번 글의 핵심은 이겁니다. journald 로그 관리는 로그를 보는 기술이 아니라, 장애 순간에 증거를 잃지 않는 운영 방식입니다. persistent 설정으로 로그를 남기고, 시간/서비스/우선순위 필터로 빨리 좁히고, vacuum 정책으로 디스크를 보호하면 기본기는 꽤 단단해집니다.

    다음 글에서는 systemd 서비스 유닛 파일 튜닝이나, rsyslog와의 연계, 중앙 로그 수집 구조도 이어서 다뤄볼 예정입니다. 이전 글에서 다뤘던 리눅스 서비스 장애 대응 흐름과 연결해서 보시면 더 이해가 잘 되실 거예요. 혹시 지금 운영 중인 서버에서 로그가 자꾸 증발하거나, 디스크가 로그 때문에 차는 경험 있으신가요? 그럴 때 오늘 소개한 5가지를 하나씩 적용해보시면 방향이 꽤 빨리 잡히실 겁니다.

    journald 설정과 검증 포인트를 한눈에 정리한 요약 인포그래픽 이미지입니다.

  • [Linux] Arch Linux 마이그레이션: Debian에서 Arch로 전환한 이유와 과정

    [Linux] Arch Linux 마이그레이션: Debian에서 Arch로 전환한 이유와 과정

    Arch Linux 마이그레이션: Debian에서 Arch로 전환한 이유와 과정

    홈랩을 굴리다 보면 한 번쯤은 운영체제 선택을 다시 보게 됩니다. 저도 꽤 오래 Debian을 메인 서버와 작업용 장비에 섞어 써왔는데요, 어느 순간부턴 패키지 흐름과 시스템 구성을 좀 더 제가 주도적으로 가져가고 싶어졌습니다. 결국 Arch Linux 마이그레이션을 직접 진행해봤고, 단순히 ‘최신 패키지가 좋아 보여서’가 아니라 실제로 왜 옮겼는지, 어떤 부분에서 만족했고 어디서 삽질했는지까지 정리해봤습니다. 혹시 지금 Debian을 쓰고 있는데 Linux 전환을 고민 중이라면, 이 글이 판단 기준을 잡는 데 도움이 될 겁니다.

    저는 13년 정도 인프라 일을 하면서 느낀 게 하나 있습니다. 운영체제는 정답보다 운영 방식이 더 중요하다는 점이죠. 안정성만 볼 건지, 패키지 최신성을 볼 건지, 아니면 시스템을 내가 어느 정도까지 이해하고 통제하고 싶은지에 따라 선택이 달라지거든요. 이번 글은 Arch가 무조건 낫다는 이야기가 아니라, Debian에서 Arch로 넘어갈 때 실제로 어떤 생각과 과정을 거치게 되는지를 경험 기준으로 풀어보는 글입니다.

    Debian에서 Arch로 전환하는 전체 흐름을 보여주는 개요 다이어그램

    Debian 환경 분석부터 Arch 설치, 데이터 이전, 검증까지의 전체 마이그레이션 흐름입니다.

    왜 Debian에서 Arch로 옮겼을까

    쉽게 말해 Debian은 예측 가능하고 안정적인 쪽에 강하고, Arch Linux는 가볍고 직접 구성하는 재미와 통제감이 큰 쪽입니다. 저도 한동안은 Debian 특유의 차분함이 정말 좋았거든요. 서버에 올려두면 조용히 자기 할 일 하면서 크게 신경 쓸 게 없으니까요. 근데 홈랩에서 이것저것 실험하다 보니, 새 도구를 붙일 때 패키지 흐름이 조금 답답하게 느껴지더라고요.

    특히 제가 중요하게 본 건 아래 세 가지였습니다.

    • 패키지 관리 흐름: 필요한 구성만 올리고 군더더기 없이 유지하고 싶었습니다.
    • 학습 효과: 시스템 부팅, 네트워크, initramfs(초기 RAM 파일시스템), bootloader(부트로더) 같은 기본기를 다시 손으로 만져보고 싶었습니다.
    • 변경 통제: 자동으로 많은 것이 깔리는 방식보다, 내가 설치한 것만 정확히 알고 운영하는 쪽이 편했습니다.

    물론 반대급부도 있습니다. Arch는 편하게 굴리려면 결국 문서를 자주 읽고, 변경 사항을 챙기고, 내 시스템을 내가 책임져야 하거든요. 이게 누군가에겐 귀찮음인데, 저한테는 오히려 장점이더라고요. 그래서 이번 Arch Linux 마이그레이션은 단순 교체가 아니라 운영 철학을 바꾸는 작업에 가까웠습니다.

    마이그레이션 전에 이해해야 할 개념

    저도 처음엔 ‘설치만 하면 비슷하지 않나?’ 싶었는데, 실제로는 접근 방식이 꽤 다릅니다. 여기서 중요한 개념 몇 가지를 먼저 짚고 가겠습니다.

    패키지 정책 차이

    Debian은 안정성 중심으로 검증된 패키지를 오래 유지하는 편입니다. 반면 Arch Linux는 rolling release(롤링 릴리스, 큰 버전 업그레이드 없이 지속적으로 최신 패키지를 반영하는 방식) 성격이 강합니다. 이 차이는 단순히 최신/구버전 문제가 아니라, 운영 리듬 자체를 바꿉니다.

    설치 철학 차이

    Debian은 설치 과정에서 비교적 많은 걸 잡아줍니다. Arch는 기본 뼈대만 주고, 나머지는 사용자가 조립하는 느낌이죠. 쉽게 말해 Debian이 ‘잘 정리된 공구함’이라면, Arch는 ‘공구는 줄 테니 네가 필요한 구조를 직접 만들라’에 가깝습니다.

    시스템 이해도 요구치

    Arch를 쓰면 파일시스템, 마운트, 네트워크, locale(로캘, 언어/지역 설정), user management(사용자 관리) 같은 기본 개념을 더 자주 보게 됩니다. 귀찮기도 한데요, 신기하게도 몇 번 삽질하고 나면 시스템이 훨씬 덜 무섭습니다. 이건 꽤 큰 장점이더라고요.

    항목 Debian Arch Linux
    운영 성향 안정성 중심 직접 구성, 최신 흐름 지향
    설치 난이도 비교적 친절함 수동 설정 비중이 큼
    패키지 흐름 보수적 빠른 반영
    학습 효과 운영 편의 중심 시스템 이해도 상승
    추천 대상 장기 안정 운영 구성 제어와 학습을 원하는 사용자

    마이그레이션 전에 제가 먼저 체크한 것들

    여기서 중요한 포인트! 운영체제 갈아타기 전에 제일 먼저 할 일은 설치 USB를 만드는 게 아닙니다. 현재 시스템 의존성 파악이 먼저거든요. 저도 초반에 이걸 대충 봤다가 서비스 하나가 안 떠서 한참 찾았습니다 ㅎㅎ

    1. 서비스 목록 정리: 웹서버, SSH, 컨테이너, cron(주기 작업), 모니터링 에이전트를 먼저 적어둡니다.
    2. 데이터 위치 확인: /etc, /var/lib, /srv, 사용자 홈 디렉터리처럼 실제 필요한 데이터가 어디 있는지 확인합니다.
    3. 패키지 의존성 확인: Debian에서 쓰던 패키지 이름이 Arch에서 그대로 통하지 않는 경우가 많습니다.
    4. 부팅 방식 확인: UEFI(통합 확장 펌웨어 인터페이스)인지 legacy BIOS인지 확인해야 합니다.
    5. 백업 검증: 백업이 있다는 것과 복구가 된다는 건 다릅니다. 작은 파일이라도 실제 복원 테스트를 해보세요.

    제가 실제로 메모했던 항목은 대략 이런 식이었습니다.

    # Debian 쪽에서 현재 상태 점검
    lsblk -f
    ip addr
    systemctl list-unit-files --type=service
    crontab -l
    sudo ss -tulpn
    sudo find /etc -maxdepth 2 -type f | sort

    이 단계가 지루해 보여도 정말 중요합니다. Arch Linux 마이그레이션은 설치보다 이전 대상 파악이 절반입니다.

    실전 설치 과정: Debian에서 Arch로의 전환 순서

    이제 본격적으로 설치 과정입니다. 저는 테스트 장비에서 먼저 한 번 해보고, 그 다음 실제로 쓰는 시스템에 적용했습니다. 그게 마음이 제일 편하더라고요.

    1. 설치 미디어로 부팅하고 네트워크 확인

    ip link
    ping -c 3 archlinux.org
    timedatectl

    유선이면 대부분 바로 잡히지만, 무선은 장비 따라 추가 설정이 필요할 수 있습니다. 시간 동기화가 꼬이면 나중에 패키지 검증이나 TLS(전송 계층 보안) 관련 문제가 생길 수 있어서 꼭 확인했습니다.

    2. 디스크 파티션과 파일시스템 준비

    lsblk
    fdisk /dev/sdX
    mkfs.fat -F32 /dev/sdX1
    mkfs.ext4 /dev/sdX2
    mount /dev/sdX2 /mnt
    mkdir -p /mnt/boot
    mount /dev/sdX1 /mnt/boot

    여기서 <code>/dev/sdX는 실제 디스크로 바꿔야 합니다. 이 부분은 정말 조심하셔야 합니다. 저도 예전에 습관적으로 명령 넣다가 다른 디스크를 건드릴 뻔한 적이 있거든요. ⚠️ 장비가 여러 개 달린 홈랩이면 특히 lsblk 결과를 두 번 보세요.

    Arch 설치 중 디스크 파티션과 마운트 구성을 보여주는 터미널 화면 또는 다이어그램

    UEFI 부팅용 파티션과 루트 파티션을 나누고, /mnt 아래에 마운트하는 흐름을 시각화한 이미지입니다.

    3. 기본 시스템 설치

    pacstrap /mnt base linux linux-firmware vim networkmanager sudo
    genfstab -U /mnt >> /mnt/etc/fstab
    arch-chroot /mnt

    처음엔 이게 뭔가 싶었는데, 생각보다 구조는 단순합니다. pacstrap으로 기본 시스템을 넣고, genfstab으로 마운트 정보를 만들고, arch-chroot로 새 시스템 안에 들어가는 방식이거든요.

    4. 시간대, 로캘, 호스트명 설정

    ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime
    hwclock --systohc
    vim /etc/locale.gen
    locale-gen
    echo "LANG=ko_KR.UTF-8" > /etc/locale.conf
    echo "arch-host" > /etc/hostname

    /etc/hosts도 함께 맞춰두는 편이 좋습니다.

    cat > /etc/hosts <<'EOF'
    127.0.0.1 localhost
    ::1       localhost
    127.0.1.1 arch-host.localdomain arch-host
    EOF

    5. 네트워크와 사용자 설정

    systemctl enable NetworkManager
    passwd
    useradd -m -G wheel -s /bin/bash myuser
    passwd myuser
    EDITOR=vim visudo

    visudo에서 wheel 그룹 sudo 권한을 활성화합니다. 저는 최소 권한 원칙을 좋아해서, 처음엔 꼭 필요한 계정만 만들고 나중에 확장하는 편입니다.

    6. 부트로더 설정

    pacman -S grub efibootmgr
    grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB
    grub-mkconfig -o /boot/grub/grub.cfg

    부팅 환경은 장비마다 차이가 큽니다. 그래서 저는 이 단계에서 절대 서두르지 않습니다. 설치가 다 된 것 같아도, 사실 가장 긴장되는 순간은 첫 재부팅 직전이거든요.

    7. 재부팅 후 기본 패키지 정리

    exit
    umount -R /mnt
    reboot

    부팅이 올라오면 SSH, 에디터, 모니터링 도구, 컨테이너 런타임 같은 필수 패키지를 하나씩 올립니다. Debian에서 쓰던 환경을 그대로 복제하려 하기보다, 정말 필요한 구성만 다시 쌓는다는 느낌으로 접근하니 훨씬 깔끔했습니다.

    설정과 데이터 이전은 이렇게 했습니다

    운영체제를 바꾸는 것보다 더 중요한 건 서비스 복구입니다. 특히 홈랩이나 개인 서버는 ‘부팅 성공’보다 ‘기존 워크로드가 제대로 도는가’가 핵심이죠.

    1. /etc 설정 비교: 서비스 설정 파일을 그대로 덮어쓰기보다, 새 기본 설정과 비교하며 필요한 값만 반영했습니다.
    2. 데이터 디렉터리 이전: 애플리케이션 데이터는 rsync(증분 복사 도구)로 옮겼습니다.
    3. 비밀 정보 분리: 키 파일, 인증서, 토큰은 따로 점검했습니다.
    4. 서비스 단위 재기동: 한 번에 다 올리지 말고 서비스별로 검증했습니다.
    sudo rsync -avh /old-root/etc/nginx/ /etc/nginx/
    sudo rsync -avh /old-root/var/lib/docker/ /var/lib/docker/
    sudo systemctl daemon-reload
    sudo systemctl restart nginx
    sudo systemctl status nginx

    근데 여기서 함정이 하나 있습니다. Debian에서 잘 돌던 설정이 Arch에서도 그대로 맞는다고 생각하면 안 된다는 거죠. 경로, 기본 서비스명, 패키지 분리가 조금씩 다를 수 있거든요. 저도 여기서 몇 번 멈췄습니다.

    기존 Debian 설정을 Arch로 이전하면서 rsync와 서비스 점검을 수행하는 장면

    설정 파일 비교, 데이터 복사, systemd 서비스 재시작과 상태 확인 과정을 보여주는 이미지입니다.

    ⚠️ 실제로 겪었던 문제와 해결 방법

    이 섹션은 좀 현실적으로 가보겠습니다. 설치 과정 문서만 보면 다 매끈하게 끝날 것 같지만, 실제 Linux 전환은 꼭 한두 군데서 걸립니다.

    문제 1. 네트워크는 잡혔는데 이름 해석이 이상함

    부팅은 됐는데 외부 패키지 저장소 접근이 들쑥날쑥했던 적이 있었습니다. 확인해보니 DNS(도메인 네임 시스템) 설정이 기대와 다르게 잡혀 있더라고요.

    resolvectl status
    systemctl status NetworkManager

    해결은 단순했습니다. NetworkManager가 관리하도록 두고, 중복 네트워크 설정 파일을 정리했습니다. 여러 네트워크 관리 도구를 섞어 쓰면 꼭 꼬이더라고요.

    문제 2. 부팅은 되는데 원하는 커널 옵션이 반영되지 않음

    이건 주로 GRUB 설정 재생성을 빼먹었을 때 생겼습니다. 설정 파일만 수정하고 끝낸 줄 알았는데 실제 부팅 메뉴에는 반영이 안 된 거죠.

    grub-mkconfig -o /boot/grub/grub.cfg

    별거 아닌데, 처음엔 왜 안 되지 싶어서 한참 봤습니다 ㅎㅎ

    문제 3. 서비스는 설치됐는데 자동 시작이 안 됨

    Debian에서 당연히 올라오던 서비스가 Arch에선 비활성 상태인 경우가 있었습니다. 특히 설치와 활성화가 분리돼 있다는 걸 잠깐 잊고 있었거든요.

    systemctl enable --now sshd
    systemctl enable --now docker

    이건 systemd(시스템 및 서비스 관리자) 운영할 때 자주 보는 패턴이라, 설치 후 enable --now 습관을 들이면 편합니다.

    문제 4. 예전 설정을 통째로 덮어써서 오히려 꼬임

    제가 가장 크게 삽질한 부분입니다. 예전 /etc 설정을 거의 그대로 가져왔더니 새 환경 기본값과 충돌하더라고요. 여기서 배운 건 하나입니다. 설정은 이관이 아니라 재해석이 필요하다는 거죠. 특히 네트워크, 로깅, 인증 관련 설정은 꼭 새 기본 파일과 비교하세요.

    검증과 결과: 마이그레이션이 끝났는지 어떻게 확인할까

    운영체제 설치가 끝났다고 마이그레이션이 끝난 건 아닙니다. 실제 검증 항목이 통과해야 비로소 끝난 거죠. 저는 아래 순서로 확인했습니다.

    1. 부팅 확인: 재부팅 후 정상 로그인 가능 여부
    2. 네트워크 확인: 내부 통신, 외부 통신, DNS 확인
    3. 서비스 확인: 웹, SSH, 컨테이너, 스케줄러 점검
    4. 로그 확인: journalctl로 에러 여부 점검
    5. 리소스 확인: 디스크 마운트, 메모리, 프로세스 상태 확인
    systemctl --failed
    journalctl -p 3 -xb
    df -h
    free -h
    ss -tulpn

    제가 직접 해보니, Arch로 옮기고 나서 가장 만족스러웠던 부분은 시스템이 가볍고 구조가 머릿속에 잘 들어온다는 점이었습니다. 내가 뭘 설치했고, 왜 돌아가고 있는지 추적이 쉽더라고요. 반면 운영 자동화가 덜 되어 있어서, 손이 더 가는 순간도 분명히 있습니다. 그래서 개인적으로는 ‘무조건 전환’보다 ‘내가 원하는 운영 방식에 맞는가’를 기준으로 보시는 걸 추천드립니다.

    마이그레이션 완료 후 서비스 상태, 디스크 사용량, 로그 점검 결과를 보여주는 운영 대시보드 스타일 이미지

    서비스 정상 상태, 디스크 마운트, 시스템 로그 점검 등 마이그레이션 검증 결과를 시각화한 이미지입니다.

    Debian과 Arch, 누구에게 더 맞을까

    사실 이 질문이 제일 중요합니다. 둘 다 좋은 운영체제인데, 쓰는 사람의 목적이 다를 뿐이죠.

    • Debian이 더 맞는 경우: 장기 안정 운영, 표준화된 서버 환경, 예측 가능한 업데이트를 선호할 때
    • Arch가 더 맞는 경우: 직접 구성, 최신 패키지 흐름, 시스템 학습 효과, 가벼운 환경을 원할 때

    저는 홈랩과 개인 작업 환경에서는 Arch가 꽤 잘 맞았습니다. 하지만 모든 프로덕션 서버에 바로 동일하게 들이밀 생각은 없습니다. 역할이 다르니까요. 이 균형감이 중요합니다.

    자주 묻는 질문

    Q. Debian에서 Arch로 바로 넘어가도 될까요?

    가능은 합니다. 다만 메인 장비 하나만 있는 상태라면 먼저 테스트 장비나 가상머신에서 설치 과정을 한 번 돌려보는 걸 추천드립니다. 저도 그게 훨씬 안전했습니다.

    Q. Arch Linux 마이그레이션이 초보자에게도 괜찮을까요?

    초보자도 할 수는 있지만, 부팅 구조와 파일시스템, 네트워크 기본 개념을 조금 알고 시작하면 훨씬 덜 힘듭니다. 아무것도 모른 채 시작하면 중간에 왜 안 되는지 판단이 어렵거든요.

    Q. 기존 Debian 설정 파일은 그대로 복사하면 되나요?

    일부는 가능하지만, 통째로 덮어쓰는 건 추천하지 않습니다. 새 환경 기본 설정과 비교해서 필요한 값만 옮기는 방식이 안전합니다.

    마무리: 운영체제를 바꾸는 게 아니라 운영 방식을 바꾸는 일

    이번 Arch Linux 마이그레이션을 하면서 다시 느낀 건, 운영체제 전환은 설치 이벤트가 아니라 운영 습관의 재설계라는 점입니다. Debian에서는 안정성과 편의성을 많이 얻었고, Arch에서는 통제감과 학습 효과를 얻었습니다. 둘 중 뭐가 더 낫다기보다, 내가 어떤 엔지니어링 경험을 원하는지가 더 중요하더라고요.

    혹시 지금 Debian에서 다른 배포판으로 Linux 전환을 고민하고 계신다면, 먼저 서비스 의존성부터 정리해보세요. 그 다음 테스트 환경에서 설치를 한 번 끝까지 밀어보면 감이 확 옵니다. 드디어 됐다! 하는 순간도 분명히 오고요. 반대로 ‘아, 이건 내 운영 스타일이 아니구나’를 빨리 깨닫는 것도 큰 수확입니다.

    다음 글에서는 이번 환경을 바탕으로 systemd 서비스 정리와 백업 자동화를 어떻게 붙였는지 이어서 다뤄볼 예정입니다. 이전 글에서 홈랩 스토리지 구성 이야기를 보셨다면, 이번 마이그레이션과 함께 보면 더 흐름이 잘 보이실 겁니다.

    Debian과 Arch의 선택 기준을 요약한 비교 인포그래픽

    안정성, 최신성, 학습 효과, 운영 편의성 관점에서 Debian과 Arch 선택 기준을 요약한 인포그래픽입니다.

  • [Linux] Fedora Ubuntu 비교: 1년 써본 홈 서버 분석

    [Linux] Fedora Ubuntu 비교: 1년 써본 홈 서버 분석

    Fedora Ubuntu 비교: 1년 써본 홈 서버 분석

    홈 서버를 처음 올릴 때 제일 오래 붙잡고 고민했던 게 바로 배포판 선택이었습니다. 특히 Fedora Ubuntu 비교는 검색하면 자료가 정말 많거든요. 그런데 막상 24시간 켜 두는 장비에 올려서 1년 정도 굴려보면, 문서에서 보던 장점과 실제 체감이 조금 다르더라고요. 저도 처음엔 “둘 다 리눅스면 비슷한 거 아닌가?” 싶었는데, 업데이트 주기, 보안 정책, 패키지 관리, 컨테이너 운영 방식에서 성격 차이가 꽤 분명했습니다.

    이번 글은 제가 홈랩에서 직접 겪은 시행착오를 바탕으로, 홈 서버용으로 Fedora와 Ubuntu를 어떻게 봐야 하는지 정리한 내용입니다. 결론부터 짧게 말하면, 최신 흐름과 보안 정책을 더 적극적으로 다루고 싶다면 Fedora가 잘 맞았고, 자료량과 익숙한 운영 흐름이 필요하면 Ubuntu가 더 편했습니다. 다만 이건 누가 더 우월하다는 얘기가 아니라 운영 스타일이 다르다는 이야기예요. 결국 중요한 건 “내 홈 서버에서 어떤 서비스를 몇 년 동안 어떤 방식으로 굴릴 건가”였습니다.

    Fedora와 Ubuntu 홈 서버 운영 흐름을 한눈에 보여주는 비교 다이어그램

    Fedora와 Ubuntu를 홈 서버 관점에서 비교한 전체 구조 이미지입니다.

    왜 Fedora Ubuntu 비교가 홈 서버에서 중요할까요

    데스크톱에서는 조금 불편해도 금방 손으로 복구하면 되는데, 홈 서버는 얘기가 다릅니다. NAS(Network Attached Storage, 네트워크 저장소), 미디어 서버, 리버스 프록시(Reverse Proxy, 요청을 대신 받아 뒤쪽 서비스로 넘기는 서버), 백업 작업, 홈 오토메이션까지 한 박스에 몰아넣는 경우가 많잖아요. 한 번 꼬이면 밤에 알림 오고, 주말에 손이 많이 갑니다.

    실제로 써보니 배포판 선택은 단순한 UI 취향 문제가 아니었습니다. 특히 아래 항목에서 차이가 또렷하게 느껴졌습니다.

    • 업데이트 주기: 자주 바뀌는 환경이 편한지, 덜 바뀌는 환경이 편한지
    • 보안 정책: SELinux(강제 접근 통제)와 AppArmor(프로파일 기반 접근 통제) 운용 감각 차이
    • 패키지 관리: DNF(dnf, 패키지 관리자)와 APT(apt, 패키지 관리자) 사용 흐름
    • 문서 생태계: 문제 생겼을 때 검색해서 바로 답을 찾기 쉬운지
    • 컨테이너 운영: Podman(Podman, 데몬리스 컨테이너 엔진)이나 Docker(Docker, 컨테이너 런타임) 적용 습관

    1년 사용 후기 기준으로 보면, “설치는 쉬웠다”보다 “6개월 지나서도 덜 귀찮았나”가 더 중요하더라고요.

    Fedora Ubuntu 비교 핵심: 두 배포판의 성격

    쉽게 말해 Fedora는 새로운 흐름을 상대적으로 빠르게 받아들이는 배포판이고, Ubuntu는 익숙한 운영 방식과 풍부한 자료를 제공하는 배포판에 가깝습니다. 둘 다 서버 운영은 충분히 가능합니다. 다만 초반 적응 비용과 장기 유지보수의 감각이 꽤 다릅니다.

    항목 Fedora Ubuntu
    패키지 관리자 DNF APT
    보안 기본 흐름 SELinux 중심 AppArmor 중심
    업데이트/지원 성향 릴리스 주기가 빠르고 지원 기간이 상대적으로 짧음 LTS 기준 장기 유지보수에 유리함
    체감 성격 최신 흐름 반영이 빠름 자료와 예제가 풍부함
    홈 서버 적합도 컨테이너/보안 실험에 강점 안정적 운영과 문서 접근성에 강점
    초보자 체감 처음엔 약간 까다로움 비교적 진입 장벽이 낮음

    제가 직접 해보니 Fedora는 “왜 막히지?” 싶은 순간이 있었지만, 원인을 이해하고 나면 구조가 꽤 깔끔하다고 느꼈습니다. 반대로 Ubuntu는 일단 원하는 서비스가 빨리 올라갑니다. 이거 진짜 편하더라고요. 대신 시간이 지나면 패키지 버전이나 구성 방식에서 “조금 더 새것을 쓰고 싶은데” 하는 갈증이 생길 때가 있었습니다.

    패키지 관리: DNF vs APT

    APT는 워낙 익숙한 분이 많아서 자료 찾기가 쉽습니다. 반면 DNF는 명령 자체는 어렵지 않지만, 초반에는 저장소 구성이나 패키지 이름 차이 때문에 손이 한 번 더 가는 편이었습니다. 그래도 두 도구 모두 실사용에는 충분히 안정적이었습니다.

    # Fedora
    sudo dnf upgrade -y
    sudo dnf install -y podman nginx git
    
    # Ubuntu
    sudo apt update
    sudo apt upgrade -y
    sudo apt install -y docker.io nginx git

    명령 자체는 단순합니다. 다만 홈 서버에서는 명령어 한 줄보다도, 장애가 났을 때 검색해서 바로 이어서 해결할 수 있느냐가 더 크게 느껴졌습니다.

    보안 정책: SELinux vs AppArmor

    여기서 많이 갈립니다. Fedora 쪽은 SELinux가 기본 흐름에 깊게 들어와 있어서, 처음에는 서비스가 안 뜨면 “설정은 맞는데 왜 안 되지?” 싶은 일이 생깁니다. 저도 초반엔 로그도 제대로 안 보고 포트만 의심했는데, 알고 보니 보안 컨텍스트(context, 접근 허용 규칙의 문맥) 문제였던 적이 몇 번 있었습니다. 반면 Ubuntu는 AppArmor가 기본으로 활성화되어 있지만, 초반 운영에서는 상대적으로 덜 거슬리게 느껴졌습니다.

    SELinux와 AppArmor 동작 차이를 보여주는 홈 서버 보안 구성 다이어그램

    홈 서버에서 보안 정책이 서비스 접근에 어떤 영향을 주는지 설명하는 이미지입니다.

    제가 1년 동안 굴려본 홈 서버 구성

    환경을 간단히 설명드리면, 특정 하드웨어 모델에 기대는 이야기는 빼고 일반적인 홈랩 구성을 기준으로 말씀드릴게요. 서비스는 크게 이런 식이었습니다.

    • 리버스 프록시(Reverse Proxy)
    • 컨테이너 기반 애플리케이션
    • 파일 동기화 및 백업 작업
    • 간단한 모니터링(Monitoring, 상태 감시)
    • 주기적인 업데이트 및 재부팅 점검

    둘 다 처음 설치하고 네트워크 잡고 SSH(Secure Shell, 원격 접속) 붙이는 데까지는 큰 차이가 없습니다. 차이는 운영 루틴에서 벌어졌습니다. Fedora는 Podman을 중심으로 가져가면 꽤 자연스럽게 흘러갔고, Ubuntu는 Docker 예제가 워낙 많아서 필요한 구성을 붙이기가 빨랐습니다. 이 부분은 검색 생산성 차이도 꽤 컸어요.

    실전 구현: 같은 역할의 홈 서버를 두 배포판에 올릴 때

    비교를 위해 저는 최대한 비슷한 역할을 맡겼습니다. 핵심은 “업데이트, 웹 서비스, 컨테이너, 방화벽” 네 가지였습니다. 아래 절차는 현재 공식 문서 흐름과도 크게 어긋나지 않는 기본 예시입니다.

    1. 기본 업데이트와 필수 패키지 설치

    1. 시스템을 최신 상태로 올립니다.
    2. 웹 서버와 버전 관리 도구를 설치합니다.
    3. 방화벽 서비스를 확인하고 필요한 포트를 엽니다.
    # Fedora
    sudo dnf upgrade -y
    sudo dnf install -y nginx git curl
    sudo systemctl enable --now nginx
    sudo systemctl enable --now firewalld
    sudo firewall-cmd --add-service=http --permanent
    sudo firewall-cmd --reload
    
    # Ubuntu
    sudo apt update
    sudo apt upgrade -y
    sudo apt install -y nginx git curl
    sudo systemctl enable --now nginx
    sudo ufw allow 'Nginx Full'
    sudo ufw enable

    여기서 중요한 포인트가 있습니다. Fedora는 firewalld(firewalld, 동적 방화벽 관리 도구) 흐름이 자연스럽고, Ubuntu는 UFW(UFW, 간편 방화벽) 예제가 많아서 접근성이 좋습니다. 다만 Ubuntu의 UFW는 기본적으로 비활성 상태인 경우가 많아서, 규칙 추가 뒤 실제 활성화 여부를 꼭 확인하는 게 좋습니다.

    2. 컨테이너 서비스 올리기

    홈 서버에서는 결국 컨테이너를 안 쓰기가 어렵더라고요. 서비스 격리도 좋고, 복구도 빠르거든요. Fedora는 Podman과 궁합이 좋았고, Ubuntu는 Docker 기준 예제가 워낙 풍부해서 초반 구축 속도가 빨랐습니다.

    # Fedora - Podman 예시
    sudo dnf install -y podman
    podman run -d --name hello-web -p 8080:80 docker.io/library/nginx:latest
    
    # Ubuntu - Docker 예시
    sudo apt install -y docker.io
    sudo systemctl enable --now docker
    sudo docker run -d --name hello-web -p 8080:80 nginx:latest

    실제로 써보니 Fedora는 Podman이 기본 흐름과 잘 맞는 느낌이 있었고, Ubuntu는 Docker 관련 문서와 예제가 많아서 트러블슈팅 속도가 빨랐습니다. 둘 다 장점이 분명했습니다.

    3. 자동 업데이트 점검 스크립트

    무턱대고 자동 업데이트를 켜는 건 조심해야 하지만, 점검 스크립트 정도는 꼭 두는 걸 추천드립니다. 저도 이걸 안 해놨다가 한동안 방치된 적이 있거든요. 최소한 업데이트가 얼마나 쌓였는지는 주기적으로 보는 편이 마음이 편했습니다.

    #!/usr/bin/env bash
    set -euo pipefail
    
    if command -v dnf >/dev/null 2>&1; then
      echo "[Fedora] Checking updates"
      sudo dnf check-update || true
    elif command -v apt >/dev/null 2>&1; then
      echo "[Ubuntu] Checking updates"
      sudo apt update
      apt list --upgradable
    fi

    이 스크립트는 어디까지나 점검용입니다. 실제 운영에서는 자동 재부팅 여부, 커널 업데이트 시점, 백업 상태까지 같이 보고 결정하는 편이 더 안전했습니다.

    4. 서비스 정의 파일 예시

    컨테이너든 스크립트든 부팅 후 자동 실행까지 묶어두면 운영이 확실히 편해집니다. 아래는 비교용으로 보기 쉬운 compose 형식 예시입니다.

    services:
      web:
        image: nginx:latest
        ports:
          - "8080:80"
        restart: unless-stopped

    물론 실제 운영에선 비밀값(secret)이나 볼륨(volume) 분리까지 같이 잡아야 합니다. 하지만 비교의 핵심은 여기서도 드러납니다. Ubuntu는 예제가 많아서 따라가기 쉽고, Fedora는 보안과 최신 도구 흐름을 이해하면 꽤 탄탄하게 쌓입니다.

    Fedora와 Ubuntu에서 웹 서비스와 컨테이너를 배치하는 구성 화면 또는 네트워크 다이어그램

    웹 서버, 방화벽, 컨테이너 구성을 실제 운영 흐름처럼 보여주는 이미지입니다.

    주의사항과 트러블슈팅: 제가 실제로 막혔던 지점들

    이 섹션은 정말 중요합니다. 검색 결과에서는 깔끔하게 끝나 보이는데, 실제 홈 서버 운영은 여기서 시간이 많이 들어갑니다. 저도 결국 문제를 푼 건 마법 같은 명령어보다 로그 확인 습관이었습니다.

    Fedora에서 자주 겪은 부분

    • SELinux 때문에 서비스 접근이 막힘: 포트를 열었는데도 연결이 안 되는 경우가 있었습니다.
    • 최신 패키지 흐름 적응: 문서 예제가 예전 방식일 때 명령이 조금씩 다를 수 있었습니다.
    • 외부 튜토리얼과 차이: Ubuntu 기준 가이드를 그대로 따라 하면 패키지명이나 서비스명에서 어긋날 수 있었습니다.

    이럴 때 저는 먼저 로그부터 봤습니다. 처음엔 이게 뭔가 싶었는데, 로그를 보기 시작하니까 삽질 시간이 확 줄더라고요.

    # 공통적으로 먼저 보는 로그
    sudo systemctl status nginx
    sudo journalctl -xeu nginx
    
    # Fedora에서 보안 문맥 의심 시 확인에 도움 되는 명령 예시
    getenforce
    ls -Z /var/www

    Ubuntu에서 자주 겪은 부분

    • 문서가 너무 많아서 오히려 헷갈림: 같은 작업도 방법이 여러 개라 기준이 흐려질 수 있습니다.
    • 패키지/도구 버전 차이: 블로그 글마다 전제 조건이 달라서 그대로 복붙하면 안 맞는 경우가 있습니다.
    • 쉬워 보여서 구조를 대충 잡게 됨: 초반 속도는 빠른데, 나중에 정리 비용이 생기더라고요.

    제 경험상 Ubuntu는 “빨리 된다”가 장점이자 함정이었습니다. 급하게 올리다 보면 권한, 백업 경로, 로그 로테이션(log rotation, 로그 순환 관리) 같은 운영 기본기를 뒤로 미루게 되거든요.

    Fedora Ubuntu 비교 결과: 1년 사용 후기에서 체감된 차이

    그럼 결국 어떤 차이가 남았냐고 물으시면, 저는 이렇게 정리합니다.

    평가 항목 Fedora 체감 Ubuntu 체감
    초기 설치 속도 무난함 조금 더 빠름
    문서 검색 편의성 괜찮지만 편차 있음 매우 좋음
    보안 정책 이해 필요성 높음 중간
    최신 도구 활용 만족도 높음 무난함
    장기 운영 심리적 안정감 설정 이해 후 높음 익숙하면 높음

    제가 직접 해보니 Fedora Ubuntu 비교에서 가장 중요한 건 성능 수치가 아니라 운영 철학이었습니다. Fedora는 “구조를 이해하고 운영하라”는 느낌이 강했고, Ubuntu는 “일단 올리고 필요할 때 넓은 자료를 참고하라”는 방향이 강했습니다. 둘 다 홈 서버에 충분히 좋습니다. 다만 제 홈랩 기준으로는, 컨테이너와 보안 흐름을 진지하게 다루는 서비스는 Fedora가 재미있었고, 가족이 같이 쓰는 서비스나 빨리 안정화해야 하는 용도는 Ubuntu가 마음이 편했습니다.

    홈 서버 모니터링 대시보드와 서비스 상태가 안정적으로 표시되는 결과 화면

    서비스 상태, 리소스 사용량, 정상 동작 여부를 확인하는 검증 결과 이미지입니다.

    어떤 분에게 Fedora가 맞고, 어떤 분에게 Ubuntu가 맞을까요

    Fedora가 잘 맞는 경우

    • 최신 리눅스 흐름을 직접 익히고 싶은 분
    • SELinux를 포함한 보안 운영 감각을 키우고 싶은 분
    • Podman 중심의 컨테이너 운영을 해보고 싶은 분
    • 홈랩 자체를 공부와 실험의 장으로 쓰는 분

    Ubuntu가 잘 맞는 경우

    • 검색해서 빨리 구축하고 싶은 분
    • 문서와 커뮤니티 자료가 많은 환경을 선호하는 분
    • 처음 홈 서버를 시작하는 분
    • 운영 표준을 단순하게 가져가고 싶은 분

    혹시 이런 경험 있으신가요? 분명 설치는 쉬웠는데, 3개월 뒤 업데이트 한 번에 갑자기 손이 많이 가는 상황이요. 그래서 저는 이제 배포판을 고를 때 “첫날 편한가”보다 “여섯 달 뒤 덜 힘든가”를 더 보게 됐습니다.

    정리와 다음 단계

    이번 Fedora Ubuntu 비교를 1년 사용 후기 관점에서 정리하면 이렇습니다. Fedora는 배울 게 많고 구조적으로 단단한 느낌, Ubuntu는 빠르게 안정권에 진입하기 쉬운 느낌이었습니다. 저도 처음엔 Ubuntu가 더 편했는데, 홈랩에서 이것저것 실험하다 보니 Fedora 쪽의 매력도 분명히 크게 느꼈습니다. 결국 정답은 하나가 아니라, 내 서비스 성격에 맞는 선택이더라고요.

    1. 처음 홈 서버를 시작한다면 Ubuntu로 기본 운영 루틴을 익혀보세요.
    2. 보안 정책과 최신 도구 흐름이 궁금하다면 Fedora를 별도 장비나 VM(Virtual Machine, 가상 머신)에서 병행해 보세요.
    3. 둘 중 무엇을 선택하든 로그 확인, 백업, 업데이트 점검 자동화는 초반부터 잡는 걸 추천드립니다.

    다음 글에서는 홈 서버 운영에서 중요한 백업 전략과 리버스 프록시 구성 이야기를 다뤄볼 예정입니다. 이전 글의 모니터링 기본편이 있다면 함께 읽어보셔도 흐름이 잘 이어집니다.

    Fedora와 Ubuntu 선택 기준을 요약한 인포그래픽 스타일 비교표

    어떤 사용자가 어떤 배포판을 선택하면 좋은지 한눈에 정리한 요약 이미지입니다.

    자주 묻는 질문

    Q. 홈 서버 입문자는 Fedora보다 Ubuntu가 낫나요?

    대체로는 그렇습니다. 자료량과 예제 폭이 넓어서 초반 시행착오를 줄이기 쉽거든요. 다만 공부 목적이 강하면 Fedora도 충분히 좋은 선택입니다.

    Q. Fedora는 서버에서 불안정한가요?

    제가 써본 기준으로 무조건 그렇진 않았습니다. 다만 업데이트 흐름과 보안 정책을 이해하지 않으면 더 까다롭게 느껴질 수 있습니다.

    Q. Ubuntu가 무조건 더 쉬운가요?

    처음엔 쉬운데, 그래서 구조를 대충 잡고 넘어가면 나중에 정리 비용이 생길 수 있습니다. 쉬운 것과 잘 운영하는 것은 조금 다른 문제더라고요.

    Q. 결론적으로 무엇을 추천하나요?

    가족이 함께 쓰는 서비스, 빠른 구축, 문서 접근성이 중요하면 Ubuntu를 추천합니다. 홈랩 실험, 최신 흐름, 보안 학습이 중요하면 Fedora를 추천드립니다.

  • [Linux] systemd 서비스 오류 진단 및 해결: journalctl 활용법

    [Linux] systemd 서비스 오류 진단 및 해결: journalctl 활용법

    [Linux] systemd 서비스 오류 진단 및 해결: journalctl 활용법

    리눅스 서버를 운영하다 보면 갑자기 서비스가 죽어버리거나, 재부팅 이후 특정 데몬(daemon, 백그라운드 서비스)이 올라오지 않는 상황을 꼭 한 번쯤 겪게 됩니다. 저도 홈랩에서 웹 서버, 백업 에이전트, VPN 서비스까지 이것저것 올려두고 쓰다 보니, systemd 서비스 오류 해결이 생각보다 자주 필요한 작업이더라고요. 처음엔 서비스가 실패했다는 메시지만 보고 멍해졌었는데, 실제로는 journalctl(저널 로그 조회 도구)만 제대로 써도 원인 파악 속도가 확 달라집니다. 혹시 서비스는 안 뜨는데 왜 죽는지 감이 안 잡히는 경험 있으신가요? 오늘은 제가 직접 삽질하면서 정리한 방식으로, journalctl 사용법부터 리눅스 서비스 디버깅, systemd 유닛 실패, 그리고 부팅 문제 추적까지 한 번에 정리해보겠습니다.

    systemd 서비스 오류 해결과 journalctl 로그 흐름을 설명하는 개요 다이어그램

    systemd가 서비스 상태를 관리하고 journalctl이 로그를 추적하는 전체 흐름을 한눈에 보여주는 개요 이미지입니다.

    1. 왜 systemd 서비스 오류 진단이 중요한가

    예전에는 SysV init(전통적인 리눅스 초기화 방식) 스크립트를 직접 뒤져보던 시절도 있었지만, 요즘 주요 배포판은 대부분 systemd(시스템 및 서비스 관리자)를 씁니다. 서비스 시작, 중지, 재시작은 물론이고 부팅 시 의존성(dependency, 선후관계)까지 systemd가 관리하죠. 문제는 여기서 서비스 하나만 꼬여도 연쇄적으로 장애가 퍼질 수 있다는 점입니다.

    예를 들어 이런 상황이 있습니다.

    • 웹 서비스는 죽었는데 포트 충돌인지, 권한 문제인지 모르겠을 때
    • 부팅은 됐는데 특정 유닛(unit, 서비스 정의 파일)이 실패해서 후속 작업이 멈췄을 때
    • 재시작 루프에 빠져 CPU를 계속 잡아먹을 때
    • 로그 파일이 흩어져 있어서 어디부터 봐야 할지 막막할 때

    이럴 때 무작정 <code>systemctl restart만 반복하면 해결이 안 됩니다. 저도 처음엔 그러다가 로그 힌트를 놓쳐서 시간을 두 배로 쓴 적이 많았거든요. 여기서 중요한 포인트! systemd 서비스 오류 해결의 핵심은 상태 확인과 로그 확인을 분리해서 보는 것입니다.

    2. systemd와 journalctl, 쉽게 말해 뭐가 다른가

    쉽게 말해 systemctl은 “서비스를 관리하는 도구”이고, journalctl은 “무슨 일이 있었는지 기록을 읽는 도구”입니다. 둘을 같이 써야 제대로 보입니다.

    도구 역할 주요 용도
    systemctl 서비스 제어 및 상태 조회 start, stop, restart, status
    journalctl 저널 로그 조회 에러 원인 분석, 시간대별 추적
    systemd unit 서비스 정의 파일 ExecStart, Restart, After 등 설정

    보통 장애 분석은 이런 흐름으로 갑니다.

    1. systemctl status로 현재 실패 상태를 확인합니다.
    2. journalctl -u 서비스명으로 해당 서비스 로그를 좁혀봅니다.
    3. 필요하면 부팅 단위 로그, 이전 부팅 로그까지 확장해서 봅니다.
    4. 원인이 설정 파일인지, 권한인지, 실행 파일 경로인지 확인합니다.

    이 패턴만 익혀도 대부분의 리눅스 서비스 디버깅은 훨씬 수월해집니다.

    3. 가장 먼저 보는 기본 명령어

    실전에서는 저는 거의 항상 아래 순서로 확인합니다. 눈에 익혀두시면 정말 편합니다.

    3-1. 서비스 상태 확인

    sudo systemctl status nginx.service

    여기서 봐야 할 포인트는 세 가지예요.

    • Loaded: 유닛 파일이 정상적으로 읽혔는지
    • Active: active, failed, activating 상태가 어떤지
    • Main PID / Exit code: 프로세스가 왜 종료됐는지

    출력 하단에 최근 로그 일부가 붙는 경우도 있는데, 그걸로 끝내면 안 됩니다. 진짜 원인은 뒤에 더 있을 때가 많거든요.

    3-2. 특정 서비스 로그 보기

    sudo journalctl -u nginx.service

    이 명령은 해당 유닛에 연결된 로그만 쏙 빼서 보여줍니다. 로그가 많으면 아래처럼 최근 것만 보는 식으로 줄여서 봐도 좋습니다.

    sudo journalctl -u nginx.service -n 50

    실시간으로 따라가려면 tail(로그 끝 추적) 같이 -f 옵션을 쓰면 편합니다.

    sudo journalctl -u nginx.service -f

    제가 직접 해보니 재시작 테스트할 때 이 조합이 제일 편하더라고요. 한쪽 터미널에서는 로그를 보고, 다른 쪽에서는 서비스를 재시작합니다.

    sudo systemctl restart nginx.service

    3-3. 에러 우선으로 좁혀보기

    sudo journalctl -p err..alert

    이건 시스템 전체에서 error 이상의 심각한 로그만 골라서 봅니다. 서비스명이 명확하지 않거나, 어디서 문제가 시작됐는지 감이 안 올 때 꽤 유용해요.

    4. 실전으로 보는 journalctl 활용법

    이제 실제 장애 분석 흐름으로 가보겠습니다. 예시로 사용자 정의 앱 서비스가 실행 실패하는 상황을 가정해볼게요.

    4-1. 실패한 유닛만 먼저 확인

    sudo systemctl --failed

    부팅 직후 이상이 있을 때는 이 명령이 정말 좋습니다. 실패한 유닛을 한 번에 보여주니까요. 특히 systemd 유닛 실패가 여러 개 겹쳐 있을 때 시작점 찾기에 좋아요.

    4-2. 해당 유닛 상세 상태 확인

    sudo systemctl status myapp.service

    예를 들어 여기서 code=exited, status=203/EXEC 같은 메시지가 보이면 실행 파일 경로나 권한을 먼저 의심해봅니다. 저도 처음엔 애플리케이션 문제인 줄 알고 코드부터 뒤졌는데, 알고 보니 ExecStart 경로 오타였던 적이 있습니다. 이런 거 은근 자주 나옵니다 ㅎㅎ

    4-3. 시간 범위로 로그 좁히기

    sudo journalctl -u myapp.service --since "2026-07-11 09:00:00" --until "2026-07-11 09:10:00"

    재배포 직후나 재부팅 직후처럼 문제 발생 시점이 뚜렷하면 시간 범위를 넣는 게 좋습니다. 로그가 긴 서버일수록 이게 체감상 엄청 크다니까요.

    systemd 서비스 오류 해결을 위해 상태와 로그를 함께 보는 터미널 화면

    서비스 상태와 저널 로그를 나란히 확인하면서 실행 경로, 권한, 포트 충돌 같은 원인을 추적하는 장면을 표현한 이미지입니다.

    4-4. 현재 부팅 기준 로그 보기

    sudo journalctl -b

    -b는 현재 부팅(boot, 시스템 시작 세션) 기준 로그를 보여줍니다. 부팅 직후 서비스가 안 뜨는 경우엔 정말 자주 씁니다. 시스템 전체를 보고 싶을 때는 좋지만, 특정 서비스 분석이라면 유닛 옵션과 같이 쓰는 편이 나아요.

    sudo journalctl -b -u myapp.service

    4-5. 이전 부팅 로그 확인

    sudo journalctl -b -1

    이건 부팅 문제 잡을 때 핵심입니다. 오늘은 정상인데 어제 재부팅에서는 실패했다면, 이전 부팅 로그를 보는 게 맞습니다. 실제로 써보니 “지금은 재현 안 되는데 아까는 왜 안 됐지?” 같은 상황에서 아주 큰 도움이 되더라고요.

    sudo journalctl -b -1 -u myapp.service

    5. 자주 만나는 장애 유형과 해결 패턴

    여기부터는 제가 실무와 홈랩에서 자주 본 패턴 위주로 정리해보겠습니다. 모든 에러를 외울 필요는 없고, 로그에서 어떤 방향으로 해석할지만 익혀도 충분합니다.

    5-1. 실행 파일 경로 오류

    ExecStart에 지정한 바이너리(binary, 실행 파일) 경로가 틀리면 서비스는 시작도 못 합니다.

    sudo systemctl cat myapp.service

    유닛 내용을 확인해서 ExecStart=/opt/myapp/bin/start.sh 같은 경로가 실제 존재하는지 봅니다.

    ls -l /opt/myapp/bin/start.sh

    없거나 실행 권한이 없으면 아래처럼 수정합니다.

    sudo chmod +x /opt/myapp/bin/start.sh
    sudo systemctl daemon-reload
    sudo systemctl restart myapp.service

    5-2. 포트 충돌

    웹 서버나 에이전트 서비스는 포트 충돌 때문에 죽는 경우가 많습니다. 로그에 address already in use 같은 문구가 보이면 거의 이쪽입니다.

    sudo ss -lntp

    어떤 프로세스가 포트를 잡고 있는지 확인하고, 중복 서비스가 있으면 정리합니다.

    5-3. 권한 문제

    systemd 서비스는 보통 root 또는 특정 사용자 계정으로 실행됩니다. 파일 접근 권한이 안 맞으면 시작 직후 종료됩니다.

    sudo journalctl -u myapp.service -n 100 | grep -i "permission\|denied"

    여기서 중요한 건 서비스 실행 계정입니다.

    sudo systemctl show myapp.service -p User -p Group

    로그에 Permission denied가 보이면 파일 소유권(owner)과 권한부터 확인해봐요.

    5-4. 환경 변수 누락

    애플리케이션이 쉘에서는 잘 뜨는데 systemd에서는 실패하는 경우가 있습니다. 이건 환경 변수(environment variable) 차이인 경우가 많습니다. 저도 Docker가 아닌 순수 서비스로 앱 띄울 때 여기서 꽤 삽질했어요.

    sudo systemctl cat myapp.service

    필요하면 유닛에 다음처럼 넣습니다.

    [Service]
    Environment="APP_ENV=production"
    Environment="JAVA_HOME=/usr/lib/jvm/java-17-openjdk"

    수정 후엔 꼭 다시 읽혀야 합니다.

    sudo systemctl daemon-reload
    sudo systemctl restart myapp.service

    6. ⚠️ 제가 실제로 자주 겪은 트러블슈팅 포인트

    이 섹션은 정말 현장에서 체감 큰 부분입니다. 문법은 맞는데 계속 안 되는 상황, 그거 꽤 답답하거든요.

    • daemon-reload를 빼먹는 실수: 유닛 파일 수정 후 sudo systemctl daemon-reload를 안 하면 이전 설정이 계속 적용됩니다.
    • 로그 보존 정책 차이: 환경에 따라 journal이 메모리 기반으로만 남아 재부팅 후 예전 로그가 제한적일 수 있습니다.
    • 서비스 이름 착각: 패키지명과 유닛명이 다를 수 있습니다. 예를 들어 실제 유닛명이 예상과 다를 수 있으니 systemctl list-units --type=service로 확인하세요.
    • Restart 정책 오해: Restart=always 때문에 서비스가 계속 재기동되면 원인 로그가 빨리 지나갑니다. 이럴 땐 실시간 로그 추적이 필수예요.

    특히 재시작 루프는 초보 때 진짜 헷갈립니다. 서비스는 살아있는 것처럼 보이는데, 사실은 죽고 다시 뜨고를 반복하고 있거든요.

    sudo systemctl show myapp.service -p Restart -p RestartSec -p ExecMainStatus

    이렇게 정책과 종료 상태를 함께 보면 흐름이 좀 더 명확해집니다.

    7. 검증과 결과 확인은 이렇게 합니다

    문제를 수정한 뒤에는 단순히 서비스가 올라왔는지만 보지 말고, 실제로 안정적으로 동작하는지 확인해야 합니다. 저도 예전엔 active (running)만 보고 끝냈다가 30초 후 다시 죽는 걸 놓친 적이 있었습니다.

    1. 서비스 상태를 다시 확인합니다.
    2. 최근 로그에 에러가 사라졌는지 봅니다.
    3. 필요하면 포트, 프로세스, 응답까지 점검합니다.
    4. 재부팅 후에도 자동 시작이 되는지 확인합니다.
    sudo systemctl status myapp.service
    sudo journalctl -u myapp.service -n 30
    sudo systemctl is-enabled myapp.service
    sudo systemctl is-active myapp.service

    웹 서비스라면 간단히 응답 체크도 해보면 좋습니다.

    curl -I http://127.0.0.1:8080

    이 단계까지 통과하면 드디어 됐다! 싶은 순간이 옵니다. 이런 맛에 로그 보는 거죠.

    systemd 서비스 오류 해결 후 정상 동작을 검증하는 장면

    수정 이후 서비스가 정상 실행되고 최근 로그에 치명적인 오류가 사라진 상태를 확인하는 검증 이미지를 위한 위치입니다.

    8. 빠르게 보는 명령어 치트시트

    정리 차원에서 많이 쓰는 명령을 표로 묶어보겠습니다. 장애 대응 중엔 이런 요약이 꽤 도움이 됩니다.

    상황 명령어 설명
    서비스 상태 확인 systemctl status 서비스명 현재 상태와 최근 로그 확인
    특정 서비스 로그 journalctl -u 서비스명 해당 유닛 관련 로그만 조회
    최근 로그 50줄 journalctl -u 서비스명 -n 50 최근 에러 빠르게 확인
    실시간 추적 journalctl -u 서비스명 -f 재시작 테스트와 함께 보기 좋음
    현재 부팅 로그 journalctl -b 이번 부팅 기준 전체 로그
    이전 부팅 로그 journalctl -b -1 재부팅 전 문제 추적
    실패 유닛 확인 systemctl --failed 실패한 서비스 일괄 조회

    이 정도만 손에 익으면 대부분의 systemd 서비스 오류 해결 작업은 훨씬 빨라집니다. 그리고 다음 글에서는 systemd unit 파일 작성법과 Restart 정책 설계도 따로 다뤄볼 예정입니다. 이전 글에서 로그 로테이션(log rotation, 로그 보관 정책) 관련 내용을 보셨다면 함께 연결해서 보셔도 좋습니다.

    journalctl 사용법과 systemd 서비스 오류 해결 순서를 요약한 인포그래픽

    자주 쓰는 journalctl 옵션과 장애 대응 순서를 요약한 인포그래픽용 이미지 위치입니다.

    9. 마무리: 로그를 보면 서비스가 왜 죽는지 보입니다

    systemd 서비스 오류 해결은 막연히 어려워 보이지만, 사실 흐름은 꽤 단순합니다. 상태 확인은 systemctl, 원인 추적은 journalctl. 이 두 축만 잘 잡으면 됩니다. 저도 처음엔 서비스가 failed로 뜨면 겁부터 났는데, 하나씩 로그를 따라가다 보니 오히려 장애 대응의 기준점이 생기더라고요.

    오늘 정리한 내용을 다시 압축하면 이렇습니다.

    • 서비스가 죽었으면 먼저 status로 현재 상태를 봅니다.
    • 원인은 journalctl로 시간대와 유닛 기준으로 좁혀봅니다.
    • 부팅 문제는 -b와 -b -1 조합으로 추적합니다.
    • 실행 경로, 권한, 포트, 환경 변수를 우선 의심하면 해결이 빠릅니다.

    혹시 지금도 특정 서비스가 이유 없이 죽고 있다면, 무작정 재시작부터 하지 마시고 저널부터 한 번 열어보세요. 생각보다 답이 로그 안에 그대로 들어있습니다. 이거 진짜 편하더라고요. 다음 글에서는 서비스 자동 재시작 정책과 의존성 설정을 조금 더 깊게 다뤄보겠습니다.

  • [Linux] Linux 사용자 관리: sudo 권한부터 계정 관리까지 1년 실전 가이드

    [Linux] Linux 사용자 관리: sudo 권한부터 계정 관리까지 1년 실전 가이드

    [Linux] Linux 사용자 관리: sudo 권한부터 계정 관리까지 1년 실전 가이드

    홈랩을 오래 굴리다 보면 결국 제일 자주 만지는 영역이 Linux 사용자 관리더라고요. 처음에는 계정 하나 만들고 <code>sudo만 붙여주면 끝인 줄 알았는데, 실제로 1년 정도 운영해보니 그게 시작이었습니다. 누가 어떤 권한을 가져야 하는지, 비밀번호 정책은 어디까지 강하게 가져갈지, SSH(Secure Shell, 원격 접속) 접근은 어떻게 나눌지 같은 문제가 계속 나오거든요. 특히 여러 대의 서버를 동시에 관리하면 작은 실수가 바로 보안 이슈로 이어질 수 있어서, 이 부분은 초반에 습관을 잘 잡는 게 정말 중요합니다.

    저도 처음엔 루트(root, 최고 관리자 계정)로 바로 접속해서 작업하던 시기가 있었는데요. 편하긴 한데, 실수 한 번이면 복구가 꽤 피곤했습니다. 그래서 지난 1년 동안은 일반 사용자 계정 기반으로 운영하고, 필요한 작업만 sudo로 올리는 방식으로 정리해봤습니다. 실제로 써보니까 관리 포인트가 명확해지고, 문제 추적도 쉬워지더라고요. 이번 글에서는 제가 직접 해보며 정리한 사용자 관리 기준, sudo 권한 설정 방법, 그리고 계정 운영할 때 자주 터지는 문제까지 한 번에 묶어서 공유해보겠습니다.

    여러 대의 Linux 서버에서 사용자, 그룹, sudo 권한, SSH 접근 흐름이 어떻게 연결되는지 보여주는 개요 이미지입니다.

    1. 왜 Linux 사용자 관리가 생각보다 중요한가

    쉽게 말해 Linux 사용자 관리는 “누가, 어디까지, 어떤 방식으로 시스템을 만질 수 있느냐”를 정하는 일입니다. 서버가 한 대일 때는 체감이 덜할 수 있는데, 두 대 세 대 넘어가고 NAS(Network Attached Storage, 네트워크 저장소)나 컨테이너 호스트까지 붙기 시작하면 이야기가 달라집니다. 계정을 아무 생각 없이 늘리면, 나중에 누가 어떤 변경을 했는지 찾기 어려워집니다.

    • 책임 추적(Accountability, 작업 책임 추적)이 쉬워집니다.
    • 최소 권한 원칙(Principle of Least Privilege, 필요한 만큼만 권한 부여)을 적용할 수 있습니다.
    • 루트 계정 직접 사용을 줄여서 사고 범위를 제한할 수 있습니다.
    • 퇴사자 계정, 테스트 계정, 임시 계정을 정리하기 쉬워집니다.

    여기서 중요한 포인트! Linux는 기본적으로 강력한 멀티유저(multi-user, 다중 사용자) 시스템입니다. 그런데 운영자가 그 특성을 제대로 활용하지 않으면, 그냥 “다들 sudo 되는 단일 사용자 환경”처럼 굴러가 버리더라고요. 저도 한동안 그렇게 썼었는데, 나중에 계정 관리가 꼬이니까 정리가 꽤 힘들었습니다.

    2. Linux 사용자 관리의 핵심 개념 정리

    저도 처음엔 헷갈렸는데, 아래 네 가지만 명확히 잡으면 절반은 끝입니다.

    2-1. 사용자(User)와 그룹(Group)

    사용자(User, 개별 계정)는 실제 로그인 주체이고, 그룹(Group, 권한 묶음)은 여러 사용자에게 공통 권한을 부여할 때 씁니다. 보통 운영은 사용자에게 직접 권한을 덕지덕지 붙이는 것보다, 그룹 설계를 먼저 하고 사용자를 그룹에 넣는 쪽이 관리가 훨씬 편하더라고요.

    2-2. sudo 권한

    sudo는 superuser do의 약자로, 일반 계정이 관리자 권한으로 특정 명령을 실행할 수 있게 해줍니다. 즉, 항상 루트로 로그인하지 않아도 필요한 순간에만 권한을 올릴 수 있는 거죠. 실제로 써보니까 이 방식이 사고 범위를 줄이는 데 확실히 도움이 됐습니다.

    2-3. 인증(Authentication)과 인가(Authorization)

    인증은 “누구냐”를 확인하는 것이고, 인가는 “무엇을 할 수 있느냐”를 정하는 겁니다. SSH 키 로그인, 비밀번호, MFA(Multi-Factor Authentication, 다중 인증) 같은 건 인증 쪽이고, sudoers 설정은 인가 쪽에 가깝습니다.

    2-4. 관련 파일

    파일 역할 실무 포인트
    /etc/passwd 사용자 기본 정보 로그인 셸, 홈 디렉터리 확인
    /etc/shadow 비밀번호 해시 저장 권한 제한 필수
    /etc/group 그룹 정보 권한 설계 시 자주 확인
    /etc/sudoers sudo 정책 직접 수정 시 반드시 visudo 사용
    /etc/sudoers.d/ sudo 분리 설정 서버 역할별 관리에 유리

    사실 Linux 계정 관리에서 제일 중요한 건 명령어를 많이 아는 것보다, 정책을 일관되게 가져가는 것입니다. 같은 팀인데 서버마다 sudo 정책이 다르면, 그게 더 큰 장애 포인트가 되더라고요.

    3. 실전 구현: 계정 생성부터 그룹 설계까지

    제가 홈랩에서 가장 많이 쓰는 방식은 “개인 사용자 계정 + 역할 그룹 + 필요한 sudo만 부여” 구조입니다. 아래 예시는 Debian/Ubuntu 계열에서도 이해하기 쉽고, 다른 배포판에서도 거의 같은 개념으로 적용됩니다.

    1. 관리용 그룹을 먼저 만듭니다.
    2. 사용자 계정을 생성하고 홈 디렉터리를 함께 준비합니다.
    3. 필요한 그룹에 사용자를 추가합니다.
    4. SSH 키 인증을 붙입니다.
    5. 마지막으로 sudo 정책을 분리 파일로 관리합니다.

    3-1. 사용자 생성

    sudo adduser minsu
    sudo passwd minsu
    id minsu
    getent passwd minsu

    adduser는 대화형으로 홈 디렉터리와 기본 설정을 함께 잡아줘서 초반엔 편합니다. 반대로 자동화가 필요할 때는 useradd를 더 자주 쓰게 되더라고요.

    3-2. 그룹 기반으로 권한 묶기

    sudo groupadd ops
    sudo usermod -aG ops minsu
    id minsu
    getent group ops

    여기서 -aG 옵션을 빼먹으면 기존 보조 그룹이 날아갈 수 있습니다. 저 이거 한 번 놓쳐서 기존 접근 권한이 꼬인 적이 있었는데요. 드디어 됐다 싶었는데, 다른 작업 권한이 사라져 있더라고요. 그 뒤로는 id 사용자명으로 바로 검증하는 습관을 붙였습니다.

    Linux 사용자 관리와 sudo 권한 설정 흐름을 보여주는 이미지

    사용자 생성, 그룹 추가, sudoers.d 정책 분리까지 이어지는 실전 구성 흐름을 보여주는 이미지입니다.

    3-3. SSH 디렉터리와 권한 정리

    sudo mkdir -p /home/minsu/.ssh
    sudo chmod 700 /home/minsu/.ssh
    sudo touch /home/minsu/.ssh/authorized_keys
    sudo chmod 600 /home/minsu/.ssh/authorized_keys
    sudo chown -R minsu:minsu /home/minsu/.ssh

    SSH 키 로그인은 보안 측면에서 거의 기본값처럼 가져가는 게 좋습니다. 특히 외부에서 접속하는 서버라면 비밀번호 로그인만 믿고 가는 건 꽤 불안하거든요. 혹시 이런 경험 있으신가요? 키는 넣었는데 접속이 안 돼서 한참 헤매는 경우요. 대부분은 파일 권한이나 소유권 문제였습니다.

    4. sudo 권한 설정: 편하게 쓰되 넓게 주지는 않기

    sudo 권한은 편리하지만, 잘못 주면 사실상 루트와 다를 게 없어집니다. 그래서 저는 요즘 /etc/sudoers를 직접 건드리기보다 /etc/sudoers.d/ 아래에 역할별 파일을 나눠서 관리합니다. 이게 나중에 보기 훨씬 좋고, 변경 이력 추적도 편하더라고요.

    4-1. visudo로 안전하게 편집

    sudo visudo -f /etc/sudoers.d/ops

    예시 파일은 이렇게 구성할 수 있습니다.

    %ops ALL=(ALL:ALL) ALL

    이 설정은 ops 그룹 사용자에게 모든 명령에 대한 sudo 실행 권한을 주는 거거든요. 홈랩이나 소규모 환경에선 현실적인 출발점이긴 한데, 실제 운영에서는 더 좁히는 게 좋습니다.

    4-2. 특정 명령만 허용하는 방식

    Cmnd_Alias SERVICE_MGMT = /usr/bin/systemctl restart nginx, /usr/bin/systemctl status nginx
    %ops ALL=(root) SERVICE_MGMT

    처음엔 이런 세분화가 좀 귀찮았습니다. 근데 실제로 써보니까 “누구나 뭐든지 sudo 가능” 상태보다 훨씬 안정적이더라고요. 특히 여러 사람이 함께 관리하는 환경에서는 이 차이가 큽니다. 쉽게 말해, sudo는 켜고 끄는 스위치가 아니라 정교하게 나눠야 하는 운영 정책에 가깝습니다.

    4-3. 비밀번호 요구 정책도 점검

    Defaults logfile=/var/log/sudo.log
    Defaults lecture=once

    서버마다 필요는 다르겠지만, 누가 어떤 sudo 명령을 썼는지 남기고 싶다면 로그 정책도 함께 보는 게 좋습니다. 나중에 문제 생겼을 때 이 로그가 꽤 유용합니다. 이거 진짜 편하더라고요.

    5. 계정 관리 운영 팁: 1년 써보니 결국 정리 습관이 남습니다

    계정 관리는 만들 때보다 치울 때 실력이 드러납니다. 테스트 계정, 임시 외주 계정, 스크립트용 서비스 계정(service account, 서비스 전용 계정)이 뒤섞이기 시작하면 금방 지저분해집니다. 제가 1년 동안 정리하면서 체감한 운영 팁은 아래와 같습니다.

    • 개인 계정과 서비스 계정을 섞지 않습니다.
    • 공용 계정을 최소화합니다. 가능하면 개인 계정 기반으로 갑니다.
    • sudo 권한은 그룹 단위로 관리합니다.
    • 서버 접속 방식은 SSH 키 중심으로 통일합니다.
    • 퇴역 계정은 잠금(lock) 후 일정 기간 뒤 삭제하는 식으로 단계적으로 정리합니다.

    5-1. 계정 잠금과 만료 처리

    sudo passwd -l minsu
    sudo usermod -L minsu
    sudo chage -l minsu

    즉시 삭제보다 잠금부터 거는 이유는, 혹시 남아 있는 프로세스나 파일 소유권 이슈를 확인할 시간이 필요해서입니다. 처음엔 저도 바로 삭제했었는데, 나중에 cron(Cron, 예약 작업)이나 백업 스크립트에서 참조 중인 경우가 있더라고요.

    5-2. 정말 삭제할 때

    sudo userdel -r minsu

    단, -r 옵션은 홈 디렉터리까지 지우기 때문에 신중해야 합니다. 여기서 중요한 포인트! 삭제 전에 파일 소유권 검색은 꼭 한 번 해보세요.

    sudo find / -user minsu 2>/dev/null | head

    6. ⚠️ 실제로 많이 겪는 문제와 해결법

    이 섹션은 정말 경험담 위주입니다. 제가 직접 해보니, Linux 사용자 관리에서 막히는 포인트는 대체로 비슷했습니다.

    6-1. sudo가 안 되는 경우

    원인은 보통 세 가지였습니다.

    1. 사용자가 올바른 그룹에 들어가 있지 않음
    2. /etc/sudoers.d/ 파일 권한이나 문법 오류
    3. 새 그룹 적용 전에 세션 재로그인 안 함
    id minsu
    sudo visudo -c
    ls -l /etc/sudoers.d/
    newgrp ops

    visudo -c로 문법 검사를 먼저 해보면 생각보다 빨리 원인을 찾습니다. 저도 sudoers 문법 한 글자 잘못 넣고 한참 헤맨 적이 있었는데, 그때 깨달았습니다. sudo 설정은 “될 것 같은데 안 되는” 상태가 제일 사람 지치게 하더라고요.

    6-2. SSH 키는 맞는데 로그인 실패

    대부분은 권한 문제였습니다.

    • ~/.ssh 권한이 너무 넓음
    • authorized_keys 소유자가 다름
    • 홈 디렉터리 권한이 과하게 열려 있음

    이럴 때는 계정만 보지 말고 상위 디렉터리까지 같이 확인해야 합니다.

    6-3. 사용자 삭제 후 파일 찌꺼기 남음

    이건 생각보다 흔합니다. 파일 서버나 백업 경로에 예전 UID(User ID, 사용자 식별자) 소유 파일이 남아 있으면 나중에 권한 꼬임으로 이어질 수 있습니다. 삭제 전에 파일 검색, 삭제 후 UID 재사용 주의, 이 두 개는 꼭 기억해두면 좋습니다.

    Linux 사용자 관리 트러블슈팅과 sudo 권한 점검 장면 이미지

    sudo 문법 검사, 그룹 확인, SSH 권한 점검 같은 트러블슈팅 과정을 터미널 시점으로 보여주는 이미지입니다.

    7. 검증과 결과 확인: 설정은 했고, 이제 믿어도 되나?

    설정이 끝났다고 바로 안심하면 안 됩니다. 저는 마지막 검증 단계를 따로 두는 편입니다. 왜냐하면 계정과 권한은 “지금 된다”보다 “다음 로그인에서도 일관되게 된다”가 더 중요하거든요.

    7-1. 기본 검증 명령

    id minsu
    getent passwd minsu
    getent group ops
    sudo -l -U minsu
    su - minsu
    whoami
    sudo whoami

    여기서 기대 결과는 명확합니다. 일반 로그인 시에는 사용자 본인, sudo 실행 시에는 root가 나와야 합니다. 그리고 sudo -l -U 사용자명으로 허용된 명령 범위를 눈으로 확인하는 습관이 좋습니다.

    7-2. 운영 기준 체크리스트

    • 루트 직접 SSH 로그인 비활성화 여부 확인
    • 불필요한 계정 잠금 또는 삭제 완료
    • sudo 정책이 그룹 단위로 분리되어 있는지 확인
    • SSH 키 권한과 소유권 점검
    • 계정 생성/변경/삭제 절차를 문서화했는지 확인

    이렇게 정리하고 나니, 서버를 새로 추가해도 기준이 흔들리지 않았습니다. 예전에는 서버마다 계정 상태가 제각각이었는데, 지금은 최소한 “어디를 보면 되는지”가 정해져 있으니 정신이 훨씬 덜 없더라고요.

    Linux 사용자 관리 검증 결과와 체크리스트를 보여주는 이미지

    계정 상태, 그룹 소속, sudo 허용 범위, SSH 점검 항목을 한눈에 확인하는 검증 결과 이미지입니다.

    8. 정리와 다음 단계: Linux 사용자 관리, 결국 기본기가 다 합니다

    이번 글을 한 줄로 정리하면 이겁니다. Linux 사용자 관리는 명령어 몇 개 외우는 일이 아니라, 운영 기준을 만들고 지키는 습관입니다. 제가 1년 동안 계속 다듬어보니 가장 효과가 컸던 건 세 가지였습니다. 일반 사용자 계정으로 작업하기, sudo 권한을 그룹과 정책 파일로 분리하기, 그리고 계정 생애주기(lifecycle, 생성부터 삭제까지)를 끝까지 챙기기. 사실 화려한 기술은 아니지만, 이런 기본기가 서버 안정성을 꽤 오래 받쳐줍니다.

    다음 단계로는 PAM(Pluggable Authentication Modules, 인증 모듈) 정책, SSH 하드닝(hardening, 보안 강화), 그리고 중앙 인증까지 확장해보면 좋습니다. 이전 글에서 다뤘던 SSH 키 운영 방법이 있다면 같이 묶어보셔도 좋고, 다음 글에서는 sudo 로그와 감사(audit, 추적 기록) 중심으로 더 깊게 다뤄볼 예정입니다.

    자주 묻는 질문

    1. 루트 계정을 완전히 안 써도 되나요?
      완전히 안 쓴다기보다, 평소 작업은 일반 계정 + sudo로 돌리고 루트 직접 로그인 빈도를 최소화하는 쪽이 안전했습니다.
    2. sudo 권한은 사용자별로 주는 게 좋나요?
      짧게는 가능하지만, 운영이 길어질수록 그룹 기반 관리가 훨씬 덜 헷갈렸습니다.
    3. 계정 삭제 전에 꼭 확인할 건 뭔가요?
      파일 소유권, 예약 작업, SSH 키, 서비스 참조 여부입니다. 삭제보다 잠금부터 거는 방식이 실무에서 덜 위험했습니다.

    사용자, 그룹, sudo 권한, SSH 보안, 계정 정리 원칙을 한 장으로 요약한 마무리 인포그래픽입니다.

    결국 Linux 운영에서 사고를 줄이는 가장 현실적인 방법은, 계정과 권한부터 차분히 정리하는 겁니다. 화려하진 않지만 효과는 확실합니다. 저도 처음엔 이게 뭔가 싶었는데, 계속 손에 익히고 나니 서버 운영의 체력이 여기서 나온다는 걸 알겠더라고요.

  • [리눅스 방화벽] iptables에서 firewalld로 전환 1년 후기

    [리눅스 방화벽] iptables에서 firewalld로 전환 1년 후기

    [리눅스 방화벽] iptables에서 firewalld로 전환 1년 후기

    운영 서버를 오래 만지신 분들이라면 한 번쯤은 iptables firewalld 비교를 고민해보셨을 겁니다. 저도 그랬습니다. 기존에는 익숙한 iptables 규칙(rule)으로만 버텼는데, 서비스가 늘고 홈랩까지 커지니까 관리 포인트가 점점 복잡해지더라고요. 그래서 1년 전부터 주요 리눅스 방화벽 정책을 firewalld로 옮겨서 운영했고, 오늘은 그 firewalld 후기를 경험 중심으로 정리해보려고 합니다. 처음엔 “이걸 굳이 왜 바꾸지?” 싶었는데, 실제로 써보니까 장점이 분명했고 반대로 불편한 점도 꽤 선명했어요.

    특히 이번 글은 단순 기능 소개가 아니라, 방화벽 마이그레이션을 하면서 제가 어디서 삽질했는지, 어떤 서버에는 잘 맞고 어떤 서버에는 굳이 안 옮겨도 되는지까지 현실적으로 적어보겠습니다. 혹시 지금도 배포판 기본 방화벽을 끄고 iptables 스크립트만 직접 관리하고 계시다면, 이 글이 판단 기준이 될 거예요.

    홈랩과 운영 서버가 섞인 리눅스 방화벽 전환 개요 다이어그램

    iptables에서 firewalld로 바꾸는 전체 흐름을 한눈에 보여주는 개요 이미지입니다.

    왜 iptables에서 firewalld로 옮겼는가

    제 경우 계기는 아주 단순했습니다. 규칙이 늘어날수록 사람이 실수하기 쉬워졌기 때문이거든요. iptables 자체가 나쁜 도구라는 뜻은 아닙니다. 오히려 굉장히 강력하고, 익숙해지면 빠릅니다. 다만 운영 기간이 길어질수록 이런 문제가 생기더라고요.

    • 서버마다 규칙 파일 구조가 조금씩 달랐어요.
    • 포트 하나 열 때도 저장 위치와 반영 방식이 서버마다 달랐어요.
    • 임시 변경과 영구 변경이 섞여서, 재부팅 후 정책이 달라지는 일이 있었습니다.
    • 새로운 팀원이 들어오면 규칙 읽는 데 시간이 꽤 걸렸어요.

    반면 firewalld는 zone(존, 신뢰 수준별 정책 구역), service(서비스, 미리 정의된 포트/프로토콜 묶음), runtime/permanent(실행 중 설정/영구 설정) 개념이 있어 운영 언어가 훨씬 사람 친화적이더라고요. 저도 처음엔 이 추상화가 오히려 번거로울 줄 알았는데, 1년 써보니 일상 운영에서는 확실히 읽기 쉽고 설명하기도 편했어요.

    iptables와 firewalld 개념 비교

    쉽게 말해 iptables는 규칙을 직접 조립하는 방식에 가깝고, firewalld는 운영에 필요한 구조를 얹어서 관리하는 방식이라고 보면 돼요. 물론 내부적으로는 리눅스 패킷 필터링 체계인 Netfilter(넷필터, 커널 네트워크 필터링 프레임워크) 위에서 동작하는 거고요.

    항목 iptables firewalld
    관리 방식 규칙 중심 존/서비스 중심
    가독성 규칙이 많아지면 급격히 떨어짐 일반 운영자는 읽기 쉬움
    즉시 반영 직접 명령 실행 필요 runtime 설정으로 빠르게 반영 가능
    영구 반영 배포판별 저장 방식 차이 존재 permanent 개념이 비교적 명확
    추상화 수준 낮음 높음
    세밀한 제어 매우 강함 rich rule로 가능하지만 사고방식이 다름

    여기서 중요한 포인트가 있습니다. firewalld가 iptables를 완전히 대체하는 느낌으로 접근하면 초반에 헷갈려요. 저도 처음엔 규칙 한 줄 한 줄을 그대로 옮기려다가 막혔거든요. 실제 firewalld 마이그레이션은 “현재 규칙을 그대로 복제”보다 “정책을 다시 모델링”하는 쪽이 훨씬 잘 돼요.

    방화벽 마이그레이션 전에 먼저 점검한 것들

    실제로 써보니까 전환 전에 이 단계가 제일 중요했어요. 여기 대충 넘어가면 나중에 SSH 잠기거나, 내부 서비스만 죽는 식으로 애매한 장애가 나옵니다.

    1. 현재 오픈 포트 목록을 정리하세요.
    2. 서버 역할을 분류합니다. 웹 서버, DB 서버, 점프 호스트(jump host), 홈랩 내부 노드처럼요.
    3. 인터페이스별 신뢰 수준을 구분하세요. 예를 들어 외부망 NIC와 내부망 NIC가 같으면 안 돼요.
    4. 기존 iptables 룰 중 예외 규칙을 따로 뽑으세요. 이 부분을 자주 놓칩니다.
    5. 콘솔 접근 수단을 확보하세요. 원격 SSH만 믿고 바꾸는 건 위험해요.

    저는 아래처럼 최소한의 체크리스트를 만들어 놓고 시작했습니다.

    # 현재 리스닝 포트 확인
    ss -tulpn
    
    # 현재 iptables 규칙 확인
    iptables -L -n -v
    iptables -S
    
    # 방화벽 관련 서비스 상태 확인
    systemctl status firewalld
    systemctl status iptables
    
    # 네트워크 인터페이스 확인
    ip addr
    ip route

    이 단계에서 제가 가장 크게 느낀 건, 오래된 서버일수록 “왜 있는지 아무도 모르는 규칙”이 꼭 있다는 점이에요. 진짜입니다. 저도 몇 개는 지우기 무서워서 한동안 주석만 달아뒀습니다 ㅎㅎ

    실전 구현: iptables에서 firewalld로 옮긴 방식

    이제 본론입니다. 아래 예시는 배포판 기본 패키지 구성이 있는 환경에서, SSH와 웹 서비스만 우선 허용하는 가장 보수적인 전환 흐름입니다. 실제 포트는 각자 환경에 맞게 바꾸시면 돼요.

    1. firewalld 상태 확인 및 시작

    sudo systemctl enable --now firewalld
    sudo firewall-cmd --state
    sudo firewall-cmd --get-active-zones

    여기서 active zone(활성 존)이 예상과 다르면 바로 멈추셔야 해요. 저는 처음에 내부 브리지 인터페이스가 원치 않는 존으로 붙어서 한참 헤맸습니다.

    2. 기본 존과 허용 서비스 점검

    sudo firewall-cmd --get-default-zone
    sudo firewall-cmd --list-all
    
    # SSH 허용
    sudo firewall-cmd --permanent --add-service=ssh
    
    # HTTP/HTTPS 허용
    sudo firewall-cmd --permanent --add-service=http
    sudo firewall-cmd --permanent --add-service=https
    
    # 특정 포트 직접 허용 예시
    sudo firewall-cmd --permanent --add-port=8443/tcp

    firewalld의 장점 중 하나가 바로 이 부분이에요. 서비스 이름으로 여는 규칙은 읽는 사람 입장에서 훨씬 직관적이거든요. 나중에 문서화할 때도 편하고요.

    3. 내부망 인터페이스를 별도 존으로 분리

    홈랩이나 사내 테스트망처럼 내부 트래픽이 많은 환경에서는 이 구성이 꽤 중요해요. 외부망과 내부망을 같은 존에 넣어버리면 정책이 너무 느슨해지거나, 반대로 필요 이상으로 빡빡해져요.

    # 내부용 zone 생성
    sudo firewall-cmd --permanent --new-zone=internal-lab
    
    # 내부 인터페이스를 새 zone에 연결
    sudo firewall-cmd --permanent --zone=internal-lab --add-interface=eth1
    
    # 내부 zone에 필요한 서비스 허용
    sudo firewall-cmd --permanent --zone=internal-lab --add-service=ssh
    sudo firewall-cmd --permanent --zone=internal-lab --add-service=samba
    
    # 설정 반영
    sudo firewall-cmd --reload

    제가 직접 해보니, 이 “존 설계”가 firewalld 운영 만족도를 거의 결정하더라고요. 규칙을 한 줄씩 옮기는 데 집중하지 말고, 어떤 네트워크를 어떤 신뢰 수준으로 볼지 먼저 정해야 해요.

    firewalld zone과 service 매핑이 보이는 서버 네트워크 구성 다이어그램

    외부망과 내부망을 zone으로 분리하는 실제 운영 구성을 설명하는 이미지입니다.

    4. 더 세밀한 예외는 rich rule로 처리

    iptables를 오래 쓰신 분들은 아마 이 지점이 제일 궁금하실 거예요. “그럼 복잡한 예외 규칙은 어떻게 하냐”는 거죠. firewalld에는 rich rule(리치 룰, 조건 기반 고급 규칙)이 있어서 이런 상황을 어느 정도 해결할 수 있어요.

    # 특정 소스 대역에서만 9100/tcp 허용 예시
    sudo firewall-cmd --permanent \
      --add-rich-rule='rule family="ipv4" source address="192.168.10.0/24" port port="9100" protocol="tcp" accept'
    
    sudo firewall-cmd --reload
    sudo firewall-cmd --list-rich-rules

    다만 솔직히 말씀드리면, 여기서부터는 다시 “추상화의 편안함”이 줄어들어요. 복잡한 제어가 많아질수록 iptables 사고방식으로 되돌아가거든요. 그래서 예외가 많은 서버라면 firewalld가 무조건 정답은 아니에요.

    5. 검증 전까지 기존 정책을 바로 폐기하지 않기

    저는 이 부분에서 예전에 크게 데인 적이 있어요. 한 번에 갈아엎지 마시고, 최소한 아래 순서로 검증하시는 걸 추천드립니다.

    1. 콘솔 또는 대체 접속 경로 확보
    2. 필수 서비스만 먼저 허용
    3. 외부에서 SSH, HTTP, 모니터링 포트 접근 테스트
    4. 내부망 서비스 통신 테스트
    5. 재부팅 후 정책 유지 여부 확인

    ⚠️ 실제로 겪었던 문제와 해결 과정

    이 섹션은 제 firewalld 후기에서 가장 현실적인 부분일 거예요. 문서만 보면 쉬워 보이는데, 막상 운영에 넣으면 생각보다 사소한 데서 걸려요.

    문제 1. runtime만 바꾸고 permanent를 빼먹음

    처음엔 이게 뭔가 싶었는데, 진짜 자주 실수해요. 테스트할 때는 잘 되는데 재부팅 후 다시 막히는 경우가 대표적이거든요.

    # 현재 runtime 설정 확인
    sudo firewall-cmd --list-all
    
    # 영구 설정 확인
    sudo firewall-cmd --permanent --list-all

    해결은 단순해요. 운영 반영은 permanent 기준으로 넣고, 마지막에 reload로 일관성 있게 맞추는 습관을 들이면 돼요.

    문제 2. 인터페이스가 예상과 다른 zone에 붙음

    특히 가상화 호스트, 브리지, VLAN 환경에서는 이 문제가 꽤 잘 나와요. 서비스는 살아 있는데 접근 정책이 엉뚱하게 적용되더라고요.

    sudo firewall-cmd --get-active-zones
    sudo firewall-cmd --zone=public --list-interfaces
    sudo firewall-cmd --zone=internal-lab --list-interfaces

    이럴 때는 인터페이스와 존 매핑을 먼저 의심하세요. 저도 포트 규칙만 계속 쳐다보다가 시간 많이 썼어요.

    문제 3. iptables 시절의 습관 때문에 구조가 더 꼬임

    이건 사람 문제인데 꽤 커요. 예전 방식대로 포트 단위 예외를 계속 덧붙이다 보면, firewalld의 장점이 사라져요. 결국 “왜 옮겼지?” 상태가 돼요. 실제로 저는 웹 서버, 점프 서버, 내부 스토리지 노드를 각각 다른 템플릿처럼 관리하면서 정리가 되기 시작했어요.

    문제 4. 서비스 정의와 직접 포트 개방이 섞여 가독성이 떨어짐

    가급적이면 잘 알려진 서비스는 service 단위로, 정말 필요한 예외만 포트 또는 rich rule로 두는 편이 좋았어요. 나중에 봐도 해석이 빠르거든요.

    운영 중 트러블슈팅 장면과 방화벽 규칙 점검 화면을 표현한 일러스트

    runtime/permanent 혼동과 zone 매핑 문제를 점검하는 트러블슈팅 상황을 담은 이미지입니다.

    검증: 전환 후 1년 운영하면서 본 변화

    제가 1년 정도 운영해보니, 가장 큰 변화는 정책 변경 속도보다 정책 이해 속도였어요. 방화벽은 한 번 만들고 끝이 아니라, 몇 달 뒤에 다시 읽고 수정해야 하잖아요. 그때 firewalld가 확실히 편했어요.

    • 새 포트 허용 요청을 처리할 때 설명이 쉬워졌어요.
    • 존 기반 구조 덕분에 내부망/외부망 정책을 분리하기 편했어요.
    • 운영 문서와 실제 설정의 괴리가 줄었어요.
    • 초기 적응만 지나면 반복 작업이 줄어들어요.

    반대로 아쉬운 점도 있었어요.

    • 아주 세밀한 예외가 많은 서버는 오히려 추상화가 답답할 수 있어요.
    • 기존 iptables 문법에 익숙한 사람은 초반 생산성이 떨어질 수 있어요.
    • 배포판과 환경에 따라 백엔드 동작 방식이 달라 보일 수 있어서, 내부 구조를 조금은 이해해야 해요.

    결론적으로 말하면, 리눅스 방화벽을 팀 단위로 운영하거나, 서버 역할이 비교적 명확한 환경에서는 firewalld가 꽤 좋았어요. 반면 초고도 커스텀 규칙 위주의 장비성 서버라면 기존 방식이 더 맞을 수도 있어요.

    # 최종 검증에 자주 쓴 명령들
    sudo firewall-cmd --list-all
    sudo firewall-cmd --list-services
    sudo firewall-cmd --list-ports
    sudo firewall-cmd --list-rich-rules
    ss -tulpn

    재부팅 테스트도 꼭 해보셔야 해요. 저는 검증의 마지막을 항상 “재부팅 후 SSH 접속, 웹 서비스 접속, 내부망 통신 확인”으로 끝냈어요. 귀찮아 보여도 이게 제일 확실하거든요. 드디어 됐다! 싶은 순간이 여기서 오더라고요.

    방화벽 전환 후 서비스 접근 테스트와 정상 통신 결과를 보여주는 대시보드 스타일 장면

    포트 개방, 서비스 접근, 내부망 통신이 정상인지 검증하는 결과 화면을 표현한 이미지입니다.

    iptables firewalld 비교: 1년 써보고 정리한 장단점

    구분 좋았던 점 아쉬웠던 점
    운영 편의성 zone/service 중심이라 설명과 인수인계가 쉬워요 개념을 익히기 전까지는 오히려 낯설 수 있어요
    정책 변경 명령이 직관적이고 확인 명령도 잘 갖춰져 있어요 runtime/permanent 이원화는 초반 실수 포인트
    가독성 역할별 정책이 잘 보여요 rich rule이 늘어나면 다시 복잡해져요
    적합한 환경 일반 서버, 홈랩, 역할 분리된 운영 환경 극단적으로 복잡한 예외 중심 환경은 고민 필요

    개인적으로는 방화벽 마이그레이션의 목적이 “더 강력한 방화벽”이 아니라 “더 읽기 쉬운 운영 체계”라면 firewalld가 좋은 선택이었어요. 이거 진짜 편하더라고요. 특히 여러 대를 비슷한 정책으로 운영할 때 더욱 그래요.

    정리: 이런 분들께는 firewalld 전환을 추천합니다

    • 서버 역할별로 방화벽 정책을 나누고 싶은 분
    • 팀 단위로 읽기 쉬운 설정을 원하시는 분
    • 홈랩에서 내부망과 외부망을 구분 운영하는 분
    • 기존 iptables 스크립트가 너무 길어져 관리가 어려운 분

    반대로 아래 경우는 조금 더 신중하게 보시는 게 좋아요.

    • 매우 복잡한 조건 규칙을 많이 쓰는 환경
    • 이미 안정적인 iptables 자동화 체계가 잘 굴러가는 환경
    • 관리자가 모두 기존 방식에 매우 익숙한 소규모 고정 환경

    저도 처음엔 헷갈렸는데, 1년 지나고 보니 핵심은 도구 자체보다 정책을 어떻게 구조화할지였어요. firewalld는 그 구조화를 돕는 쪽에 강점이 있었고요. 다음 글에서는 홈랩 기준으로 zone 설계 템플릿과 서비스별 기본 허용 정책을 따로 정리해볼 예정입니다. 이전 글에서 다뤘던 SSH 보안 강화와 함께 보시면 더 흐름이 잘 이어질 거예요.

    iptables와 firewalld 장단점을 한 장에 요약한 인포그래픽 스타일 비교 이미지

    iptables와 firewalld의 차이, 추천 환경, 운영 포인트를 요약한 비교 이미지입니다.

    자주 묻는 질문

    Q1. 기존 iptables 규칙을 그대로 옮기면 되나요?

    가능한 부분도 있지만, 저는 권장하지 않아요. 서비스와 인터페이스 기준으로 다시 설계하는 편이 훨씬 깔끔했거든요.

    Q2. firewalld가 항상 더 좋은가요?

    그건 아니에요. 운영 팀의 숙련도와 규칙 복잡도에 따라 다르거든요. 단순히 최신처럼 보여서 바꾸기보다는, 읽기 쉬움과 유지보수성을 기준으로 보시는 게 좋아요.

    Q3. 홈랩에도 쓸 만한가요?

    충분히 쓸 만해요. 특히 내부망, 실험망, 외부 노출 구간을 분리해서 운영하신다면 zone 개념이 꽤 유용하거든요.

  • [Linux] YUM에서 DNF로: CentOS 7에서 Rocky Linux 9로 마이그레이션

    [Linux] YUM에서 DNF로: CentOS 7에서 Rocky Linux 9로 마이그레이션

    [리눅스] YUM에서 DNF로: CentOS 7에서 Rocky Linux 9로 마이그레이션

    CentOS 7에서 Rocky Linux 9로 넘어가야 하는 시점이 오면 제일 먼저 부딪히는 게 YUM DNF 마이그레이션이더라고요. 운영 서버를 오래 굴려보신 분들은 아시겠지만, 패키지 관리자(package manager) 하나 바뀌는 문제가 생각보다 큽니다. 단순히 명령어만 바뀌는 게 아니라 저장소(repository), 의존성(dependency), 자동화 스크립트, 보안 업데이트 흐름까지 전부 영향받거든요. 특히 CentOS EOL 이후에는 더 미루기 어려워졌습니다. 저도 홈랩이랑 사내 테스트 장비에서 리눅스 OS 이전을 여러 번 해봤는데, 처음엔 “yum만 dnf로 바꾸면 끝 아닌가?” 싶었다가 삽질 좀 했습니다. 이번 글에서는 Rocky Linux 9 기준으로 YUM에서 DNF로 옮길 때 무엇을 확인해야 하는지, 어떤 식으로 이전하면 덜 위험한지 경험 기준으로 정리해보겠습니다.

    CentOS 7에서 Rocky Linux 9로 YUM DNF 마이그레이션 개요 이미지

    CentOS 7 환경에서 Rocky Linux 9 환경으로 넘어가며 패키지 관리 흐름이 바뀌는 모습을 보여주는 개요 이미지입니다.

    1. 왜 지금 YUM DNF 마이그레이션을 봐야 할까요?

    여기서 중요한 포인트가 있습니다. CentOS 7은 이미 수명 주기 종료(EOL, End of Life) 상태라서, 운영 환경에 그대로 두면 보안 패치와 유지보수 측면에서 부담이 커져요. 실제로 서버를 오래 운영하다 보면 “지금 잘 돌아가는데 굳이?”라는 생각이 드는데요, 이런 시기에 더 무서운 건 조용히 쌓이는 기술 부채(technical debt)입니다.

    패키지 관리자 관점에서 보면 CentOS 7은 익숙한 YUM(Yellowdog Updater Modified, RPM 계열 패키지 관리 도구) 중심이었고, Rocky Linux 9는 DNF(Dandified YUM, 개선된 차세대 패키지 관리자)가 기본입니다. 이름만 보면 YUM의 후속 버전처럼 보이지만, 실제로 써보니까 의존성 해결 방식, 메타데이터 처리, 플러그인 사용감이 꽤 달라졌더라고요.

    • CentOS 7은 오래된 운영 환경에 익숙한 자동화가 많이 붙어 있어요.
    • Rocky Linux 9는 보안과 최신 패키지 생태계 측면에서 훨씬 유리합니다.
    • YUM DNF 마이그레이션은 명령어 치환이 아니라 운영 습관 전체를 점검하는 작업에 가깝습니다.

    2. YUM과 DNF, 쉽게 말해 뭐가 다른가요?

    쉽게 말해, YUM이 오래된 익숙한 작업 방식이라면 DNF는 그걸 좀 더 현대적으로 다듬은 도구예요. 저도 처음엔 헷갈렸는데, 실제로 써보니까 차이는 몇 가지로 정리되더라고요.

    항목 CentOS 7 / YUM Rocky Linux 9 / DNF
    기본 패키지 관리자 yum dnf
    의존성 처리 기본적이며 오래된 방식 더 개선된 의존성 해결
    메타데이터 처리 익숙하지만 구형 환경 중심 성능과 관리 편의성이 개선됨
    자동화 스크립트 영향 yum 명령 하드코딩 사례 많음 dnf 기준으로 스크립트 점검 필요
    운영 포인트 레거시 유지보수 현행 표준 운영에 가까움

    Rocky Linux 9에서 yum 명령이 아예 완전히 사라진 건 아닐 수 있어요. 다만 운영 기준으로는 DNF를 표준으로 보고 스크립트와 문서를 정리하는 게 맞습니다. 저는 이 부분을 대충 넘겼다가 자동 배포 스크립트 일부가 애매하게 남아서, 나중에 어떤 서버는 yum, 어떤 서버는 dnf를 쓰는 어정쩡한 상태가 됐더라고요. 이런 건 초기에 정리하는 게 진짜 중요합니다.

    3. 마이그레이션 전략: 인플레이스 업그레이드보다 새 환경 이전이 안전합니다

    여기서 많이 물어보시는 게 “CentOS 7을 Rocky Linux 9로 바로 올리면 되나요?”인데요, 제 경험상 신규 Rocky Linux 9 서버를 만들고 워크로드를 이전하는 방식이 훨씬 안전했어요. 특히 메이저 버전을 두 단계 가까이 건너뛰는 식의 접근은 패키지 충돌, 라이브러리 차이, 서비스 설정 변경 때문에 예상보다 위험하거든요.

    1. 현재 CentOS 7 서버에서 설치 패키지와 저장소 구성을 수집합니다.
    2. 애플리케이션, 데이터, 설정 파일을 분리해서 백업합니다.
    3. 새 Rocky Linux 9 서버를 준비합니다.
    4. DNF 기준으로 필요한 패키지를 다시 설치합니다.
    5. 서비스 설정을 이관하고 동작을 검증합니다.
    6. 컷오버(cutover, 운영 전환) 후 구 서버를 단계적으로 종료합니다.

    이 방식이 귀찮아 보여도, 장애 대응이 훨씬 쉬워요. 실패했을 때 원복(rollback)도 명확하고요.

    4. 실전 구현: CentOS 7에서 현재 상태 정리하기

    제가 직접 해보니 마이그레이션의 절반은 “현재 상태를 얼마나 정확히 기록하느냐”에서 갈려요. 특히 오래된 서버는 누가 왜 추가했는지 모르는 패키지와 서드파티 저장소(third-party repository)가 꼭 있거든요.

    4-1. 설치된 패키지 목록 백업

    rpm -qa | sort > /root/centos7-rpm-list.txt
    yum repolist all > /root/centos7-repolist.txt
    yum history list > /root/centos7-yum-history.txt

    이 세 파일만 있어도 나중에 정말 도움이 돼요. 특히 rpm -qa 결과는 “어떤 기능 때문에 이 패키지가 필요했는지”를 추적하는 출발점이 됩니다.

    4-2. 서비스 목록과 활성화 상태 확인

    systemctl list-unit-files --type=service > /root/centos7-services.txt
    systemctl list-units --type=service --state=running > /root/centos7-running-services.txt

    운영 서버는 패키지보다 서비스가 더 중요해요. 패키지는 다시 깔면 되지만, 어떤 서비스가 자동 시작되었는지를 놓치면 전환 후에 “설치는 됐는데 왜 안 뜨지?” 상황이 바로 생기거든요.

    4-3. 설정 파일과 애플리케이션 데이터 백업

    tar czf /root/etc-backup.tar.gz /etc
    mkdir -p /root/migration-notes
    cp -a /var/www /root/migration-notes/ 2>/dev/null
    cp -a /opt /root/migration-notes/ 2>/dev/null

    물론 실제 운영에서는 애플리케이션별 데이터 경로를 더 정확히 잡아야 합니다. 웹 서버라면 /var/www, 자체 배포 앱이면 /opt, DB면 별도 덤프가 필수죠.

    CentOS 7 서버에서 YUM DNF 마이그레이션 사전 점검을 수행하는 이미지

    이전 작업 전에 현재 서버의 패키지와 서비스 상태를 정리하는 과정을 보여주는 이미지입니다.

    5. 실전 구현: Rocky Linux 9에서 DNF 기반으로 재구성하기

    이제 새 서버 쪽입니다. Rocky Linux 9에 들어오면 운영 습관을 DNF 중심으로 재정리하는 게 핵심이에요.

    5-1. 시스템 갱신과 기본 도구 설치

    sudo dnf update -y
    sudo dnf install -y dnf-plugins-core vim tar rsync

    dnf-plugins-core는 실무에서 꽤 자주 써요. 저장소 관리나 쿼리 작업할 때 진짜 편하더라고요.

    5-2. 자주 쓰는 YUM 명령을 DNF로 치환

    기존 YUM 명령 Rocky Linux 9 DNF 명령 설명
    yum install httpd dnf install httpd 패키지 설치
    yum remove httpd dnf remove httpd 패키지 제거
    yum update dnf update 패키지 갱신
    yum search nginx dnf search nginx 패키지 검색
    yum info podman dnf info podman 패키지 정보 확인
    yum repolist dnf repolist 저장소 목록 확인

    처음엔 별 차이 없어 보이죠. 근데 운영 자동화에서 이 차이가 커요. Ansible(앤서블, 자동화 도구) 플레이북이나 셸 스크립트 안에 yum이 하드코딩되어 있으면, 이참에 dnf 기준으로 정리하는 게 좋아요.

    5-3. 패키지 그룹과 저장소 확인

    sudo dnf repolist
    sudo dnf group list
    sudo dnf module list

    여기서 module(모듈, 버전 스트림 관리 기능) 개념이 처음엔 좀 낯설 수 있어요. 예전처럼 무조건 패키지 이름만 보고 설치하다가 원하는 버전이 안 맞는 경우가 생기거든요. 특히 언어 런타임이나 DB 클라이언트 계열은 모듈/저장소 정책을 한 번 더 확인하는 습관이 필요합니다.

    5-4. 예시: 웹 서버 재구성

    sudo dnf install -y httpd
    sudo systemctl enable --now httpd
    sudo systemctl status httpd

    여기서 중요한 포인트! 패키지 설치만 끝내고 만족하면 안 돼요. 서비스 활성화, 방화벽, SELinux(Security-Enhanced Linux, 보안 정책 프레임워크)까지 같이 봐야 실제 서비스가 떠요.

    sudo firewall-cmd --permanent --add-service=http
    sudo firewall-cmd --permanent --add-service=https
    sudo firewall-cmd --reload
    sudo restorecon -Rv /var/www/html

    CentOS 7에서 대충 넘어가던 권한/보안 이슈가 Rocky Linux 9에선 더 또렷하게 드러나는 경우가 많았어요. 저도 처음엔 “분명 httpd는 떴는데 왜 페이지가 안 보이지?” 하다가 SELinux 컨텍스트(context) 때문에 한참 봤었네요.

    Rocky Linux 9에서 DNF 기반 패키지 관리와 서비스 설정을 보여주는 이미지

    Rocky Linux 9에서 DNF, systemd, firewall-cmd, SELinux를 함께 점검하는 흐름을 보여주는 이미지입니다.

    6. ⚠️ 실제로 많이 걸리는 문제와 해결법

    이 섹션은 제가 특히 강조하고 싶은 부분이에요. YUM DNF 마이그레이션 자체보다, 주변 요소에서 더 많이 막히거든요.

    6-1. 서드파티 저장소가 그대로 안 붙는 문제

    CentOS 7 시절에 붙여둔 외부 저장소가 Rocky Linux 9에서는 바로 호환되지 않는 경우가 있어요. 배포판 버전, GPG 키, 패키지 경로가 달라졌기 때문입니다.

    • 기존 .repo 파일을 그대로 복사하지 마세요.
    • Rocky Linux 9 지원 여부를 먼저 확인하세요.
    • 지원이 불분명하면 OS 기본 저장소 우선으로 재설계하는 게 안전해요.

    6-2. 패키지 이름이 달라졌거나 사라진 문제

    레거시 패키지는 이름이 바뀌거나 더 이상 기본 저장소에 없을 수 있어요. 이럴 때는 억지로 같은 이름만 찾기보다, 기능 단위로 대체 패키지를 찾는 쪽이 낫습니다.

    sudo dnf search <keyword>
    sudo dnf provides '*/binary-name'

    예전엔 패키지 이름을 외워서 설치했다면, 이제는 파일 제공자(provides) 검색을 더 자주 써요. 이거 진짜 편하더라고요.

    6-3. 오래된 스크립트가 yum 전제인 문제

    배치 스크립트나 운영 문서에 이런 코드가 많이 남아 있어요.

    yum install -y rsync
    if yum repolist | grep -q epel; then
      echo "repo exists"
    fi

    이런 부분은 명시적으로 DNF 기준으로 바꾸는 게 좋아요.

    dnf install -y rsync
    if dnf repolist | grep -q epel; then
      echo "repo exists"
    fi

    호환 래퍼(wrapper)가 있더라도 운영 표준은 하나로 맞추세요. 혼용하면 나중에 문서, 인수인계, 자동화에서 꼭 꼬여요.

    6-4. SELinux와 방화벽 이슈

    사실 패키지 설치는 됐는데 서비스가 안 되는 경우, 원인은 DNF가 아니라 보안 정책인 경우가 많아요. 특히 다음 항목을 꼭 같이 봐야 합니다.

    • getenforce로 SELinux 상태 확인
    • journalctl -xeu 서비스명으로 서비스 로그 확인
    • firewall-cmd --list-all로 방화벽 규칙 확인
    • 웹/앱 데이터 경로의 컨텍스트와 권한 확인

    7. 검증: 마이그레이션 결과를 어떻게 확인할까요?

    저는 전환 작업이 끝나면 “설치됐다”가 아니라 “운영 관점에서 정상인가”를 봐요. 검증 체크리스트를 짧게라도 만드는 게 좋습니다.

    1. 필수 패키지가 DNF 기준으로 모두 설치되었는지 확인
    2. 주요 서비스가 부팅 후 자동 시작되는지 확인
    3. 애플리케이션 로그에 의존성 오류가 없는지 확인
    4. 방화벽과 SELinux 정책이 서비스 요구사항과 맞는지 확인
    5. 모니터링과 백업 작업이 새 서버에서 정상 동작하는지 확인
    dnf repolist
    rpm -qa | sort
    systemctl --failed
    ss -tulpn
    journalctl -p err -b

    이 다섯 줄만 잘 봐도 초반 점검은 꽤 돼요. 저는 여기에 애플리케이션 헬스체크(health check)까지 붙여서 최종 확인하는 편이에요. 드디어 됐다! 싶은 순간이 여기서 오죠.

    Rocky Linux 9 이전 후 YUM DNF 마이그레이션 검증 결과 이미지

    이전 후 서비스 상태와 로그를 검증하는 운영 점검 결과를 보여주는 이미지입니다.

    8. 정리와 FAQ: CentOS EOL 이후 운영 습관도 같이 바꿔야 합니다

    이번 YUM DNF 마이그레이션에서 핵심은 간단해요. CentOS 7의 레거시 운영 습관을 Rocky Linux 9 환경에 그대로 들고 오지 말자는 거예요. 패키지 관리자만 바뀌는 게 아니라 저장소 운영, 보안 정책, 자동화 기준까지 함께 정리해야 실제로 편해져요. 저도 처음엔 명령어 몇 개만 바꾸면 되는 줄 알았는데, 결국 문서와 스크립트까지 손봐야 마음이 편하더라고요.

    다음 글에서는 Rocky Linux 9로 넘어온 뒤 EPEL(Extra Packages for Enterprise Linux)이나 컨테이너 도구를 어떻게 정리하면 좋은지 다뤄볼 예정입니다. 이전 글에서 다룬 시스템 백업 전략과 함께 보시면 흐름이 더 잘 잡히실 겁니다.

    자주 묻는 질문

    • Q. CentOS 7에서 Rocky Linux 9로 바로 인플레이스 업그레이드해도 되나요?
      제가 직접 해본 기준으로는 권장하지 않아요. 새 서버를 만들고 데이터와 설정을 옮기는 방식이 훨씬 안전했습니다.
    • Q. Rocky Linux 9에서도 yum 명령을 써도 되나요?
      일부 환경에서는 동작할 수 있어도 운영 표준은 DNF로 맞추는 게 좋아요. 문서와 자동화도 함께 정리하세요.
    • Q. 가장 많이 놓치는 건 뭔가요?
      서드파티 저장소, SELinux, 자동 시작 서비스, 그리고 배포 스크립트 안의 yum 하드코딩입니다.
    YUM DNF 마이그레이션 핵심 체크포인트 요약 이미지

    CentOS 7에서 Rocky Linux 9로 옮길 때 꼭 확인할 체크포인트를 요약한 이미지입니다.

    마무리 체크리스트

    • CentOS EOL 대응이 필요한 서버인지 확인
    • 기존 YUM 기반 패키지와 저장소 목록 백업
    • Rocky Linux 9 신규 서버 준비
    • DNF 기준으로 패키지 재설치 및 저장소 정리
    • 서비스, 방화벽, SELinux, 로그까지 검증
    • 자동화 스크립트와 운영 문서를 DNF 기준으로 통일

    혹시 지금 CentOS 7 서버를 붙잡고 계신다면, 오늘은 최소한 패키지 목록이랑 서비스 목록부터 백업해보세요. 그 한 걸음이 나중에 진짜 큰 차이를 만들어요.