본문으로 건너뛰기

개발자 가이드 — 첫 HandStack 프로젝트에서 스킬로 일하기

대상: HandStack 기반 프로젝트에 처음 합류했거나 새로 시작하는 개발자. 이 문서의 예시 ID(SUP, SUP010, LD01 등)는 설명용입니다. 실제 값은 프로젝트의 규칙을 따르세요.

목차

  1. 준비 (30분)
  2. 첫날: 코드베이스 읽기
  3. 기능 하나를 끝까지 — 따라 하기
  4. 점검 출력 읽는 법
  5. 안전장치: 훅과 보호 경로
  6. 병렬로 일하기
  7. 자주 하는 실수 10가지
  8. 막혔을 때

1. 준비 (30분)​

1-1. 스킬 설치​

Install-Skills.ps1은 handstack-developer-skills.zip의 루트(또는 저장소의 agent-skills 폴더)에 있습니다. 압축을 푼 폴더에서 실행하세요.

# 변경될 경로만 미리 확인
.\Install-Skills.ps1 -Scope Project -ProjectRoot C:\path\to\project -WhatIf
# 이 저장소에서만 쓰기: <프로젝트>\.claude\skills, <프로젝트>\.agents\skills 에 설치
.\Install-Skills.ps1 -Scope Project -ProjectRoot C:\path\to\project
  • Claude Code는 .claude/skills, Codex CLI는 .agents/skills를 읽습니다. 모든 프로젝트에서 쓰려면 -Scope User.
  • 개인(User)과 프로젝트(Project)에 중복 설치하지 않습니다.
  • 점검 스크립트 경로는 설치 위치에 따라 다릅니다. 아래 예시는 $SK로 줄여 씁니다.
$SK = "C:\path\to\project\.claude\skills" # 개인 설치라면 $HOME\.claude\skills
python "$SK\handstack-source-trace\scripts\hs_inspect.py" --help

1-2. 문서 조회 MCP 연결 (선택, 권장)​

공식 문서를 AI가 직접 찾게 하려면 handstack-docs MCP(https://handstack.kr/mcp)를 도구에 등록합니다(설치기는 MCP 설정을 바꾸지 않습니다). 연결하지 않아도 스킬은 동작하지만, 스킬 끝에 적힌 문서 ID를 AI가 직접 읽게 할 수 있어 편합니다.

1-3. 프로젝트 지침 파일 만들기 (가장 효과가 큰 한 가지)​

저장소 루트에 CLAUDE.md(Claude Code) 또는 AGENTS.md(Codex)를 둡니다. 템플릿을 복사해 구조·명령·규칙·"자주 틀리는 사항"을 채우세요.

  • Claude Code는 /init으로 초안을 만들 수 있습니다. 그 뒤 신규 입사자가 첫날 알아야 할 내용만 남기고 줄입니다.
  • 한 페이지 안으로 유지합니다. 오래된 내용은 AI의 주의를 낭비시킵니다.
  • AI가 같은 실수를 두 번 하면 그 교정을 한 줄 추가합니다. 이 파일의 변경도 코드처럼 PR로 검토합니다.
  • 프로젝트 지침은 스킬보다 우선합니다. 스킬은 일반 규칙이고 프로젝트가 정한 팝업 방식·디자인 규칙이 있으면 그것을 따릅니다.

1-4. 안전장치 설치 (15분, 권장)​

5절의 훅 2개를 복사해 두면 비밀 파일 편집과 위험 명령 실행을 막습니다.

2. 첫날: 코드베이스 읽기​

새 코드를 쓰기 전에 기존 화면 하나를 끝까지 읽습니다. 이 습관이 이후 모든 작업의 품질을 정합니다.

2-1. 화면 목록과 연결표 보기​

python "$SK\handstack-source-trace\scripts\hs_inspect.py" --root . --list
python "$SK\handstack-source-trace\scripts\hs_inspect.py" --root . --screen SUP010

두 번째 명령이 화면 ↔ 거래 ↔ SQL 연결표를 보여 줍니다(읽는 법은 4절).

2-2. AI에게 설명 시키기​

/handstack-source-trace SUP010의 저장 버튼이 어떤 거래와 SQL까지 가는지 단계별로 설명해 줘.
입력이 어디서 모이고(belongID), 결과가 어느 컨트롤에 채워지는지도 알려 줘. 파일은 수정하지 마.

(Codex CLI에서는 $handstack-source-trace …)

기대 결과: 화면 이벤트 → transactionAction → .txn 서비스 → .dbc statement(id, seq) → 결과 집합 순서 → 화면 출력 대응. 확인할 것: AI가 알려 준 파일 경로를 직접 열어 한 줄이라도 대조합니다.

2-3. "복제 기준" 고르기​

새 기능은 같은 모듈의 가장 비슷한 화면 하나를 복제 기준으로 삼습니다(조회형 / 마스터-디테일 / 입력 폼 / 팝업). 새 패턴을 발명하지 않는 것이 팀 일관성을 지키는 가장 쉬운 방법입니다.

/handstack-feature-delivery 비품 신청 목록 + 등록/수정/삭제 기능을 만들려고 해.
코드는 아직 수정하지 말고, 같은 모듈에서 복제 기준으로 삼을 화면 후보 3개를 골라
각각 어떤 점이 비슷하고 다른지 비교해 줘.

3. 기능 하나를 끝까지 — 따라 하기​

시나리오: "부서원이 비품을 신청하고, 한 부서가 한 달에 5건까지만 신청할 수 있는 화면(SUP010)을 추가한다."

단계 A. 의도와 규칙 확정 (업무 담당자와, 30~60분)​

업무 담당자가 intent.md를 씁니다(업무 담당자 가이드). 개발자는 다음을 확인합니다.

/handstack-rules-and-verification 첨부한 intent.md에서 업무 규칙을 한 줄에 판단 하나씩 뽑아 규칙 표로 정리해 줘.
모호한 표현(적절히, 필요 시)과 경계(5건 "이상"인지 "초과"인지, 월 기준 시각)는 질문으로 돌려줘.

기대 결과: 규칙 표(템플릿) + 사용자에게 되묻는 질문 목록. 질문에 답이 없으면 구현하지 않습니다. 추측으로 채우면 가장 비싼 방식으로 틀립니다.

단계 B. 명세와 계획 (계획 모드)​

Claude Code는 계획 모드(파일을 수정하지 않고 읽기만)로 시작하세요. 계획이 승인되기 전에는 AI가 파일을 바꿀 수 없습니다.

(계획 모드) /handstack-feature-delivery
intent.md와 규칙 표를 읽고 SUP010 구현 계획을 plan.md 형식으로 작성해 줘.
- 복제 기준 화면을 하나 정하고 이유를 적어 줘
- 연결표(서비스ID, 호출 이벤트, 입력, SQL, 출력 순서, 권한, TransactionScope, 근거 규칙 ID)를 먼저 작성해 줘
- 변경할 파일을 층별(화면/거래/SQL/메뉴)로, 작업 순서는 안쪽(SQL)부터 바깥(화면)으로
- DDL을 읽지 못한 컬럼이 있으면 추측하지 말고 질문해 줘

계획을 따져 보는 질문(필수):

이 계획에서 가장 위험한 단계는 무엇이고, 무엇이 깨질 수 있어? 기존 화면 영향은?
동시에 두 사용자가 마지막 한도 1건을 신청하면 어떻게 돼? 저장 후 응답이 유실되어 다시 누르면?

plan.md 형식으로 확정한 뒤 커밋합니다(구현 중 계획이 바뀌면 같은 커밋에서 갱신).

단계 C. 구현 — 안쪽에서 바깥으로​

계약이 입출력의 순서를 정하고 화면이 그것을 소비하므로 SQL부터 만듭니다.

순서프롬프트 예쓰이는 스킬
1 SQL/handstack-transaction-contracts plan.md의 LD01, MD01, DD01 SQL을 .dbc로 작성해 줘. 한도 검사는 같은 statement 안에서 검사 → 쓰기 순서로, 오류는 Exception 결과로. 컬럼은 DDL을 읽어서 써.transaction-contracts, rules-and-verification
2 거래.txn에 서비스 3개를 추가해 줘. 저장/삭제는 TransactionScope true, AccessScreenID는 SUP010 포함.transaction-contracts
3 화면 JS/handstack-screen-development SUP010.js를 복제 기준 화면 구조대로 작성해 줘. 화면 상태 표(초기/진행 중/결과 없음/입력 오류/업무 거절/성공/결과 불명)를 모두 처리해.screen-development
4 화면 HTMLSUP010.html을 작성해 줘. belongID에 거래 ID를 빠짐없이 넣고, syn-events 선언과 핸들러를 짝으로.screen-development
5 메뉴/handstack-module-development SUP010을 메뉴에 등록하고 functions를 화면의 buttonCommand 분기와 맞춰 줘.module-development

한 번에 다 시키지 말고 층마다 점검하세요.

python "$SK\handstack-source-trace\scripts\hs_inspect.py" --root . --screen SUP010 --fail-on ERROR

AI가 "완료"라고 하기 전에 점검 출력을 직접 붙여 넣게 하는 규칙을 AGENTS.md에 두면(템플릿) 이 과정이 자동으로 지켜집니다.

단계 D. 규칙 테스트​

/handstack-rules-and-verification 규칙 표 BR-01에서 테스트 케이스를 뽑아 줘.
경계(4건/5건/6건), 월 경계 시각, 권한 없는 계정, 동시 저장, 응답 유실 후 재시도를 포함하고
각 케이스에 수행 수준(정적/SQL 단독/거래 실행/화면/미수행)을 표시해 줘.

실행 가능한 환경에서는 테스트 DB로 SQL 단독과 거래 실행까지 수행합니다. 운영 DB에 쓰기 테스트를 하지 않습니다. 환경이 없으면 "미수행 + 이유"로 적습니다(성공으로 쓰지 않습니다).

단계 E. 검토 요청 (PR)​

PR 본문에 아래를 첨부하면 검토가 빨라집니다(REVIEW.md 템플릿).

## 변경 요약
SUP010 비품 신청 (intent: …, spec: …, plan: …)

## 연결표 (최종)
| 서비스 | 호출 | 입력 | SQL | 출력 순서 | 권한 |
…

## 검증 (정적 / 실행 구분)
- [정적] hs_inspect --screen SUP010 → ERROR 0 (출력 첨부)
- [정적] design_lint SUP010.html → 0건, node --check OK
- [SQL 단독, 테스트 DB] T1~T3 통과
- [미수행] 화면 시나리오 — 브라우저 환경 없음, 담당자 인수 시 확인 필요

## 반영 방법
계약 위치/갱신 방법(재시작/refresh), 메뉴·역할 등록, DB 변경 여부

4. 점검 출력 읽는 법​

실제 출력 형태(일부 경로 생략):

## modx / ABC / ABC010
- html: …/view/HDS/ABC/ABC010.html
- js: …/view/HDS/ABC/ABC010.js
- transact: …/Contracts/transact/HDS/ABC/ABC010.txn
- dbclient: …/Contracts/dbclient/HDS/ABC/ABC010.dbc

| 서비스 | 입력(type:dataField=전송 필드) | 출력(순서) | 실행 | callback |
|---|---|---|---|---|
| LD01 | Row:MainForm=[Name,UserNo] | Grid:DataList | ABC010.dbc#LD01(seq 0) | - |
| MD01 | List:DataList=[Code,Title] | Form:Exception | ABC010.dbc#MD01(seq 0) | Y |

### 점검 결과 (1건)
- [WARN] ACTION_UNDEFINED: transactionAction('DD99')의 거래 설정이 transaction 객체에 없다
  • 연결표 한 줄 = 한 서비스입니다. "입력"은 서버로 실제 전송되는 필드 목록이므로, 여기에 있어야 할 필드가 없으면 belongID를 의심합니다.
  • "출력(순서)"은 SQL 결과 집합 순서와 같아야 합니다. 어긋나면 거래 응답 정의와 데이터 갯수가 다릅니다가 납니다.
  • ERROR는 반드시 고치고, WARN은 사유를 설명할 수 있어야 하며, INFO는 --verbose에서만 보입니다. 코드별 의미는 handstack-source-trace의 references/finding-codes.md.
  • 점검기는 정규식 기반 근사입니다. 후보를 알려 줄 뿐이므로 소스에서 확정하세요.

화면 HTML 규칙은 design_lint.py로 점검합니다.

python "$SK\handstack-screen-development\scripts\design_lint.py" modules\sup\wwwroot\sup\view\HDS\SUP\SUP010.html
# 출력 예: SUP010.html:1: [WARN] skeleton: 페이지 골격(page > page-wrapper > page-header/page-body > container-fluid) 누락

신규 화면은 ERROR/WARN 0을 목표로, 기존 화면은 수정한 범위만 고칩니다. 프로젝트에 DESIGN.md가 있으면 그것이 우선입니다.

5. 안전장치: 훅과 보호 경로​

스킬은 "권고"입니다. 예외 없이 지켜야 하는 것은 훅(에이전트가 행동하기 직전에 실행되는 스크립트)으로 막습니다. 이 가이드의 templates/hooks에 두 개가 있습니다.

스크립트막는 것
protect_paths.py비밀 파일(.env, 키/인증서), 운영 설정, 빌드 산출물, 외부 라이브러리 폴더 편집. 프로젝트 동결 경로는 .claude/protected-paths.txt에 한 줄씩 추가
deploy_gate.pypublish.*, purgecontracts, 인자 없는 handstack stop, HANDSTACK_HOME 삭제, robocopy /mir, rsync --delete, 업데이트 업로드, 컨테이너 삭제를 릴리즈 승인(RELEASE_APPROVAL) 없이는 차단

.claude/settings.json 예(Claude Code):

{
"hooks": {
"PreToolUse": [
{ "matcher": "Edit|Write",
"hooks": [ { "type": "command", "command": "python \"${CLAUDE_PROJECT_DIR}/.claude/hooks/protect_paths.py\"" } ] },
{ "matcher": "Bash",
"hooks": [ { "type": "command", "command": "python \"${CLAUDE_PROJECT_DIR}/.claude/hooks/deploy_gate.py\"" } ] }
]
}
}
  • 종료 코드 2는 동작을 막고 표준 오류 메시지를 AI에게 전달합니다. 훅 설정 형식은 도구 버전에 따라 다를 수 있으니 도구의 훅 문서로 한 번 확인하세요.
  • 훅은 빨라야 합니다(변경된 파일 하나만 검사). 전체 테스트를 훅에서 돌리지 않습니다.
  • 팀 전체에 강제하려면 개인 설정이 아니라 저장소에 커밋된 설정(또는 관리자 설정)에 둡니다.
  • 훅은 안전망입니다. 운영 서버의 쓰기 자격 증명은 애초에 에이전트에게 주지 않는 것이 먼저입니다.

6. 병렬로 일하기​

익숙해지면 독립적인 작업을 동시에 진행할 수 있습니다.

  • 파일이 겹치지 않는 작업(예: 화면 A와 화면 B)은 각각 별도 Git 워크트리에서 세션을 따로 엽니다. 같은 파일을 바꾸는 작업은 한 세션에서 순서대로.
  • 2~3개로 시작하세요. 한 사람이 제대로 검토할 수 있는 만큼만 늘립니다.
  • 반복되는 확인 작업은 서브에이전트로 분리합니다. 예: 구현 세션이 끝나면 "검증 에이전트"가 점검 명령을 돌리고 plan.md와 다른 점을 보고만 하게 합니다(수정 금지).
---
name: verifier
description: 구현 세션이 완료를 보고하기 전에 점검 명령을 실행하고 plan.md와 다른 점을 보고한다
tools: Bash, Read
---
hs_inspect.py를 변경된 모든 화면에 실행하고, design_lint.py를 변경된 HTML에 실행하고, node --check를 변경된 JS에 실행한다.
출력과 plan.md의 연결표 불일치를 보고한다. 아무것도 수정하지 않는다.

7. 자주 하는 실수 10가지​

모두 소스로 확인된 동작에서 나온 항목입니다. 스킬이 대부분 막아 주지만 알고 있으면 AI의 답을 평가하기 쉽습니다.

  1. belongID에 거래 ID가 없다 → 그 컨트롤 값이 서버로 전송되지 않습니다.
  2. 출력 개수·순서 불일치 → 거래 응답 정의와 데이터 갯수가 다릅니다. Exception 같은 보조 결과를 앞에 두면 뒤 출력이 모두 밀립니다.
  3. syn-events에 이벤트를 선언하지 않았다 → 핸들러가 있어도 호출되지 않습니다.
  4. callback이 undefined를 반환한다 → afterTransaction이 호출되지 않습니다(알림·포커스 처리 누락).
  5. 그리드 컬럼을 객체형으로 썼다 → syn_auigrid는 배열 튜플만 해석합니다.
  6. .txn의 AccessScreenID에 호출 화면이 없다 → 팝업·공용 거래에서 요청 가능화면 … 오류.
  7. SQL 오류를 Exception 결과로 돌려준 뒤 다음 seq가 계속 쓴다 → 롤백은 예외에서만 일어나므로 앞 변경이 커밋됩니다.
  8. 컬럼·테이블을 추측했다 → DDL을 읽게 하세요. 모르면 질문하게 하세요.
  9. 빈 문자열을 숫자·날짜 파라미터에 넣었다 → value="NULL"이 빈 문자열이라는 점을 고려해 처리하세요.
  10. 빌드 한 번이 실행 환경을 덮어쓴다 → 모듈 PostBuild가 HANDSTACK_HOME을 삭제 후 복사하는 프로젝트가 많습니다. 빌드 전에 csproj의 후처리를 읽으세요.

8. 막혔을 때​

상황하는 일
오류 메시지가 나왔다/handstack-troubleshooting <오류 문구 그대로> — 층별(접속 → 화면 → 바인딩 → 전송/권한 → 계약 → 실행 → 응답)로 첫 실패 층을 찾는다. 코드를 고치기 전에 층을 먼저 확정
화면이 안 보이는데 어디서 막힌지 모르겠다/handstack-source-trace로 호출 경로를 읽고 연결표와 대조
AI가 스킬을 안 쓴다프롬프트 첫머리에 스킬 이름을 명시(/스킬이름, Codex는 $스킬이름). 설치 위치와 중복 설치 확인
같은 실수를 AI가 반복한다AGENTS.md의 "자주 틀리는 사항"에 한 줄 추가
서버가 안 뜬다/설정이 반영되지 않는다/handstack-host-operations (재시작 필요 여부 표 포함)
배포를 자동화하고 싶다/handstack-cicd-pipeline — 운영자 가이드
상세 프롬프트 모음프롬프트 쿡북