핵심 요약
- systemd는 리눅스가 부팅될 때 가장 먼저 실행되는 1번 프로세스(PID 1)로, 모든 서비스(데몬)를 시작·감시·재시작하는 관리자입니다.
- 서비스를 등록하려면
/etc/systemd/system/이름.service파일을 만들고[Unit] [Service] [Install]세 블록을 작성합니다. systemctl enable --now 이름한 줄이면 부팅 자동 실행 + 즉시 시작이 함께 됩니다.- 프로세스가 죽어도
Restart=always로 자동 복구할 수 있어, 신입 인프라 업무에서 가장 많이 쓰는 도구입니다.
서버에 직접 만든 프로그램이나 내려받은 웹 애플리케이션을 올려 두면, “터미널을 닫으면 프로그램도 같이 꺼지는” 문제를 반드시 만나게 됩니다. 재부팅하면 다시 손으로 켜 줘야 하고, 프로세스가 갑자기 죽으면 아무도 모르게 서비스가 멈춰 있습니다. 이 문제를 리눅스 표준 방식으로 해결하는 도구가 바로 systemd 서비스입니다. 이 글에서는 systemd가 무엇인지부터, 실제로 서비스를 하나 등록해 자동 실행·자동 복구시키는 방법까지 순서대로 정리합니다.
systemd란 무엇인가?
systemd는 대부분의 최신 리눅스 배포판(Ubuntu, CentOS/Rocky, Debian 등)이 채택한 init 시스템 겸 서비스 관리자입니다. init 시스템이란 커널이 부팅을 마친 직후 실행되어 나머지 모든 프로세스의 부모가 되는 프로그램으로, 항상 PID 1을 가집니다. 즉 시스템의 모든 서비스는 결국 systemd의 자식으로 관리됩니다.
systemd가 하는 일은 크게 세 가지입니다. 첫째, 부팅 시 필요한 서비스들을 의존성 순서에 맞춰 병렬로 시작합니다. 둘째, 실행 중인 서비스가 죽으면 정책에 따라 자동으로 재시작합니다. 셋째, 각 서비스의 상태와 로그를 systemctl·journalctl이라는 일관된 명령으로 조회·제어할 수 있게 해 줍니다. 서비스마다 실행 방법이 제각각이던 과거와 달리, systemd 아래에서는 모든 서비스를 똑같은 방식으로 다룰 수 있다는 점이 가장 큰 장점입니다.
유닛과 서비스 파일의 구조
systemd가 관리하는 대상 하나하나를 유닛(unit)이라고 부릅니다. 서비스(.service), 소켓(.socket), 타이머(.timer), 마운트(.mount) 등 여러 종류가 있는데, 프로그램을 상시 실행하는 데 쓰는 것이 .service 유닛입니다. 직접 만든 서비스 파일은 보통 /etc/systemd/system/ 아래에 둡니다. 예를 들어 Node.js로 만든 API 서버를 myapi라는 이름으로 등록한다면 /etc/systemd/system/myapi.service 파일을 다음과 같이 작성합니다.
[Unit]
Description=My API Server
After=network.target
[Service]
User=deploy
WorkingDirectory=/opt/myapi
ExecStart=/usr/bin/node /opt/myapi/server.js
Restart=always
RestartSec=3
Environment=NODE_ENV=production
[Install]
WantedBy=multi-user.target
세 개의 블록이 각각 역할을 나눠 가집니다. [Unit]은 설명과 실행 순서(의존성)를 정의합니다. After=network.target은 네트워크가 준비된 뒤 시작하라는 뜻입니다. [Service]는 실제로 무엇을 어떻게 실행할지 정하는 핵심 블록입니다. [Install]은 enable 했을 때 어느 부팅 단계에 연결할지를 지정하며, 일반 서버 서비스는 대부분 multi-user.target을 사용합니다.
[Service] 블록의 주요 옵션
| 옵션 | 의미 |
|---|---|
ExecStart | 서비스를 시작할 때 실행할 명령(절대 경로 권장) |
User | 어떤 사용자 권한으로 실행할지 지정(보안상 root 대신 전용 계정) |
WorkingDirectory | 명령이 실행되는 기준 디렉터리 |
Restart | 종료 시 재시작 정책(always, on-failure, no) |
RestartSec | 재시작까지 대기 시간(초) |
Environment | 서비스에 전달할 환경변수 |
특히 Restart=always와 RestartSec 조합은 실무에서 매우 중요합니다. 애플리케이션이 예기치 않게 죽어도 systemd가 몇 초 뒤 자동으로 다시 띄우기 때문에, 한밤중에 서비스가 멈춰 있는 사고를 크게 줄일 수 있습니다. 다만 시작 자체가 실패해 무한 재시작에 빠지지 않도록 on-failure와 StartLimitIntervalSec 같은 옵션을 함께 검토하는 것이 좋습니다.
서비스 등록부터 자동 실행까지
서비스 파일을 만들었다면, 다음 순서로 systemd에 반영하고 실행합니다.
# 1) 서비스 파일을 새로 만들거나 수정한 뒤 반드시 데몬 재로딩
sudo systemctl daemon-reload
# 2) 부팅 자동 실행 등록 + 지금 바로 시작(동시에)
sudo systemctl enable --now myapi
# 3) 상태 확인 (active(running) 인지 확인)
systemctl status myapi
# 4) 실시간 로그 확인
journalctl -u myapi -f
가장 자주 실수하는 지점은 서비스 파일을 고친 뒤 daemon-reload를 빼먹는 것입니다. systemd는 유닛 파일을 메모리에 캐시하기 때문에, 파일만 수정하고 재로딩하지 않으면 예전 설정으로 동작합니다. 또 enable은 “부팅 시 자동 실행 등록”이고 start는 “지금 실행”이라는 점을 구분해야 합니다. 두 가지를 한 번에 하는 것이 enable --now입니다.
문제가 생겼을 때 확인하는 법
서비스가 뜨지 않으면 먼저 systemctl status 이름으로 상태와 최근 로그 몇 줄을 봅니다. 여기서 failed가 보이면 journalctl -u 이름 --no-pager -n 50으로 최근 50줄 로그를 확인해 원인을 좁힙니다. 대부분의 실패는 ExecStart 경로 오타, 권한 부족(User 설정), 필요한 환경변수 누락, 포트 충돌 중 하나입니다. 로그에 나온 메시지를 그대로 검색하는 습관만 들여도 해결 속도가 크게 빨라집니다.
자주 묻는 질문 (FAQ)
Q. enable과 start는 무엇이 다른가요?start는 지금 한 번 실행하는 것이고, enable은 부팅할 때마다 자동으로 실행되도록 등록하는 것입니다. 재부팅 후에도 계속 떠 있어야 하는 서버 서비스라면 enable이 반드시 필요합니다.
Q. 서비스 파일은 어디에 두어야 하나요?
직접 만든 서비스는 /etc/systemd/system/에 둡니다. 패키지로 설치된 서비스는 /lib/systemd/system/에 있으며, 이를 덮어쓰기보다는 /etc/systemd/system/의 override 파일로 설정을 수정하는 것이 안전합니다.
Q. 로그는 어떻게 모아서 보나요?
systemd 서비스의 표준 출력은 journald가 자동으로 수집합니다. journalctl -u 서비스이름으로 조회하고, -f를 붙이면 실시간으로, --since "1 hour ago"로 기간을 지정해 볼 수 있습니다.
마무리
systemd 서비스 파일 하나만 제대로 작성할 줄 알면, “서버에 올린 프로그램이 재부팅 후에도, 죽어도 알아서 다시 뜨는” 상태를 만들 수 있습니다. 처음에는 [Unit] [Service] [Install] 세 블록과 daemon-reload → enable --now → status → journalctl 흐름만 손에 익혀도 충분합니다. 실무에서 마주치는 대부분의 배포·운영 작업이 이 기본기 위에서 이루어집니다.
더 읽어보기
- 신입 인프라 엔지니어 공부 순서: 리눅스·네트워크·도커·클라우드 로드맵
- 리눅스 권한 755는 무슨 뜻일까? chmod·chown 이해하기
- 프로세스와 스레드 차이: 운영체제 면접에서 자주 묻는 이유
이 글은 학습·정보 제공을 목적으로 작성되었으며, 실제 운영 환경에 적용하기 전에는 각자의 시스템 구성과 버전에 맞게 검증하시기 바랍니다.