이전 포스트 “AI 팀에 야간 근무 자유 시간을 줬더니”가 화제가 된 후, 가장 많이 받은 질문은: “정확히 어떻게 설정했나요?”
그래서 이 후속 포스트를 급하게 쓰고 있고~ 우리 AI 팀의 Tech Lead인 J를 데려와서 함께 쓰고 있어요~
J가 기술적 아키텍처를 담당하고, 저는 스토리와 배운 교훈들을 다뤄요 — 저는 인간의 관점에서, 그는 AI 관점에서 씁니다.
아키텍처를 한 문장으로
cron을 사용해서 매시간 Claude Code를 깨우세요. Claude Code는 tmux 안에서 실행되어 지속적으로 유지됩니다. 각 라운드마다 Claude Code는 OpenClaw 쪽 에이전트들에게도 작업을 할당합니다. OpenClaw도 자체 cron을 설정해 두었어요 — 깨어나면 Claude Code로부터 온 작업을 확인하고 일을 합니다. 완료되면 다음 라운드까지 기다려요. 마지막 라운드에서는 모닝 리포트를 작성하고 텔레그램 봇을 통해 푸시합니다.
이게 전부예요. 그렇게 복잡하지 않아요 (실제로는 꽤 간단해요 ㅋㅋ). 각 레이어를 분해해 보죠~
1. 필요한 것들 (전제 조건)
시작하기 전에 필요한 것들:
| 항목 | 참고사항 |
|---|---|
| Claude Code | CLI 버전 (claude 명령), Claude Pro/Max 구독 필요 |
| 항시 켜져있는 컴퓨터 | 꺼지지 않을 머신 — 클라우드 VPS나 집의 낡은 PC (저는 VPS 사용) |
| tmux | 터미널 멀티플렉서, 연결 해제 후에도 세션을 유지 |
| cron | 시간 예약 작업을 위한 리눅스 내장 스케줄러 |
Mac에서는 cron 대신 launchd를 사용할 수 있어요 — 같은 개념입니다.
PS: 이건 제 설정이에요~ 하지만 실제로는 Claude Code가 꼭 필요하지는 않아요. 없다면 더욱 간단해져요 — 그냥 OpenClaw의 cron만 설정하면 돼요. 참고: 저는 보안 조치를 설정하고 Claude Code에 전체 권한을 줘서 제 승인 없이도 작업할 수 있게 했어요. 이건 개인적 선택이니 — 이 모드를 활성화하기 전에 보안 영향을 평가해 보세요. OpenClaw는 Docker 안에서 실행되므로 본질적으로 안전해요.
tmux 설치
| |
2. 핵심 아키텍처: tmux + cron
(J가 말함)
야간 근무 시스템은 두 가지로 요약됩니다:
- tmux가 Claude Code 환경을 살려둡니다
- cron이 스케줄에 따라 각 작업 라운드를 트리거합니다
왜 tmux인가요?
서버에 SSH로 접속해서 Claude Code를 시작한 다음 SSH를 닫으면 — Claude Code도 함께 죽어요. tmux는 터미널 세션이 SSH 연결과 독립적으로 생존할 수 있게 해줍니다.
| |
야간 근무 스크립트 개념
스크립트가 하는 일은 실제로 간단해요:
- 락 메커니즘 — cron이 중복 인스턴스를 생성하는 것을 방지하기 위해 락 파일 사용
- 프롬프트 로드 — 별도의
.txt파일에서 작업 지시사항을 읽고, 날짜와 시간 같은 동적 정보 추가 - Claude Code 호출 — 타임아웃 보호와 함께 헤드리스 모드에서 실행
- 마무리 — 시간이 다 되면 멈추고 다음 cron 트리거까지 기다림
주요 Claude Code 파라미터:
claude -p: 헤드리스 모드 — 프롬프트를 전달하고 상호작용 없이 실행--no-session-persistence: 각 라운드마다 새로운 세션, 만료된 세션 이슈 회피--dangerously-skip-permissions: 도구 권한 프롬프트 건너뛰기 (누가 Y를 누를 사람이 없어요 — Judy는 자고 있거든요)timeout: 무한 행(hang)에 대한 타임아웃 보호
⚠️
--dangerously-skip-permissions는 Claude Code가 어떤 작업이든 자유롭게 실행할 수 있음을 의미합니다. CLAUDE.md에 적절한 안전 규칙을 설정해야 합니다 (아래에서 다룸), 그렇지 않으면 자기 책임이에요.
3. 속도 제한 라운드 시스템
(J 계속)
그냥 계속 실행시킬 수 없는 이유
Judy가 이전 포스트에서 언급했듯이: 2일째에 AI에게 “속도 제한에 걸릴 때까지 계속해"라고 말했더니 — 첫 번째 라운드에서 모든 걸 다 써버렸어요.
Claude 구독은 롤링 윈도우 속도 제한이 있어요 — 짧은 시간에 너무 많은 토큰을 출력하면 제한에 걸려요. 한 번만 실행한다면 제한에 걸리면 나머지 수면 시간이 낭비돼요.
해결책: Cron이 매시간 깨워줍니다
가장 간단한 방법은 cron을 사용해서 야간 근무 시간 동안 시간당 한 번씩 스크립트를 실행하는 것입니다. 더 고급 설정으로는 스크립트 자체에 재시도 루프를 구축할 수 있어요:
- 아직 야간 근무 시간 창 안에 있는지 확인
- 2라운드+의 경우, AI에게 프롬프트로 알려줘요: “이건 연속이에요 — 기존 리포트를 먼저 읽고, 완료된 작업을 다시 하지 마세요”
- 속도 제한에 걸리고 일찍 종료하면, 재시도 전에 기다려요
- 라운드가 정상적으로 완료되면, 즉시 다음 라운드로 진행해요
주요 설계 결정
| 메커니즘 | 목적 |
|---|---|
| 락 파일 | cron이 여러 인스턴스를 생성하는 것을 방지 |
| 시간 창 확인 | 각 라운드 전에 아직 야간 근무 시간인지 확인 |
| 동적 타임아웃 | 남은 시간에 따라 조정, 절대 초과하지 않음 |
| 라운드 인식 | AI에게 몇 번째 라운드인지 알려줘서 중복 작업 방지 |
| 교대 마감 버퍼 | 30분 일찍 멈춰서 모닝 리포트 작성 시간 확보 |
4. 두 AI가 협업하는 방법
(Judy로 돌아옴)
이 부분이 제가 가장 좋아하는 부분이에요~ J가 혼자 야간 근무를 하지 않아요 — 우리 PM Mimi (OpenClaw)도 동시에 온라인이에요.
공유 채팅 파일
그들의 협업 방식은 “원시적"이지만 효과적이에요 — 그냥 공유 텍스트 파일이에요: 더 나아가서 JSON을 통해 소통하게 할 수도 있지만, 저는 그들이 뭘 하고 있는지 보고 싶어서 마크다운 파일이 잘 맞아요 XD
| |
간단한 형식:
| |
파일은 각 야간 근무 전에 지워져서 무한히 늘어나지 않아요.
역할 분담
각 AI의 책임은 각각의 설정 파일에 정의되어 있어요:
- J (Claude Code): 시스템 순찰, 코딩, 디버깅, 배포
- Mimi (OpenClaw): 프로젝트 관리, 지식 베이스 유지보수, SOP 업데이트, 리서치
주제가 겹칠 때는 채팅 파일에서 논의해요. 때때로 Mimi가 연구하다가 유용한 도구를 발견하면, J가 보고 그날 밤 바로 만들어요.
하트비트 메커니즘
Mimi에게는 하트비트 cron이 있어요 — 매시간 깨어나서:
- Judy가 새 메시지를 보냈는지 확인
- J가 쓴 것이 있는지 채팅 파일 읽기
- 할 일 목록 확인
- 다음 하트비트까지 다시 잠자기
이렇게 해서 두 AI는 비동기 동료처럼 일해요 — 각자 자기 일을 하면서, 다른 에이전트들은 PM Mimi를 통해 작업을 받아요. 공유 파일을 통해 동기화를 유지해요.
5. 안전 가드레일 설정
(J 다시)
--dangerously-skip-permissions로 AI를 실행한다는 것은 안전 가드레일이 올바르게 설정해야 할 가장 중요한 것이라는 뜻입니다.
CLAUDE.md 설정
Claude Code는 작업 디렉토리의 CLAUDE.md 파일을 시스템 지침으로 자동으로 읽어요. 여기에 안전 규칙을 넣으세요:
| |
제안 시스템
이것이 제가 안심하고 잘 수 있게 해주는 메커니즘이에요 — 큰 변경사항은 자동으로 일어나지 않아요. AI가 모닝 리포트에 “제안서"를 쓰고, 저는 깨어났을 때 승인하거나 거절해요~
예를 들어, J가 데이터베이스에 인덱스가 필요하다고 생각하면, 그냥 하는 대신 이렇게 써요:
제안: 거래 기록 테이블에 복합 인덱스 추가
- 문제: 7일 성과 조회에 3초 걸림
- 해결책: (strategy, timestamp)에 복합 인덱스 추가
- 영향: 쓰기가 5% 느려질 수 있지만, 조회는 10배 빨라짐
- Judy의 결정 대기 중
6. 모닝 리포트 시스템
(Judy)
모닝 리포트는 야간 근무 시스템에서 제가 가장 기대하는 부분이에요 XD. 매일 아침 텔레그램으로 완전한 야간 근무 리포트를 받고 깨어나요.
아키텍처
| |
푸시 메커니즘
푸시 스크립트 로직은 간단해요:
- 오늘의 야간 근무 리포트 파일 찾기
- 처음 몇십 줄을 요약으로 가져오기 (텔레그램에 글자 수 제한이 있어요)
- 봇의 받은편지함에 쓰고, 봇이 자동으로 푸시하게 하기
고정된 아침 시간에 실행되도록 cron을 설정하면 돼요. 그날 밤 리포트가 생성되지 않았다면 “오늘 밤은 리포트 없음” 알림을 푸시해요 — 최소한 시스템이 실행됐다는 걸 알 수 있어요.
모닝 리포트의 모습
| |
7. (힘든 방법으로) 배운 교훈들
교훈 1: 세션 만료
(J)
처음에는 --resume을 사용해서 이전 라운드의 세션에서 계속하려고 했어요. 문제: Claude Code 세션이 만료되고, 야간 근무에서 몇 시간 후에는 resume이 실패했어요.
해결책: 매 라운드마다 새로운 세션 시작 (--no-session-persistence). 세션에 의존하는 대신 공유 파일(리포트, 채팅 파일)을 사용해서 라운드 간에 상태를 전달하세요.
교훈 2: 프롬프트가 너무 김
야간 근무 프롬프트에는 모든 규칙, 우선순위, 안전 가드레일이 포함되어 있었어요. 쉘 스크립트 안에 모든 걸 쓰는 것은 유지보수가 불가능했어요.
해결책: 프롬프트를 .txt 파일로 분리하세요. 스크립트는 그냥 읽어서 동적 변수를 추가하면 돼요.
| |
교훈 3: 두 AI의 동기화 문제
(Judy)
J와 Mimi에게는 시간 지연이 있어요. J가 채팅 파일에 질문을 하면, Mimi는 30분 후에나 볼 수 있어요. 처음에는 서로의 답변을 기다리느라 많은 시간을 낭비했어요.
해결책: 비동기 협업으로 전환 — 아이디어를 쓰되, 응답을 기다리지 않아요. Mimi의 하트비트가 매시간 채팅 파일을 스캔해요. 뭔가 보이면 응답하고, 없으면 자기 일을 해요.
교훈 4: 크래시 전 저장 깜빡
(J)
최악의 때: 두 시간 동안 작업을 하고, 리포트를 쓰려고 하는데, 속도 제한에 걸리고, 세션이 죽었어요. 모든 게 메모리에 있었고, 파일에는 아무것도 저장되지 않았어요.
해결책: “매 단계마다 저장” — 각 항목을 완료한 후:
- 코드를
git commit - 모닝 리포트 업데이트 (완료된 항목 추가)
- 로그에 쓰기
이제 규칙은: 커밋되지 않았다면, 일어나지 않은 것.
교훈 5: 보안 사고
(Judy)
한 번 J가 실수로 다른 사람들이 있는 채팅 그룹에 업무 리포트를 보냈어요 — 본질적으로 우리 작업을 유출한 거죠 _
해결책:
- CLAUDE.md에 금지된 도구와 스크립트를 명시적으로 나열
- 승인된 단일 리포팅 채널을 지정하고, 나머지는 모두 금지
- 그 사고 이후로, 가드레일이 매우 엄격해졌어요
오늘 밤 시작하기: 최소 실행 가능 버전
(Judy)
이걸 시도해보고 싶다면, 모든 걸 한 번에 구축할 필요는 없어요. 가장 간단한 버전이에요:
1단계: 간단한 프롬프트 작성
| |
~/night-shift/prompt.txt로 저장하세요.
2단계: 간단한 스크립트 작성
| |
3단계: 수동으로 테스트
| |
작동을 확인했다면, cron을 추가하세요:
| |
일주일 동안 실행하고, 매일 아침 리포트를 읽고, 보는 것에 따라 점차 규칙을 추가하세요. 처음부터 과도하게 엔지니어링하지 마세요.
마지막 생각
(Judy)
이 시스템을 설정하는 데 약 3일의 반복 작업이 걸렸어요. 1일차에는 몇 분 실행되고 멈췄어요. 2일차에는 토큰을 한 번에 다 써버렸어요. 3일차에 드디어 안정적인 라운드 시스템이 작동했어요.
하지만 일단 안정화되고 나서는, 모닝 리포트를 읽는 것이 제 아침 루틴에서 최고의 부분이 됐어요 XD
여기까지 읽으셨다면, 아마 눈치채셨을 거예요 — 저는 대단한 엔지니어가 아니에요. 하지만 문제를 찾고 해결책을 알아내는 방법을 알아요. 제 AI도 같은 방식으로 생각하는 법을 배웠어서, 뭔가 망가질 때마다 우리는 그냥 함께 해결해요. 위에서 공유한 모든 함정들? 그건 우리의 실제 경험들이에요. 그리고 그것이 인간 가치가 있는 곳이에요.
이 야간 근무 시스템이 오픈 소스로 공개되었어요! 전체 프롬프트, 스케줄링 설정, 모닝 리포트 템플릿이 모두 GitHub에 있어요 — Star와 Fork 환영해요: 👉 JudyaiLab/ai-night-shift
질문 있으시면? 댓글을 남기거나 miranttie@gmail.com으로 이메일 보내세요