07. 진짜 데이터 모으기#
📚 학습 목표: 실제 메디콘솔 도메인 데이터를 안전하고 효과적으로 수집
⏱️ 읽는 시간: 25분
🎯 적용 시점: 맛보기 완료 후, MVP 학습 직전
🚨 가장 먼저: 의료 데이터 보안 원칙#
절대 하지 말아야 할 것#
- ❌ 환자 실명 포함: "김철수 환자가..."
- ❌ 주민번호/전화번호: "850101-1234567"
- ❌ 병원명 직접 명시: "OO요양병원에서..."
- ❌ 의료진 실명: "박OO 간호사가..."
- ❌ Colab/ChatGPT에 원본 업로드: 맥미니 로컬만!
반드시 해야 할 것#
- ✅ 익명화 먼저, 학습 나중에
- ✅ 이름 → "환자 A", "환자 B"로 치환
- ✅ 날짜 → 상대적 표현: "3일 전", "오늘 오전"
- ✅ 병원명 → "본원", "요양병원"
- ✅ 맥미니에서만 작업: 데이터가 외부로 안 나가게
데이터의 5가지 카테고리#
목표: 총 1,500건 (MVP), 분포는 다음과 같이:
카테고리 1: 간호 기록 (25%, 375건)#
핵심 목표: Voice ENR이 음성을 SOAP 형식으로 자동 변환
하위 주제 (각 30-60건씩)#
| 주제 | 목표 건수 | 예시 질문 |
|---|---|---|
| 음성 → SOAP 변환 | 80 | "다음 음성을 SOAP로: 김○○ 혈압 140/90..." |
| 활력징후 기록 | 50 | "BP 130/85, HR 72, SpO2 95%의 의미는?" |
| 투약 기록 | 50 | "PRN 투약 후 간호 기록 작성법" |
| 낙상 관찰 | 40 | "낙상 위험도 사정 도구 설명" |
| 욕창 관찰 | 40 | "욕창 2단계 관찰 기록" |
| 통증 사정 | 30 | "NRS 7점 통증 기록 방법" |
| 섭취/배설 | 30 | "섭취량 부족 환자 기록" |
| 정서/인지 | 30 | "치매 환자 정서 상태 기록" |
| 재활 경과 | 25 | "물리치료 후 경과 기록" |
예시 데이터 포맷#
{"messages":[
{"role":"system","content":"당신은 요양병원 간호 기록 AI입니다. SOAP 형식으로 정리하세요."},
{"role":"user","content":"음성 입력: 환자 A, 오전 9시 혈압 140/90, 무릎 통증 NRS 6점 호소"},
{"role":"assistant","content":"S: 환자 A는 무릎 통증 호소 (NRS 6점)\nO: 혈압 140/90 mmHg (09:00 측정)\nA: 중등도 통증, 혈압 경계치\nP: 통증 양상 지속 관찰, 혈압 2시간 간격 재측정, 의료진 보고"}
],"category":"nursing","subcategory":"voice_to_soap"}
카테고리 2: 병원 운영/경영 (25%, 375건)#
핵심 목표: 원장/행정이 경영 질문 시 즉답
하위 주제#
| 주제 | 건수 | 예시 |
|---|---|---|
| 병원 유형별 수가 체계 | 70 | "요양병원 일당정액제", "종합병원 행위별수가·DRG", "의원 정액수가" |
| 적정성 평가·인증 | 70 | "요양병원 적정성평가", "의료기관 인증평가" |
| 인증평가 준비 | 60 | "의료기관 인증 조사 체크리스트" |
| 인력 기준 | 50 | "요양병원 간호인력 1~9등급", "종합병원 간호 등급" |
| 원가 분석 | 40 | "병상당 원가 계산법" (유형별 조정) |
| 병상 가동률·외래 | 30 | "가동률 90% 최적화" (입원 중심), "외래 환자 수" (의원 중심) |
| 환자 구성비 | 30 | "요양병원 1~5군 구성비", "종합병원 DRG 분포" |
| 보험 청구 | 25 | "청구 삭감 주요 원인" (유형별 공통) |
카테고리 3: 의료 용어 (15%, 225건)#
핵심 목표: 도메인 용어를 정확히 "안다"
접근법: 미니 사전 형식#
{"messages":[
{"role":"user","content":"KPCS가 뭔가요?"},
{"role":"assistant","content":"KPCS(Korean Patient Classification System)는 환자의 간호 요구도를 6등급으로 분류하는 한국형 환자분류체계입니다. 1등급이 가장 중증이고, 6등급이 경증입니다. 주로 간호 인력 산정과 간호료 청구의 근거로 활용됩니다."}
],"category":"medical_terms"}
수집 대상#
- 병원 유형별 다빈도 진단명 (50) — 요양·재활은 만성, 전문병원은 특정 질환
- 검사 용어 (40) — 공통
- 약품 정보 (40) — 공통
- 간호 표준 용어 (50) — KPCS(요양), ICNP/NANDA(공통)
- 재활/물리치료 용어 (25) — 재활병원 중심, 요양도 일부
- 감염관리 용어 (20) — 공통
- 한방 의료 용어 (별도 20) — 경락·본초·처방명 (한방병원 포함 시)
중요: 여기는 팩트 체크 필수. 틀린 정보 학습하면 할루시네이션 원인.
카테고리 4: 컨설팅 프레임워크 (20%, 300건)#
핵심 목표: 메디콘솔 고유 프레임워크 학습
GODCH 프레임워크 (80건)#
메디콘솔 고유 컨설팅 프레임워크. 각 요소별로 최소 15건씩.
{"messages":[
{"role":"user","content":"GODCH 프레임워크가 뭔가요?"},
{"role":"assistant","content":"GODCH는 메디콘솔이 개발한 요양병원 경영 컨설팅 프레임워크로, 다음 5개 축으로 구성됩니다:\n\nG: Governance (거버넌스)\nO: Operations (운영)\nD: Development (성장/개발)\nC: Culture (조직문화)\nH: Healthcare (의료 품질)\n\n각 축에서 현재 수준을 진단하고 개선 로드맵을 도출합니다."}
],"category":"consulting","subcategory":"godch"}
하위 주제#
| 주제 | 건수 |
|---|---|
| GODCH 프레임워크 전반 | 80 |
| ABC 원가 분석 | 60 |
| 인증평가 준비 가이드 | 50 |
| 감염관리 | 40 |
| QI 활동 | 40 |
| 직원 교육 프로그램 | 30 |
카테고리 5: 커뮤니케이션/문서 작성 (15%, 225건)#
핵심 목표: 병원 실무 문서 자동 작성
하위 주제#
| 주제 | 건수 | 예시 |
|---|---|---|
| 월간 경영 보고서 | 50 | "월간 경영 보고서 목차 작성" |
| 행정 공문 | 40 | "직원 안전교육 공문 초안" |
| 회의록 | 40 | "부서장 회의록 정리 방법" |
| 환자 안내문 | 40 | "면회 규정 안내문" |
| 보호자 상담 | 30 | "임종 임박 보호자 면담 가이드" |
| 직원 교육 자료 | 25 | "신입 간호사 오리엔테이션 자료" |
📊 데이터 수집 3단계 전략#
Stage 1: 기존 자산 정리 (Week 1)#
이미 메디콘솔이 갖고 있는 자산을 정리:
📂 기존 자산 소스
├── 메디콘솔 Connect 채팅 로그 (간호 관련)
├── RNDiary 음성→텍스트 샘플
├── 스마트병원경영 책 내용
├── Naver Premium Content 칼럼
├── 상반기 학술 세미나 자료
├── 고객사 컨설팅 보고서
├── 직원 교육 자료
└── FAQ 모음
작업:
1. 맥미니에 data/source/ 디렉토리 생성
2. 위 자산을 텍스트로 변환 (PDF → txt, HWP → txt)
3. 카테고리별 정리
예상 수확: 500-800건 (MVP 초안)
Stage 2: Q&A 형식 변환 (Week 2)#
원본 자료를 질문-답변 쌍으로 변환:
변환 패턴 1: 설명문 → Q&A#
원본:
"요양병원 의료급여 1종 수가는 일당정액제로, 환자분류군에 따라 차등 적용된다. 1군(의료최고도)은..."
변환:
{"messages":[
{"role":"user","content":"요양병원 의료급여 1종 수가 체계 설명해주세요"},
{"role":"assistant","content":"요양병원 의료급여 1종 수가는 일당정액제로..."}
]}
변환 패턴 2: 체크리스트 → 실무 질문#
원본:
"인증평가 대비 체크리스트: 1. 감염관리 매뉴얼 최신화, 2. ..."
변환:
{"messages":[
{"role":"user","content":"인증평가 준비 이번주에 뭐부터 해야 할까요?"},
{"role":"assistant","content":"인증평가 임박 시 우선순위:\n1. 감염관리 매뉴얼 최신화 확인\n2. ..."}
]}
변환 패턴 3: 사례 → 시뮬레이션#
원본:
"효사랑 가족요양병원 2023년 1분기 사례: 병상가동률 85%에서..."
변환:
{"messages":[
{"role":"user","content":"병상가동률 85%인데 적자에요. 개선 방향?"},
{"role":"assistant","content":"85% 가동률이 적자라면 다음 원인 점검:\n1. 환자 구성비 확인 (1-2군 비율..."}
]}
Stage 3: 빈틈 메우기 (Week 3)#
Stage 1-2에서 부족한 부분을 채움.
도구 1: Claude로 합성 데이터 생성#
주의: 맥미니에서 로컬 Claude (claude.ai API)나 기존 Claude 사용
프롬프트 예시:
"요양병원 수가 체계에 대한 실무자 질문 10개와 답변을 생성해주세요.
- 형식: JSONL
- 질문: 병원 행정직원이 실제로 할만한 구체적 질문
- 답변: 정확한 사실 + 실무 팁 포함
- 한국어, 200-400자 답변"
생성 후 반드시 검수: - ✅ 사실 관계 맞는지 - ✅ 메디콘솔 용어 쓰는지 - ✅ 병원 유형(요양·전문·의원·재활·한방)이 명시되어 있는지 — 유형별 수가/제도 차이가 크므로 모호하게 쓰지 않기
도구 2: 수간호사 인터뷰#
동료에게 1시간만 시간 받기: - "현장에서 매일 쓰는 간호 기록 패턴 알려주세요" - 음성 녹음 → 맥미니에서 Whisper로 텍스트 변환 - Q&A 형식으로 정리
도구 3: 기존 chatbot 로그 활용#
메디콘솔 제품에 이미 쌓인 대화 로그: - 자주 물어보는 TOP 100 질문 - 실제 답변을 다듬어서 학습 데이터로
🛠️ 실제 수집 작업 방법#
방법 A: 스프레드시트 → JSONL (초보자)#
Google Sheets로 수집#
| category | user_message | assistant_response | subcategory |
|---|---|---|---|
| nursing | 혈압 140/90 의미? | 고혈압 1기에 해당... | vital_signs |
| management | 병상가동률 계산? | (가동병상일수/가용... | occupancy |
CSV 다운로드 → JSONL 변환#
# scripts/convert_csv_to_jsonl.py (예시)
import csv
import json
with open('data/raw/collected.csv', 'r') as csvfile:
reader = csv.DictReader(csvfile)
for row in reader:
record = {
"messages": [
{"role": "user", "content": row['user_message']},
{"role": "assistant", "content": row['assistant_response']}
],
"category": row['category'],
"subcategory": row.get('subcategory', '')
}
category_dir = f"data/raw/{get_category_folder(row['category'])}"
with open(f"{category_dir}/collected.jsonl", 'a') as f:
f.write(json.dumps(record, ensure_ascii=False) + '\n')
방법 B: 직접 JSONL 작성 (숙련자)#
한 줄에 하나의 JSON 객체:
{"messages":[{"role":"user","content":"Q1"},{"role":"assistant","content":"A1"}],"category":"nursing"}
{"messages":[{"role":"user","content":"Q2"},{"role":"assistant","content":"A2"}],"category":"nursing"}
방법 C: aatto에서 관리 (추천)#
메디콘솔이 이미 쓰는 aatto에 학습 데이터 수집 프로젝트 만들기:
- 각 카테고리별 Document
- Document 하단에 Q&A 누적 기록
- 주기적으로
scripts/로 JSONL 변환
✅ 품질 체크리스트 (필수)#
학습 전에 반드시 확인:
개별 데이터 검증#
# 랜덤 샘플 10개 수동 검수
python3 -c "
import json, random
with open('data/processed/train.jsonl') as f:
lines = f.readlines()
samples = random.sample(lines, 10)
for s in samples:
print(json.loads(s)['messages'][-1]['content'][:200])
print('---')
"
체크 항목: - [ ] PHI 없음 (이름, 주민번호 등) - [ ] 답변이 200-1000자 (너무 짧거나 길지 않음) - [ ] 한국어 자연스러움 - [ ] 사실 관계 정확 - [ ] 메디콘솔 용어 사용
전체 통계#
python3 -c "
import json
from collections import Counter
cats = []
lengths = []
with open('data/processed/train.jsonl') as f:
for line in f:
d = json.loads(line)
cats.append(d.get('category', 'unknown'))
lengths.append(len(d['messages'][-1]['content']))
print('카테고리 분포:')
for cat, cnt in Counter(cats).most_common():
pct = cnt / len(cats) * 100
print(f' {cat}: {cnt} ({pct:.1f}%)')
print(f'\n답변 길이:')
print(f' 평균: {sum(lengths)/len(lengths):.0f}자')
print(f' 최소: {min(lengths)}자')
print(f' 최대: {max(lengths)}자')
"
목표: - 카테고리 분포: ±5% 내외 (25/25/15/20/15) - 평균 길이: 300-500자 - 최소: 50자 이상 (너무 짧으면 정보량 부족) - 최대: 2000자 이하 (너무 길면 학습 어려움)
PHI 자동 스캔#
# 위험 패턴 검사
python3 -c "
import json, re
patterns = {
'주민번호': r'\d{6}-\d{7}',
'전화번호': r'01[0-9]-?\d{3,4}-?\d{4}',
'실명(흔한)': r'(김|이|박|최|정|강|조|윤|장|임)[가-힣]{2}',
}
with open('data/processed/train.jsonl') as f:
for i, line in enumerate(f, 1):
text = line
for name, pat in patterns.items():
matches = re.findall(pat, text)
if matches:
print(f'Line {i} [{name}]: {matches[:3]}')
"
발견되면: 해당 데이터 수정 후 재실행.
📈 데이터 양 vs 품질 (원칙)#
경험적 가이드#
| 건수 | 예상 품질 | 비고 |
|---|---|---|
| 100건 이하 | ⚠️ 부족 | 과적합 위험 높음 |
| 300-500건 | 🔶 MVP 최소 | 파이프라인 검증용 |
| 1,000-1,500건 | ✅ MVP 권장 | 의미 있는 성능 |
| 3,000-5,000건 | 🚀 프로덕션 | 고품질 |
| 10,000+ | 💎 엔터프라이즈 | Colab 추천 |
"많이 vs 정확히" 비교#
1,500건 고품질 > 10,000건 저품질
이유: - 저품질 데이터는 잘못된 패턴을 가르침 - 할루시네이션 증가 - Overfitting 가속
증강 허용 기준#
실제 데이터가 부족할 때 전체의 30% 이하로 증강 허용: - Paraphrasing (같은 내용 다른 표현) - 역번역 (한→영→한) - 난이도 변주 (초보자용/전문가용)
절대 금지: - 100% 합성 데이터로 학습 - 검증 없이 AI 생성 데이터 사용
🎯 현실적 수집 계획 (예시)#
Week 1: 최소 MVP (500건)#
월: 기존 자산 정리 (100건)
화: 기존 자산 Q&A 변환 (150건)
수: GODCH/ABC 프레임워크 (100건)
목: 간호 SOAP 예시 (100건)
금: 의료 용어 사전 (50건)
→ 500건으로 첫 학습 시도
Week 2: MVP 완성 (1,500건)#
→ 1,500건으로 정식 v1.0.0 학습
Week 3+: 지속 확장#
- 실제 사용 중 수집되는 bad case
- 사용자 피드백 반영
- 월 100-300건씩 추가
🔐 보안 워크플로우#
원본 → 익명화 → 학습#
[맥미니 로컬만]
1. data/source/ ← 원본 (PHI 포함 가능)
↓ (익명화 스크립트)
2. data/raw/ ← 익명화 완료
↓ (전처리)
3. data/processed/ ← JSONL 통합
↓
4. 학습 입력
익명화 자동화 스크립트#
# scripts/anonymize.py (직접 만들거나 Claude Code에게 요청)
import re
def anonymize(text):
# 이름 치환
text = re.sub(r'(김|이|박|최|정)[가-힣]{2}\s+환자', '환자 A', text)
# 주민번호 제거
text = re.sub(r'\d{6}-\d{7}', 'XXXXXX-XXXXXXX', text)
# 병원명
text = text.replace('효사랑요양병원', '본원')
text = text.replace('원주불로병원', '본원')
# 날짜
text = re.sub(r'2026-04-\d{2}', '최근', text)
return text
학습 데이터에 PHI 절대 금지 확인 방법#
# 학습 직전 마지막 검증
python3 -c "
import json, re
has_phi = False
patterns = [r'\d{6}-\d{7}', r'\d{3}-\d{4}-\d{4}']
with open('data/processed/train.jsonl') as f:
for i, line in enumerate(f, 1):
for pat in patterns:
if re.search(pat, line):
print(f'⚠️ Line {i}: PHI 패턴 발견')
has_phi = True
break
if not has_phi:
print('✅ PHI 스캔 통과')
"
🎓 다음 단계#
데이터 수집이 끝나면:
- 양이 500건 넘음? → Yes → 08_HYPERPARAMETERS.md
- 아직 부족? → 이 문서로 다시 돌아오기
💡 핵심 요약#
1순위: PHI 절대 금지 (맥미니 로컬에서만 작업)
2순위: 5개 카테고리 균형 (25/25/15/20/15)
3순위: 1,500건 목표 (MVP)
원칙: 품질 > 양
전략: 기존 자산 → Q&A 변환 → 빈틈 메우기