13년차의 서버실

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

[태그:] 사례 연구

  • [보안] IoT 기기 보안 사고 분석과 홈 네트워크 점검

    [보안] IoT 기기 보안 사고 분석과 홈 네트워크 점검

    [보안] IoT 기기 보안 사고 분석과 홈 네트워크 점검

    홈에서 카메라, 도어벨, 스마트 플러그, NAS(Network Attached Storage, 네트워크 저장장치), 공유기까지 다 붙여 쓰다 보면 편하긴 한데요. 문제는 IoT 기기 보안이 한 번만 삐끗해도 집 안 네트워크 전체가 흔들릴 수 있다는 겁니다. 저도 홈랩을 굴리면서 처음엔 “설마 집까지 노리겠나” 싶었는데, 실제로 포트 포워딩(Port Forwarding, 포트 전달) 잘못 열어둔 장비 로그를 보고 생각이 완전히 바뀌었어요. 로그인 시도는 생각보다 훨씬 자주 들어오더라고요. 오늘은 실제로 널리 알려진 사례를 바탕으로 홈 네트워크 보안을 어떻게 봐야 하는지, 그리고 개인이 당장 점검할 수 있는 방법까지 정리해보겠습니다.

    IoT 기기 보안과 홈 네트워크 보안 구조를 보여주는 아키텍처 다이어그램

    공유기, VLAN, IoT 기기, 인터넷을 연결한 전체 보안 구조를 한눈에 보여주는 개요 이미지입니다.

    1. 왜 IoT 기기 보안이 계속 사고로 이어질까요?

    쉽게 말해 IoT 기기는 “작은 컴퓨터”예요. 근데 서버처럼 꼼꼼하게 운영되지 않는 경우가 많거든요. 기본 비밀번호(Default Credentials, 출고 계정), 느린 업데이트, 과한 권한, 클라우드 계정 재사용 같은 문제가 겹치면 사고가 납니다.

    • 기본 계정을 바꾸지 않음
    • 펌웨어(Firmware, 장비 내장 소프트웨어) 업데이트가 늦음
    • UPnP(Universal Plug and Play, 자동 포트 개방 기능)로 외부 노출이 쉬워짐
    • 카메라 영상, 음성, 위치 같은 개인 정보 보호 이슈가 큼
    • 한 대가 뚫리면 같은 네트워크 다른 장비로 이동하기 쉬움

    여기서 중요한 포인트는, 공격자가 꼭 우리 집 자체에 관심이 있어서 들어오는 건 아니라는 거예요. 취약한 장비를 대량으로 스캔해서 봇넷(Botnet, 감염 장비 집합)에 편입시키거나, 계정 탈취 후 영상에 접근하거나, 내부망 이동의 발판으로 삼는 경우가 더 많거든요.

    2. 실제 사례 연구: 사고는 이렇게 터졌습니다

    사례 1. Mirai 봇넷과 기본 비밀번호 문제

    2016년에 악명 높았던 Mirai는 인터넷에 노출된 라우터, 카메라, DVR(Digital Video Recorder, 디지털 영상 녹화장치) 같은 IoT 기기를 노렸습니다. 핵심은 거창하지 않았어요. 기본 사용자명과 비밀번호를 그대로 둔 장비가 많았고, 그걸 자동으로 긁어서 감염시켰죠. 이건 “고급 해킹”이라기보다 운영 부주의가 대형 사고로 번진 전형적인 사례였습니다.

    제가 이 사례를 계속 꺼내는 이유가 있어요. 홈 네트워크 보안 상담 비슷하게 주변 지인들 환경을 같이 봐주다 보면, 아직도 admin/admin 류 조합이나 제조사 기본 계정이 남아 있는 경우를 꽤 보거든요. 저도 예전에 테스트용 카메라 하나를 세팅만 해두고 계정 변경을 미뤘다가 식은땀 났던 기억이 있어요. 삽질 좀 했습니다 ㅎㅎ

    사례 2. 가정용 카메라의 계정 보호 실패와 사생활 침해

    또 하나 많이 회자된 사례가 가정용 보안 카메라 서비스의 계정 보호 실패 문제예요. 잘 알려진 공개 사례에서는 직원 또는 계약자가 고객 영상에 과도하게 접근할 수 있었고, 일부 계정은 Credential Stuffing(크리덴셜 스터핑, 유출된 계정 정보 재사용 공격)이나 무차별 대입에 취약해 사용자 카메라와 영상이 침해됐어요. 이 사례가 보여준 건 딱 두 가지입니다. 첫째, 기기 자체 보안만 보면 안 된다는 거고, 둘째, 클라우드 계정 보안이 뚫리면 집 안 영상까지 넘어간다는 겁니다.

    즉, IoT 기기 보안은 장비 한 대의 문제가 아니라 계정, 네트워크, 클라우드, 앱 권한까지 다 같이 봐야 해요.

    3. 핵심 개념 정리: 내 홈 네트워크는 어디서 위험해질까?

    쉽게 말해 공격 경로는 아래 네 군데에서 시작됩니다.

    위험 지점 설명 대표 문제
    기기(Device) 카메라, 센서, 플러그 자체 취약점 기본 계정, 미적용 패치
    공유기(Router) 외부와 내부를 잇는 관문 UPnP, 불필요한 포트 개방
    계정(Account) 앱/클라우드 로그인 정보 비밀번호 재사용, MFA 미설정
    내부망(LAN) 같은 네트워크의 다른 장비 평면망, 세그먼트 미분리

    저는 홈랩에서 이걸 항상 이렇게 설명해요. IoT 전용망을 따로 두고, 메인 PC와 NAS는 멀리 떼어놓는 것. 이게 생각보다 체감 효과가 크거든요. VLAN(브이랜, 가상 LAN)까지 가면 더 좋고, 그게 아직 부담되면 최소한 게스트 네트워크라도 분리해보세요.

    4. 실전 점검 1단계: 우리 집에 뭐가 붙어 있는지부터 확인

    보안 점검은 화려한 장비보다 가시성(Visibility, 무엇이 있는지 아는 것)이 먼저예요. 모르는 기기가 붙어 있으면 방어가 안 되거든요.

    1. 공유기 관리자 화면에서 연결 기기 목록을 확인해보세요.
    2. 기기 이름이 모호하면 MAC 주소와 제조사 정보를 대조합니다.
    3. 사용하지 않는 장비는 Wi-Fi 자격 증명부터 바꿉니다.
    4. 외부 개방 포트와 UPnP 상태를 같이 봐야 해요.

    리눅스 환경이나 홈 서버가 있다면 아래처럼 확인할 수 있어요.

    ip neigh
    nmap -sn 192.168.0.0/24
    sudo ss -tulpn
    

    <code>nmap -sn은 핑 스캔(Ping Scan, 생존 호스트 탐지)이고, ss -tulpn은 현재 열려 있는 소켓을 봅니다. 결과를 해석할 때는 “이 포트가 왜 열려 있지?”를 꼭 묻는 습관이 필요해요. 저도 처음엔 mDNS(multicast DNS, 로컬 장치 자동 발견) 트래픽을 보고 괜히 놀랐었는데, 정상 서비스와 비정상 노출을 구분하는 눈이 생기면 훨씬 편해집니다.

    IoT 기기 보안을 위한 공유기 연결 기기 목록과 포트 점검 이미지

    공유기 연결 목록, 포트 포워딩, UPnP 설정 위치를 설명하는 이미지입니다.

    5. 실전 점검 2단계: 바로 효과 보는 홈 네트워크 보안 설정

    제가 실제로 추천하는 순서는 복잡하지 않아요. 비싼 장비보다 기본기부터 잡는 게 먼저거든요.

    1. 기본 계정 변경: 제조사 기본 ID/PW는 바로 교체해야 해요.
    2. MFA(Multi-Factor Authentication, 다중 인증) 활성화: 클라우드 연동 서비스는 꼭 켜세요.
    3. UPnP 비활성화: 자동 포트 개방은 편하지만 사고가 납니다.
    4. 세그먼트 분리: IoT 전용 SSID 또는 게스트 네트워크를 분리하세요.
    5. 원격 관리 차단: 외부에서 공유기 관리자 페이지 접근은 꺼두는 게 좋아요.
    6. 정기 업데이트: 펌웨어 자동 업데이트가 가능하면 꼭 켜세요.

    예를 들어 방화벽(Firewall, 트래픽 통제 장치)이나 리눅스 라우터를 직접 운영한다면 개념은 이런 식입니다.

    # IoT 대역은 인터넷만 허용하고 내부 주요 자산은 차단하는 예시 개념
    iptables -A FORWARD -s 192.168.50.0/24 -d 192.168.10.0/24 -j DROP
    iptables -A FORWARD -s 192.168.50.0/24 -d 192.168.20.0/24 -j DROP
    iptables -A FORWARD -s 192.168.50.0/24 -p tcp --dport 443 -j ACCEPT
    iptables -A FORWARD -s 192.168.50.0/24 -p udp --dport 53 -j ACCEPT
    

    이건 어디까지나 개념 예시예요. 실제 정책은 DNS, NTP, 앱 연동 주소를 고려해서 조정해야 해요. 처음엔 차단 후 허용 방식이 답답한데, 한 번 틀을 잡아두면 나중엔 진짜 편해집니다.

    구성 파일을 IaC(Infrastructure as Code, 코드형 인프라)처럼 관리한다면 이런 식으로 기록을 남겨두는 것도 좋습니다.

    iot_network:
      subnet: 192.168.50.0/24
      allow_outbound:
        - dns
        - ntp
        - https
      deny_internal_access:
        - 192.168.10.0/24
        - 192.168.20.0/24
      upnp: false
      remote_admin: false
    

    6. ⚠️ 트러블슈팅: 제가 실제로 자주 본 문제들

    경고 포인트는 대체로 비슷해요. 설정은 맞는 것 같은데 기기가 안 붙거나, 앱 연동이 끊기거나, 영상 업로드가 실패하는 경우가 많거든요.

    • 문제 1. IoT 전용망으로 옮기니 앱에서 장비가 안 보임
      원인: 같은 브로드캐스트 도메인(Broadcast Domain, 장치 자동 검색이 도는 네트워크 범위)이 아니어서 자동 발견이 깨진 경우가 많아요.
    • 해결: 초기 등록만 메인망에서 하고, 이후 IoT망으로 이동하거나 mDNS 릴레이가 가능한 장비를 써보세요.
    • 문제 2. 카메라가 갑자기 오프라인으로 보임
      원인: DNS, NTP, HTTPS 중 하나를 과하게 막았을 가능성이 커요.
    • 해결: 먼저 DNS와 시간 동기화부터 열어봐요. 시간 틀어지면 TLS(Transport Layer Security, 암호화 통신) 인증서 검증이 꼬이는 경우가 있거든요.
    • 문제 3. 외부 접속이 안 돼서 포트를 열고 싶어짐
      원인: 편의성 압박이죠. 근데 여기서 많이 무너져요.
    • 해결: 가능하면 VPN(Virtual Private Network, 가상 사설망)으로 우회하세요. 직접 포트 노출은 정말 마지막 수단으로 두는 게 좋아요.

    혹시 이런 경험 있으세요? 분리까지는 했는데 음성 스피커 연동이 꼬이고, 가족들이 불편하다고 해서 다시 합치는 경우 말이에요. 저도 그랬어요. 그래서 제 기준은 “완벽한 제로 트러스트”보다 가족이 유지 가능한 수준의 보안이에요. 현실적으로 굴러가야 하니까요.

    홈 네트워크 보안을 위한 IoT 전용 VLAN 분리 구성 이미지

    메인 네트워크와 IoT 전용 네트워크를 분리한 예시 구성도입니다.

    7. 검증: 설정 후 무엇을 확인해야 안전하다고 볼 수 있을까?

    설정만 해두고 끝내면 아쉬워요. 검증이 있어야 해요.

    1. 공유기에서 UPnP 비활성화 상태를 재확인해보세요.
    2. 포트 포워딩 목록에 불필요한 규칙이 없는지 봐요.
    3. IoT 대역에서 NAS, 메인 PC로 핑이나 관리 포트 접근이 막히는지 확인하세요.
    4. 각 서비스 계정의 MFA 적용 여부를 다시 체크해봐요.
    5. 이상 로그인 알림, 새 장치 로그인 메일을 켜세요.

    간단한 확인 예시는 아래처럼 해볼 수 있어요.

    nmap 192.168.10.20
    nmap 192.168.20.30
    ping 192.168.10.20
    

    IoT 대역 장비에서 위 테스트가 막히거나 제한적으로만 동작하면 의도한 분리가 어느 정도 적용된 거예요. 반대로 NAS 관리 포트나 SSH가 그대로 열리면 아직 평면망에 가깝다고 보셔야 해요.

    그리고 로그를 꼭 봐요. 방화벽 로그든 공유기 보안 로그든, 실제로 써보면 생각보다 많은 스캔과 실패한 로그인 시도가 보여요. 처음엔 좀 무섭거든요. 근데 그걸 보는 순간부터 보안이 추상적인 개념이 아니라 운영 이슈로 바뀌어요. 저는 그때부터 습관이 바뀌더라고요.

    IoT 기기 보안 검증을 위한 방화벽 로그와 차단 결과 대시보드 이미지

    차단 로그, 실패한 접속 시도, 세그먼트 분리 결과를 보여주는 검증용 이미지입니다.

    8. 정리와 FAQ: 개인 정보 보호까지 같이 봐야 합니다

    오늘 사례 연구의 결론은 단순해요. IoT 기기 보안은 장비 스펙보다 운영 습관이 더 중요합니다. Mirai 같은 사례는 기본 비밀번호 하나가 얼마나 큰 문제로 이어질 수 있는지 보여줬고, 가정용 카메라 계정 침해 사례는 개인 정보 보호가 곧 보안이라는 걸 보여줬어요.

    • Q. 비싼 공유기면 안전한가요?
      A. 장비 품질은 도움이 되지만, 기본 계정 방치와 포트 노출을 막아주진 않아요.
    • Q. IoT 기기를 전부 버려야 하나요?
      A. 아니에요. 네트워크 분리, 계정 보호, 업데이트만 제대로 해도 위험을 크게 줄 수 있습니다.
    • Q. 가장 먼저 할 한 가지는 뭔가요?
      A. UPnP를 끄고, 클라우드 계정 MFA를 켜고, 기본 비밀번호를 바꾸는 거예요.

    다음 글에서는 VLAN을 이용한 좀 더 촘촘한 홈 네트워크 보안 구성과, NAS/서버/IoT를 어떻게 나눠야 관리가 쉬운지 실제 홈랩 기준으로 풀어보겠습니다. 이전 글에서 다뤘던 백업 전략과 연결해서 보면 더 이해가 잘 될 거예요.

    IoT 기기 보안 점검 체크리스트와 홈 네트워크 보안 우선순위 요약 이미지

    기본 계정 변경, MFA, 업데이트, 네트워크 분리, 로그 확인 순서로 요약한 이미지입니다.

    마지막으로 한 줄 요약하자면 이거예요. 내 홈 네트워크는 “안전하겠지”가 아니라 “어디까지 노출됐는지 확인했는가”로 판단해야 합니다. 이 차이가 꽤 커요. 직접 점검해보면 생각보다 금방 개선할 수 있어요. 드디어 됐다! 싶은 순간이 오거든요. 그때부터 운영이 훨씬 덜 불안해져요.

  • [Linux] 리눅스 시스템 장애, 프로세스 비정상 종료 원인 분석 및 해결 사례 연구

    [Linux] 리눅스 시스템 장애, 프로세스 비정상 종료 원인 분석 및 해결 사례 연구

    [Linux] 리눅스 시스템 장애, 프로세스 비정상 종료 원인 분석 및 해결 사례 연구

    운영 중인 서버에서 갑자기 애플리케이션이 내려가고, 재시작은 되는데 원인이 안 보일 때가 있죠. 저도 홈랩과 실무에서 이런 일을 여러 번 겪었습니다. 특히 리눅스 프로세스 비정상 종료는 겉으로 보기엔 단순한 장애처럼 보여도, 실제로는 메모리 부족, 시그널(signal, 운영체제가 프로세스에 보내는 제어 신호), 파일 디스크립터(file descriptor, 열린 파일 핸들), 권한 문제, 디스크 I/O 지연처럼 여러 원인이 겹쳐 있는 경우가 많거든요. 이번 글에서는 제가 직접 겪었던 실제 시스템 장애 사례를 바탕으로, 로그 분석과 원인 분석을 어떻게 진행했는지, 그리고 어떤 순서로 복구했는지 차근차근 정리해보겠습니다.

    리눅스 프로세스 비정상 종료 분석 흐름을 보여주는 서버 운영 다이어그램

    장애 발생부터 로그 수집, 원인 분석, 복구까지의 전체 흐름을 한눈에 보는 개요 이미지입니다.

    1. 왜 리눅스 프로세스 비정상 종료가 까다로운가

    처음 장애를 보면 보통 이렇게 생각합니다. “프로세스가 죽었네? 다시 올리면 되겠지.” 근데 여기서 끝내면 같은 문제가 또 터지더라고요. 쉽게 말해 리눅스 프로세스 비정상 종료는 결과일 뿐이고, 진짜 봐야 하는 건 그 직전의 시스템 상태입니다.

    • OOM Killer(Out Of Memory Killer, 메모리 부족 시 커널이 프로세스를 강제 종료하는 기능)가 개입했는지
    • SIGKILL, SIGSEGV, SIGABRT 같은 종료 신호가 있었는지
    • systemd가 재시작 정책으로 계속 덮어쓰고 있지는 않은지
    • 애플리케이션 로그와 커널 로그의 시간이 정확히 맞는지
    • 디스크 공간이나 inode(아이노드, 파일 메타데이터 구조)가 바닥난 건 아닌지

    여기서 중요한 포인트! 애플리케이션만 보면 절반만 보는 겁니다. 커널 로그, 서비스 매니저, 리소스 한계값까지 같이 봐야 퍼즐이 맞습니다.

    2. 개념부터 정리: 프로세스는 왜 비정상 종료될까요?

    저도 처음엔 헷갈렸는데, 원인을 큰 범주로 나누면 훨씬 수월합니다.

    2-1. 대표적인 종료 원인

    원인 설명 대표 징후
    메모리 부족 커널이 OOM Killer를 실행 dmesg에 kill process 기록
    세그멘테이션 폴트 잘못된 메모리 접근 Segmentation fault, core dumped
    강제 종료 시그널 운영자, 스크립트, 오케스트레이터가 종료 exit code 137, signal 9
    리소스 제한 초과 ulimit, nofile, nproc 초과 Too many open files
    스토리지 문제 디스크 full, inode 고갈, I/O 지연 write 실패, journal 오류
    권한/환경 문제 파일 권한, 환경 변수, 라이브러리 누락 permission denied, missing library

    2-2. 종료 코드(exit code)도 힌트입니다

    운영하다 보면 종료 코드 하나가 실마리가 되기도 합니다. 예를 들어 137은 보통 SIGKILL과 연결해서 보게 되고, 139는 Segmentation fault 가능성을 먼저 의심하게 되죠. 물론 이 숫자만 보고 단정하면 안 됩니다. 저는 항상 “종료 코드 확인 → journald 확인 → 커널 로그 확인” 순서로 갔습니다.

    3. 사례 연구: 새벽에 반복된 시스템 장애, 처음엔 앱 버그인 줄 알았습니다

    이번 사례 연구는 제가 홈랩에서 돌리던 API 서비스에서 실제로 겪은 패턴을 바탕으로 재구성한 내용입니다. 구조는 단순했습니다. Nginx(엔진엑스, 웹 서버) 뒤에 Python 기반 API가 있었고, systemd로 서비스 관리 중이었죠. 증상은 이랬습니다.

    1. 특정 시간대에 응답 지연이 먼저 발생했습니다.
    2. 이후 워커 프로세스가 하나씩 사라졌습니다.
    3. systemd가 자동 재시작했지만 잠시 뒤 다시 종료됐습니다.
    4. 모니터링에서는 CPU보다 메모리 사용량이 비정상적으로 치솟았습니다.

    처음엔 코드 메모리 누수(memory leak, 메모리를 반환하지 못하는 현상)인 줄 알았거든요. 근데 로그를 차근차근 맞춰보니, 원인이 하나가 아니었습니다. 삽질 좀 했습니다 ㅎㅎ

    4. 실전 분석 1단계: 로그 분석으로 타임라인부터 맞췄습니다

    장애 분석에서 제가 제일 먼저 하는 건 “시간축 맞추기”입니다. 여러 로그를 뒤섞어 보면 정신없는데, 같은 시각 기준으로 정렬하면 보이는 게 많아집니다.

    date
    uptime
    systemctl status myapi.service
    journalctl -u myapi.service --since "2026-07-01 00:00:00" --until "2026-07-01 03:00:00"
    journalctl -k --since "2026-07-01 00:00:00" --until "2026-07-01 03:00:00"
    

    여기서 제가 확인한 포인트는 세 가지였습니다.

    • 서비스 종료 시각과 커널 로그 시각이 맞는지
    • 재시작 직전의 에러 메시지가 있는지
    • 같은 시간대에 다른 시스템 이벤트가 있었는지

    실제로 써보니까 journalctl -u만 보면 부족한 경우가 많더라고요. journalctl -k로 커널 메시지를 같이 봐야 합니다.

    journalctl -u myapi.service -n 50
    journalctl -k -n 100 | egrep -i "killed process|oom|segfault|out of memory"
    dmesg -T | egrep -i "killed process|oom|segfault"
    
    리눅스 프로세스 비정상 종료 원인 분석을 위한 로그 분석 장면

    서비스 로그와 커널 로그를 나란히 비교하면서 장애 시점을 맞춰보는 분석 화면을 표현한 이미지입니다.

    5. 실전 분석 2단계: OOM, 파일 디스크립터, 디스크 상태를 함께 봤습니다

    로그를 보니 일단 OOM 메시지가 보였습니다. 그런데 거기서 끝이 아니더라고요. 왜 메모리가 찼는지, 다른 자원도 같이 무너졌는지를 확인해야 재발을 막을 수 있거든요.

    5-1. 메모리 상태 확인

    free -h
    vmstat 1 5
    cat /proc/meminfo | egrep "MemAvailable|SwapTotal|SwapFree"
    ps aux --sort=-%mem | head -20
    

    여기서 특정 워커 프로세스가 메모리를 비정상적으로 많이 먹는 걸 확인했습니다. 근데 또 하나, 스왑(swap, 메모리 부족 시 디스크를 임시 메모리처럼 쓰는 공간)이 사실상 여유가 없더라고요. 메모리 압박이 생기면 커널이 버티지 못하고 강제 종료로 넘어가더라고요.

    5-2. 파일 디스크립터와 프로세스 제한 확인

    ulimit -n
    cat /proc/$(pgrep -f myapi | head -1)/limits
    lsof -p $(pgrep -f myapi | head -1) | wc -l
    ss -tanp | head -20
    

    혹시 이런 경험 있으신가요? 메모리만 보고 있었는데 실제론 소켓(socket, 네트워크 연결 끝점)이 쌓여서 Too many open files가 먼저 터지는 경우요. 저도 예전에 이걸 놓쳐서 원인 분석을 반나절 더 했었습니다.

    5-3. 디스크와 inode 상태 확인

    df -h
    df -i
    iostat -xz 1 3
    

    로그 적재 서버에서는 디스크 공간보다 inode 고갈이 더 자주 문제였습니다. 파일이 너무 잘게 쪼개져 쌓이면 공간이 남아도 쓰기를 못 하거든요. 이 경우 프로세스가 로그 기록 실패 후 연쇄적으로 비정상 동작하는 경우도 있습니다.

    6. 원인 분석 결과: 단일 원인이 아니라 복합 장애였습니다

    분석 결과를 정리하면 이랬습니다.

    1. 배치 작업이 시작되면서 API 워커 메모리 사용량이 급증했습니다.
    2. 동시에 외부 요청이 몰리며 연결 수가 늘어났습니다.
    3. 애플리케이션의 로그 파일 회전(log rotation, 로그 파일 순환 관리)이 늦어져 쓰기 부하가 커졌습니다.
    4. 결국 커널이 OOM Killer를 실행해 워커 프로세스를 종료했습니다.

    즉, 표면적으로는 리눅스 프로세스 비정상 종료였지만, 실제 뿌리는 메모리 압박 + 연결 누적 + 로그 처리 지연의 조합이었습니다. 처음엔 앱 버그 하나만 의심했는데, 시스템 전반을 봐야 답이 나오더라고요.

    6-1. 제가 적용한 systemd 보완 설정

    [Unit]
    Description=My API Service
    After=network.target
    
    [Service]
    User=www-data
    Group=www-data
    WorkingDirectory=/srv/myapi
    ExecStart=/srv/myapi/venv/bin/gunicorn app:app --workers 2 --bind 0.0.0.0:8000
    Restart=on-failure
    RestartSec=5
    LimitNOFILE=65535
    TimeoutStopSec=30
    KillSignal=SIGTERM
    
    [Install]
    WantedBy=multi-user.target
    

    KillSignal과 LimitNOFILE 설정은 생각보다 중요합니다. 종료 시그널을 정리해두면 강제 종료 전에 정리 작업을 할 여지가 생기고, 파일 디스크립터 한계를 현실적으로 맞춰두면 예기치 않은 장애를 줄일 수 있습니다.

    리눅스 프로세스 비정상 종료 대응을 위한 systemd 설정 구성 이미지

    서비스 재시작 정책, 파일 디스크립터 제한, 종료 시그널 처리 지점을 정리한 구성 이미지입니다.

    7. ⚠️ 트러블슈팅: 실제로 자주 놓치는 포인트

    여기부터는 제가 많이 당했던 부분들입니다. 진짜 사소해 보여도 장애 때는 이런 게 치명적이더라고요.

    • 애플리케이션 로그만 보고 커널 로그를 안 보는 실수
      OOM이나 segfault는 앱 로그에 안 남는 경우가 많습니다.
    • 재시작 성공을 복구 완료로 착각하는 실수
      systemd가 살려놨을 뿐, 원인은 그대로일 수 있습니다.
    • exit code를 안 보는 실수
      137, 139 같은 숫자가 꽤 큰 힌트가 됩니다.
    • 모니터링 해상도가 너무 낮은 실수
      1분 단위 그래프만 보면 급격한 스파이크를 놓치기도 합니다.

    저는 이 문제 이후로 장애 체크리스트를 아예 만들어뒀습니다.

    #!/usr/bin/env bash
    set -eu
    
    echo "== service status =="
    systemctl status myapi.service --no-pager || true
    
    echo "== recent service logs =="
    journalctl -u myapi.service -n 50 --no-pager || true
    
    echo "== kernel errors =="
    journalctl -k -n 100 --no-pager | egrep -i "oom|killed process|segfault|error" || true
    
    echo "== memory =="
    free -h || true
    
    echo "== disk =="
    df -h || true
    df -i || true
    

    이런 식으로 기본 수집 스크립트를 만들어두면, 새벽 장애 때 멘탈이 덜 흔들립니다. 드디어 됐다! 싶었던 순간이 이 자동화 만든 뒤였어요.

    8. 검증과 결과: 재현, 완화, 모니터링까지 묶어야 끝입니다

    문제를 고친 뒤에는 반드시 검증해야 합니다. 저는 아래 순서로 확인했습니다.

    1. 동일 부하 조건에서 메모리 사용량이 다시 치솟는지 확인
    2. 서비스 재시작 없이 일정 시간 안정적으로 유지되는지 확인
    3. 로그 회전과 디스크 사용량이 정상 범위인지 확인
    4. 알람 임계치가 현실적으로 설정됐는지 확인
    systemctl daemon-reload
    systemctl restart myapi.service
    systemctl is-active myapi.service
    watch -n 2 'ps aux --sort=-%mem | head -10'
    

    결과적으로 워커가 반복 종료되던 현상은 멈췄고, 피크 시간대에도 응답이 훨씬 안정적으로 유지됐습니다. 무엇보다 좋았던 건, 다음번 비슷한 시스템 장애가 와도 어디부터 볼지 기준이 생겼다는 점입니다.

    리눅스 프로세스 비정상 종료 해결 후 안정화 결과 시각화

    장애 조치 후 메모리 사용량이 안정되고 프로세스 재시작이 줄어든 결과를 보여주는 검증 이미지입니다.

    9. 정리와 다음 단계: 리눅스 프로세스 비정상 종료 대응 체크리스트

    이번 경험에서 다시 느낀 건 하나입니다. 리눅스 프로세스 비정상 종료는 프로세스 하나의 문제가 아니라, 시스템 전체의 신호를 읽는 문제라는 점이죠. 저도 처음엔 “왜 죽었지?”만 붙잡고 있었는데, 지금은 “죽기 전에 시스템이 어떤 상태였지?”를 먼저 봅니다.

    • 1순위: 종료 시각과 로그 타임라인 정렬
    • 2순위: 커널 로그에서 OOM, segfault, I/O 오류 확인
    • 3순위: 메모리, 파일 디스크립터, 디스크 상태 점검
    • 4순위: 재시작 정책과 서비스 제한값 재검토
    • 5순위: 재현 테스트와 모니터링 임계치 보완

    마지막으로, 장애 원인을 찾았더라도 문서화는 꼭 해두세요. 다음 장애 때 팀 전체 속도가 완전히 달라집니다. 다음 글에서는 coredump(core dump, 비정상 종료 시 메모리 상태를 남긴 파일) 분석과 gdb 기반 세그폴트 추적 방법도 다뤄볼 예정입니다. 이전 글에서 다룬 systemd 서비스 운영 팁과 함께 보면 더 흐름이 잘 잡히실 거예요.

    자주 묻는 질문

    • Q. 프로세스가 죽었는데 앱 로그가 비어 있습니다.
      A. 커널 로그와 journalctl -k를 먼저 보세요. OOM이나 segfault는 앱 로그에 안 남을 수 있습니다.
    • Q. 재시작되면 괜찮은 것 아닌가요?
      A. 아닙니다. 자동 재시작은 증상 완화일 뿐이고, 원인 분석이 안 되면 반복됩니다.
    • Q. 가장 먼저 볼 명령어는 뭔가요?
      A. 보통 systemctl status, journalctl -u, journalctl -k, dmesg -T 조합이면 출발점으로 충분합니다.
    리눅스 프로세스 비정상 종료 대응 체크리스트 인포그래픽

    리눅스 프로세스 비정상 종료 대응 절차를 빠르게 복습할 수 있도록 정리한 요약 인포그래픽입니다.