프리셋(Node.js, Python, Go, Java)을 클릭하면 기본값이 자동 입력됩니다. 서비스 이름, ExecStart 경로, 작업 디렉터리를 앱에 맞게 수정하세요.
2. 실행 정책 설정
서비스 타입(요즘 앱은 대부분 simple), 재시작 정책, 실행 계정을 선택하세요 — 웹 앱은 절대 root로 실행하지 마세요.
3. 환경변수 추가
NODE_ENV=production, PORT=3000 같은 KEY=value 쌍을 추가하거나, EnvironmentFile로 유닛 밖의 시크릿 파일을 지정하세요 — API 키 관리에 유용합니다.
4. 설치 및 활성화
파일을 /etc/systemd/system/에 저장하고 생성된 명령어를 실행하세요: daemon-reload, enable --now, journalctl로 로그 확인.
자주 묻는 질문
Type=simple(기본값)은 ExecStart의 프로세스가 포그라운드에 머문다고 가정합니다 — 프로세스가 실행되는 순간 서비스가 시작된 것으로 간주합니다. Type=forking은 백그라운드로 fork한 뒤 부모 프로세스가 종료되는 전통적인 데몬용이며, 보통 PIDFile=이 필요합니다. Node.js, Python, Go, Java 같은 현대 앱은 거의 모두 포그라운드로 실행되므로 simple을 사용하세요.
Restart=on-failure는 비정상 종료(0이 아닌 종료 코드, 시그널 종료, 타임아웃)일 때만 재시작하고, 정상 종료(코드 0)는 그대로 둡니다. Restart=always는 종료 방식과 무관하게 항상 재시작합니다. 절대 죽으면 안 되는 웹 앱·API에는 always가 안전하고, 배치성 작업에는 on-failure가 재시작 루프를 방지합니다. 어느 쪽이든 RestartSec=5와 함께 사용해 크래시 루프가 CPU를 점유하지 않게 하세요.
journalctl을 사용하세요. 실시간 로그: sudo journalctl -u myapp -f. 마지막 100줄: sudo journalctl -u myapp -n 100. 시간 필터: sudo journalctl -u myapp --since "1 hour ago". 앱이 stdout/stderr로 출력하는 내용은 저널이 자동으로 수집하므로 로그 파일 설정이 필요 없습니다 — 앱을 포그라운드(Type=simple)로 실행하는 큰 이유 중 하나입니다.
시스템 서비스는 /etc/systemd/system/에 위치하고 sudo systemctl로 관리하며 부팅 시 시작되고, User= 지시자로 임의 계정으로 실행할 수 있습니다. 유저 서비스는 ~/.config/systemd/user/에 위치하고 systemctl --user(sudo 불필요)로 관리하며, 기본적으로 로그인 중에만 실행됩니다 — loginctl enable-linger로 상시 실행 가능. VPS 프로덕션 앱은 비특권 계정을 User=로 지정한 시스템 서비스를 사용하세요.
유닛 파일에 WantedBy=multi-user.target이 포함된 [Install] 섹션이 있는지 확인한 뒤, sudo systemctl daemon-reload 후 sudo systemctl enable --now myapp을 실행하세요. enable은 multi-user.target.wants에 심볼릭 링크를 만들어 매 부팅마다 시작되게 하고, --now는 즉시 시작합니다. systemctl is-enabled myapp으로 확인하세요.