MMeshOps
바이브코딩을 위한 Git과 리눅스 기초
7예상 10입문

서버 프로그램 실행 유지와 에러 로그 보기

웹 서버 프로그램을 안정적으로 유지하기 위한 systemctl 명령어와 문제 해결을 위해 에러 로그를 확인하는 journalctl 사용법을 익힙니다.

내가 짠 웹 서버 코드를 터미널에서 `node server.js`나 `python app.py`로 실행하면 웹사이트가 잘 열립니다. 하지만 작업을 끝내고 내가 터미널 접속을 종료(로그아웃)해 버리면, 실행 중이던 프로그램도 함께 죽어버려서 웹사이트 접속이 끊깁니다. 또한, 자는 동안 서버에 알 수 없는 에러가 발생해서 멈췄을 때 원인을 파악할 단서가 필요합니다. 이번 시간에는 내가 없어도 프로그램이 24시간 안정적으로 돌아가도록 만들고, 꼼꼼하게 에러 일지를 기록하고 확인하는 방법에 대해 배웁니다.

터미널을 꺼도 죽지 않는 불사조: 데몬(Daemon)과 서비스

내가 서버 터미널에 접속해서 직접 실행시킨 프로그램(프로세스)은 내 계정에 종속되기 때문에, 내가 퇴근하고 컴퓨터를 끄기 위해 터미널 창을 닫으면 함께 운명을 맞이합니다. 하지만 웹 서버나 데이터베이스 프로그램은 전 세계 사람들이 24시간 언제든 접속해야 하므로 내가 접속해 있지 않을 때도 배경에서 묵묵히 혼자 실행되어야 합니다.

리눅스에서는 이렇게 보이지 않는 뒤편(백그라운드)에서 사용자의 개입 없이 계속해서 실행되는 프로그램을 데몬(Daemon) 혹은 서비스(Service)라고 부릅니다. 우리가 바이브코딩으로 웹사이트 코드를 완성했다면, 마지막 단계에서는 이 코드를 단순히 한 번 실행하고 마는 것이 아니라, 리눅스 시스템에 "이 프로그램을 서비스로 등록해서 1년 365일 안 죽게 잘 관리해 줘!"라고 맡겨야 합니다.

서비스 관리의 총사령관: `systemctl`

이러한 수많은 서비스들의 생사여탈권을 쥐고 관리하는 리눅스의 핵심 관리 도구가 바로 `systemctl`입니다. `systemctl` 명령어를 사용하면 웹 서버를 켜고, 끄고, 문제가 생겼을 때 재시작하고, 서버 컴퓨터가 재부팅될 때 자동으로 함께 켜지도록 설정할 수 있습니다.

시스템의 핵심 서비스를 조작하는 일이기 때문에, `systemctl` 명령 앞에는 관리자 권한을 뜻하는 `sudo`를 거의 항상 붙여야 합니다.

systemctl을 활용한 서비스 생명주기 관리

bash
```bash
$ sudo systemctl status my-website
● my-website.service - My Vibe Coding Website
   Loaded: loaded (/etc/systemd/system/my-website.service; enabled; vendor preset: enabled)
   Active: active (running) since Mon 2026-07-13 10:00:00 KST; 24h ago
 Main PID: 12345 (node)
```
  1. 1상태 확인: sudo systemctl status nginx (Nginx 웹 서버가 잘 돌아가고 있는지(active) 죽었는지(failed) 현재 건강 상태를 점검합니다.)
  2. 2서비스 시작/종료: sudo systemctl start nginx (서버를 켭니다.) / sudo systemctl stop nginx (서버를 끕니다.)
  3. 3서비스 재시작: sudo systemctl restart nginx (새로운 설정을 적용하거나 먹통이 되었을 때, 완전히 껐다가 즉시 다시 켭니다.)
  4. 4자동 실행 등록: sudo systemctl enable nginx (정전 등의 이유로 리눅스 컴퓨터가 재부팅되더라도, 켜지자마자 웹 서버가 스스로 실행되도록 예약합니다.)

결과 화면에서 `active (running)`이라는 초록색 글씨를 본다면, 여러분의 웹사이트가 튼튼하게 서비스로 등록되어 잘 작동하고 있다는 뜻입니다.

시스템 일기장 꺼내 보기: `journalctl`

웹사이트가 잘 돌아가다가 어느 날 갑자기 `systemctl status`를 쳐보니 빨간색으로 `failed (죽음)` 상태가 되어있다면 어떻게 해야 할까요? 왜 멈췄는지 이유를 알아내야만 코드를 고칠 수 있습니다.

내가 직접 터미널에서 실행했을 때는 에러가 나면 화면에 텍스트가 쏟아졌지만, 배경에서 돌아가는 서비스는 에러가 났을 때 화면에 보여줄 길이 없습니다. 대신, 리눅스는 이 모든 서비스의 투덜거림, 정상 작동 여부, 에러 메시지들을 거대한 중앙 일기장에 꼼꼼하게 기록해 둡니다. 이 통합 일기장을 열어보는 명령어가 `journalctl`입니다.

하지만 무턱대고 `journalctl`을 치면 서버가 태어난 날부터 기록된 수백만 줄의 모든 일기가 쏟아져 나와 내용을 파악할 수 없습니다. 목적에 맞게 옵션을 주어 필터링해야 합니다.

실무에서 자주 쓰는 journalctl 에러 추적 옵션

명령어 조합수행 목적
journalctl -u my-website특정 유닛(-u), 즉 my-website라는 특정 서비스가 뱉어낸 로그 일기만 추려내서 봅니다.
journalctl -u my-website -e그 서비스의 로그 중에서도, 가장 마지막 페이지(-e, end)로 스크롤을 바로 내려서 최근에 발생한 에러를 확인합니다.
journalctl -u my-website -f과거 기록뿐만 아니라, 지금 이 순간부터 실시간으로 쏟아지는 로그를 계속 추적(-f, follow)하면서 화면에 찍어줍니다. 코드를 고치고 테스트할 때 필수입니다.

바이브코딩의 진가는 에러를 만났을 때 발휘됩니다. `journalctl -u my-website -e`를 입력하여 나타난 최근 빨간색 에러 메시지 몇 줄을 복사한 다음, AI에게 "서버가 죽었는데 이런 에러가 떴어. 해결해 줘."라고 물어보는 것이 가장 빠르고 정확한 디버깅 워크플로우입니다.

팁: 환경 변수(Environment Variables)란?

에러 로그를 보다 보면 종종 "환경 변수가 누락되었습니다"라는 메시지를 보게 됩니다. 내 컴퓨터(개발 환경)와 실제 서버(운영 환경)는 비밀번호나 접속 주소가 달라야 합니다. 소스 코드 안에 이런 비밀번호를 하드코딩해버리면 나중에 깃허브에 코드가 공개되었을 때 대형 보안 사고가 터집니다.

그래서 코드 바깥, 즉 리눅스 시스템 자체에 포스트잇처럼 설정값을 붙여놓고 코드가 실행될 때 이를 읽어가게 만드는데, 이 포스트잇을 환경 변수라고 부릅니다. 주로 파일 이름이 `.env`인 숨김 파일에 저장해두며, 서비스가 죽었을 때는 이 파일 안에 들어있는 환경 변수 세팅이 올바른지 가장 먼저 의심해 보아야 합니다.

환경 변수 파일(.env)의 예시

PORT=8080
DB_PASSWORD=my_super_secret_password
API_KEY=1234567890abcdef

이 파일은 실제 소스 코드에 포함되지 않으며, 서버가 실행될 때 이 값들을 몰래 읽어와서 안전하게 사용합니다.

개념 퀴즈

퀴즈 답을 맞춰야 학습 완료가 됩니다.

웹 서버 설정 파일을 수정한 뒤, 이 새로운 설정이 반영되도록 백그라운드에서 돌아가고 있는 웹 서버 서비스(nginx)를 안전하게 껐다가 즉시 다시 켜려고 합니다. 알맞은 명령어는 무엇인가요?

3줄 요약

  1. 1터미널 창을 꺼도 24시간 내 코드가 백그라운드에서 죽지 않고 돌아가게 하려면, 리눅스 시스템의 서비스(데몬) 형태로 등록해야 합니다.
  2. 2systemctl 명령어를 통해 웹 서버 서비스의 현재 상태를 점검하고 시작, 종료, 재시작 및 부팅 시 자동 실행 여부를 관리할 수 있습니다.
  3. 3백그라운드 서비스에 문제가 생겨서 죽었을 때는, journalctl 명령어에 특정 유닛(-u)과 실시간 추적(-f) 옵션을 활용하여 중앙 에러 로그를 확인하고 원인을 파악합니다.