리눅스

리눅스 서버에서 OOM으로 서비스가 죽었는지 확인하는 실제 점검 흐름

opsnote 2026. 9. 28. 23:27

OOM CHECK 서비스가 갑자기 죽었다 재시작 전에 확인

운영 중인 리눅스 서버에서 서비스가 갑자기 내려갔다는 연락을 받으면 가장 먼저 떠오르는 대응 중 하나가 재시작입니다.

systemctl restart 서비스명

 

서비스를 빨리 살려야 하는 상황에서는 필요한 조치일 수 있습니다.

하지만 바로 재시작해 버리면 왜 서비스가 종료됐는지 확인할 수 있는 단서를 놓칠 수 있습니다.

특히 메모리 부족으로 Linux 커널의 OOM Killer가 프로세스를 종료한 상황이라면 단순히 서비스를 다시 올리는 것만으로는 원인이 해결되지 않습니다.

저라면 서비스가 갑자기 죽었을 때 다음 순서로 확인합니다.

서비스 종료 확인
→ OOM 로그 확인
→ 어떤 프로세스가 종료됐는지 확인
→ 현재 메모리와 Swap 확인
→ 메모리를 많이 사용하는 프로세스 확인
→ 서비스 상태와 로그 확인
→ 조치
→ 재확인

이번 글에서는 이 흐름대로 정리해보겠습니다.


1. 서비스가 죽었다고 바로 restart부터 하지 않는다

예를 들어 웹 애플리케이션 서비스가 갑자기 내려갔다고 가정해보겠습니다.

초보 운영자 입장에서는 일단 서비스를 다시 올리고 싶어집니다.

systemctl restart myapp

하지만 운영 서버에서는 먼저 생각할 것이 있습니다.

지금 재시작하면 장애 원인을 확인하는 데 필요한 상태가 바뀌지 않는가?

그리고 서비스 재시작이 사용자에게 어떤 영향을 주는지도 확인해야 합니다.

서비스를 즉시 복구해야 하는 긴급 상황이라면 재시작이 우선일 수도 있습니다. 반대로 원인을 확인할 시간이 있다면 먼저 로그와 현재 상태를 확보하는 편이 좋습니다.

우선 서비스 상태부터 확인합니다.

systemctl status myapp

여기서 서비스가 실제로 내려가 있는지, 종료 시점은 언제인지, 어떤 종료 상태가 남아 있는지 확인합니다.

서비스 상태 확인 방법은 아래 글에서도 따로 정리했습니다.

https://opsnote.tistory.com/73

 

리눅스 서버 서비스가 안 뜰 때 systemctl status와 journalctl로 원인 좁히는 과정

리눅스 서버를 운영하다 보면 서비스가 안 뜨는 상황을 만날 때가 있습니다.처음에는 단순하게 보입니다.서비스가 안 뜬다.프로세스가 죽은 것 같다.restart 하면 되지 않을까?저도 처음에는 이렇

opsnote.tistory.com

 


2. OOM 흔적부터 확인한다

서비스가 특별한 이유 없이 갑자기 종료됐고 메모리 문제가 의심된다면 커널 로그에서 OOM 관련 기록을 찾아봅니다.

먼저 다음과 같이 확인할 수 있습니다.

dmesg -T | grep -i -E "out of memory|killed process|oom"

systemd 환경에서는 커널 로그를 다음처럼 확인할 수도 있습니다.

journalctl -k | grep -i -E "out of memory|killed process|oom"

예를 들어 로그에서 다음과 비슷한 내용을 발견했다고 가정해보겠습니다.

Out of memory: Killed process 12345 (java) total-vm:...

여기서 중요한 것은 단순히 OOM이라는 문자열이 있다는 사실만 보는 것이 아닙니다.

실제로 어떤 프로세스가 종료됐는지 확인해야 합니다.

위 예시에서는 PID 12345의 java 프로세스가 종료됐다는 흔적을 확인할 수 있습니다.

이런 기록이 장애 발생 시각과 일치한다면 OOM과 서비스 종료의 연관성을 의심할 수 있는 중요한 근거가 됩니다.

다만 dmesg 출력은 시스템 설정이나 권한에 따라 제한될 수 있고, 로그 보존 상태에 따라 과거 기록이 남아 있지 않을 수도 있습니다.

그래서 한 가지 명령 결과만 보고 바로 결론을 내리기보다 서비스 로그와 당시 상황을 함께 확인하는 것이 좋습니다.


3. 종료된 프로세스가 실제 서비스 프로세스인지 확인한다

OOM 로그에서 Killed process를 찾았다면 다음 질문으로 넘어갑니다.

죽은 프로세스가 장애가 발생한 서비스와 관련된 프로세스인가?

예를 들어 다음과 같은 기록이 있다고 해보겠습니다.

Killed process 12345 (java)

java라는 이름만으로는 어떤 서비스인지 확실하지 않을 수 있습니다.

이미 프로세스가 종료됐다면 현재 ps에서 해당 PID를 찾을 수 없을 가능성이 높습니다.

따라서 장애 시각의 서비스 로그, systemd 기록 등을 같이 확인합니다.

systemctl status myapp
journalctl -u myapp

특정 시간대를 알고 있다면 범위를 좁혀 보는 것도 좋습니다.

journalctl -u myapp --since "2026-09-28 14:00:00" --until "2026-09-28 14:10:00"

예시의 날짜와 시간은 실제 장애 발생 시각에 맞게 바꿔서 사용하면 됩니다.

이렇게 보면 커널에서 프로세스가 종료된 시각과 서비스가 내려간 시각이 비슷한지 비교할 수 있습니다.


4. free -m으로 현재 메모리 상태를 확인한다

OOM 흔적을 확인했다면 현재 메모리 상태도 봅니다.

free -m

예를 들면 다음과 같은 항목이 표시됩니다.

               total        used        free      shared  buff/cache   available
Mem:           15900       14200         300         100        1400         800
Swap:           4096        3900         196

여기서 초보 운영자가 많이 보는 값이 free입니다.

하지만 free 값 하나만 보고 메모리가 부족하다고 판단하면 안 됩니다.

Linux는 사용하지 않는 메모리를 캐시 등에 활용하기 때문에 실제로 추가 프로세스가 사용할 수 있는 메모리를 판단할 때는 available도 같이 보는 것이 좋습니다.

free -m 결과를 볼 때 제가 같이 확인하는 것은 다음입니다.

  • 전체 메모리
  • available 메모리
  • Swap 사용량
  • 장애 이후에도 메모리 압박이 계속되고 있는지

free -m의 available에 대해서는 아래 글에 따로 정리했습니다.

https://opsnote.tistory.com/44

 

리눅스 서버 메모리 used만 보면 판단이 틀리는 이유와 available 확인법

리눅스 서버에서 메모리 상태를 확인할 때 가장 많이 쓰는 명령어 중 하나가 free -m입니다.free -m그런데 초보 운영자 입장에서 가장 헷갈리는 부분이 있습니다.used 값이 높게 보이면 바로 “메모

opsnote.tistory.com

 

여기서 한 가지 주의할 점이 있습니다.

현재 free -m 결과가 정상이라고 해서 장애 당시에도 메모리가 정상이었다는 뜻은 아닙니다.

OOM Killer가 프로세스를 종료하면 해당 프로세스가 사용하던 메모리가 반환될 수 있습니다.

따라서 OOM 발생 여부는 현재 메모리 상태만으로 판단하지 않고 커널 로그와 장애 시각의 모니터링 데이터가 있다면 함께 확인하는 것이 좋습니다.


5. Swap도 같이 확인한다

다음으로 Swap 상태를 봅니다.

free -m

또는 다음 명령으로 현재 Swap 사용 상태를 확인할 수 있습니다.

swapon --show

Swap을 많이 사용하고 있다고 해서 무조건 장애라고 볼 수는 없습니다.

반대로 Swap이 없다고 해서 그것만으로 OOM의 원인이라고 단정할 수도 없습니다.

중요한 것은 장애 당시 물리 메모리와 Swap이 어떤 상태였는지 전체적으로 보는 것입니다.

특히 평소보다 Swap 사용량이 크게 증가했고 메모리 압박도 같이 발생했다면 추가 확인이 필요합니다.

Swap 확인에 대한 내용은 아래 글과 같이 보면 이해하기 쉽습니다.

https://opsnote.tistory.com/43

 

리눅스 서버 Swap 올라갔다고 바로 재기동하지 말고 확인하는 순서

리눅스 서버를 확인하다 보면 free -m 결과에서 Swap 사용량이 높게 보일 때가 있습니다.초보 운영자 입장에서는 이 숫자를 보면 바로 불안해집니다.free -m예를 들어 이런 식입니다. total used free share

opsnote.tistory.com

 


6. 현재 메모리를 많이 사용하는 프로세스를 확인한다

OOM 로그와 현재 메모리 상태를 확인했다면 어떤 프로세스가 메모리를 많이 사용하고 있는지도 확인합니다.

먼저 top을 사용할 수 있습니다.

top

top 실행 후 메모리 사용량 기준으로 확인하거나, 명령으로 바로 정렬해서 볼 수도 있습니다.

ps -eo pid,ppid,user,%mem,%cpu,rss,cmd --sort=-rss | head -20

여기서는 특히 다음 항목을 봅니다.

PID
%MEM
RSS
CMD

RSS가 큰 프로세스가 무엇인지 확인하고 해당 프로세스가 장애가 발생한 서비스와 관련 있는지 봅니다.

하지만 여기서도 바로 프로세스를 종료하면 안 됩니다.

예를 들어 메모리를 많이 사용하는 프로세스를 발견했다고 해서 곧바로 다음과 같이 처리하는 것은 위험합니다.

kill -9 PID

메모리를 많이 사용한다는 사실과 비정상 프로세스라는 판단은 다른 문제입니다.

먼저 어떤 서비스의 프로세스인지, 정상적인 사용량인지, 종료했을 때 서비스 영향이 무엇인지 확인해야 합니다.


7. 서비스 상태와 로그를 다시 확인한다

커널과 메모리 쪽을 확인했다면 서비스 자체의 기록도 확인합니다.

systemctl status myapp

그리고 서비스 로그를 확인합니다.

journalctl -u myapp

최근 로그만 보고 싶다면 다음처럼 볼 수도 있습니다.

journalctl -u myapp -n 100 --no-pager

여기서는 단순히 에러 문자열 하나를 찾기보다 OOM이 발생한 시각 전후에 서비스에서 어떤 일이 있었는지 확인하는 것이 중요합니다.

예를 들어 다음과 같은 흐름을 맞춰볼 수 있습니다.

14:03 메모리 사용량 증가
14:05 커널 OOM 발생
14:05 java 프로세스 종료
14:05 myapp 서비스 중단

이런 식으로 시간 순서가 연결되면 장애 상황을 설명하기 훨씬 쉬워집니다.


8. 여기까지 확인한 결과를 조합한다

실제 장애 분석에서는 명령어 하나의 결과보다 여러 결과를 조합해서 판단하는 경우가 많았습니다.

예를 들어 다음과 같은 상황입니다.

systemctl
→ 서비스가 비정상 종료된 상태

커널 로그
→ 장애 시각에 OOM 기록 존재

Killed process
→ 서비스와 관련된 java 프로세스 확인

free -m
→ 현재 available 메모리는 회복된 상태

서비스 로그
→ 커널의 프로세스 종료 시점과 서비스 종료 시점이 유사

이 정도까지 확인했다면 단순히 "서비스가 죽었다"보다 훨씬 구체적으로 상황을 정리할 수 있습니다.

반대로 커널 로그에 OOM 흔적이 없다면 OOM으로 단정하지 않고 애플리케이션 오류, 수동 종료, systemd 동작 등 다른 가능성을 확인해야 합니다.


9. 조치하기 전에 영향도를 먼저 확인한다

OOM이 의심된다고 해서 바로 재부팅하거나 프로세스를 강제 종료하는 것은 피하는 편이 좋습니다.

조치 전에 최소한 다음 내용을 생각합니다.

서비스를 재시작하면 사용자 영향이 있는가?
이중화된 서비스인가?
재시작하면 원인 분석에 필요한 정보가 사라지는가?
메모리를 많이 사용하는 프로세스가 정상 업무 프로세스인가?
프로세스를 종료했을 때 자동으로 다시 올라오는가?
원복이 가능한 조치인가?

특히 운영 서버에서는 다음과 같은 명령을 실행하기 전에 영향도를 확인해야 합니다.

systemctl restart myapp
kill PID
kill -9 PID
reboot

서비스 복구가 최우선인 상황이라면 담당자와 영향도를 확인한 뒤 재시작이 필요할 수 있습니다.

중요한 것은 명령어를 실행할 수 있느냐가 아니라 지금 실행해도 되는 상황인지 판단하는 것이라고 생각합니다.


10. 조치 후에는 반드시 재확인한다

서비스를 재시작하기로 결정했다고 가정해보겠습니다.

systemctl restart myapp

명령어가 에러 없이 끝났다고 작업이 끝난 것은 아닙니다.

서비스 상태를 다시 확인합니다.

systemctl status myapp

프로세스가 필요한 포트에서 정상적으로 대기하고 있는지도 확인할 수 있습니다.

ss -lntp

HTTP 서비스라면 실제 응답도 확인합니다.

curl -I https://example.com

그리고 메모리가 다시 빠르게 증가하지 않는지도 확인합니다.

free -m
ps -eo pid,ppid,user,%mem,%cpu,rss,cmd --sort=-rss | head -20

즉 조치 후에는 최소한 다음 흐름까지 확인하는 것이 좋습니다.

서비스 정상 기동
→ 포트 정상
→ 실제 요청 정상
→ 메모리 상태 확인
→ 동일 증상 재발 여부 확인

재시작 후 확인해야 할 항목은 아래 글에서도 정리했습니다.

https://opsnote.tistory.com/29

 

리눅스 서버 systemctl restart 후 정상 기동 확인하는 법, 명령어만 치고 끝내지 마세요

리눅스 서버에서 서비스 장애가 발생했을 때 systemctl restart를 실행하는 경우가 많습니다.systemctl restart nginx 그런데 실제 운영에서는 재시작 명령어가 실행됐다고 해서 서비스가 정상 기동한 것은

opsnote.tistory.com

 


11. OOM 로그가 있다고 서비스 장애 원인으로 바로 확정할 수 있을까?

OOM 로그를 확인했다고 해서 해당 서비스가 메모리 부족으로 종료됐다고 바로 결론 내리기는 어렵습니다.

예를 들어 커널 로그에 다음과 같은 기록이 있다고 가정해 보겠습니다.

Out of memory: Killed process 12345 (java)

여기서 확인된 사실은 커널이 메모리 부족 상황에서 PID 12345인 Java 프로세스를 종료했다는 것입니다.

하지만 서버에 Java 애플리케이션이 여러 개 실행되고 있었다면 어느 서비스가 종료된 것인지 로그 한 줄만으로는 알기 어렵습니다.

그래서 저는 다음 세 가지를 함께 확인하는 편입니다.

  1. OOM 발생 시각과 실제 서비스 중단 시각이 일치하는지
  2. 종료된 PID가 장애가 발생한 서비스의 프로세스인지
  3. 서비스 로그에도 같은 시각에 종료 또는 비정상 종료 기록이 남아 있는지

서비스 종료 상태도 함께 확인

systemd로 관리하는 서비스라면 다음 명령으로 종료 결과를 확인할 수 있습니다.

systemctl show myapp -p Result -p ExecMainCode -p ExecMainStatus

여기서 myapp은 실제 서비스명으로 변경해야 합니다.

예를 들어 ExecMainStatus=9가 표시되었다면 SIGKILL 신호로 종료됐을 가능성을 확인할 수 있습니다.

다만 이것만으로 OOM이 원인이라고 확정할 수는 없습니다. 관리자가 강제로 종료했거나 다른 이유로 SIGKILL이 발생했을 수도 있기 때문입니다.

OOM 로그가 없다면?

커널 로그에 OOM 기록이 없다고 해서 메모리 문제를 바로 제외하지는 않습니다.

로그가 이미 사라졌거나, 별도의 메모리 제한이 적용된 환경일 수도 있습니다.

Kubernetes에서 실행되는 서비스라면 다음 명령으로 컨테이너 종료 사유를 확인할 수 있습니다.

kubectl describe pod myapp-pod -n default

실제 운영에서는 myapp-pod와 default를 대상 Pod 및 네임스페이스로 변경합니다.

이때 종료 사유에 OOMKilled가 표시된다면 컨테이너가 메모리 부족으로 종료됐다는 중요한 근거가 됩니다.

다만 컨테이너가 OOM으로 종료됐다는 사실이 서버 전체 메모리가 부족했다는 의미는 아닙니다.

컨테이너에 설정된 메모리 제한을 초과했는지도 함께 확인해야 합니다.

확인한 결과를 어떻게 정리할까?

예를 들어 다음과 같이 구분할 수 있습니다.

확인된 사실

  • 14:05경 커널 OOM 로그 발생
  • Java 프로세스가 종료된 기록 확인
  • 같은 시각 서비스 응답 실패 발생

추가 확인이 필요한 부분

  • 종료된 Java 프로세스가 실제 장애 서비스의 프로세스인지
  • 메모리 사용량이 증가한 원인
  • 동일한 문제가 반복될 가능성

이렇게 정리하면 확인되지 않은 내용을 원인으로 단정하지 않으면서도 현재까지 파악한 장애 상황을 설명할 수 있습니다.

결국 OOM 장애에서 중요한 것은 로그에 Out of memory가 있는지만 확인하는 것이 아닙니다.

OOM 발생 시각, 종료된 프로세스, 서비스 중단 시점을 연결해 실제 장애 원인인지 판단하는 과정이 중요합니다.


12. 장애 보고는 확인한 사실 중심으로 작성한다

OOM 장애를 확인한 뒤 보고할 때도 처음부터 원인을 확정해서 쓰기보다는 확인한 사실을 중심으로 정리하는 편이 안전합니다.

예를 들어 다음처럼 작성할 수 있습니다.

서비스 비정상 종료 확인 후 장애 발생 시각의 커널 로그를 점검했습니다.

동일 시간대에 OOM 발생 및 서비스 관련 프로세스 종료 기록을 확인했으며,
현재 메모리와 Swap 사용 상태 및 서비스 로그를 추가 확인했습니다.

영향도 확인 후 서비스를 재기동했으며,
현재 서비스 상태와 포트 및 요청 응답은 정상입니다.

메모리 사용량을 추가 모니터링하며 동일 증상 재발 여부를 확인할 예정입니다.

아직 OOM과 서비스 장애의 관계가 명확하지 않다면 표현도 달라져야 합니다.

서비스 비정상 종료 시점에 메모리 부족 관련 로그가 확인되어
OOM 연관 가능성을 확인 중입니다.

현재 서비스 상태와 메모리 사용량은 정상이며,
장애 시점의 서비스 로그와 메모리 사용 추이를 추가 확인하고 있습니다.

운영 보고에서는 확인된 사실과 추정하고 있는 원인을 구분해서 쓰는 것이 중요합니다.

서버 장애 상황을 전체적으로 어떤 순서로 확인할지는 아래 글에 정리했습니다.

https://opsnote.tistory.com/69

 

초보 운영자를 위한 리눅스 서버 장애 대응 순서 총정리

리눅스 서버를 운영하다 보면 어느 날 갑자기 이런 말을 듣게 됩니다.서버가 느립니다.접속이 안 됩니다.서비스가 안 뜹니다.디스크가 가득 찼습니다.로그가 계속 쌓입니다.재기동하면 될까요?

opsnote.tistory.com

 


마무리

서비스가 갑자기 죽으면 가장 먼저 서비스를 다시 올리고 싶은 마음이 듭니다.

하지만 OOM처럼 장애가 발생한 순간의 흔적이 중요한 경우에는 재시작 전에 로그를 확인하는 것이 원인을 좁히는 데 도움이 됩니다.

제가 기억하려고 하는 순서는 단순합니다.

서비스가 죽었다
→ 바로 restart하지 않는다
→ 커널 로그에서 OOM 흔적을 찾는다
→ 어떤 프로세스가 죽었는지 확인한다
→ 현재 메모리와 Swap을 확인한다
→ 메모리를 많이 사용하는 프로세스를 확인한다
→ 서비스 로그와 시간을 맞춰본다
→ 영향도를 확인하고 조치한다
→ 서비스와 메모리를 다시 확인한다

결국 중요한 것은 restart 명령어를 아는 것보다 왜 서비스가 죽었는지 확인할 수 있는 증거를 먼저 확보하는 것입니다.

운영 서버에서는 특히 restart, kill, reboot 같은 조치부터 시작하기보다 현재 상태와 로그를 먼저 남겨두는 습관이 장애 원인을 찾는 데 도움이 됩니다.