운영자 가이드 — 서버 운영, 배포, 장애 대응을 스킬과 함께
대상: HandStack 서버(ack/rdy 호스트)를 운영하거나 배포를 맡은 사람(인프라·운영 엔지니어, 운영을 겸하는 개발자).
목차
- 첫 주: 내 환경 파악하기
- 일상 운영 점검
- 설정 바꾸기 (반영 방식)
- 배포: 방식 선택 → 파이프라인 → 승인 → 롤백
- 장애 대응
- 위험 명령 목록
- 보안 점검
- 신호를 의도로 되돌리기 (유지보수 순환)
1. 첫 주: 내 환경 파악하기
운영 사고의 대부분은 (1) 설정이 어느 파일에서 오는지 모르거나, (2) 빌드·배포 명령이 실행 폴더를 덮어쓰거나, (3) 재시작이 필요한 설정을 실시간 반영으로 오해해서 생깁니다. 먼저 아래 표를 채우세요(비밀 값은 적지 않습니다).
| 항목 | 확인 방법 | 내 환경 |
|---|---|---|
| 호스트 종류와 포트 | ack 8421, rdy 8420, forbes 8420(같은 호스트에 함께 두면 충돌), agent 8422, deploy 8520 — 운영 호스트 | |
HANDSTACK_HOME | 환경 변수 확인, env.* 스크립트 | |
| 환경 구분 | ACK_ENVIRONMENT(D/S/P) | |
| 로드되는 모듈 | appsettings.json의 LoadModules, --modules 인자 | |
| 설정 파일 계층 | appsettings.json → OS별 → 환경 변수 AppSettings__키 → appsettings.{환경}.json(뒤가 앞을 덮어씀) — 설정을 읽는 순서 | |
| 배포 방식 | 폴더 반영 / 업데이트 패키지 / Docker | |
| 프로세스 관리 | 서비스, IIS 앱 풀, pm2, 컨테이너 | |
| 로그 위치 | ${HANDSTACK_HOME}/log/app*.log (컨테이너는 docker logs) | |
| 백업/롤백 방법 |
AI에게 시킬 때:
/handstack-host-operations 이 서버의 구성을 파악하려고 해. 읽기 전용으로만 진행해 줘.
HANDSTACK_HOME 아래의 폴더 구성, 로드되는 모듈 목록, 설정 파일 계층(어떤 파일이 어떤 순서로 덮어쓰는지),
재시작이 필요한 설정과 필요 없는 설정을 표로 정리해 줘. 비밀 값은 열지 말고 키 이름만 알려 줘.
기대 결과: 위 표와 같은 정리. 확인할 것: AI가 module.json/appsettings의 비밀 값을 출력하지 않았는지.
2. 일상 운영 점검
curl -I http://localhost:8421 # 200
curl http://localhost:8421/checkip
curl "http://localhost:8421/diagnostics?hostAccessID=<SHA-256 해시>"
- 관리 API의
hostAccessID에는AppSettings:HostAccessID평문이 아니라 SHA-256 해시를 보냅니다(불일치가 401의 흔한 원인). 엔드포인트 목록은 관리 엔드포인트를 보세요. - 모듈 관리 API는
AuthorizationKey/AllowClientIP로 판정하고 실패하면401이 아니라400입니다(계약 관리 API 공통 규칙). 인증을 우회해 호출하지 않습니다. - 매일 볼 것: 프로세스/컨테이너 상태, 로그의 오류 추이, 디스크(
log,sqlite,storage), 인증서 만료, 대표 거래 1건 응답.
3. 설정 바꾸기 (반영 방식)
변경 전에 "이 설정은 재시작이 필요한가?"를 먼저 답합니다.
실시간 반영되는 키와 재시작이 필요한 키의 전체 목록은 실시간 반영과 재시작이 필요한 설정에 있습니다. IsConfigurationWatching=true일 때 HostAccessID, BusinessServerUrl, IsExceptionDetailText, WithOnlyIPs 같은 일부 키와 로드된 모듈의 module.json(데이터 원본 포함)이 재시작 없이 반영되고, LoadModules, CORS, 프록시, 세션, DLL 추가·교체, 새 모듈, OS별 파일, 환경 변수는 재시작이 필요합니다.
/handstack-host-operations 로그 상세 메시지(IsExceptionDetailText)를 개발 서버에서만 켜고 싶어.
어떤 파일의 어떤 키를 바꾸고, 재시작이 필요한지, 반영됐는지 확인하는 방법과 되돌리는 방법을 알려 줘.
운영 서버 설정은 바꾸지 말고 계획만 줘.
원칙: 운영 설정 변경도 코드처럼 PR(또는 변경 요청)로 남기고, 변경 후 확인 방법과 되돌리는 값을 같이 기록합니다.
4. 배포: 방식 선택 → 파이프라인 → 승인 → 롤백
4-1. 방식은 환경마다 하나
| 방식 | 적합 | 핵심 주의 |
|---|---|---|
| 폴더 반영(복사/미러링 + 재시작) | 단일 서버, 모듈·계약·정적 파일 위주 변경 | 공유 contracts 미러링 금지, 서비스 정지 후 복사, 설정 파일 환경 일치 |
업데이트 패키지(publish → publish-package → deploy → updater) | 여러 서버, 버전 단위 증분 배포 | contracts는 표준 패키지에 없음, 업로드 키 필수, 적용 중 오류 시 자동 복원 없음 |
| Docker(ack 이미지) | 컨테이너 운영 | 볼륨이 비어 있을 때만 시드 복사 → 이미지 교체만으로 앱이 갱신되지 않음 |
4-2. 현재 상태 점검부터
$SK = "C:\path\to\project\.claude\skills"
python "$SK\handstack-cicd-pipeline\scripts\pipeline_lint.py" . --min-severity WARN
찾는 것: 비밀 리터럴(값은 마스킹됨), 공유 contracts 미러링, HANDSTACK_HOME 삭제, 인자 없는 handstack stop, publish의 홈 격리 누락, 운영 잡의 개발 설정 복사, Docker 기반 이미지 버전·고정, 배포 호스트 ManagementKey 공백.
/handstack-cicd-pipeline 현재 저장소의 빌드·배포 스크립트와 CI 정의를 읽고 pipeline_lint 결과를 정리해 줘.
(1) 지금 파이프라인의 단계를 표로, (2) 안전하지 않은 지점과 고치는 순서,
(3) 격리 스모크와 롤백이 빠져 있다면 추가하는 방법을 제안해 줘. 서버에는 아무것도 반영하지 마.