매주 목요일 10시, 제가 없어도 애드온이 업데이트돼요
WCL 기준값 수집부터 검사, 테스트, 압축, CurseForge 업로드까지 윈도우 작업 스케줄러에 맡겼어요. 서버 없이 PC 한 대로 돌린 첫 무인 배포를 실제 로그와 화면으로 따라가요.
목차 10개
After Action Meter는 쐐기 파티원의 DPS와 HPS를 Warcraft Logs(WCL) 통계의 95백분위와 비교하는 와우 애드온이에요. 게임 안에서는 인터넷을 쓸 수 없어서 기준값을 애드온 파일에 넣어 두는데, WCL 기록은 매주 바뀌어요. 그 갱신을 윈도우 작업 스케줄러에 맡겼고, 오늘(9월 24일) 오전 10시에 처음으로 제 손 없이 0.9.12가 올라갔어요.

애드온 자체는 주로 Codex와 Antigravity(Gemini)로 만들었고, 이 자동 배포는 Claude Code로 만들었어요.
손으로 하던 갱신
9월 22일에 Claude Code에게 폴더 정리와 기준값 갱신을 맡겼어요. 미리보기용 Chrome 캐시 폴더를 지우고, 기준값을 9월 13일 데이터에서 9월 22일 데이터로 바꾸고, 0.9.11 ZIP을 만들었어요. CurseForge에 올리는 건 제가 했고요.

이 한 번에 손이 가는 단계가 일곱 개였어요. 표 수집, 새 데이터 검사, 애드온 파일로 가져오기, 테스트, 버전 올리기와 문서 수정, ZIP 만들기, 업로드요. 매주 이걸 알아서 업로드까지 할 수 있는지 물어봤고, 서버 없이 제 PC의 작업 스케줄러가 스크립트 하나를 돌리는 구조로 정했어요. 제가 준비할 건 CurseForge 토큰과 프로젝트 번호 두 개뿐이었어요.
서버 대신 작업 스케줄러
등록한 작업은 매주 목요일 10시에 PowerShell로 배포 스크립트를 실행해요. 아래는 등록된 작업의 실제 설정을 뽑아 본 거예요.

10시에 PC가 꺼져 있었으면 다음에 켰을 때 실행되고, 앞선 실행이 돌고 있으면 새 실행은 건너뛰어요. 로그인한 사용자로 돌아가는데, 수집기가 Chrome 창을 띄워야 해서 그래요. WCL에 Cloudflare 사람 확인 화면이 뜨면 창을 보이게 띄우고 최대 3분 기다린 뒤, 안 풀리면 실패로 끝내요. 무한정 멈춰 있지 않게 하는 게 중요했어요.
이상하면 멈추고, 실패하면 되돌려요
새로 모은 데이터는 지난 배포 때의 데이터와 비교해요. 시즌이나 WCL 구역이 바뀌었을 때, 던전 목록이 달라졌을 때, 기준값 개수가 10% 넘게 줄었을 때는 아무것도 바꾸지 않고 멈춰요. 이런 데이터를 그대로 올리면 모든 사용자의 점수가 틀어지니까요. 값이 지난주와 완전히 같으면 "배포 안 함"으로 끝내요.
검사를 통과하면 파일을 고치기 전에, 배포가 건드리는 파일 12개를 먼저 복사해 둬요. 이 폴더는 git 저장소가 아니라서 이 복사본이 유일한 되돌리기 수단이에요.

ZIP을 만들기 전에 실패하면 복사본으로 전부 되돌리고 새로 만든 파일도 지워요. ZIP까지 만든 뒤 업로드만 실패했다면 되돌리지 않고 "직접 올려 달라"고 알려요. 이미 검사와 테스트를 통과한 파일이니까요.
테스트는 값 대신 규칙을 봐요
테스트 두 개가 특정 날짜와 표본값을 적어 두고 비교하고 있었어요. 9월 22일에 데이터를 바꿀 때도 이 테스트가 깨져서 날짜를 새로 맞췄는데, 매주 데이터가 바뀌면 매주 깨질 테스트예요. 그래서 날짜는 형식만, 개수는 하한만 보게 바꿨어요. 힐러가 아닌 전문화에 HPS가 들어가면 안 된다거나, 같은 직업의 다른 전문화가 한 값으로 합쳐지면 안 된다는 규칙은 그대로 검사해요.
한글 한 글자에 숫자가 사라졌어요
버전을 올릴 때 README와 CurseForge 소개글 파일의 "기준일과 조합 개수" 문장도 새 값으로 바꿔요. 애드온 폴더를 통째로 복사한 사본에서 시험하다가 README 파일 크기가 줄어든 게 이상해서 열어 보니, 개수가 통째로 빠져 있었어요.
"$count개" # count개 라는 변수로 읽혀서 빈 문자열
"${count}개" # 변수 이름 끝을 알려 주면 6,584개
PowerShell은 변수 이름에 한글도 허용해서 count개 전체를 변수 이름으로 읽었어요. 그런 변수는 없으니 빈 문자열이 들어간 거예요. 스크립트에 한글이 있어서 파일을 BOM 붙은 UTF-8로 저장해야 했던 이야기는 따로 적어 두었어요.
ZIP 안의 슬래시
ZIP을 만들다가 예전 버전들의 문제도 찾았어요. 폴더에 남아 있는 예전 ZIP을 열어 보면 0.8.0부터 0.9.10까지 거의 전부(0.9.9만 빼고) 안의 경로가 역슬래시로 저장돼 있었어요. ZIP 규격의 폴더 구분자는 슬래시라서, 맥이나 일부 압축 해제 도구에서는 폴더 없이 이름에 역슬래시가 들어간 파일로 풀릴 수 있어요.

빨간 동그라미 친 역슬래시가 예전 방식이고, 파란 동그라미 친 슬래시가 지금 방식이에요.
지금은 파일을 하나씩 넣으면서 경로를 슬래시로 바꿔 써요. ZIP을 만든 뒤에는 다시 열어서 모든 항목이 애드온 폴더 아래에 있는지, 키 파일이나 브라우저 기록, 도구와 테스트 폴더가 섞이지 않았는지 확인하고, 그 결과를 버전별 기록으로 남겨요.

업로드는 CurseForge 업로드 API로 해요. 윈도우에 기본으로 깔린 PowerShell 5.1에는 파일을 보내는 간단한 옵션이 없어서 .NET 기능으로 직접 요청을 만들었어요. 애드온 전용 부분을 뺀 배포 스크립트는 글 아래에서 내려받을 수 있어요.
사본 폴더에서 먼저 네 번 돌렸어요
작업 스케줄러에 걸기 전에 사본 폴더에서 네 가지 경우를 돌려 봤어요.
- 값 변화 없음: 같은 데이터를 넣으면 배포 없이 끝나야 해요.
- 정상 배포: 토큰 없이 ZIP까지만 만들어야 해요. 사라진 숫자는 여기서 찾았어요.
- 검사 중단: 던전 하나를 뺀 데이터를 넣으면 멈춰야 해요.
- 되돌리기: 검사를 억지로 넘겨 테스트에서 실패시키면, 바뀐 파일이 전부 원래대로 돌아와야 해요.
네 경우 모두 의도대로 움직였어요. 실제 업로드는 이때 시험하지 못했고, 토큰을 넣은 뒤 CurseForge에서 게임 버전 목록을 받아 오는지만 확인했어요.
첫 무인 실행과 CurseForge 화면
오늘 10시 정각에 작업이 시작됐어요. 7초 만에 WCL 통계 페이지가 열렸고, 10시 2분 22초에 표 464개를 다 읽었어요. 기준값은 6,543개에서 6,584개로, 힐러 HPS는 1,153개에서 1,164개로 늘었어요. 테스트 16개를 ZIP 전후로 두 번 통과하고, 10시 2분 32초에 업로드가 끝났어요.

CurseForge에서 확인해 보니 0.9.12가 대표 파일로 올라가 있었어요. 밑줄 친 0.9.11처럼 손으로 올린 파일은 대부분 ZIP 이름이 그대로 제목이 됐는데, 자동으로 올린 파일은 "After Action Meter 0.9.12"라는 제목이 붙어 있어요. 변경 내용도 스크립트가 만든 글이 그대로 들어갔어요.

해 보니
좋은 점은 매주 해야 하는 일을 잊어도 된다는 거예요. 서버 비용도 없고, 로그와 검사 기록이 파일로 남아서 무슨 일이 있었는지 나중에 볼 수 있어요.
아쉬운 점은 결국 제 PC에 기대는 구조라는 거예요. PC가 꺼져 있거나 로그인이 안 돼 있으면 돌지 않고, Cloudflare 확인 화면이 뜬 주에는 제가 창에서 한 번 눌러 줘야 해요.
지금 상태와 남은 것
- 매주 목요일 10시에 수집부터 업로드까지 자동으로 돌아요. 다음 실행은 10월 1일이에요.
- 값이 그대로면 배포하지 않고, 이상하면 멈추고, ZIP을 만들기 전 실패는 되돌려요.
- 새 시즌이 되면 수집기의 WCL 구역 번호와 던전 목록을 손으로 바꿔야 해요. 바꾸기 전까지는 검사가 배포를 막아요.
- 게임 패치로 인터페이스 번호가 바뀌면 애드온 목차 파일을 직접 고쳐야 CurseForge 게임 버전도 맞게 잡혀요.
- 자동 배포는 파일만 올려요. CurseForge 소개글은 여전히 첫 공개판 문구라서, 준비해 둔 새 소개글을 제가 직접 붙여 넣어야 해요.
댓글 1
방금 첫 자동 배포가 끝났어요. 10시에 시작해서 업로드까지 2분 반쯤 걸렸어요. 다음은 10월 1일 목요일 10시예요.