systemd 서비스 관리 완벽 가이드: 자동 시작·복구·journalctl 로그 (2026)

재부팅 후 서비스가 안 올라온다면 — 새벽 호출의 원인

VPS에 Node.js 앱·DB·웹서버를 직접 띄워놓고, 보안 패치 때문에 서버가 재부팅됐는데 서비스가 자동으로 올라오지 않아 새벽에 장애 알림을 받은 적이 있나요? 서비스가 자동으로 시작되지 않으면 결국 사람이 직접 접속해서 재시작해야 합니다. systemd로 서비스를 등록하면 이 문제가 사라집니다.

이 튜토리얼에서는 systemd unit 파일을 직접 작성해서 서비스를 등록하고, 자동 시작·크래시 복구·통합 로그 관리까지 설정하는 전체 과정을 다룹니다. Ubuntu, Debian, CentOS 등 대부분의 현대 Linux 배포판에서 그대로 적용됩니다.

1. systemd란? — PID 1에서 모든 서비스를 관리

systemd는 Linux 부팅 시 가장 먼저 시작되는 PID 1 프로세스로, 이후 실행되는 모든 시스템 서비스를 통합 관리합니다. 과거의 SysV init 스크립트를 대체하며, 의존성 기반 병렬 부팅, 온디맨드 서비스 활성화, 통합 로그(journald) 등을 제공합니다.

핵심 장점은 서비스가 죽어도 자동으로 재시작하고, 서버가 재부팅돼도 자동으로 시작한다는 점입니다. 더 이상 nohup이나 screen에 의존할 필요가 없습니다.

2. unit 파일 구조 — [Unit]/[Service]/[Install]

systemd 서비스는 /etc/systemd/system/ 아래 .service 확장자의 unit 파일로 정의합니다. 기본 구조는 세 섹션입니다:

sudo nano /etc/systemd/system/myapp.service
[Unit]
Description=My Node.js Application
After=network.target

[Service]
Type=simple
User=deploy
WorkingDirectory=/home/deploy/myapp
ExecStart=/usr/bin/node /home/deploy/myapp/server.js
Restart=always
RestartSec=3
Environment=NODE_ENV=production

[Install]
WantedBy=multi-user.target

[Unit] 섹션은 서비스의 메타데이터와 의존성을 정의합니다. [Service]는 실제 실행 명령과 동작 방식을, [Install]은 enable 시 어떤 target에 연결될지를 지정합니다.

3. 서비스 등록 — daemon-reload, enable, start, status

unit 파일을 만들었으면 systemd가 인식하도록 reload하고, 활성화합니다:

sudo systemctl daemon-reload
sudo systemctl enable myapp.service
sudo systemctl start myapp.service
sudo systemctl status myapp.service

daemon-reload는 unit 파일 변경사항을 반영하는 명령입니다. 파일을 수정할 때마다 반드시 실행해야 합니다. enable은 부팅 시 자동 시작을 등록하고, start는 지금 당장 서비스를 시작합니다.

4. 자동 시작 — enable vs disable, multi-user.target

systemctl enable[Install]의 WantedBy=multi-user.target에 따라 심볼릭 링크를 생성합니다. multi-user.target은 런레벨 3(멀티유저 모드)에 해당하므로, 일반적인 서버 부팅 시 자동으로 서비스가 시작됩니다.

sudo systemctl enable myapp    # 자동 시작 ON
sudo systemctl disable myapp   # 자동 시작 OFF

is-enabled로 현재 상태를 확인할 수 있습니다:

sudo systemctl is-enabled myapp

5. 자동 재시작 — Restart=always, RestartSec

서비스가 크래시로 종료됐을 때 systemd가 자동으로 재시작하게 하려면 Restart=always를 설정합니다. RestartSec는 재시작 사이의 대기 시간입니다:

[Service]
Restart=always
RestartSec=3

Restart 옵션의 종류:

  • always — 종료 이유와 무관하게 항상 재시작 (권장)
  • on-failure — 비정상 종료(0이 아닌 exit code, 시그널) 시에만 재시작
  • no — 재시작 안 함 (기본값)

크래시 루프 방지를 위해 StartLimitBurstStartLimitIntervalSec으로 재시작 횟수 제한을 걸 수도 있습니다.

6. journalctl 로그 — -u, -f, –since, 영속 로그

systemd는 journald라는 통합 로그 시스템을 사용합니다. journalctl 명령으로 모든 서비스 로그를 통합 조회할 수 있습니다:

# 특정 서비스 로그 (follow)
sudo journalctl -u myapp -f

# 최근 100줄
sudo journalctl -u myapp -n 100

# 오늘 로그만
sudo journalctl -u myapp --since today

# 특정 시간 이후
sudo journalctl -u myapp --since "2026-07-05 00:00:00"

# 에러만
sudo journalctl -u myapp -p err

주의: 기본적으로 journald 로그는 /run/log/journal/에 저장되어 재부팅 시 삭제됩니다. 영속 로그를 원하면 디렉토리를 만들어줍니다:

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

7. 의존성과 순서 — After, Requires, Wants

서비스 간 의존성을 정의하면 올바른 순서로 시작됩니다. 예를 들어 DB가 필요한 앱이라면:

[Unit]
Description=My App
After=network.target postgresql.service
Requires=postgresql.service
  • After= — 지정한 서비스 이후에 시작 (순서만)
  • Requires= — 강한 의존성. 지정한 서비스가 실패하면 이 서비스도 실패
  • Wants= — 약한 의존성. 지정한 서비스 실패와 무관하게 진행

마무리 — systemd로 서버 운영을 자동화하자

systemd unit 파일 하나로 서비스 자동 시작, 크래시 복구, 통합 로그 관리가 모두 해결됩니다. 더 이상 새벽에 서버 접속해서 수동으로 재시작할 필요가 없습니다. VPS에 서비스를 직접 운영한다면 systemd 등록은 선택이 아닌 필수입니다.

다음 단계로는 Fail2ban으로 SSH 무차별 대입 공격을 차단하는 설정을 추천합니다. VPS 보안의 핵심입니다.

관련 글

📎 이 영상의 발표 자료

누구나 무료로 다운로드할 수 있습니다.