집 PC에 작업을 "던져 놓는" 법: GitHub 저장소 하나로 만드는 원격 작업 대기열
노트북이나 휴대폰에서 집 PC에 "이거 돌려 놔"라고 맡기고, 결과만 나중에 받아 보고 싶을 때가 있습니다. 원격 데스크톱을 켜 두거나 공유기 포트를 여는 방법도 있지만, 이 사이트는 더 단순한 방법을 썼습니다. GitHub 저장소의 폴더 하나를 작업 대기열로 쓰는 것입니다. 이틀 동안 이 방식으로 PC 작업 110개 넘게(모델 받기·설정 변경 포함)를 돌렸고, 이 글은 그 구조를 누구나 따라 할 수 있게 줄인 버전입니다.
결론부터 정리하면 이렇습니다.
- 보내는 쪽은 파일을
inbox에 넣고 올리기만 하면 됩니다. 받는 PC가 5분마다 확인해서 실행하고, 기록과 결과를done·results에 올려 둡니다. - 포트를 열 필요가 없습니다. 두 기기 모두 GitHub에만 접속합니다.
- 실제로 가장 많이 막힌 곳은 git 동기화였습니다. 받는 PC는 자기 대기열 폴더만 고치고 그 폴더만 올린다는 규칙 하나로 대부분 해결됐습니다.
구조

저장소 안의 폴더는 이렇게 씁니다.
queue/pc/inbox/ ← 할 일 파일(.cmd / .ps1 / .sh)을 넣는 곳
queue/pc/done/ ← 끝난 작업 파일과 실행 기록(.log)이 옮겨지는 곳
queue/pc/results/ ← 작업이 만든 결과 파일
queue/pc/heartbeat.txt ← PC가 마지막으로 살아 있던 시각
pc 자리는 기기 이름입니다. 기기가 여러 대면 queue/nas/, queue/laptop/처럼 폴더를 나누면 됩니다. 폴더는 실행기가 처음 돌 때 알아서 만듭니다.
준비물
- 작업을 받을 Windows PC 한 대 (git, Python 3.9 이상 설치)
- 대기열 전용 비공개(private) GitHub 저장소 하나. 실행기가 대기열 폴더 밖의 로컬 변경을 매번 지우므로, 다른 작업용 저장소와 같이 쓰지 마세요.
- 작업을 보낼 기기 (노트북, 다른 PC 등. git만 있으면 됩니다)
따라하기
1. 저장소를 만들고 두 기기에 받기
GitHub에서 비공개 저장소를 만들고, 보내는 기기와 받는 PC 양쪽에서 git clone 합니다. 받는 PC에서는 로그인 창 없이 git pull·git push가 되는지 먼저 확인하세요. 실행기는 로그인 창을 띄우지 말라고 git에 알려 두지만, 로그인이 안 되면 매 회차 실패만 합니다. 커밋에 쓸 이름도 받는 PC의 저장소 폴더에서 한 번 정해 두세요(git config user.name "pc", git config user.email "메일 주소"). 없으면 결과가 올라가지 않습니다.
2. 실행기 파일 넣기
받는 PC의 저장소 폴더 밖(예: C:\work\remote_queue.py)에 실행기 파일(remote_queue.py)을 받아 둡니다. 약 220줄짜리 파이썬 파일이고, 한 회차에 하는 일은 이렇습니다.
- 이미 다른 회차가 도는 중이면 바로 끝냅니다(잠금 파일).
- 자기 대기열 폴더 밖의 로컬 변경과 git이 모르는 새 파일을 지우고
git pull합니다. 받기가 막히면 원격 상태로 맞춘 뒤 이 기기가 만든 결과만 되살립니다. inbox의 파일을 이름 순서대로 하나씩 처리합니다. 실행하기 전에 먼저done으로 옮기고 "실행 중" 기록을 올려 둡니다. 그래서 작업이 PC를 끄거나 실행기가 도중에 죽어도 같은 작업이 다시 돌지 않습니다.- 실행이 끝나면 출력과 종료 코드를
done/<이름>.log에 적습니다. - 자기 대기열 폴더만 커밋해서 올립니다. 올리기가 거절되면 한 번 받아서 합친 뒤 다시 올리고, 그래도 못 올린 커밋은 다음 회차에 올립니다.
손으로 한 번 돌려 봅니다.
python C:\work\remote_queue.py --repo C:\work\myrepo --device pc
3. 5분마다 자동으로 돌리기
PowerShell에서 아래를 실행하면 Windows 예약 작업이 등록됩니다. 경로는 자기 환경에 맞게 바꾸세요(pythonw.exe의 전체 경로는 where.exe pythonw로 확인할 수 있습니다).
$a = New-ScheduledTaskAction -Execute "C:\Python312\pythonw.exe" `
-Argument "C:\work\remote_queue.py --repo C:\work\myrepo --device pc" -WorkingDirectory "C:\work\myrepo"
$t = New-ScheduledTaskTrigger -Once -At (Get-Date).AddMinutes(1) -RepetitionInterval (New-TimeSpan -Minutes 5)
$s = New-ScheduledTaskSettingsSet -StartWhenAvailable -MultipleInstances IgnoreNew `
-ExecutionTimeLimit ([TimeSpan]::Zero) -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries
Register-ScheduledTask -TaskName "RemoteQueue" -Action $a -Trigger $t -Settings $s
pythonw.exe로 실행하면 5분마다 검은 창이 뜨지 않습니다. 실행기 안에서 부르는 git·cmd도 창을 만들지 않게 해 두었습니다.-MultipleInstances IgnoreNew는 앞 회차가 아직 도는 중이면 예약 작업이 새 회차를 건너뛰게 합니다. 손으로 돌린 회차와 겹치는 경우는 실행기의 잠금 파일이 막습니다.-ExecutionTimeLimit ([TimeSpan]::Zero)는 윈도우 기본값인 "3일(72시간) 뒤 강제 종료"를 끕니다. 작업마다의 제한 시간은 작업 파일에 따로 적습니다.-AllowStartIfOnBatteries -DontStopIfGoingOnBatteries는 받는 기기가 노트북일 때 필요합니다. 기본값은 배터리로 돌 때 시작하지 않는 것입니다.- 각 옵션의 설명은 Microsoft 문서에 있습니다.
- 이렇게 등록하면 그 사용자가 로그인해 있을 때만 돕니다. Windows 업데이트로 재부팅된 뒤 로그인 화면에 멈춰 있으면 대기열도 멈춥니다. 로그인 없이 돌리려면 등록할 때
-User와-Password를 주거나 작업 스케줄러 화면에서 "사용자의 로그온 여부에 관계없이 실행"을 고르세요.
4. 작업 보내기
보내는 기기에서 queue/pc/inbox/에 파일을 만들고 올립니다. 이름 앞의 번호가 실행 순서입니다.
queue/pc/inbox/010_sysinfo.cmd
rem timeout=300
chcp 65001 > nul
systeminfo | findstr /c:"OS" /c:"Memory"
nvidia-smi --query-gpu=name,memory.used --format=csv
- 파일 앞부분의
rem timeout=300(.ps1·.sh는# timeout=300)이 이 작업의 제한 시간(초)입니다. 넘기면 그 작업과 작업이 띄운 프로그램을 멈추고, 기록에TIMEOUT이 남습니다. 적지 않으면 30분입니다. - 실행기는 출력을 UTF-8로 읽습니다.
.cmd에서는chcp 65001을,.ps1에서는 맨 위에[Console]::OutputEncoding=[Text.Encoding]::UTF8을 넣어야 한글이 깨지지 않습니다. - 결과 파일을 남기려면 작업 안에서
queue\pc\results\에 저장하게 하세요. - 이미 실행된 작업 파일을 고쳐서 다시 올려도 다시 돌지 않습니다. 새 번호로 새 파일을 넣으세요.
- 작업 파일은 실행 직전에
done으로 옮겨집니다. 작업 안에서 파일 경로는 작업 파일 위치(%~dp0,$PSScriptRoot)가 아니라 저장소 폴더 기준으로 적으세요(작업은 저장소 폴더에서 실행됩니다). inbox에서 파일을 지워 취소하는 것은 PC가 그 파일을 받기 전에만 확실합니다. 이미 받아 간 뒤라면 실행될 수 있습니다.
5. 결과 받기
5분쯤 뒤 보내는 기기에서 git pull 하면 queue/pc/done/010_sysinfo.log가 생겨 있습니다.
job: 010_sysinfo.cmd
start: 2026-09-27 14:07:32
end: 2026-09-27 14:07:34
exit: 0
========================================
...
exit: 0이 아니면 실패한 작업입니다. exit: running에서 멈춰 있으면 실행 도중 PC가 꺼졌거나 실행기가 죽은 것입니다. heartbeat.txt의 시각이 오래됐으면 PC가 꺼졌거나 예약 작업이 멈춘 것입니다(작업이 없을 때는 한 시간에 한 번만 갱신합니다).
실제로 막혔던 것과 해결
이 사이트를 운영하며 겪은 문제들입니다. 위 실행기에는 해결책이 이미 들어 있습니다.
| 겪은 문제 | 증상 | 해결 |
|---|---|---|
| 줄바꿈(CRLF) 변환 | 받는 PC에서 git이 파일을 "바뀜"으로 보고 pull이 계속 실패 |
받는 PC는 자기 폴더 밖 변경을 매번 버림. 저장소에 .gitattributes 추가 |
| 고친 파일이 옛 내용으로 실행됨 | 한 번은 옛 제목 목록으로 자료를 받아 다시 돌려야 했음. 처음에는 받는 PC가 옛 사본을 올린 탓으로 봤지만, 실제로는 보내는 쪽에서 옛 파일을 올린 것이었음 | 보낸 뒤 파일 크기로 새 내용이 갔는지 확인. 받는 PC가 다른 폴더를 되돌리는 일도 없도록 자기 대기열 폴더만 올림 |
| 충돌 흔적이 남음 | 한 번 충돌한 뒤로 모든 회차가 실패 | 매 회차 시작 때 멈춘 rebase를 취소하고 폴더 밖 변경을 되돌림 |
| 빈 커밋이 쌓임 | 할 일이 없어도 5분마다 커밋 | 작업이 없으면 한 시간에 한 번만 살아 있음을 기록 |
| PC가 절전 모드로 들어감 | 밤에 넣어 둔 작업이 아침에 PC를 깨운 뒤에야 돌았음 | 전원 설정에서 절전을 끄거나(powercfg /change standby-timeout-ac 0), 예약 작업 설정에 -WakeToRun을 추가(전원 옵션의 "절전 모드 해제 타이머 허용"이 켜져 있어야 하고, 5분마다 PC를 깨웁니다) |
마지막 줄과 관련해, 밤새 작업을 넣을 때 "다 끝나면 PC 끄기" 작업을 맨 뒤에 넣고 싶을 수 있습니다. 이 실행기는 실행 전에 작업을 done으로 옮기고 올려 두므로 끄기 작업이 켤 때마다 반복되지는 않습니다. 다만 끄기 작업은 결과가 다 올라간 뒤 꺼지도록 shutdown /s /t 120처럼 몇 분 여유를 두세요.
.gitattributes는 저장소 맨 위에 이렇게 두면 됩니다. Windows 배치 파일은 CRLF로, 셸 스크립트는 LF로, 나머지는 git이 알아서 맞추게 합니다(git 문서). 이미 올린 파일이 있는 저장소라면 추가한 뒤 git add --renormalize .로 한 번 다시 맞춰 주세요.
* text=auto
*.cmd text eol=crlf
*.bat text eol=crlf
*.ps1 text eol=crlf
*.sh text eol=lf
.sh 작업은 받는 PC에 Git Bash가 bash로 잡혀 있어야 합니다. WSL의 bash가 먼저 잡히면 C:\ 경로를 못 찾을 수 있습니다.
공개 전에 한 시험
이 실행기는 이 사이트에서 쓰는 것을 줄인 버전입니다. 공개 전에 독립 검토를 한 번 받았고, 거기서 나온 문제(처음 실행할 때 결과가 안 올라가는 문제, 올리기 실패 뒤 결과가 한참 늦게 오는 문제, 작업이 띄운 프로그램 때문에 실행기가 멈추는 문제, 같은 작업이 두 번 도는 문제 등)를 고친 뒤 다시 시험했습니다.
- Linux, 가상 저장소 두 개: 처음 실행, 정상 작업(
exit: 0), 실패 작업(exit: 3), 제한 시간 3초 초과(exit: -1, 3초에 끝남), 백그라운드 프로그램을 남기고 끝나는 작업(바로exit: 0), 받는 PC의 로컬 변경과 git이 모르는 파일, 올리기가 거절된 뒤 다음 회차에 올라가는지, 실행기를 죽이는 작업(다시 실행되지 않고exit: running으로 남음), 두 회차를 겹쳐 실행(뒤 회차가 건너뜀), 실행 도중 보내는 쪽이inbox의 작업을 지워 받기가 막힌 경우(다음 회차에 복구되고 결과 기록 4개가 모두 올라감, 앞 작업이 남긴 프로그램의 출력은 다음 작업 기록에 섞이지 않음). 모두 예상대로 동작했습니다. - Windows 노트북, 로컬 저장소:
.cmd작업 4개와.ps1작업 1개. 정상exit: 0, 실패exit: 3, 제한 시간 3초 초과exit: -1(띄운ping까지 종료돼 남은 프로세스 0개), 백그라운드로ping을 띄우고 끝나는 작업은 기다리지 않고 바로exit: 0,.ps1의 출력도 기록됨. 다섯 작업에 약 9초 걸렸고, 백그라운드ping의 출력은 다음 작업 기록에 섞이지 않았습니다. 두 번째 빈 회차는 아무것도 올리지 않았고, 작업마다 "실행 시작" 커밋과 마지막 결과 커밋이 올라갔습니다.
시간 초과 때 하위 프로세스까지 끄는 이유는, 이 사이트에서 남은 프로세스가 그래픽 메모리를 붙잡아 측정이 두 배 넘게 느려진 적이 있어서입니다(자세한 이야기). 그때는 제한 시간 때문이 아니라 Ollama를 강제로 끄면서 남은 프로세스였지만, 작업이 남긴 프로그램이 다음 작업을 방해할 수 있다는 점은 같습니다.
보안: 이것만은 꼭
inbox에 파일을 넣을 수 있는 사람은 곧 내 PC에서 명령을 실행할 수 있는 사람입니다. 저장소는 반드시 비공개로 두고, 쓰기 권한은 나만 갖게 하세요.- 받는 PC의 GitHub 접근은 이 저장소 하나에만 쓸 수 있는 토큰(세분화된 개인 액세스 토큰)이나 배포 키로 주는 편이 안전합니다. 토큰은 저장소 파일에 적지 말고 Windows 자격 증명 관리자에 맡기세요.
- 작업 결과에 비밀번호·개인정보가 섞이지 않게 하세요.
done의 기록은 저장소에 그대로 올라갑니다.
한계
- 5분마다 확인하므로 결과까지 최소 몇 분이 걸립니다. 바로 반응해야 하는 일에는 맞지 않습니다.
- 받는 PC가 꺼져 있으면 작업은 켜질 때까지 기다립니다(
-StartWhenAvailable덕분에 켜지고 로그인하면 바로 이어서 돕니다). - 작업 하나가 오래 걸리면 그동안 다른 작업은 기다립니다. 한 기기에서 동시에 여러 작업을 돌리지는 않습니다.
- 작업이 제한 시간 안에 끝났는데 띄운 프로그램이 남아 있으면(서버를 켜는 작업 등) 실행기는 그대로 둡니다. 일부러 남기는 경우가 있기 때문입니다. 끄려면 작업 안에서 직접 정리하세요.