직원 PC 배포 · 운영
카톡·인스타 작업을 직원 PC 11대에 한 줄 설치로 배포하고 운영합니다 (2026-09-16 등록 기준)
카톡과 인스타에는 서버에서 부를 공식 API가 없습니다. 그래서 작업은 직원 맥과 윈도우 PC에서 돌아야 했습니다. 설치는 한 줄 명령, 인증은 기기별 키, 갱신은 도구별 자동 주기로 맞췄습니다. 서버도 직접 굴립니다. 클라우드 DB 한도로 업무툴 API가 모두 멈춘 2026-08-20에는 같은 API를 VM에 세워 그날 복구했습니다.
- 설치 토큰은 UPDATE 한 번으로 소진합니다. 조회와 사용 처리를 나누면 두 PC가 한 토큰으로 동시에 등록할 수 있습니다. used_at IS NULL과 만료 조건을 건 UPDATE가 행을 돌려줄 때만 통과시킵니다. 실패 이유는 직원이 읽을 문장으로 나눠 줍니다. 기기 한 대가 털리면 그 행만 폐기합니다.
- 버전 번호 대신 zip 해시를 씁니다. 공개된 zip의 sha256이 곧 버전입니다. 버전 대장이 따로 없으니 대장과 파일이 어긋날 일도 없습니다. 워커는 잡 사이에만 교체하고 그냥 종료합니다. 재실행은 launchd와 작업 스케줄러 몫입니다. 스스로 다시 띄우다 둘이 뜨면 인스타 프로필이 깨집니다.
- 갱신 시각은 PC마다 다르게 둡니다. 전 기기가 같은 분에 갱신하면 잘못된 배포를 거둘 틈이 없습니다. 맥 실시간 동기화는 14시에 분만 무작위로 고르고, 재설치해도 그 분을 지킵니다. 윈도우 CS 도구는 09:00~18:59 사이 무작위 시각에 받고, 로그온 2분 뒤 한 번 더 시도합니다.
- 윈도우 카톡은 읽기 전용 수집기를 씁니다. 수집기는 읽기 권한만 열고 쓰기는 하지 않습니다.
- 발송 성공은 exit code 말고 DB로 확인합니다. 2026-09-07에 사진만 가고 글이 빠졌는데 sent로 남았습니다. 이제 보낸 직후 카톡 로컬 DB를 읽고, 빠진 쪽만 그 자리에서 한 번 보충합니다. 사진이 안 보이면 업로드가 느린 경우를 감안해 더 기다립니다. 70명 방에 사진이 두 장 가는 건 유실보다 나쁩니다.
- 기기 지정과 조건부 claim을 겹쳐 뒀습니다. 2026-07-29에 개발 맥이 원격 전용 맥의 큐를 집었습니다. 성공과 실패가 번갈아 나와 원인을 찾는 데 하루가 걸렸습니다. 지금은 지정 호스트가 아니면 바로 끝납니다. claim은 status='pending' 조건부 UPDATE이고, 오픈채팅 큐는 UNIQUE(send_date, room_name)이 한 번 더 막습니다.
- 기기 차단은 푸시로 바로 전달합니다. 푸시 허브는 Postgres LISTEN/NOTIFY를 받아 SSE로 워커를 깨웁니다. device_keys가 바뀌면 깨우기 전에 다시 인증합니다. 차단된 기기에는 revoked를 보내고 연결을 끊습니다. 서버 쪽에서는 revoked_at 한 칸만 채우면 됩니다.
- deploy.sh는 배포할 커밋의 판으로 재실행합니다. 2026-09-28 배포 실패는 도는 스크립트와 커밋의 스크립트가 달라서였습니다. 이미지 태그는 sha-<커밋>으로 한 번 정하고, pull이 실패하면 :latest로 물러나지 않고 멈춥니다. compose는 빌드 전에 렌더해 빠진 변수를 40분 빌드보다 먼저 잡습니다.