QuickForm 대화형 수업 도구 생성 Skill
개요
이 스킬은 교사가 전문적인 대화형 HTML 수업 도구를 빠르게 만들고 QuickForm 데이터 수집 플랫폼에 자동으로 연결하여 데이터 분석 시각화 대시보드를 생성할 수 있도록 도와줍니다. 전체 과정은 8단계로 구성됩니다.
1단계: QuickForm 버전 및 계정 확인
사용 중인 버전 확인
사용자에게 질문:
"어떤 QuickForm 버전을 사용하시겠습니까?
- A. 공식 버전 (https://quickform.cn)
- B. 로컬 버전 (로컬 네트워크 배포 버전)"
공식 버전 처리
- 자격 증명 캐시 파일
~/.claude/quickform_credentials.json존재 여부 확인:cat ~/.claude/quickform_credentials.json 2>/dev/null - 파일이 존재하고
official.username및official.password가 포함되어 있으면 바로 읽어서 사용하며, 다시 묻지 않고 사용자에게 "이전에 저장된 계정을 사용합니다: xxx"라고 알림 - 파일이 없으면 사용자에게 공식 계정과 비밀번호를 묻고, 받은 후 캐시 파일에 저장:
bash로 작성:{ "official": { "username": "사용자가 제공한 계정", "password": "사용자가 제공한 비밀번호" } }echo '{"official":{"username":"xxx","password":"xxx"}}' > ~/.claude/quickform_credentials.json
로컬 버전 처리
-
기본 계정:
wst, 기본 비밀번호:quickform(로컬 배포의 출고 기본값, 변경하지 않음) -
로컬 주소 자동 획득 (다음 우선순위대로 시도):
첫 번째 단계: 저장된 주소 확인
cat ~/.claude/quickform_credentials.json 2>/dev/nullJSON에
local.base_url필드가 있으면 바로 사용하고, 사용자에게 "이전에 저장된 로컬 주소를 사용합니다: xxx"라고 알린 후, 이후 감지를 건너뜀.두 번째 단계: 로컬 IP + 5001 포트 자동 감지 저장된 주소가 없으면 Python으로 로컬 네트워크 IP를 가져옴:
import socket s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.connect(("8.8.8.8", 80)) local_ip = s.getsockname()[0] s.close() print(local_ip)http://<local_ip>:5001로 조합한 후 사용 가능 여부 확인:curl -s -o /dev/null -w "%{http_code}" http://<local_ip>:5001/- 200 또는 302 반환 시: 사용자에게 "로컬 주소를 자동으로 감지했습니다: http://<local_ip>:5001, 사용 중"이라고 알리고 자격 증명 파일에 저장
- 연결 실패 시: 세 번째 단계로 이동
세 번째 단계: 자동 감지 실패, 사용자에게 수동 입력 요청
자동 감지된 주소 http://<local_ip>:5001에 접근할 수 없습니다. 로컬 QuickForm의 접속 주소를 수동으로 입력해 주세요. (예: http://192.168.1.100:5001):사용자 입력을 받은 후 다시 확인하고, 확인이 완료되면 저장.
자격 증명 파일에 주소 저장:
python3 -c " import json, os path = os.path.expanduser('~/.claude/quickform_credentials.json') try: d = json.load(open(path)) except: d = {} d.setdefault('local', {})['base_url'] = 'http://최종확인된주소' json.dump(d, open(path, 'w'), ensure_ascii=False) print('주소가 저장되었습니다') " -
사용자에게 질문: "로컬 QuickForm 서비스가 시작되었습니까? 시작되지 않았다면 먼저 서비스를 시작해 주세요."
이후 모든 단계에서 로컬 주소는 변수 LOCAL_BASE_URL(위 프로세스에서 획득)을 사용하며, IP를 하드코딩해서는 안 됩니다.
2단계: 수업 도구 디자인 스타일 파악
사용자에게 질문 (옵션을 제시하여 안내하고, 자유로운 설명도 허용):
"수업 도구의 디자인 스타일을 선택해 주세요 (다중 선택 또는 직접 설명 가능):
- 🎨 간결 모던 스타일 — 카드 레이아웃, 깔끔한 색상, 대부분의 상황에 적합
- 🌈 그라데이션 화려한 스타일 — 선명한 그라데이션, 역동적인 효과, 활기찬 수업에 적합
- 🌙 다크 모드 스타일 — 어두운 배경, 형광색, 기술적인 느낌의 수업에 적합
- 🎠 어린이 친화적 스타일 — 둥글고 귀여운 디자인, 밝고 만화 같은 느낌, 초등학교 저학년에 적합
- 📊 학술적 진지한 스타일 — 전문적이고 깔끔하며 데이터 중심, 고등학교 또는 대학교에 적합
- 🖌️ 직접 정의 — 원하는 스타일을 설명해 주세요"
또한 질문:
- 적용 학년 (예: 초등학교 3학년, 중학교 2학년, 고등학생, 대학생)
- 과목 (예: 국어, 수학, 영어, 과학, 정보 기술, 역사 등)
3단계: 수업 도구 구체적 요구 사항 수집
이 단계에서는 개발을 시작하기에 충분히 상세한 정보를 수집해야 합니다. 다음 세 가지 측면을 반드시 포함해야 합니다:
3.1 상호작용 방식 요구 사항
다음을 명확히 해야 함:
- 수업 도구의 핵심 기능 (투표/설문/퀴즈/실험 기록/과제 제출/토론/게임형 연습 등)
- 학생이 도구와 상호작용하는 방식 (옵션 클릭/텍스트 입력/드래그 앤 드롭/그리기/시간 제한 답변 등)
- 즉각적인 피드백이 필요한지 여부 (답변 후 즉시 정답/해설 표시)
사용자 설명이 모호할 경우, 능동적으로 질문:
"학생들이 이 페이지에서 어떤 작업을 수행하길 바라시나요? 완료 후 어떤 결과를 보게 될까요?"
3.2 데이터 제출 필드
수집할 각 필드를 명확히 해야 함:
- 필드 이름 (영문 키, API 용)
- 필드 의미 (중국어 설명)
- 필드 유형 (텍스트/숫자/옵션/시간 등)
사용자가 필드를 언급하지 않으면, 생각을 유도:
"학생들의 어떤 정보를 수집하길 바라시나요? 예: 학생 이름, 반, 답변 옵션, 점수, 소요 시간 등, 하나씩 설명해 주세요."
예시 필드 형식 (참고용, 실제는 사용자 요구에 따름):
student_name: 학생 이름 (텍스트)
class: 반 (텍스트)
answer: 답변 옵션 (A/B/C/D)
score: 점수 (숫자)
duration: 소요 시간(초) (숫자)
3.3 데이터 분석/시각화 대시보드 요구 사항
다음을 명확히 해야 함:
- 원하는 차트 유형 (막대 그래프/원형 그래프/꺾은선 그래프/워드 클라우드/랭킹 등)
- 데이터 통계 차원 (반별 비교/답변 분포/정답률/평균 점수/시간 추세 등)
- 대시보드 전체 스타일 (수업 도구와 일치/독립적인 스타일/프로젝션 디스플레이 스타일)
- 실시간 새로 고침 필요 여부
정보가 부족할 경우, 질문:
"수업 시간에 학급 전체에 어떤 데이터를 보여주고 싶으신가요? 학생들이 학급 내에서 자신의 위치를 볼 수 있기를 바라시나요?"
정보 확인
위 세 가지 측면을 수집한 후 요구 사항 요약을 정리하여 사용자에게 확인:
📋 요구 사항 확인 요약
【기본 정보】
- QuickForm 버전: 공식 버전/로컬 버전
- 디자인 스타일: xxx
- 적용 학년: xxx 과목: xxx
【수업 도구 상호작용】
- 기능 유형: xxx
- 상호작용 방식: xxx
- 즉각적인 피드백: 예/아니오
【데이터 수집 필드】
- field1: 의미 (유형)
- field2: 의미 (유형)
...
【시각화 대시보드 요구 사항】
- 차트 유형: xxx
- 통계 차원: xxx
- 실시간 새로 고침: 예/아니오
사용자가 확인한 후 4단계로 진행합니다.
4단계: QuickForm에 작업 생성
1단계에서 선택한 버전에 따라 QuickForm 작업을 생성합니다.
작업 명명 규칙: 수업 도구 주제에 따라 명명하며, 간결하고 명확하게 (예: "3학년 수학 덧셈 뺄셈 연습", "고등학교 화학 원소 주기율표 퀴즈")
공식 버전 생성
curl -s -X POST https://quickform.cn/cli/add \
-H "Content-Type: application/json" \
-d '{"username":"<계정>","password":"<비밀번호>","task_name":"<작업 이름>","description":"<도구 소개>"}'
성공 응답 예시: {"success":true,"apiid":"k5egb0lbzi"}
- 데이터 제출 인터페이스:
https://quickform.cn/api/<apiid> - 데이터 조회 인터페이스:
https://quickform.cn/api/<apiid>/all
로컬 버전 생성
로컬 버전에는 /cli/add 인터페이스가 없으므로, Python 세션 방식으로 로그인한 후 작업을 생성하고, 작업 페이지에서 실제 API ID를 파싱해야 합니다:
⚠️ 중요: 로컬 버전의 API 인터페이스 주소는 숫자 작업 번호(예:
/api/10)가 아닙니다. 시스템이 각 작업에 대해 생성한 랜덤 문자열 ID(예:/api/C9VaWGMQEZY)입니다. 로그인 후 작업 상세 페이지 HTML에서 파싱해야만 얻을 수 있으므로, 숫자 ID로 데이터를 제출할 수 없습니다.
import urllib.request, urllib.parse, http.cookiejar, re
cj = http.cookiejar.CookieJar()
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))
# 1. 로그인
login_data = urllib.parse.urlencode({'username': 'wst', 'password': 'quickform'}).encode()
req = urllib.request.Request('<LOCAL_BASE_URL>/login', data=login_data)
req.add_header('Content-Type', 'application/x-www-form-urlencoded')
opener.open(req)
# 2. 작업 생성
task_data = urllib.parse.urlencode({'title': '<작업 이름>', 'description': '<도구 소개>'}).encode()
req2 = urllib.request.Request('<LOCAL_BASE_URL>/create_task', data=task_data)
req2.add_header('Content-Type', 'application/x-www-form-urlencoded')
resp = opener.open(req2)
final_url = resp.geturl() # /task/<숫자 id>로 리다이렉트
numeric_id = re.search(r'/task/(\d+)', final_url).group(1)
# 3. 작업 상세 페이지에서 실제 API ID(랜덤 문자열, 숫자가 아님) 파싱
req3 = urllib.request.Request(f'<LOCAL_BASE_URL>/task/{numeric_id}')
resp3 = opener.open(req3)
html = resp3.read().decode('utf-8')
api_links = re.findall(r'/api/([a-zA-Z0-9\-_]+)', html)
real_api_id = list(set(api_links))[0] # 실제 API ID
print(f"숫자 작업 ID: {numeric_id}")
print(f"실제 API ID: {real_api_id}")
- 데이터 제출 인터페이스:
<LOCAL_BASE_URL>/api/<real_api_id> - 데이터 조회 인터페이스:
<LOCAL_BASE_URL>/api/<real_api_id>/all
로컬 버전 데이터 인터페이스가 반환하는
data필드는 Python dict 문자열 형식(작은따옴표)이므로, HTML 대시보드에서 파싱할 때 JSON으로 변환(작은따옴표를 큰따옴표로 대체)해야 합니다.
인터페이스 정보 기록
다음 정보를 기록하여 이후 단계에서 사용:
SUBMIT_URL: 데이터 제출 인터페이스 주소FETCH_URL: 데이터 조회 인터페이스 주소TASK_NAME: 작업 이름
5단계: 대화형 HTML 수업 도구 페이지 개발
수집된 모든 요구 사항을 기반으로 완전한 단일 파일 HTML 수업 도구를 생성합니다.
기술 사양
반드시 준수해야 할 원칙:
- 단일 HTML 파일, 모든 CSS와 JS는 인라인
- 중국 본토에서 원활하게 접근 가능한 CDN 사용 (아래 목록 참조)
- 데이터 제출 주소는
SUBMIT_URL사용 - 제출 성공 후 학생에게 명확한 피드백 제공 (성공 메시지/점수/해설)
- 페이지가 모바일과 데스크톱 모두에서 정상적으로 표시되어야 함 (반응형)
권장 CDN (중국 본토에서 접근 가능):
<!-- Tailwind CSS -->
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<!-- ECharts 차트 (시각화 페이지용) -->
<script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>
<!-- Font Awesome 아이콘 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6/css/all.min.css">
<!-- Alpine.js 경량 상호작용 -->
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3/dist/cdn.min.js"></script>
데이터 제출 코드 템플릿:
async function submitData(formData) {
try {
const response = await fetch('SUBMIT_URL', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(formData)
});
const result = await response.json();
return result;
} catch (error) {
console.error('제출 실패:', error);
return null;
}
}
수업 도구 품질 요구 사항
- 페이지 주제가 명확하고 선택한 디자인 스타일에 부합해야 함
- 글꼴 크기는 대상 연령대에 적합해야 함 (어린이는 더 큰 글꼴 사용)
- 상호작용 요소에 시각적 피드백이 명확해야 함 (hover 효과, 클릭 애니메이션)
- 제출 버튼이 눈에 띄고 제출 프로세스가 간결해야 함 (단계 수 적게)
- 수업 도구 제목과 간단한 사용 설명 포함
- 모든 폼 필드가 3.2단계에서 정의한 필드와 완전히 일치해야 함
파일 저장
생성된 HTML을 현재 작업 디렉토리에 저장하며, 명명 규칙:
<작업이름_수업도구>.html
6단계: 테스트 데이터 3건 자동 제출
수업 도구의 필드 구조에 따라 현실감 있는 테스트 데이터 3건을 생성하여 제출합니다.
테스트 데이터 원칙:
- 데이터에 차별성이 있어야 함 (3건이 동일하지 않아야 함)
- 데이터가 실제 시나리오에 부합해야 함 (실제 학생 이름, 합리적인 성적 분포)
- 다양한 상황 포함 (예: 정답 맞춘 경우, 틀린 경우, 다른 반의 경우)
제출 방식: curl을 사용하여 한 건씩 제출
curl -s -X POST "SUBMIT_URL" \
-H "Content-Type: application/json" \
-d '{"field1":"value1","field2":"value2",...}'
제출 완료 후 사용자에게 알림: "✅ 3건의 테스트 데이터가 성공적으로 제출되었습니다"
7단계: 데이터 분석 시각화 대시보드 개발
7.1 테스트 데이터 구조 조회
curl -s "FETCH_URL"
반환된 전체 JSON 데이터를 읽고 데이터 구조(필드명, 데이터 유형, 중첩 관계)를 파악합니다.
전체 데이터 구조를 개발 참조용으로 기록합니다.
7.2 시각화 대시보드 HTML 개발
다음 정보를 종합하여 개발:
- 7.1단계에서 획득한 실제 데이터 구조와 필드
- 3.3단계에서 사용자가 제시한 시각화 요구 사항
- 수업 도구 페이지의 주제와 스타일 (일관성 유지)
기술 사양:
- 단일 HTML 파일, 모든 코드 인라인
- ECharts(
cdn.jsdelivr.net)를 사용하여 차트 렌더링 - 페이지 로드 시 자동으로
FETCH_URL에서 데이터를 가져와 렌더링 - 실시간 새로 고침이 필요한 경우
setInterval을 사용하여 10-15초마다 새로 고침 - 대시보드 레이아웃은 프로젝션 디스플레이에 적합 (16:9 비율 선호, 글꼴 약간 크게)
대시보드에 반드시 포함되어야 할 내용:
- 페이지 상단: 도구 제목 + 현재 데이터 통계 개요 (참여 인원, 평균 점수 등 핵심 지표)
- 본문 영역: 사용자가 요청한 차트 (ECharts 사용)
- 데이터 출처 인터페이스 주소 (페이지 하단 작은 글씨로 표시)
데이터 조회 코드 템플릿:
async function fetchData() {
const response = await fetch('FETCH_URL');
const data = await response.json();
// data 구조는 7.1단계에서 실제 가져온 내용에 따라 처리
return data;
}
파일 저장
명명 규칙: <작업이름_데이터대시보드>.html
8단계: 완료 보고서
개발 완료 후 사용자에게 간단한 보고서 출력:
🎉 QuickForm 수업 도구 개발 완료!
📁 생성된 파일
- 수업 도구 페이지: <파일명>.html
- 데이터 분석 대시보드: <파일명>.html
🔗 인터페이스 정보
- 데이터 제출: SUBMIT_URL
- 데이터 조회: FETCH_URL
📊 테스트 데이터
- 3건의 테스트 데이터가 제출되었으며, 대시보드 페이지에서 결과를 확인할 수 있습니다
💡 사용 팁
1. 수업 도구 페이지를 학생과 공유 (로컬 네트워크 또는 공개 주소)
2. 학생이 작성하여 제출한 후, 데이터 대시보드를 열어 실시간 결과 확인
3. 스타일이나 필드를 수정하려면 HTML 파일을 직접 편집
참고 자료
- QuickForm API 문서:
references/quickform-api.md참조 - 시각화 차트 예제:
references/echarts-examples.md참조 - 중국 본토에서 사용 가능한 CDN 목록:
references/china-cdn.md참조