맥 터미널에서 python server.py를 실행하면, 터미널 창을 닫는 순간 서버도 함께 종료됩니다.
이는 터미널이 닫힐 때 macOS가 해당 세션(터미널 창 하나의 작업 공간)에서 실행 중인 모든 자식 프로세스에 SIGHUP 신호(터미널 종료 시 프로세스에 보내는 종료 명령)를 보내기 때문입니다.
터미널 창의 열림 여부와 상관 없이 파이썬 서버를 유지하려면 상황에 따라 세 가지 방법 중 하나를 선택하면 됩니다.
지금 당장 창을 닫아야 한다면 nohup, 나중에 서버 출력을 다시 확인해야 한다면 tmux, 재부팅 후에도 자동으로 켜져야 한다면 launchd를 씁니다.
방법마다 설정 난이도와 유지 방식이 다릅니다. nohup은 명령어 한 줄로 끝나지만 서버 출력을 실시간으로 볼 수 없고, tmux는 세션을 열어둔 채 자유롭게 드나들 수 있으며, launchd는 macOS 부팅 시 자동 실행까지 처리하는 정식 서비스 방식입니다.
| 방법 | 터미널 닫아도 유지 | 재부팅 후 자동 시작 | 실시간 로그 확인 |
|---|---|---|---|
| nohup | ✓ | ✗ | ✗ (파일로 저장) |
| tmux | ✓ | ✗ | ✓ |
| launchd | ✓ | ✓ | ✓ (파일로 저장) |
1. 터미널 창을 닫아도 서버가 꺼지지 않는 방법
nohup은 “no hangup”의 줄임말로, 터미널이 닫힐 때 macOS가 보내는 SIGHUP 신호를 프로세스가 무시하도록 만듭니다. 가장 빠르게 적용할 수 있는 방법입니다.

nohup python server.py > server.log 2>&1 &
명령어를 구조별로 설명하면 다음과 같습니다:
nohup: 터미널 종료 시 프로세스가 함께 죽지 않도록 보호> server.log: 표준 출력(화면에 출력되는 일반 메시지)을server.log파일로 저장2>&1: 에러 출력도 같은 파일로 합쳐서 저장&: 백그라운드로 실행 (프롬프트, 즉$커서를 바로 돌려받음)
실행하면 터미널에 PID(프로세스 ID, 실행 중인 프로그램에 macOS가 붙여주는 고유 번호)가 출력됩니다.
예를 들어 [1] 48291이 나오면 48291이 서버의 PID입니다. 이 번호를 메모해 두면 나중에 서버를 종료할 때 사용됩니다.
서버 로그 실시간 확인

tail -f server.log
서버 종료

kill 36158
PID를 잊어버렸다면 아래 명령으로 다시 찾을 수 있습니다. ps aux는 현재 실행 중인 전체 프로세스 목록을 보여주고, | grep server.py는 그 중 server.py가 포함된 줄만 걸러냅니다.
ps aux | grep server.py
주의사항
nohup 없이 python server.py &만 입력하면 터미널을 닫는 순간 서버가 함께 종료되므로 반드시 nohup을 앞에 붙여야 합니다.
또한 이 방법은 1회성으로 맥을 끄거나 사용자 로그아웃을 하면 파이썬 서버가 꺼집니다. 재부팅 후 자동 시작이 필요하다면 3번 방법(launchd)을 사용합니다.
2. 서버 화면을 그대로 두고 터미널에서 나가는 방법
tmux는 하나의 터미널을 여러 독립적인 세션으로 나눠 쓰는 도구입니다.
서버를 실행한 상태에서 세션을 “분리(detach)”하면, 터미널을 닫아도 서버는 계속 돌아가며 나중에 같은 세션에 재접속해 출력을 이어서 볼 수 있습니다. nohup과 달리 서버의 출력을 실시간으로 확인할 수 있는 것이 장점입니다.
설치 (Homebrew 필요)

brew install tmux
사용 순서

아래 명령으로 새 tmux 세션을 시작합니다.
tmux new-session -s myserver
-s myserver는 세션 이름입니다. 원하는 이름으로 바꿔도 됩니다. 세션 안에서 서버를 실행합니다.
python server.py
서버가 실행 중인 상태에서 세션을 분리하려면 키보드에서 Control + B를 누른 후 손을 떼고 D를 누릅니다.

터미널에 [detached (from session myserver)]가 표시되면 분리 성공입니다. 이제 터미널을 닫아도 서버는 계속 실행 중입니다.
세션에 다시 접속
tmux attach-session -t myserver
실행 중인 세션 목록 확인
tmux ls
서버 종료 및 세션 삭제
세션에 재접속한 후 Ctrl + C로 서버를 종료하고, exit를 입력하면 세션이 삭제됩니다.
3. 맥을 재시작해도 서버가 자동으로 켜지는 방법
macOS의 launchd는 시스템 부팅 시 자동으로 서비스를 실행하는 공식 메커니즘입니다.
.plist 파일(macOS가 읽는 XML 형식의 설정 파일)을 ~/Library/LaunchAgents/(로그인 시 자동 실행할 사용자 서비스를 모아두는 폴더)에 등록하면, 로그인할 때마다 자동으로 서버가 시작됩니다.
이 방법은 nohup이나 tmux와 달리 재부팅 후 수동으로 서버를 다시 켤 필요가 없습니다.
주의 : plist 파일은 절대 경로(루트 /부터 시작하는 전체 경로)만 허용합니다. ~(틸드, 홈 디렉터리 단축 표기) 또는 $HOME 같은 환경변수를 사용하면 서비스가 실행되지 않습니다. 반드시 /Users/사용자명/... 형태로 작성해야 합니다.
1단계: Python 경로와 사용자명 확인
which python3
# 출력 예: /usr/local/bin/python3
whoami
# 출력 예: johndoe
2단계 : plist 파일 생성
~/Library/LaunchAgents/에 com.myserver.python.plist 파일을 생성합니다.
mkdir -p ~/Library/LaunchAgents
nano ~/Library/LaunchAgents/com.myserver.python.plist
아래 내용을 붙여넣고, 사용자 계정(johndoe)과 파이썬 서버 경로를 실제 값으로 교체합니다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.myserver.python</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/python3</string>
<string>/Users/johndoe/myproject/server.py</string>
</array>
<key>WorkingDirectory</key>
<string>/Users/johndoe/myproject</string>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/Users/johndoe/myproject/server.log</string>
<key>StandardErrorPath</key>
<string>/Users/johndoe/myproject/server.err.log</string>
</dict>
</plist>
각 키의 역할입니다:
Label: 서비스 식별자. 파일명과 일치시키는 것이 관례입니다.ProgramArguments: 실행할 명령어를 배열로 분리해서 입력합니다. 공백 구분 없이 각 인자를 별도<string>으로 작성합니다.WorkingDirectory:server.py가 실행될 기준 디렉터리입니다. 상대 경로로 파일을 읽는 코드가 있다면 반드시 설정해야 합니다.RunAtLoad:true로 설정하면 plist 등록 즉시 서버가 시작됩니다.KeepAlive:true로 설정하면 서버가 비정상 종료되어도 자동 재시작됩니다.
3단계 : 서비스 등록
macOS Ventura(13) 이상에서는 bootstrap 명령(서비스를 launchd에 등록하는 최신 방식)을 사용합니다. UID(사용자 고유 번호)를 먼저 확인합니다.
id -u
# 출력 예: 501
launchctl bootstrap gui/501 ~/Library/LaunchAgents/com.myserver.python.plist
macOS Monterey(12) 이하에서는 아래 명령을 사용합니다.
launchctl load -w ~/Library/LaunchAgents/com.myserver.python.plist
서비스 상태 확인
launchctl list | grep com.myserver.python
출력에서 두 번째 열이 0이면 정상 실행 중, 음수이면 오류 발생입니다. 오류가 있으면 server.err.log를 확인합니다.
서비스 중지 및 등록 해제
bootout은 등록된 서비스를 launchd에서 제거하는 명령입니다. 서비스를 완전히 내리고 싶을 때 사용합니다.
# Ventura 이상
launchctl bootout gui/501/com.myserver.python
# Monterey 이하
launchctl unload ~/Library/LaunchAgents/com.myserver.python.plist
plist 수정 후 재적용
plist 파일을 수정했다면 반드시 bootout → bootstrap 순서로 재등록해야 변경이 반영됩니다. 파일만 수정해서는 launchd가 변경 내용을 인식하지 않습니다.
마치며
세 방법 모두 터미널 창에 대한 의존성을 끊는다는 목적은 같지만, 용도가 다릅니다. 개발 중에 빠르게 테스트하려면 nohup, 서버 출력을 나중에 다시 확인해야 한다면 tmux, 실제 서비스처럼 운영할 계획이라면 launchd가 적합합니다.
launchd는 설정이 다소 복잡하지만 KeepAlive 옵션 덕분에 서버가 충돌해도 자동으로 재시작되므로, 로컬 서버를 장기간 안정적으로 운영할 때 가장 신뢰할 수 있는 선택입니다.
이 방식이 번거롭다면 맥에서도 크론탭을 사용할 수 있으므로, 손쉽게 백그라운드에서 파이썬을 동작할 수 있습니다.
FAQ
가상환경(venv)에서 실행 중인 server.py를 nohup으로 백그라운드 실행하려면 어떻게 하나요?
가상환경의 Python 인터프리터를 절대 경로로 지정하면 됩니다. 가상환경을 활성화한 상태에서 which python을 실행해 경로를 확인한 후, 아래처럼 사용합니다.nohup /Users/johndoe/myproject/.venv/bin/python server.py > server.log 2>&1 &launchd에서도 동일하게 ProgramArguments의 첫 번째 <string>에 가상환경 Python 경로를 입력합니다.
launchd로 등록한 서버가 시작되지 않을 때 가장 먼저 확인할 것은 무엇인가요?
plist 파일의 경로 문제가 가장 흔합니다. ~나 $HOME 대신 /Users/사용자명/ 형태로 모든 경로가 절대 경로로 작성되어 있는지 확인합니다. 그 다음 server.err.log를 열어 Python 오류 메시지를 확인합니다. plist 문법 오류는 plutil -lint ~/Library/LaunchAgents/com.myserver.python.plist로 검증할 수 있습니다.
tmux 세션이 살아있는지 확인하는 방법은 무엇인가요?
tmux ls를 실행해 세션 목록이 출력되면 살아있는 상태입니다. 세션이 없으면 no server running이 표시됩니다. tmux는 재부팅하면 세션이 사라지므로, 재시작 후 자동 유지가 필요하다면 launchd 또는 tmux-resurrect 플러그인을 함께 사용합니다



