| name | snu-external-lecture-report |
| description | mySNU 포털에서 외부강의 신고를 자동으로 작성·제출하는 스킬. 사용자가 이메일, 공문, 또는 대화 내용을 바탕으로 외부강의/평가/자문/발표 등의 외부활동 신고를 요청하면, 필요한 정보를 추출하고 mySNU 외부강의 신고 양식을 Chrome 브라우저를 통해 자동으로 입력한다. 신청 제출은 반드시 사용자 확인 후 진행한다. MANDATORY TRIGGERS: 외부강의, 외부강의 신고, 외부활동 신고, 강의신고, 자문신고, 평가신고, 심사신고, mySNU 외부강의, 외부강의등 신고, external lecture report, 외부강의신고서 작성. 사용자가 "이 이메일 보고 외부강의 신고해줘", "평가 참여하는데 신고 좀 해줘", "자문 신고 해야 해", "외부강의 등록" 등의 요청을 할 때 이 스킬을 사용한다. 이메일 내용이나 공문을 참조하라는 맥락이 있으면 더더욱 이 스킬이 적합하다.
|
mySNU 외부강의등 신고 자동화
Overview
서울대학교 교직원은 외부에서 강의, 평가, 자문, 발표, 심사 등의 활동을 하면 mySNU 포털을 통해 신고해야 한다. 이 스킬은 이메일이나 공문에서 필요한 정보를 추출하고, Chrome 브라우저를 제어하여 mySNU 외부강의 신고 양식을 자동으로 작성한다.
최종 "신청" 버튼 클릭은 되돌릴 수 없으므로, 반드시 사용자에게 입력 내용을 확인받은 뒤 진행한다.
Workflow
Step 0: 이메일 화면 확인
tabs_context_mcp로 현재 탭 그룹을 확인한다.
- 기존 탭이 있고 Gmail 이메일이 열려 있는 경우: 해당 탭에서 바로 스크린샷을 찍어 내용을 읽는다.
- 탭 그룹이 비어 있거나 이메일이 열려 있지 않은 경우: Gmail 받은편지함(
https://mail.google.com)으로 이동하여 화면을 보여주고, 사용자에게 "신고할 이메일을 클릭해서 열어주세요"라고 요청한다. 이메일 목록까지는 자동으로 열지만, 어떤 이메일을 선택할지는 사용자가 직접 클릭한다.
Step 1: 원문에서 정보 추출
사용자가 열어둔 이메일 화면을 screenshot으로 읽고 (스크롤하여 전체 내용 확인), 다음 항목을 파악한다.
필수 추출 항목:
| 항목 | 설명 | 비고 |
|---|
| 활동 유형 | 강의/기고/발표/토론/심사/평가/자문/의결/강연/기타 | 아래 매핑 참고 |
| 요청기관 명 | 활동을 요청한 기관 이름 | 정식 명칭 사용 |
| 요청기관 연락처 | 전화번호 (예: 02-123-4567) | 이메일에서 추출 |
| 외부강의등 주제 | 평가명, 강의명, 자문 주제 등 | |
| 장소 | 대면 장소 또는 "비대면(서면평가)" 등 | 비대면이면 명시 |
| 일시 (시작~종료) | 활동 날짜 및 시각 | 시각은 확인 필요할 수 있음 |
| 사례금 | 세전 금액 (숫자만) | 항상 세전 기준. 명시되지 않으면 500000(50만원)을 기본값으로 입력 |
| 교통비/숙박비/식비 | 각각의 금액 | 언급 없으면 0 |
활동유형 매핑 가이드: 이메일에 나온 표현을 mySNU 드롭다운 값으로 변환한다.
- 선정평가, 과제평가, 성과평가, 중간평가, 최종평가 → 평가
- 학회발표, 구두발표, 포스터발표, 초청발표 → 발표
- 위원회 자문, 정책자문, 기술자문, 전문가 자문 → 자문
- 특강, 출강, 대학원 강의, 집중강의 → 강의 또는 강연
- 논문심사, 학위심사, 과제심사, 서면심사 → 심사
- 원고작성, 기고문, 칼럼 → 기고
- 패널토론, 좌담회 → 토론
- 운영위원회, 정책위원회 의결 참여 → 의결
이메일에서 잘 누락되는 항목과 기본값: 다음은 이메일에 명시되지 않는 경우가 많다. 기본값을 우선 적용하되, 사용자 확인 단계(Step 2)에서 반드시 확인을 받는다.
- 사례금: 명시되지 않으면 **500000원(50만원)**을 기본값으로 입력. 사용자 확인 시 반드시 언급.
- 총강의시간(분): 서면평가 등은 명확한 시간이 없으므로 60분을 기본값으로 입력.
- 시작/종료 시각: 날짜만 있고 시각이 없으면 0900~1000 등 기본값 제안.
- 일시 (비대면/서면 활동): 기간이 여러 날인 경우 전체 기간을 입력하지 않는다. 종료일 하루의 마지막 1시간만 기록한다. 예: 3/17~3/23 기간의 서면평가 → 시작일 2026-03-23 시작시간 0900, 종료일 2026-03-23 종료시간 1000.
- 장소: 비대면인 경우 "비대면(서면평가)", "비대면(화상회의)" 등으로 기재.
Step 2: 사용자에게 추출 결과 확인
양식을 채우기 전에, 추출한 정보를 사용자에게 정리하여 보여주고 확인을 요청한다. 특히 불확실한 항목(시각, 장소, 총강의시간)은 명확히 표시한다. AskUserQuestion 도구를 활용하면 좋다.
Step 3: mySNU 접속 및 외부강의 신고 페이지 이동
Chrome 브라우저를 사용하여 mySNU에 접속한다.
- mySNU 메인 이동:
https://my.snu.ac.kr 로 이동한다.
- 로그인 확인: 이미 로그인된 상태라면 메인 페이지가 보인다. 로그인이 안 되어 있으면 사용자에게 로그인을 요청한다 (비밀번호 입력은 직접 해야 하므로).
- 외부강의 신고 메뉴 진입: 메인 페이지에서 "외부강의 신고 등" 퀵메뉴를 찾아 클릭한다.
- 직접 URL:
https://shine.snu.ac.kr/mysnu/subIndex_haksa.html?_portal=P|13|P130201|ko
- 퀵메뉴가 바로 보이지 않으면, 화면을 스크롤하거나
find 도구로 "외부강의" 텍스트를 찾는다.
중요: 퀵메뉴 클릭 시 새 탭이 열린다. tabs_context_mcp로 새로 열린 탭의 ID를 확인하고, 이후 모든 작업은 새 탭에서 진행해야 한다.
Step 4: 신규 신고 작성
- 외부강의등 신고 목록 화면에서 "신규" 버튼을 찾아 클릭한다. (
read_page에서 filter=interactive로 버튼을 찾는다.)
- 신고 양식이 열리면 각 필드를 채운다.
4-1. 활동유형 드롭다운 설정
read_page(filter=interactive)로 활동유형 드롭다운의 ref를 찾은 뒤, form_input 도구로 option value를 설정한다.
드롭다운 option value 매핑:
| 활동유형 | value |
|---|
| 강의 | A01D600001 |
| 기고 | A01D600002 |
| 발표 | A01D600003 |
| 토론 | A01D600004 |
| 심사 | A01D600005 |
| 평가 | A01D600006 |
| 자문 | A01D600007 |
| 의결 | A01D600008 |
| 기타 | A01D600009 |
| 강연 | A01D600010 |
예: 평가인 경우 → form_input(ref=<드롭다운ref>, value="A01D600006")
4-2. 텍스트/숫자/날짜 필드 입력 (JavaScript 필수)
중요: 이 사이트의 텍스트 필드는 form_input 도구나 click+type으로 값이 들어가지 않는다. 반드시 javascript_tool로 아래 패턴을 사용하여 값을 설정해야 한다.
function setVal(name, value) {
const el = document.querySelector('input[name="' + name + '"]');
if (!el) return 'not found: ' + name;
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
window.HTMLInputElement.prototype, 'value'
).set;
nativeInputValueSetter.call(el, value);
el.dispatchEvent(new Event('input', { bubbles: true }));
el.dispatchEvent(new Event('change', { bubbles: true }));
el.dispatchEvent(new Event('blur', { bubbles: true }));
return name + ' = ' + el.value;
}
const results = [];
results.push(setVal('dmndBreuNm', 'OO연구원'));
results.push(setVal('dmndBreuCntinfo', '02-123-4567'));
results.push(setVal('outsidLtTtl', 'OO분야 OO과제 평가'));
results.push(setVal('outsidLtPl', '비대면(서면평가)'));
results.push(setVal('outsidLtFrDt', '2026-04-15'));
results.push(setVal('outsidLtFrHour', '0900'));
results.push(setVal('outsidLtToDt', '2026-04-15'));
results.push(setVal('outsidLtToHour', '1000'));
results.push(setVal('outsidLtTmTtMint', '60'));
results.push(setVal('caseAmt', '200000'));
results.push(setVal('trafHtcgFoodAmt', '0'));
JSON.stringify(results);
필드 name 참조표:
| 필드 | input name | 비고 |
|---|
| 요청기관 명 | dmndBreuNm | |
| 요청기관 연락처 | dmndBreuCntinfo | 숫자, +, -, (, ) 만 허용. 6~20자 |
| 외부강의등 주제 | outsidLtTtl | |
| 장소 | outsidLtPl | |
| 일시 시작 날짜 | outsidLtFrDt | YYYY-MM-DD |
| 일시 시작 시간 | outsidLtFrHour | HHMM (콜론 없이. 예: 0900) |
| 일시 종료 날짜 | outsidLtToDt | YYYY-MM-DD |
| 일시 종료 시간 | outsidLtToHour | HHMM (콜론 없이. 예: 1000) |
| 총강의시간(분) | outsidLtTmTtMint | 숫자 |
| 사례금(세전) | caseAmt | 숫자만 입력하면 자동으로 천단위 쉼표 포맷됨 |
| 교통비·숙박비·식비 | trafHtcgFoodAmt | |
| 비고 | (비고 필드) | read_page로 ref 찾아서 입력 |
Step 5: 저장
양식 입력이 완료되면 사용자에게 묻지 않고 바로 저장한다. (내용 확인은 Step 2에서 이미 완료했으므로 다시 확인하지 않는다.)
read_page(filter=interactive)에서 "저장" 버튼의 ref를 찾아 클릭한다.
- 저장 완료까지 2~3초 대기한다.
- 스크린샷을 찍어 저장이 정상적으로 되었는지 확인한다.
- 사용자에게 "외부강의 신고 저장 완료. 신청 버튼은 직접 눌러주세요."라고 안내한다.
- mySNU 탭은 닫지 않고 그대로 둔다. 바로 다음 단계(Step 6 또는 Step 7)로 진행한다.
Step 6: 대면 활동인 경우 출장신청서 작성
외부강의 신고가 대면 활동(즉, 장소가 "비대면"이 아닌 경우)이면, 출장신청서도 함께 작성한다. 비대면/서면 활동인 경우 이 단계는 건너뛴다.
출장신청서는 write_btrip.py 스크립트로 HWPX 템플릿(assets/btrip-form.hwpx)에 데이터를 채워 생성한다.
python3 write_btrip.py \
--template assets/btrip-form.hwpx \
--output <출력경로>/출장신청서.hwpx \
--json <데이터JSON경로>
데이터 JSON 형식:
{
"department": "OO학부",
"rank": "교수",
"name": "홍길동",
"purpose": "OO학회 춘계학술대회 초청강연",
"period": "2026. 4. 15.(수)",
"destination": "부산광역시 해운대구",
"route": "서울 → 부산 → 서울"
}
필드 작성 규칙:
| 필드 | 규칙 | 예시 |
|---|
| department | 사용자의 소속 학부(과) | OO학부 |
| rank | 사용자의 직급 | 교수 |
| name | 사용자의 성명 | 홍길동 |
| purpose | 이메일 내용을 바탕으로 짧게 작성 | OO학회 춘계학술대회 초청강연 |
| period | 일 단위 기간 (시간은 안 씀). 1일이면 "2026. 4. 15.(수)", 여러 날이면 "2026. 4. 14.(화) ~ 4. 15.(수)" | 2026. 4. 15.(수) |
| destination | 출장지역을 시/군/구 단위까지 | 부산광역시 해운대구 |
| route | 서울에서 출발해서 돌아오는 일정 | 서울 → 부산 → 서울 |
여비계산은 항상 0원, 출근부 대조는 비워둔다 (스크립트가 자동 처리).
생성된 HWPX 파일은 사용자의 workspace 폴더에 저장하고, computer:// 링크로 제공한다. 이후 Step 7로 진행하여 Trello에 업로드한다.
Step 7: Trello에 출장신청 카드 생성 (대면 활동만)
대면 활동으로 출장신청서를 생성한 경우, Trello 보드에 카드를 만들어 출장신청서를 업로드한다.
- 설정 파일 읽기:
config.json에서 trello_board_url을 읽는다.
- Trello 보드 접속: Chrome에서 해당 URL로 이동한다. 로그인이 안 되어 있으면 사용자에게 요청한다.
- "새로운 일" 리스트에서 "+ Add a card" 클릭:
find 도구로 "새로운 일" 리스트 하단의 "Add a card" 버튼을 찾아 클릭한다.
- 카드 제목 입력:
"출장신청 (출장지 또는 용건)" 형식으로 입력한다.
- 예: "출장신청 (부산 OO학회 초청강연)"
- 예: "출장신청 (대전 OO위원회 자문회의)"
- 카드 생성: Enter 키 또는 "Add card" 버튼을 클릭한다.
- 카드 열기: 생성된 카드를 클릭하여 상세 보기를 연다.
- 설명(Description) 입력: "출장 신청 부탁드립니다."를 입력한다.
- Description 영역을 클릭 → 텍스트 입력 → Save 버튼 클릭
- 첨부파일 안내: VM 환경에서는 Trello에 직접 파일 업로드가 불가능하다 (
file_upload가 VM 내부 파일에 접근 못함). 대신 생성된 HWPX 파일의 computer:// 링크를 제공하고, 사용자에게 Trello 카드의 Attachment에서 직접 첨부해달라고 안내한다.
- 완료 확인: 스크린샷을 찍어 카드(제목+설명)가 제대로 생성되었는지 사용자에게 보여준다.
기존 신고 목록 활용
외부강의등 신고 목록에 기존 신고 건이 있으면 참고할 수 있다. 유사한 기관명이나 활동유형의 이전 신고를 확인하면 입력 패턴(장소 표기 방식, 시간 기재 방식 등)을 빠르게 파악할 수 있다.
주의사항
- mySNU 세션이 만료되면 다시 로그인이 필요하다. 비밀번호 입력은 사용자에게 맡긴다.
- 사례금은 항상 세전 금액 기준이다. 이메일에 "세후" 금액만 명시된 경우 사용자에게 세전 금액을 확인한다.
- 비대면/서면 활동의 장소는 "비대면(서면평가)", "비대면(화상회의)", "비대면(온라인)" 등 괄호 안에 구체적 방식을 적는다.
- 동일 건에 대해 중복 신고하지 않도록, 기존 목록을 먼저 확인하는 것이 좋다.
파일 구조
snu-external-lecture-report/
├── SKILL.md ← 이 파일
├── config.json ← Trello 보드 URL 등 설정
├── assets/
│ └── btrip-form.hwpx ← 출장신청서 HWPX 템플릿
└── write_btrip.py ← 출장신청서 생성 스크립트 (lxml 필요)