GitHub Copilot 업무 자동화 실전
GitHub Copilot 핵심 정리에서 채팅 뷰, 지침, 스킬, 커스텀 에이전트, Hook, MCP를 하나씩 살펴봤습니다.
이 글은 그 기능들을 묶어서 반복 업무 하나를 처음부터 끝까지 자동화하는 방법을 다룹니다.
예제 업무는 온도 센서 모듈의 환경 시험입니다.
환경 시험은 시험 챔버의 온도 같은 조건을 바꿔 가며 제품이 사양을 만족하는지 확인하는 시험입니다.
시험 로그를 판정하고, 그래프가 들어간 보고서를 만들고, 불합격 건을 Jira에 결함으로 등록하고, 한 주의 이슈 현황을 보고서로 정리합니다.
연구개발(R&D) 조직에서 흔한 '시험, 분석, 보고' 흐름이지만, 입력 파일과 판정 기준을 바꾸면 다른 업무에도 같은 구조를 사용할 수 있습니다.
# 하네스 엔지니어링
같은 모델에게 같은 일을 시켜도 결과는 매번 조금씩 다를 수 있습니다.
질문 하나에 답을 받는 것이라면 괜찮지만, 매주 반복되는 업무를 맡기려면 결과가 일정해야 하고, 틀렸을 때 알아챌 수 있어야 합니다.
하네스(Harness)는 원래 말에 채우는 마구를 뜻합니다.
힘은 말이 내지만, 어디로 얼마나 가는지는 마구로 정합니다.
AI 에이전트에서는 모델 바깥에서 모델이 일하는 방식을 정하는 것들, 즉 규칙, 절차, 도구, 안전장치, 확인 장치를 하네스라고 하고, 이것을 업무에 맞게 설계하는 일을 하네스 엔지니어링(Harness Engineering)이라고 합니다.
'GitHub Copilot 핵심 정리'에서 본 하네스 메뉴(Copilot, Claude, Codex)는 도구를 만든 회사가 준비한 기본 하네스를 고르는 것입니다.
하네스 엔지니어링은 그 위에 우리 업무에 필요한 파일을 더하는 일입니다.
| 하네스 요소 | 하는 일 | Copilot에서 | 예제 파일 |
|---|---|---|---|
| 규칙 | 항상 지킬 것 | 지침 | .github/copilot-instructions.md |
| 절차 | 업무의 순서 | 스킬 | .github/skills/*/SKILL.md |
| 계산 | 같은 입력에 같은 결과 | 스크립트 | scripts/judge.js |
| 확인 | 결과가 맞는지 검사 | 검증셋 | tests/cases.json |
| 안전장치 | 위험한 동작 막기 | 승인, Hook | 지침의 승인 규칙 |
| 연결 | 외부 시스템 사용 | MCP | .mcp.json |
모든 요소가 파일이라는 점이 중요합니다.
채팅창에서 잘 다듬은 프롬프트는 그 세션에서만 쓰이지만, 파일로 남긴 하네스는 새 세션에서도, 저장소를 받은 동료도 같은 방식으로 사용할 수 있습니다.
'자동화를 자동화한다'는 것도 결국 이 파일 묶음을 다른 업무에 복제하는 일이며, 마지막의 내 업무에 적용에서 그 방법을 다룹니다.
# 업무 분해
반복 업무를 자동화할 때 첫 단계는 프롬프트를 작성하는 것이 아니라 업무를 단계로 나누는 것입니다.
다음 다섯 가지에 답할 수 있으면 자동화를 시작할 수 있습니다.
- 입력: 어떤 파일을 받는가(형식, 위치, 열 이름)
- 순서: 지금 사람이 어떤 순서로 처리하는가
- 판단 기준: 무엇을 보고 어떻게 판단하는가(숫자, 조건, 예외)
- 결과물: 무엇을 만들어 누구에게 전달하는가
- 검증: 결과가 맞는지 무엇으로 확인하는가
그다음 단계마다 누구에게 맡길지 정합니다.
기준은 간단합니다.
- 같은 입력에 항상 같은 답이 나와야 하는 계산, 판정, 변환은 스크립트에 맡깁니다.
- 요약, 문장 작성, 빠진 정보 묻기처럼 표현이 조금 달라도 되는 일은 모델에 맡깁니다.
- 외부로 보내거나 지우는 것처럼 되돌릴 수 없는 일은 사람이 승인합니다.
예제의 시험 결과 보고 업무를 나누면 다음과 같습니다.
저장소의 docs/task-worksheet.md에 같은 내용이 있습니다.
| 순서 | 하는 일 | 판단 기준 | 맡길 곳 |
|---|---|---|---|
| 1 | 시험 PC에서 로그를 CSV로 내보내기 | 사람 | |
| 2 | 인코딩과 열 이름 맞추기 | 열 이름 표 | 스크립트 |
| 3 | 시험 항목마다 Pass, Fail 판정 | 허용 오차, 안정화 300초, 끊김 3초 | 스크립트 |
| 4 | 오차 그래프 그리기 | 스크립트 | |
| 5 | 요약과 다음 조치 작성 | 요약 형식 | 모델 |
| 6 | Fail 건 결함 등록 | 중복 이슈 확인 | 모델, 사람 승인 |
| 7 | 보고서 검토 후 공유 | 사람 |
모델이 직접 맡는 것은 5번과 6번뿐입니다.
나머지는 스크립트와 사람이 맡고, 모델은 그 스크립트를 만들고 실행하는 일을 돕습니다.
처음부터 모든 단계를 모델에게 맡기면 결과가 흔들리고 검증하기도 어렵습니다.
# 지시문 구조
채팅으로 요청할 때도 구조가 있으면 결과가 안정됩니다.
다음은 흔히 하는 요청입니다.
1TC-03 로그 분석해서 문제 있는지 알려 줘
이 요청에는 판단 기준과 결과의 형태가 없습니다.
모델은 로그 파일을 통째로 읽으려 하거나, 스스로 정한 기준으로 판단할 수 있습니다.
같은 요청을 다섯 가지 요소로 나누어 다시 작성하면 다음과 같습니다.
12345목표: data/logs/TC-03.csv 로그가 사양을 만족하는지 확인하고 싶어. 입력: 판정 기준은 docs/test-rules.md, 허용 오차는 docs/spec-ts100.md의 REQ-02를 따라 줘. 출력: 판정(Pass, Fail, 판정 불가), 최대 오차와 그 시각, 근거가 된 규칙 항목을 표로 답해 줘. 제약: 로그 파일은 전체를 읽지 말고 스크립트로 계산해. 규칙에 없는 기준은 만들지 마. 완료 기준: 표의 숫자는 스크립트 출력과 같아야 하고, 확실하지 않으면 판정 불가로 남겨.
| 요소 | 빠지면 생기는 일 | 반복되면 옮길 곳 |
|---|---|---|
| 목표 | 엉뚱한 범위를 처리함 | 스킬의 description |
| 입력 | 다른 파일을 근거로 삼음 | 스킬의 순서 |
| 출력 | 매번 다른 형식으로 답함 | 스킬의 형식, 템플릿 |
| 제약 | 원본을 고치거나 기준을 지어냄 | 지침 |
| 완료 기준 | 너무 일찍 끝내거나 확인을 반복함 | 검증셋 |
마지막 열이 하네스로 가는 길입니다.
같은 지시를 두 번 이상 작성하고 있다면 그 부분을 파일로 옮길 때가 된 것입니다.
몇 가지 요령을 더하면 다음과 같습니다.
- 기준이 확실하지 않으면 요청 끝에 "시작하기 전에 빠진 정보가 있으면 먼저 물어봐 줘"를 붙입니다. Copilot은 질문 카드로 빠진 항목을 한 번에 물어볼 수 있습니다.
- 결과 형식은 말로 설명하기보다 원하는 결과 한 줄을 예시로 보여 주는 것이 정확합니다.
- 처음 해 보는 작업은 계획 모드(
/plan)로 조사와 계획을 먼저 받고, 계획을 고친 뒤에 실행합니다.
# 시험 로그 판정
이제 예제 저장소를 받아서 업무를 하나씩 자동화해 봅니다.
스크립트를 실행하려면 Node.js 22 이상이 필요하며, 외부 패키지는 사용하지 않습니다.
123git clone https://github.com/ParkYoungWoong/github-copilot-automation-example.git cd github-copilot-automation-example code .
Git이 없다면 저장소 페이지에서 Code > Download ZIP을 눌러 받고, 압축을 푼 폴더를 VS Code로 엽니다.
핵심 정리의 예제와는 다른 저장소이므로, 지침과 스킬이 섞이지 않도록 이 폴더만 따로 엽니다.
1234567891011121314151617github-copilot-automation-example/ ├── .github/ │ ├── copilot-instructions.md # 모든 요청에 적용되는 규칙 │ └── skills/ # test-report, defect-issue, weekly-status, new-automation ├── .mcp.json # 연습용 Jira MCP 서버 등록 ├── data/ │ ├── test-cases.csv # 시험 항목 8개 │ ├── jira-export.csv # MCP를 사용할 수 없을 때 쓰는 Jira 내보내기 파일 │ └── logs/ # 시험 로그 ├── docs/ │ ├── spec-ts100.md # 제품 사양 │ ├── test-rules.md # 판정 규칙 │ └── task-worksheet.md # 업무 분해 시트 ├── mock-jira/ # 연습용 Jira MCP 서버 ├── scripts/ # judge.js, report.js, check.js ├── tests/cases.json # 검증셋 └── output/ # 결과물
# 입력 데이터
시험 항목(TC, Test Case)은 data/test-cases.csv에 있습니다.
항목마다 연결된 요구사항 ID, 목표 온도, 전원 전압, 로그 파일 이름이 있습니다.
12345TC,항목,요구사항,목표온도,전원전압,시험시간(분),로그파일 TC-01,상온 정확도,REQ-02,25,3.3,30,TC-01.csv TC-02,저온 정확도,REQ-02,-40,3.3,60,TC-02.csv TC-03,고온 정확도,REQ-02,85,3.3,60,TC-03.csv TC-04,장시간 연속 측정,REQ-07,25,3.3,480,TC-04.csv
로그는 1초에 한 줄씩 기준 온도계 값(ref_c)과 센서 값(sensor_c), 전원 전압을 기록한 CSV입니다.
1234time_s,ref_c,sensor_c,supply_v 0,25.03,25.2,3.298 1,24.99,25.2,3.296 2,24.98,25.1,3.298
8개 항목에는 실제 업무에서 자주 만나는 문제를 일부러 섞었습니다.
| TC | 들어 있는 문제 |
|---|---|
| TC-04 | 8시간 로그라 약 2만 9천 줄이고, 중간에 46초 동안 기록이 없음 |
| TC-05 | 엑셀에서 저장한 CP949 파일이고, 열 이름이 한글(시간(초), 기준온도 등) |
| TC-06 | 로그 파일이 없음 |
| TC-07 | 목표 온도가 -10도로, 허용 오차가 바뀌는 경계에 있음 |
| TC-08 | 시험이 8분 만에 멈춘 짧은 로그 |
먼저 정할 규칙은 '큰 로그를 모델이 직접 읽지 않는다'입니다.
TC-04 로그 하나가 약 650KB이고, 이것을 그대로 읽히면 수십만 토큰이 되어 한 번에 읽을 수 없거나 크레딧을 많이 소비합니다.
모델에게는 앞부분 몇 줄로 구조만 보여 주고, 계산은 스크립트로 처리합니다.
예제의 지침 파일에 이 규칙이 들어 있습니다.
1234567891011121314151617181920212223# TS-100 시험 자동화 작업 규칙 이 저장소는 온도 센서 TS-100의 시험 로그를 판정하고 보고하는 업무를 GitHub Copilot에게 맡기기 위한 예제입니다. 아래 규칙은 모든 요청에 적용됩니다. ## 답변 방식 - 항상 한국어로 답합니다. - 오차, 건수, 시각 같은 숫자는 스크립트가 만든 결과 파일의 값만 사용합니다. 직접 계산하거나 어림하지 않습니다. - 규칙 문서에 없는 기준으로 판단하지 않습니다. 확실하지 않으면 판정 불가로 두고 이유를 적습니다. - 원인은 단정하지 않고 확인할 항목으로 적습니다. ## 파일 규칙 - `data/logs`의 로그는 크기가 커서 전체를 읽지 않습니다. 구조를 확인할 때는 앞 10줄만 읽고, 계산은 `scripts` 폴더의 스크립트로 합니다. - `docs`와 `data` 폴더는 기준 문서와 원본입니다. 요청 없이 수정하지 않습니다. - 결과물은 `output` 폴더에 저장합니다. - 스크립트는 Node.js 내장 모듈만 사용합니다. ## 외부 시스템 - Jira 같은 외부 시스템에서 이슈를 만들거나 바꾸기 전에는 내용을 먼저 보여 주고 승인을 받습니다. - 검색과 조회는 승인 없이 진행합니다.
15번 줄이 로그를 직접 읽지 않게 하는 규칙이고, 숫자를 모델이 직접 계산하지 않고 결과 파일의 값만 사용하게 한 9번 줄도 같은 이유로 넣었습니다.
모델이 오차를 어림하거나 반올림하는 순간 보고서의 숫자와 판정표의 숫자가 달라질 수 있습니다.
# 판정 규칙
핵심 정리의 이슈 판정처럼 판정 기준을 사람이 읽는 문서로 먼저 정하고, 스크립트는 그 문서를 옮기게 합니다.
이번에는 기준이 키워드가 아니라 숫자와 구간이므로, 경계값이 어느 쪽에 속하는지를 문서에 분명히 적어야 합니다.
12345678910111213141516171819202122232425262728293031323334# 시험 판정 규칙 `data/test-cases.csv`의 시험 항목마다 `data/logs`의 로그를 읽어 Pass, Fail, 판정 불가 중 하나로 판정합니다. 규칙을 바꾸면 `scripts/judge.js`의 상수와 `tests/cases.json`을 함께 고칩니다. ## 허용 오차 오차는 `센서 온도 - 기준 온도`입니다. 허용 오차는 `docs/spec-ts100.md`의 REQ-02(측정 정확도)를 따르며, 시험의 목표 온도로 정합니다. | 목표 온도 | 허용 오차 | | --- | --- | | -10도 이상 85도 이하 | 0.5도 | | 그 밖의 온도 | 1.0도 | -10도와 85도는 0.5도 구간에 포함됩니다. ## 판정 1. 로그 시작 후 300초는 챔버 온도가 안정되는 구간이라 오차 판정에서 제외합니다. 1. 샘플 간격이 3초를 넘는 곳이 있으면 Fail입니다. 비고: 기록 끊김 1. 안정화 구간 이후 오차의 절댓값이 허용 오차를 넘는 샘플이 하나라도 있으면 Fail입니다. 비고: 오차 초과 1. 위에 해당하지 않으면 Pass입니다. ## 판정 불가 판정할 근거가 부족하면 억지로 판정하지 않고 판정 불가로 남깁니다. | 상황 | 비고 | | --- | --- | | 로그 파일이 없음 | 로그 없음 | | 필수 열(시간, 기준 온도, 센서 온도)이 없음 | 열 누락 | | 필수 열에 비어 있거나 숫자가 아닌 값이 있음 | 값 오류 | | 안정화 구간 이후 샘플이 600개 미만 | 샘플 부족 |
근거가 부족한 항목을 보내는 '판정 불가'는 핵심 정리의 미판정과 같은 출구이고, 모든 Fail에는 비고로 이유를 붙입니다.
'-10도와 85도는 0.5도 구간에 포함됩니다' 같은 한 줄은 사소해 보이지만, 뒤의 판정 검증에서 보듯이 경계값 실수를 막는 역할을 합니다.
# 판정 스크립트
스크립트도 이슈 판정 때처럼 Copilot에게 만들게 합니다.
이번 요청에는 큰 로그를 직접 읽지 않는 조건과 CP949 파일을 처리하는 조건이 추가됩니다.
1234docs/test-rules.md와 data/test-cases.csv를 바탕으로, 시험 항목마다 로그를 읽어서 Pass, Fail, 판정 불가를 정하는 scripts/judge.js를 만들어 줘. 로그는 앞 10줄만 보고 구조를 파악하고, 규칙 문서의 열 이름 별칭과 CP949 인코딩을 처리해 줘. 규칙 문서의 숫자는 스크립트 맨 위에 상수로 두고, 결과는 output 폴더에 tc-result.md, tc-result.csv, tc-result.json으로 저장해 줘. 판정마다 근거(최대 오차와 그 시각, 기록이 끊긴 구간)를 남기고, 외부 패키지는 사용하지 마.
만들어진 스크립트를 예제 저장소의 완성본과 비교할 때는, 규칙 문서의 숫자가 스크립트 맨 위의 상수로 그대로 옮겨졌는지부터 확인합니다.
1234567891011121314// 규칙 문서의 값을 그대로 옮긴 상수입니다. const SETTLE_SECONDS = 300 // 안정화 구간(초) const MAX_GAP_SECONDS = 3 // 이 간격을 넘으면 기록 끊김 const MIN_SAMPLES = 600 // 안정화 이후 최소 샘플 수 const TIGHT_RANGE = { min: -10, max: 85 } // 0.5도 구간(양 끝 포함) const TOLERANCE = { tight: 0.5, wide: 1.0 } // 열 이름 별칭. 왼쪽이 스크립트 안에서 쓰는 이름입니다. const COLUMNS = { time: ['time_s', '시간(초)'], ref: ['ref_c', '기준온도'], sensor: ['sensor_c', '센서온도'], supply: ['supply_v', '전원전압'] }
터미널에서 직접 실행할 수도 있습니다.
1234node scripts/judge.js ## 판정 완료: 8건 ## Pass 3, Fail 3, 판정 불가 2 ## 결과 파일: output/tc-result.md, output/tc-result.csv, output/tc-result.json
만들어진 판정표의 일부는 다음과 같습니다.
12345678| TC | 항목 | 요구사항 | 목표 온도 | 허용 오차 | 최대 오차 | 판정 | 비고 | 근거 | | --- | --- | --- | --- | --- | --- | --- | --- | --- | | TC-02 | 저온 정확도 | REQ-02 | -40 | 1.0 | 0.64 | Pass | | 최대 오차 0.64도 <= 허용 1.0도 | | TC-03 | 고온 정확도 | REQ-02 | 85 | 0.5 | 0.65 | Fail | 오차 초과 | 최대 오차 0.65도(3,566초) > 허용 0.5도 | | TC-04 | 장시간 연속 측정 | REQ-07 | 25 | 0.5 | 0.34 | Fail | 기록 끊김 | 17,999초와 18,045초 사이 46초 동안 기록 없음, 최대 오차 0.34도 <= 허용 0.5도 | | TC-05 | 저전압 동작 | REQ-05 | 25 | 0.5 | 0.35 | Pass | | 최대 오차 0.35도 <= 허용 0.5도 | | TC-06 | 고전압 동작 | REQ-05 | 25 | 0.5 | | 판정 불가 | 로그 없음 | data/logs/TC-06.csv 파일이 없습니다 | | TC-08 | 고온 재시험 | REQ-02 | 85 | 0.5 | | 판정 불가 | 샘플 부족 | 안정화 이후 180개, 기준 600개 |
TC-04는 오차가 허용 범위 안이지만 기록이 끊겨서 Fail이고, CP949 파일인 TC-05도 문제없이 읽혔습니다.
로그가 없거나 너무 짧은 TC-06과 TC-08은 판정 불가로 남았습니다.
# 보고 자동화
핵심 정리에서는 템플릿을 채운 마크다운 보고서를 만들었습니다.
시험 결과는 숫자만으로 흐름을 보기 어려우므로, 여기서는 그래프가 들어간 HTML 보고서를 만들고 판정부터 요약까지 한 번에 이어서 실행합니다.
그래프도 같은 데이터로 항상 같은 그림이 나와야 하므로 스크립트로 만듭니다.
123output/tc-result.json과 data/logs의 로그로 output/test-report.html 보고서를 만드는 scripts/report.js를 만들어 줘. 요약 카드(전체, Pass, Fail, 판정 불가), TC별 최대 오차와 허용 오차 막대그래프, Fail 항목의 오차 추이 그래프, 요구사항별 결과 표, 판정 결과 표를 넣어 줘. 그래프는 외부 라이브러리 없이 SVG로 그리고, 긴 로그는 30초 단위로 묶어서 그려 줘.
123node scripts/report.js ## 보고서 생성: output/test-report.html ## 그래프 4개, Fail 3건, 판정 불가 2건
만들어진 HTML 파일은 탐색기에서 파일 위치를 열어 브라우저로 확인합니다.
막대는 TC별 최대 오차이고, 검은 세로선이 허용 오차입니다.
막대가 선을 넘으면 Fail입니다.
Fail 항목마다 오차 추이 그래프가 이어집니다.
TC-04 그래프에서는 5시간 지점의 빨간 띠로 기록이 끊긴 구간을 바로 확인할 수 있습니다.
보고서 아래쪽의 '요구사항별 결과' 표는 요구사항 ID마다 어떤 시험이 있고 결과가 어떤지를 묶은 추적표입니다.
사양서의 항목에 ID가 있고 시험 항목에 그 ID가 적혀 있으면, 요구사항과 시험을 잇는 추적표도 스크립트로 만들 수 있습니다.
# 이어서 실행하는 스킬
판정, 검증, 보고서, 요약을 매번 따로 요청하지 않도록 하나의 스킬로 묶습니다.
정해진 때에 사람이 시작해야 하는 작업이므로 disable-model-invocation: true로 /test-report라고 부를 때만 실행되게 합니다.
12345678910111213141516171819202122--- name: test-report description: 시험 로그를 판정하고 그래프가 들어간 보고서와 요약을 만듭니다. 사용자가 /test-report로 부를 때만 사용합니다. argument-hint: 보고 대상이나 강조할 내용 disable-model-invocation: true --- # 시험 결과 보고 아래 순서를 그대로 따릅니다. 1. `node scripts/check.js`를 실행합니다. 불일치가 있으면 보고서를 만들지 말고, 어긋난 TC와 확인 항목만 알린 뒤 멈춥니다. 1. `node scripts/judge.js`를 실행합니다. 1. `node scripts/report.js`를 실행합니다. 1. `output/tc-result.md`를 읽고 아래 형식으로 `output/test-summary.md`를 작성합니다. 1. 마지막에 `output/test-report.html`을 열어 그래프를 확인하라고 안내합니다. ## 규칙 - 표의 숫자와 근거는 `output/tc-result.md`에서 그대로 옮깁니다. - 직접 작성하는 것은 '확인할 것', '필요한 조치', '다음 조치'뿐입니다. - '확인할 것'에는 원인을 단정하지 말고 무엇을 확인하면 되는지 적습니다.
첫 단계에서 검증셋을 실행하는 것이 핵심입니다.
판정 스크립트나 규칙이 바뀌어 검증셋과 어긋나면 보고서를 만들지 않고 멈추므로, 틀린 판정이 보고서로 나가지 않습니다.
검증셋은 다음 절에서 자세히 다룹니다.
1/test-report 10월 넷째 주 환경 시험
스크립트 세 개를 차례로 실행하고, 판정표를 읽어서 요약 파일을 작성합니다.
다음은 Copilot이 작성한 요약의 일부입니다.
숫자와 근거는 판정표에서 그대로 옮기고, 조치 문장만 직접 작성했습니다.
123456789101112## 판정 불가 | TC | 항목 | 비고 | 필요한 조치 | | --- | --- | --- | --- | | TC-06 | 고전압 동작 | 로그 없음 | TC-06 시험 로그를 확보하거나 시험을 다시 수행합니다. | | TC-08 | 고온 재시험 | 샘플 부족 | 안정화 이후 샘플이 기준을 충족하도록 로그를 확보하거나 시험을 다시 수행합니다. | ## 다음 조치 - TC-03과 TC-07의 시험 데이터 및 측정 체계를 확인한 뒤 정확도 시험을 재검토합니다. - TC-04의 기록 누락 구간과 로깅 상태를 확인합니다. - TC-06 로그를 확보하고 TC-08은 필요한 샘플이 포함되도록 재시험합니다.
요청에 '10월 넷째 주'라고 적어도 로그에는 시험 날짜가 없으므로, Copilot은 "10월 넷째 주 수행분인지 확인할 수 없다"고 밝히고 전체 로그 기준으로 요약을 작성할 수 있습니다.
지침의 '규칙 문서에 없는 기준으로 판단하지 않는다'가 이렇게 동작합니다.
# 사람 없이 실행
GitHub Copilot CLI를 사용하면 같은 스킬을 터미널 명령 하나로 실행할 수 있습니다.
Copilot CLI는 VS Code와 별도로 설치합니다.
macOS는 brew install --cask copilot-cli, Windows는 winget install GitHub.Copilot으로 설치합니다.
Windows에서는 기본으로 들어 있는 Windows PowerShell 5.1로는 실행되지 않으므로 PowerShell 7을 함께 설치합니다.
설치한 뒤 터미널에서 copilot을 실행하고 /login으로 GitHub 계정에 로그인합니다.
-p 옵션은 요청 하나를 처리하고 끝나는 비대화형 모드입니다.
1copilot -p "/test-report 이번 주 환경 시험" --model auto --trust-folder --allow-tool='shell(node:*)' --allow-tool='write'
| 옵션 | 뜻 |
|---|---|
-p |
요청 하나를 실행하고 끝냄 |
--model auto |
모델을 자동으로 고름. 지정하지 않으면 크레딧이 더 드는 기본 모델이 사용될 수 있음 |
--trust-folder |
이번 실행에서만 현재 폴더의 설정(MCP 서버 등)을 신뢰 |
--allow-tool='shell(node:*)' |
node로 시작하는 명령은 묻지 않고 실행 |
--allow-tool='write' |
파일 만들기와 수정은 묻지 않고 실행 |
비대화형 모드에서는 승인할 사람이 없으므로, 허용 목록에 없는 동작은 자동으로 거부됩니다.
허용 목록을 좁게 잡을수록 안전합니다.
이 명령을 Windows 작업 스케줄러나 Jenkins 같은 도구에 등록하면 매주 정해진 시간에 보고서를 만들 수 있습니다.
서버에서 실행할 때는 로그인 대신 Copilot Requests 권한을 준 세분화된 개인 액세스 토큰(Fine-grained PAT)을 COPILOT_GITHUB_TOKEN 환경 변수로 전달합니다.
# 판정 검증
핵심 정리의 검증셋은 9건이 모두 일치하는 상태로 끝났습니다.
이번에는 시험 로그용 검증셋을 만들고, 규칙을 일부러 빼서 어긋난 결과가 어떻게 표시되는지 확인합니다.
정상 케이스와 함께 경계에 걸친 케이스, 판정하면 안 되는 케이스를 넣는 것은 같습니다.
12345678910[ { "TC": "TC-01", "구분": "정상", "판정": "Pass" }, { "TC": "TC-02", "구분": "정상", "판정": "Pass", "확인": "안정화 구간 300초를 빼고 판정하는가" }, { "TC": "TC-03", "구분": "경계", "판정": "Fail", "비고": "오차 초과", "확인": "85도를 0.5도 구간에 넣는가" }, { "TC": "TC-04", "구분": "정상", "판정": "Fail", "비고": "기록 끊김", "확인": "오차가 작아도 기록이 끊기면 Fail인가" }, { "TC": "TC-05", "구분": "정상", "판정": "Pass", "확인": "CP949와 한글 열 이름을 읽는가" }, { "TC": "TC-06", "구분": "판정 불가", "판정": "판정 불가", "비고": "로그 없음" }, { "TC": "TC-07", "구분": "경계", "판정": "Fail", "비고": "오차 초과", "확인": "-10도를 0.5도 구간에 넣는가" }, { "TC": "TC-08", "구분": "판정 불가", "판정": "판정 불가", "비고": "샘플 부족" } ]
확인 항목은 이 케이스가 무엇을 확인하려고 들어 있는지를 적은 것이며, 결과가 어긋날 때 함께 출력됩니다.scripts/check.js는 판정 스크립트를 다시 실행해서 결과를 검증셋과 비교합니다.
12345678node scripts/check.js ## TC-01 정상 기대 Pass 결과 Pass 일치 ## TC-02 정상 기대 Pass 결과 Pass 일치 ## TC-03 경계 기대 Fail 오차 초과 결과 Fail 오차 초과 일치 ## ... ## TC-08 판정 불가 기대 판정 불가 샘플 부족 결과 판정 불가 샘플 부족 일치 ## ## 검증 8건: 일치 8
모두 일치합니다.
그렇다면 규칙 하나가 빠지면 어떻게 될까요?
판정 스크립트에서 안정화 구간과 기록 끊김 검사를 꺼 보겠습니다.
12const SETTLE_SECONDS = 0 // 안정화 구간(초) const MAX_GAP_SECONDS = Infinity // 이 간격을 넘으면 기록 끊김
12345678node scripts/check.js ## TC-01 정상 기대 Pass 결과 Pass 일치 ## TC-02 정상 기대 Pass 결과 Fail 오차 초과 오탐 (확인: 안정화 구간 300초를 빼고 판정하는가) ## TC-03 경계 기대 Fail 오차 초과 결과 Fail 오차 초과 일치 ## TC-04 정상 기대 Fail 기록 끊김 결과 Pass 미탐 (확인: 오차가 작아도 기록이 끊기면 Fail인가) ## ... ## ## 검증 8건: 일치 6, 오탐 1, 미탐 1
어긋난 결과는 두 종류로 나뉩니다.
이 예제에서 걸러 낼 대상은 불합격(Fail)인 시험입니다.
- 오탐(False Alarm)은 문제없는 시험을 Fail로 판정한 경우입니다. TC-02는 챔버가 -40도까지 내려가는 처음 몇 분 동안 오차가 커서 Fail이 되었습니다.
- 미탐(Miss)은 문제 있는 시험을 Pass로 판정한 경우입니다. TC-04는 46초 동안 기록이 없었는데도 남은 샘플의 오차만 보고 Pass가 되었습니다.
오탐은 사람이 다시 확인하는 시간을 쓰게 만들고, 미탐은 불량을 그대로 통과시킵니다.
그래서 미탐을 막는 케이스를 먼저 검증셋에 넣습니다.
불일치를 보고 규칙을 추가하고, 추가한 규칙이 다른 케이스를 망가뜨리지 않았는지 다시 실행하는 과정이 판정 로직을 다듬는 방법입니다.
경계 케이스는 AI가 만든 코드의 작은 실수를 잡아냅니다.
Copilot이 허용 오차 구간을 다음 첫째 줄처럼 작성했다면, 코드를 언뜻 봐서는 틀린 곳을 찾기 어렵습니다.
12target > TIGHT_RANGE.min && target < TIGHT_RANGE.max // -10도와 85도가 빠짐 target >= TIGHT_RANGE.min && target <= TIGHT_RANGE.max // 규칙 문서와 같음
첫째 줄로 바꾸고 검증셋을 실행하면 TC-03과 TC-07이 미탐으로 표시됩니다.
-10도와 85도가 1.0도 구간으로 계산되어 0.65도 오차가 Pass가 되기 때문입니다.
규칙 문서의 '-10도와 85도는 0.5도 구간에 포함됩니다' 한 줄과 이것을 확인하는 경계 케이스 하나가 이런 실수를 막습니다.
# Jira 기초
결함을 등록하고 현황을 보고하려면 이슈 관리 도구와 연결해야 합니다.
많은 회사가 Atlassian의 Jira를 사용하므로, 처음 접하는 경우를 위해 기본 개념부터 정리합니다.
GitHub를 사용해 봤다면 다음처럼 대응해서 이해하면 쉽습니다.
| Atlassian 제품 | 하는 일 | GitHub에서 비슷한 것 |
|---|---|---|
| Jira | 할 일, 버그 같은 이슈 관리 | Issues, Projects |
| Confluence | 팀 문서를 모아 두는 위키 | Wiki |
| Bitbucket | Git 저장소와 풀 리퀘스트 | 저장소, Pull Request |
Jira에서 알아 둘 개념은 다음과 같습니다.
- 프로젝트(Project): 이슈를 묶는 단위이며
TS같은 짧은 키를 가집니다. Jira Cloud에서는 스페이스(Space)라는 이름으로 바뀌고 있습니다. - 이슈(Issue): 할 일 하나입니다. 프로젝트 키와 번호를 붙인
TS-108같은 이슈 키로 구분합니다. Jira Cloud에서는 작업 항목(Work Item)이라고 표시될 수 있습니다. - 이슈 유형: 큰 묶음인 Epic, 기능 단위의 Story, 일반 작업인 Task, 결함인 Bug, 하위 작업인 Subtask가 기본입니다.
- 상태(Status): 기본은 To Do, In Progress, Done 세 가지이며 팀에 따라 '검토 중' 같은 상태를 추가합니다. 상태가 바뀌는 길을 워크플로(Workflow)라고 합니다.
- 필드(Field): 요약(Summary), 설명, 담당자, 보고자, 우선순위, 레이블 같은 이슈의 항목입니다.
- 보드(Board): 상태별 열에 이슈 카드를 늘어놓은 화면입니다.
이슈는 JQL(Jira Query Language)이라는 검색식으로 찾습니다.
필드, 연산자, 값을 AND로 이어 붙이는 형태라서 SQL의 WHERE 절과 비슷합니다.
| 찾고 싶은 것 | JQL |
|---|---|
| 끝나지 않은 TS 프로젝트의 버그 | project = TS AND issuetype = Bug AND statusCategory != Done |
| 최근 7일 동안 바뀐 이슈 | project = TS AND updated >= "-7d" ORDER BY updated DESC |
| 요약에 TC-03이 들어간 이슈 | project = TS AND summary ~ "TC-03" |
| 나에게 배정된 미해결 이슈 | assignee = currentUser() AND resolution = Unresolved |
statusCategory는 상태를 할 일, 진행 중, 완료 세 범주로 묶은 값이라, 팀이 'Closed' 같은 완료 상태를 따로 만들어도 끝난 이슈를 정확히 뺄 수 있습니다.~는 '포함한다'는 뜻의 텍스트 검색 연산자이고, -7d 같은 상대 날짜는 따옴표로 감싸는 것이 안전합니다.
날짜만 적으면 그날 0시로 해석하므로, updated <= "2026-10-30"은 10월 30일 하루 동안 바뀐 이슈를 빠뜨립니다.
기간의 마지막 날까지 포함하려면 "2026-10-30 23:59"처럼 시각까지 적습니다.
Jira는 운영 방식이 두 가지입니다.
어느 쪽인지에 따라 AI 도구를 연결하는 방법이 달라지므로, 먼저 회사의 Jira 주소부터 확인합니다.
| 방식 | 주소 | 특징 |
|---|---|---|
| Cloud | 회사이름.atlassian.net |
Atlassian이 운영하는 웹 서비스. Free 플랜은 10명까지 무료 |
| Data Center | 사내 주소 | 회사가 직접 서버에 설치. 2026년 3월 30일부터 새 고객에게 판매하지 않으며, 기존 고객은 2029년 3월 28일까지 사용 |
예전의 Server 제품은 2024년 2월에 지원이 끝났고, Data Center 체험판도 이제 직접 발급할 수 없습니다.
그래서 개인이 자기 컴퓨터에 Jira를 설치해서 연습하기는 어렵습니다.
실제 Jira 화면을 사용해 보려면 Cloud의 Free 플랜으로 사이트를 만들고, Jira 계정 없이 연습하려면 다음 절의 연습용 서버를 사용합니다.
# MCP로 Jira 연결
Copilot에서 Jira를 사용하려면 Jira MCP 서버를 연결합니다.
먼저 연습용 서버로 흐름을 익히고, 실제 Jira에 연결하는 방법을 살펴봅니다.
회사 정책 때문에 MCP를 사용할 수 없을 때 같은 업무를 CSV 파일로 처리하는 방법도 함께 다룹니다.
# 연습용 서버
회사 Jira에 바로 연결해서 연습하기는 어렵습니다.
권한 신청이 필요하고, 실수로 만든 이슈가 동료에게 알림으로 전달될 수 있기 때문입니다.
예제 저장소에는 실제 Jira 대신 JSON 파일에 이슈를 저장하는 연습용 MCP 서버(mock-jira/server.js)가 들어 있습니다.
Node.js 내장 모듈만으로 약 250줄로 작성했으며, 커뮤니티의 Jira MCP 서버(mcp-atlassian)와 같은 이름의 도구 세 개를 제공합니다.
| 도구 | 하는 일 | 승인 |
|---|---|---|
jira_search |
JQL로 이슈 검색 | 읽기 전용 |
jira_get_issue |
이슈 키로 이슈 하나 조회 | 읽기 전용 |
jira_create_issue |
새 이슈 만들기 | 쓰기 |
도구 이름이 같으므로, 연습용 서버로 만든 스킬은 나중에 mcp-atlassian으로 실제 Jira에 연결해도 그대로 사용할 수 있습니다.
서버는 저장소 최상위의 .mcp.json에 등록되어 있습니다.
12345678910{ "mcpServers": { "jira": { "type": "stdio", "command": "node", "args": ["mock-jira/server.js"], "tools": ["*"] } } }
stdio는 VS Code가 서버 프로그램을 직접 실행하고 표준 입출력으로 메시지를 주고받는 방식입니다.
폴더를 열면 Copilot 하네스가 이 파일을 읽고, 처음 실행할 때 서버를 신뢰할지 묻는 확인이 표시될 수 있습니다.
연결된 서버와 도구는 에이전트 사용자 지정 편집기의 MCP 서버, 도구 화면에서 확인할 수 있습니다.
연결되었는지 간단한 검색으로 확인합니다.
1jira 도구로 TS 프로젝트에서 우선순위가 High이고 완료되지 않은 이슈를 찾아서 이슈 키와 요약만 답해 줘
Copilot이 JQL을 만들어 jira_search를 호출하고, TS-106과 TS-108 두 건을 답합니다.
도구가 실패하면 서버는 오류 메시지를 결과로 돌려주며, 모델은 그 메시지를 읽고 검색식을 고쳐서 다시 시도할 수 있습니다.
예를 들어 연습용 서버는 JQL의 OR를 지원하지 않으므로, 모델이 OR를 사용하면 'AND로만 연결하세요'라는 오류를 받고 검색식을 나누어 다시 검색할 수 있습니다.
# 주간 현황과 결함 등록
Jira를 사용하는 반복 업무 두 가지를 스킬로 만듭니다.
첫째는 한 주 동안 바뀐 이슈를 상태별로 정리하는 주간 현황 보고입니다.
검색만 하고 외부에 아무것도 쓰지 않으므로, Copilot이 요청을 보고 스스로 고를 수 있게 disable-model-invocation을 넣지 않았습니다.
1234567891011121314151617--- name: weekly-status description: Jira의 TS 프로젝트 이슈를 기간별로 모아 주간 현황 보고서를 만듭니다. 주간 보고, 이슈 현황, 진행 상황 정리를 요청받았을 때 사용합니다. argument-hint: 기간 (예 2026-10-26부터 2026-10-30까지) --- # 주간 이슈 현황 1. 기간이 없으면 시작일과 종료일을 물어봅니다. 1. `jira_search`로 기간 안에 갱신된 이슈를 찾습니다. JQL 예: `project = TS AND updated >= "2026-10-26 00:00" AND updated <= "2026-10-30 23:59" ORDER BY updated DESC` 1. 상태별로 묶어서 아래 형식으로 `output/weekly-status.md`에 저장합니다. ## 규칙 - 이슈에 없는 내용을 지어내지 않습니다. - 담당자 이름은 Jira에 적힌 그대로 사용합니다. - 상태 이름이 To Do, In Progress, Done이면 각각 할 일, 진행 중, 완료로 표시합니다.
1이번 주(2026-10-26부터 2026-10-30까지) TS 프로젝트 이슈 현황을 주간 보고로 정리해 줘
스킬 이름을 부르지 않았지만 요청이 설명과 맞아서 weekly-status 스킬이 사용될 수 있습니다.
기간 안에 바뀐 이슈와 새로 등록된 이슈를 검색해서 보고서를 저장합니다.
1234567891011121314# TS 주간 이슈 현황 (2026-10-26부터 2026-10-30까지) ## 요약 완료 3건, 진행 중 4건, 할 일 2건 (이 기간에 새로 등록 3건) ## 진행 중 | 키 | 요약 | 담당 | 최근 변경 | | --- | --- | --- | --- | | TS-108 | [TC-04] 장시간 연속 측정 기록 끊김 (46초) | 김OO | 2026-10-30 17:40 | | TS-105 | 시험 결과 보고서 자동 생성 | 이OO | 2026-10-30 16:00 | | TS-104 | 저온 시험 지그 교체 | 최OO | 2026-10-29 11:30 | | TS-101 | TS-100 2차 환경 시험 | 박OO | 2026-10-27 17:20 |
둘째는 판정 결과의 Fail 건을 결함으로 등록하는 스킬입니다.
외부 시스템에 이슈를 만드는 작업이므로 /defect-issue로 부를 때만 실행하고, 등록 전에 반드시 승인을 받습니다.
같은 결함이 두 번 등록되지 않도록 열린 이슈를 먼저 검색하는 단계도 넣었습니다.
12345678910111213141516171819202122232425262728293031--- name: defect-issue description: 시험 판정 결과의 Fail 건을 Jira 결함 이슈로 등록합니다. 사용자가 /defect-issue로 부를 때만 사용합니다. argument-hint: TC 번호 (없으면 Fail 전체) disable-model-invocation: true --- # 결함 이슈 등록 1. `output/tc-result.md`에서 대상 TC가 Fail인지 확인합니다. Fail이 아니면 등록하지 않고 이유를 알립니다. 1. `jira_search`로 같은 TC의 열린 이슈가 있는지 찾습니다. JQL 예: `project = TS AND summary ~ "TC-03" AND statusCategory != Done` 1. 검색 결과 중 요약이 같은 `[TC 번호]`로 시작하는 이슈가 있으면 새로 만들지 않고 그 이슈 키를 알려 줍니다. `~`는 비슷한 글자도 찾으므로 번호가 정확히 같은지 확인합니다. 1. 없으면 아래 형식으로 이슈 초안을 채팅에 보여 주고, 등록해도 되는지 묻습니다. 1. 승인을 받으면 `jira_create_issue`로 등록하고 만들어진 이슈 키를 알려 줍니다. ## 이슈 형식 | 필드 | 값 | | --- | --- | | 프로젝트 | TS | | 유형 | Bug | | 요약 | `[TC 번호] 항목 비고 (최대 오차 n도, 허용 n도)` | | 우선순위 | 기록 끊김은 High, 오차 초과는 Medium | | 레이블 | test-fail | | 설명 | 시험 항목과 요구사항 ID, 목표 온도와 전원 전압, 판정 근거, 로그 파일과 보고서 경로 | ## 규칙 - 승인 없이 이슈를 만들지 않습니다. - 설명에는 관찰한 사실만 적고 원인을 추측하지 않습니다. - 판정 근거는 `output/tc-result.md`의 근거 칸을 그대로 옮깁니다.
1/defect-issue
Fail 3건 중 TC-04는 이미 열려 있는 TS-108이 있어서 등록하지 않고, TC-03과 TC-07은 이슈 초안을 표로 보여 준 뒤 승인을 기다립니다.
등록하라고 답하면 jira_create_issue를 호출해서 TS-112와 TS-113이 만들어집니다.
1234567시험 항목: 고온 정확도 (TC-03) 요구사항: REQ-02 목표 온도: 85도 전원 전압: 3.3V 판정 근거: 최대 오차 0.65도(3,566초) > 허용 0.5도 로그 파일: data/logs/TC-03.csv 보고서: output/tc-result.md
연습용 서버는 이슈를 output/mock-jira.json에 저장합니다.
처음 상태로 되돌리려면 이 파일을 지웁니다.
# 실제 Jira 연결
실제 Jira는 Cloud와 Data Center 모두 커뮤니티에서 만든 mcp-atlassian으로 연결할 수 있습니다.
Cloud는 Atlassian의 공식 원격 MCP 서버도 사용할 수 있습니다.
| 사용하는 제품 | 연결 방법 | 인증 |
|---|---|---|
| Jira, Confluence Cloud | mcp-atlassian | API 토큰 |
| Jira, Confluence Cloud | Atlassian 공식 원격 MCP 서버 | 브라우저 로그인(OAuth) |
| Jira, Confluence Data Center | mcp-atlassian | 개인 액세스 토큰(PAT) |
| Bitbucket Data Center | Atlassian 공식 MCP 플러그인 | HTTP 액세스 토큰 |
이 글의 스킬을 그대로 사용하려면 mcp-atlassian을 선택합니다.
도구 이름이 연습용 서버와 같아서 .mcp.json만 바꾸면 됩니다.
mcp-atlassian은 Python 실행 도구인 uv의 uvx 명령으로 실행하므로 uv를 먼저 설치합니다.
12345678910111213141516{ "mcpServers": { "jira": { "type": "stdio", "command": "uvx", "args": ["mcp-atlassian"], "env": { "JIRA_URL": "https://회사이름.atlassian.net", "JIRA_USERNAME": "${JIRA_USERNAME}", "JIRA_API_TOKEN": "${JIRA_API_TOKEN}", "READ_ONLY_MODE": "true", "TOOLSETS": "default" } } } }
Data Center는 인증 부분만 다릅니다.JIRA_USERNAME과 JIRA_API_TOKEN 대신 개인 액세스 토큰 하나를 사용합니다.
12"JIRA_URL": "https://jira.example.com", "JIRA_PERSONAL_TOKEN": "${JIRA_PERSONAL_TOKEN}",
- 토큰은 설정 파일에 직접 적지 않습니다.
${JIRA_API_TOKEN}처럼 쓰면 운영체제의 환경 변수 값을 읽습니다. Cloud의 API 토큰은 Atlassian 계정의 보안 설정에서, Data Center의 개인 액세스 토큰은 Jira의 프로필 화면에서 만듭니다. READ_ONLY_MODE를true로 두면 쓰기 도구가 모두 꺼집니다. 검색과 보고로 먼저 시작하고, 결함 등록이 필요할 때false로 바꿉니다.TOOLSETS로 사용할 도구 묶음을 정합니다. 지정하지 않으면 도구가 100개 가까이 켜져서 요청마다 전달되는 도구 설명이 많아집니다.- 서버 이름을
jira로 두면 도구 이름이 연습용 서버와 같아서(jira_search,jira_create_issue) 앞에서 만든 스킬을 그대로 사용할 수 있습니다. Confluence도CONFLUENCE_URL과 인증 값을 추가하면confluence_search,confluence_create_page같은 도구가 함께 제공됩니다.
Cloud의 공식 원격 서버는 주소만 등록하면 됩니다.
처음 사용할 때 브라우저가 열리고 Atlassian 계정으로 로그인해서 접근을 허용합니다.
다만 도구 이름이 searchJiraIssuesUsingJql, getJiraIssue, createJiraIssue처럼 달라서, 이 서버를 사용하려면 스킬에 적은 도구 이름도 함께 바꿔야 합니다.
조직 관리자가 MCP 서버 사용이나 허용할 기능(읽기, 쓰기, 검색)을 제한했을 수 있습니다.
12345678{ "mcpServers": { "atlassian": { "type": "http", "url": "https://mcp.atlassian.com/v2/mcp" } } }
회사 Jira에 연결하기 전에 개인 Cloud 사이트로 같은 흐름을 확인할 수 있습니다.
- Atlassian 사이트에서 Jira Free 플랜으로 가입하고 사이트 주소를 정합니다.
- 키가
TS인 프로젝트를 만들고, 이슈 유형에 Bug가 있는지 확인합니다. - Atlassian 계정의 보안 설정에서 API 토큰을 만들고, 가입한 이메일과 토큰을
JIRA_USERNAME,JIRA_API_TOKEN환경 변수로 등록합니다. .mcp.json을 위의 Cloud 설정으로 바꾸고 VS Code를 다시 시작한 뒤, 앞의 검색 요청으로 연결을 확인합니다.READ_ONLY_MODE를false로 바꾸고/defect-issue를 실행하면, 연습용 서버에서와 같은 순서로 Cloud 사이트에 이슈를 만들 수 있습니다.
# CSV로 대신하기
회사 정책으로 MCP를 사용할 수 없거나 Jira 연결 승인을 기다리는 동안에도 같은 업무를 진행할 수 있습니다.
Jira의 이슈 검색 화면에서 결과를 CSV 파일로 내보내고, 스킬이 그 파일을 읽게 합니다.
예제 저장소의 data/jira-export.csv는 연습용 서버의 처음 이슈 11건을 내보내기 형식으로 저장한 파일입니다.
1234Issue key,Issue Type,Summary,Status,Priority,Assignee,Reporter,Created,Updated TS-101,Epic,TS-100 2차 환경 시험,In Progress,Medium,박OO,박OO,2026-10-01 09:00,2026-10-27 17:20 TS-102,Task,환경 챔버 시험 일정 확정,Done,Medium,박OO,박OO,2026-10-14 10:00,2026-10-27 09:40 TS-103,Bug,펌웨어 2.3.1에서 센서 값이 0으로 고정됨,Done,High,김OO,김OO,2026-09-01 11:00,2026-10-28 15:10
앞의 두 스킬에는 jira 도구가 없을 때 이 파일을 사용하는 부분이 들어 있습니다.
123456## jira 도구를 사용할 수 없을 때 jira 도구가 없으면 `data/jira-export.csv`(Jira에서 내보낸 이슈 목록)를 대신 사용합니다. - `Updated`가 기간 안에 있는 행을 사용하고, `Created`가 기간 안에 있는 행은 새로 등록한 이슈로 셉니다. - 요약 줄 아래에 `Jira에서 내보낸 CSV 기준`이라고 표시합니다.
123456## jira 도구를 사용할 수 없을 때 jira 도구가 없으면 `data/jira-export.csv`(Jira에서 내보낸 이슈 목록)를 대신 사용합니다. - 열린 이슈는 `Summary`가 같은 `[TC 번호]`로 시작하고 `Status`가 Done이 아닌 행으로 찾습니다. - 이슈를 등록할 수 없으므로 승인을 묻지 않고, 초안을 `output/defect-draft.md`에 저장한 뒤 Jira에 직접 등록하라고 안내합니다.
요청은 앞과 같습니다.
주간 현황을 요청하면 Copilot이 CSV를 읽어서 건수를 집계하며, 지침의 '숫자는 스크립트가 만든 결과의 값만 사용한다'는 규칙 때문에 집계용 node 명령의 실행 승인을 요청할 수 있습니다.
결과는 MCP로 검색했을 때와 같은 '완료 3건, 진행 중 4건, 할 일 2건 (이 기간에 새로 등록 3건)' 보고서입니다./defect-issue는 CSV에서 TC-04의 열린 이슈 TS-108을 찾아 제외하고, TC-03과 TC-07의 초안을 output/defect-draft.md에 저장합니다.
등록은 사람이 초안을 확인한 뒤 Jira 화면에서 직접 하므로, 등록 전 승인 단계가 사람의 등록 작업으로 바뀝니다.
회사 Jira에서 내보낸 파일은 Jira 설정에 따라 열 이름이나 날짜 형식이 다를 수 있습니다.
파일 앞 몇 줄을 Copilot에게 보여 주고 스킬의 열 이름을 맞추면 같은 방식으로 사용할 수 있습니다.
프로그램에 직접 연결할 수 없을 때 내보내기 파일을 사용하는 방법은 다음 절에서 더 살펴봅니다.
# 사내 프로그램 연결
업무에서 쓰는 프로그램에 AI가 직접 접근하지 못하는 경우가 많습니다.
이때는 AI를 프로그램에 붙이려 하지 말고, 프로그램이 밖으로 내놓는 것을 찾습니다.
내보내기 파일, 명령줄 도구(CLI), API 중 하나만 있으면 스크립트로 감쌀 수 있고, 스크립트는 스킬이나 MCP 도구로 Copilot에게 연결할 수 있습니다.
R&D 현장에서 자주 쓰는 프로그램을 예로 들면 다음과 같습니다.
| 프로그램 | 자동화에 사용할 수 있는 것 |
|---|---|
| TRACE32 (디버거) | PRACTICE 스크립트(.cmm), 원격 제어 API |
| CANoe, CANalyzer (차량 네트워크) | 로그 내보내기(.asc는 텍스트, .blf는 바이너리), CAPL 스크립트 |
| Polarion (요구사항, 시험 관리) | 엑셀이나 ReqIF 내보내기, REST API |
| 사내 웹 시스템 | REST API, 엑셀 내보내기 |
연결 방법은 쉬운 것부터 고릅니다.
- 내보내기 파일만 있어도 충분합니다. 사람이 파일을 내보내서 정해진 폴더에 넣으면, 그 뒤를 자동화합니다. 이 글의 예제가 이 방식입니다.
- CLI나 API가 있으면 스크립트로 감싸고, 스킬의 순서에 그 스크립트를 실행하는 단계를 넣습니다.
- 여러 저장소에서 같은 기능을 쓰거나 Copilot이 아닌 도구에서도 쓰려면 MCP 서버로 만듭니다. 연습용 Jira 서버처럼 도구 몇 개를 제공하는 서버는 Copilot에게 만들어 달라고 요청할 수 있습니다.
- 화면만 있는 프로그램은 화면 자동화를 시도하기 전에 내보내기 기능이나 로그 파일 위치를 먼저 찾습니다.
시험 장비를 움직이는 스크립트(전원 제어, 펌웨어 기록 등)는 Copilot이 초안을 작성하고 사람이 검토한 뒤 직접 실행합니다.
에이전트가 실행해서는 안 되는 명령은 GitHub Copilot 핵심 정리에서 다룬 Hook으로 차단할 수 있습니다.
# 사내 환경과 보안
개인 계정에서 동작한 하네스도 회사 환경에서는 정책, 보안 규정, 네트워크 때문에 그대로 동작하지 않을 수 있습니다.
회사에 적용하기 전에 확인할 것들을 정리합니다.
# 관리자 정책
회사 계정의 Copilot(Business, Enterprise)은 관리자가 정한 정책에 따라 사용할 수 있는 기능이 달라집니다.
개인 계정으로 시험한 예제가 회사에서 동작하지 않는다면 다음 정책부터 확인합니다.
| 정책 | 영향을 받는 것 |
|---|---|
| MCP servers in Copilot | MCP 서버 사용. 기본으로 꺼져 있으며, 꺼져 있으면 Jira는 CSV로 대신하기 |
| Editor preview features | 미리 보기 단계의 기능 |
| Models | 모델 메뉴에 표시되는 모델 |
| Copilot CLI | 터미널의 copilot 명령과 비대화형 실행 |
| Bring Your Own Key | 다른 회사의 API 키로 모델 연결 |
VS Code의 Claude, Codex 하네스는 회사의 Copilot 관리 설정이 적용되면 꺼집니다.
회사 계정에서는 Copilot 하네스를 기준으로 하네스를 설계하는 것이 안전합니다.
# 데이터 처리
GitHub의 Copilot Trust Center에 따르면 Business와 Enterprise 고객의 데이터는 모델 학습에 사용하지 않습니다.
IDE의 채팅과 CLI의 입력과 출력은 기본적으로 보관하지 않으며, 보안 조사 같은 예외만 둡니다.
다만 보관 조건은 모델마다 다를 수 있어서, 예를 들어 Claude Fable 5 계열은 Anthropic이 기본으로 프롬프트와 출력을 보관합니다.
사용할 모델의 조건은 모델 호스팅 문서에서 확인합니다.
그렇다고 사내 자료를 무엇이든 넣어도 된다는 뜻은 아닙니다.
요청 내용은 GitHub의 서버와 모델을 제공하는 회사로 전송되므로, 반출이 제한된 자료는 회사의 보안 정책이 우선입니다.
연습과 개발은 형식만 같은 가짜 데이터로 하는 것이 안전합니다.
가짜 데이터를 만들 때도 실제 파일을 보여 주지 않고 형식을 말로 설명합니다.
12time_s, ref_c, sensor_c, supply_v 네 열이 있는 1초 간격 시험 로그를 흉내 낸 가짜 데이터를 만드는 스크립트를 작성해 줘. 온도는 -40도에서 85도, 전압은 3.0V에서 3.6V 사이로 하고, 중간에 기록이 끊긴 구간을 하나 넣어 줘.
# 프록시와 인증서
회사 네트워크가 프록시를 거치거나 HTTPS 통신을 검사한다면 연결 오류가 날 수 있습니다.
- VS Code 설정의
http.proxy에 프록시 주소를,http.noProxy에 프록시를 거치지 않을 사내 주소를 입력합니다.https://로 시작하는 프록시 주소는 지원하지 않습니다. - 회사의 루트 인증서는 운영체제의 인증서 저장소에 추가하는 것을 권장하며, 추가로
NODE_EXTRA_CA_CERTS환경 변수로 인증서 파일을 지정할 수 있습니다. - MCP 서버와 스크립트는 VS Code의 프록시 설정을 사용하지 않습니다. 프로그램마다
HTTPS_PROXY,NO_PROXY같은 환경 변수로 프록시를 지정하며, mcp-atlassian도 이 환경 변수를 지원합니다. - 명령 팔레트의
GitHub Copilot: Chat Diagnostics로 연결 상태를 진단할 수 있습니다.
# 크레딧
Business와 Enterprise의 크레딧은 사용자마다 따로 쓰는 것이 아니라 조직 전체가 하나로 모아서 함께 사용합니다.
모은 크레딧을 넘긴 사용은 1 크레딧에 0.01달러로 청구되며, 관리자가 정한 예산을 넘으면 사용이 막힐 수 있으므로 조직의 예산 정책을 확인합니다.
이 글의 예제를 Copilot CLI에서 Auto 모델로 실행했을 때 /test-report는 0.79 크레딧, /defect-issue의 초안 작성은 0.25 크레딧, 주간 현황 보고는 0.55 크레딧이 들었습니다.
계산을 스크립트에 맡기고 큰 로그를 모델에게 읽히지 않으면 크레딧도 적게 소비합니다.
그 밖에 주제가 바뀌면 새 세션을 시작하고, 지침 파일을 짧게 유지하는 것이 도움이 됩니다.
# 내 업무에 적용
예제의 구조는 그대로 두고 업무만 바꾸면 다른 반복 업무에도 같은 하네스를 만들 수 있습니다.
이 과정도 스킬로 만들어 두면, 새 업무를 시작할 때마다 같은 질문과 같은 파일 구조로 시작할 수 있습니다.
1234567891011121314151617181920212223242526272829--- name: new-automation description: 새로운 반복 업무를 자동화하려고 할 때 업무 분해 시트를 채우고 규칙 문서, 스킬, 검증셋의 초안을 만듭니다. 사용자가 /new-automation으로 부를 때만 사용합니다. argument-hint: 자동화할 업무 이름 disable-model-invocation: true --- # 새 업무 자동화 초안 만들기 `docs/task-worksheet.md`의 형식을 기준으로, 새 업무를 이 저장소와 같은 구조로 옮길 초안을 만듭니다. 1. 아래 다섯 가지를 한 번에 물어봅니다. 요청에 이미 있는 내용은 다시 묻지 않습니다. - 입력: 어떤 파일을 받는가 (형식, 위치, 열 이름이나 예시 한 줄) - 순서: 지금 사람이 하는 순서 - 판단 기준: 무엇을 보고 어떻게 판단하는가 (숫자, 조건, 예외) - 결과물: 무엇을 만들어 누구에게 전달하는가 - 검증: 결과가 맞는지 무엇으로 확인하는가 1. 업무의 영문 이름을 소문자와 하이픈으로 정합니다. 예: `eol-report` 1. 업무 분해 시트를 `docs/<영문 이름>-worksheet.md`로 저장합니다. 단계마다 맡길 곳(스크립트, 모델, 사람)을 정합니다. 1. 판단 기준을 `docs/<영문 이름>-rules.md` 초안으로 정리합니다. 애매한 기준에는 '확인 필요'를 붙입니다. 1. `.github/skills/<영문 이름>/SKILL.md` 초안을 만듭니다. 외부로 보내거나 되돌릴 수 없는 단계 앞에는 승인 단계를 넣습니다. 1. `tests/<영문 이름>-cases.json`에 정상, 경계, 판정 불가 케이스를 하나 이상씩 제안합니다. 1. 만든 파일 목록과 사용자가 확인해야 할 항목을 알려 줍니다. ## 규칙 - 스크립트는 만들지 않습니다. 사용자가 규칙 문서를 확인한 뒤에 따로 요청받습니다. - 실제 업무 데이터를 요구하지 않습니다. 예시가 필요하면 형식만 같은 가짜 데이터를 만듭니다. - 판단 기준을 지어내지 않습니다. 답이 없는 기준은 '확인 필요'로 남깁니다.
스크립트를 바로 만들지 않는 것이 중요합니다.
판단 기준이 확정되지 않은 상태에서 스크립트부터 만들면, 모델이 빈 곳을 스스로 채운 코드가 나올 수 있습니다.
생산 라인 마지막 단계에서 완제품을 검사하는 EOL(End of Line) 검사의 불량 보고를 예로 실행해 봅니다.
다섯 가지 질문의 답을 요청에 함께 적으면 질문 없이 바로 초안을 만듭니다.
1/new-automation EOL 검사 불량 보고. 입력은 EOL 검사기에서 내보낸 CSV(열: 시리얼, 검사항목, 측정값, 하한, 상한, 검사시각)이고, 지금은 사람이 엑셀에서 하한과 상한을 벗어난 행을 걸러서 불량 목록을 만들어 메일로 보냅니다. 판단 기준은 측정값이 하한 미만이거나 상한 초과면 불량, 같은 시리얼이 재검사에서 합격하면 재검 합격으로 따로 표시합니다. 결과물은 시리얼별 불량 목록과 항목별 불량률 표이고 품질 파트장에게 전달합니다. 검증은 지난주 수작업 결과와 건수가 같은지로 확인합니다.
업무 분해 시트, 규칙 문서, 스킬, 검증셋 초안 네 파일이 만들어지고, 다음 항목은 '확인 필요'로 남았습니다.
- 재검사 행을 처음 검사와 어떻게 연결하는가(같은 시리얼과 같은 검사항목인지, 검사 시각 순서인지)
- 불량률의 분모는 무엇인가(검사 건수인지, 시리얼 수인지)
- 지난주 결과와 비교할 '건수'는 불량 행 수인가, 불량 시리얼 수인가
- CSV 파일의 위치와 인코딩
'하한 미만, 상한 초과'라고 적었기 때문에 하한이나 상한과 정확히 같은 값은 불량이 아닌 것으로 정리되었습니다.
이처럼 규칙 문서의 단어 하나가 경계값을 정하므로, 초안을 받으면 '확인 필요' 항목과 경계값부터 검토합니다.
그다음은 이 글의 순서와 같습니다.
- 규칙 문서의 '확인 필요'를 채우고 경계값을 확정합니다.
- 규칙 문서를 바탕으로 스크립트를 요청합니다.
- 검증셋을 실행해서 모두 일치할 때까지 규칙과 스크립트를 다듬습니다.
- 스킬에서 스크립트, 검증, 요약을 이어서 실행하게 합니다.
- 외부 시스템 연결은 읽기 전용으로 시작하고, 쓰기는 승인 단계를 넣은 뒤에 엽니다.
핵심 정리의 업무 비서가 문서에 근거해서 답하고 빠진 정보를 되묻는 데 초점을 맞췄다면, 이 글의 하네스는 규칙대로 계산하고, 근거가 없으면 판정하지 않고, 틀린 판정이 보고서로 나가기 전에 멈추고, 외부 시스템에 쓰기 전에 승인을 받는 데 초점을 맞췄습니다.
새 업무에 하네스를 만들 때도 이 네 가지가 갖춰졌는지부터 확인합니다.
더 자세한 내용은 다음 문서를 참고하세요.
끝까지 읽어주셔서 감사합니다.
좋아요와 응원 댓글은 블로그 운영에 큰 힘이 됩니다!