분석을 배우고 싶은데 실제 출동·점검 데이터를 쓰기엔 개인정보가 걸립니다. 이 안내서는 실데이터 없이 분석 레시피를 끝까지 연습하도록 합성 데이터를 만드는 방법입니다. 같은 seed면 항상 똑같은 CSV가 나와, 시연과 테스트에 안정적으로 쓸 수 있습니다.
- 합성 데이터와 비식별화한 실데이터의 차이를 설명할 수 있습니다.
- seed와 업무 규칙을 사용해 재현 가능한 연습 데이터를 생성할 수 있습니다.
- 생성 규칙을 검산식으로 바꾸어 모순 행을 탐지할 수 있습니다.
- 합성 결과의 사용 범위와 공개 표기를 판단할 수 있습니다.
왜 합성 데이터인가
운전을 배울 때 처음부터 도심 도로로 나가지 않습니다. 실제 교통과 분리된 연습장에서 후진과 주차를 익히죠. 합성 데이터는 분석의 연습장입니다. 진짜 119 데이터에는 신고자·환자 정보가 섞여 있어 연습용으로 함부로 쓸 수 없습니다. 규칙에서 새로 만든 합성 데이터는 실자료를 복사하지 않고 분석 레시피를 처음부터 끝까지 굴려 보게 해 줍니다.
실데이터로 연습하면 두 가지가 걸립니다 — 개인정보 사고 위험, 그리고 매번 데이터가 달라 결과를 비교하기 어렵다는 점입니다. 규칙에서 새 행을 만들면 실자료 노출을 줄이고, 조건이 같을 때 같은 표를 다시 만들 수 있습니다.
⚠️ "합성" 표기의 한계: 합성 표기는 개인정보·보안 검토나 외부 도구 사용 승인을 대신하지 않습니다. 입력에 실자료가 섞이지 않았는지 확인하고, 기관의 승인된 환경과 도구 범위 안에서만 사용합니다. 합성 데이터라도:
- 비식별 처리는 여전히 필요합니다 (실제 학습에 들어가면)
- 외부 전송이 필요하면 별도 개인정보·보안 검토를 받아야 합니다
- 기관의 승인된 도구와 환경 안에서만 사용합니다
왜 실데이터가 위험한지는 개인정보, AI에 넣기 전에 점검하기에 정리돼 있습니다. 이 합성 데이터로 연습하기 좋은 대표 레시피는 지저분한 출동 데이터 깔끔하게 정제하기와 출동 통계, CSV 한 장으로 월간 집계입니다.
동작 원리
합성 데이터 생성기는 빈 표에 아무 값을 채우는 도구가 아닙니다. 먼저 스키마가 어떤 열을 갖는지 정하고, 각 열의 가능한 값과 열 사이 관계를 규칙으로 적습니다. 난수 생성기는 seed에서 시작해 값 선택 순서를 반복하고, 행 생성 함수는 그 값을 날짜·유형·ID·결과 열에 배치합니다. 따라서 같은 조건과 같은 생성 순서를 쓰면 같은 결과를 다시 만들 수 있습니다.
중요한 것은 한 열의 범위보다 열 사이 관계입니다. items_failed가 items_checked보다 클 수 없고, 결과가 특정 상태일 때만 재점검일이 생긴다는 식의 관계가 있어야 분석 연습이 가능합니다. 이 관계는 생성 코드와 검산 코드에 각각 표현합니다. 생성 쪽 실수가 있어도 독립된 검산 조건이 모순을 잡게 하는 구조입니다.
합성이라는 이름은 생성 방식만 설명합니다. 현실 분포를 닮았다는 보증도, 개인정보 검토가 끝났다는 승인도 아닙니다. 실제 행을 조금 바꾸어 섞으면 생성 규칙으로 만든 순수 합성이 아니며 원자료 위험이 남습니다. 그래서 입력 출처, 생성 명령, seed, 행 수, 사용한 규칙을 결과와 함께 기록해야 사용자가 범위를 판단할 수 있습니다.
같은 seed, 같은 데이터 — 왜 중요한가
정확한 계량이 적힌 레시피는 누가 언제 만들어도 같은 맛이 납니다. seed는 그 계량과 같습니다.
컴퓨터의 "무작위"는 사실 시드(seed)라는 시작 숫자에서 규칙적으로 펼쳐지는 값입니다. 시드를 고정하면 그 "무작위"가 매번 똑같이 재생됩니다. 그래서 --seed가 같으면 결과 CSV도 한 글자까지 같습니다.
import random def one_row(rng): return rng.choice(["화재", "구조", "구급"]), rng.randint(60, 1800) # 같은 시드 → 같은 값, 매번 재현 print(one_row(random.Random(7))) # 언제 돌려도 동일 print(one_row(random.Random(7))) # 위와 같은 결과
이 재현성이 시연·테스트·디버깅을 안정시킵니다. 교육 자료의 숫자가 발표할 때마다 바뀌면 곤란하고, 코드를 고친 뒤 결과가 달라졌다면 그게 내 수정 탓인지 데이터가 바뀐 탓인지 알 수 없습니다. 시드를 고정하면 데이터를 상수로 묶어 두고 코드 변화만 관찰할 수 있습니다.
한 가지 균형이 있습니다. 시드를 하나로 고정하는 것은 시연·테스트·교육처럼 같은 결과가 필요할 때 씁니다. 반대로 분석 실력을 기르려면 시드를 바꿔 여러 벌을 만들어 보는 편이 낫습니다 — 한 벌에만 익숙해지면 그 벌의 우연한 특징에 나를 맞춰 버리기 때문입니다. 고정은 재현을 위해, 변경은 연습의 다양성을 위해 씁니다.
선택지와 트레이드오프
"합성 데이터를 쓴다"는 결정 안에서도 목적에 따라 생성 방식을 나눕니다.
| 선택지 | 맞는 상황 | 장점 | 주의할 점 |
|---|---|---|---|
| 고정 seed 한 벌 | 강의 화면·문서 예시·회귀 테스트 | 모두가 같은 입력과 기대 결과를 공유 | 한 벌의 우연한 패턴에만 맞출 수 있음 |
| 여러 seed 묶음 | 코드가 다양한 입력에서도 버티는지 연습 | 값 조합과 분포 변화를 더 넓게 경험 | 실행별 seed와 결과를 기록해야 재현 가능 |
| 규칙 기반 행 생성 | 열 사이 업무 관계를 연습해야 할 때 | 모순 조건을 의도적으로 통제하고 검산 가능 | 작성한 규칙 밖의 현실 복잡성은 나타나지 않음 |
| 작은 경계 사례 파일 | 결측·중복·날짜 오류 같은 실패를 가르칠 때 | 기대 답을 사람이 미리 확인하기 쉬움 | 일반 현황이나 현실 비율을 대표하지 않음 |
| 실제 자료를 일부 바꾼 파일 | 이번 연습 목적에는 선택하지 않음 | 실제와 비슷해 보일 수 있음 | 개인정보·재식별 위험이 남고 순수 합성으로 표시할 수 없음 |
실행
표준 라이브러리만 쓰므로 설치가 필요 없습니다.
python generate.py python generate.py --rows-dispatch 10000 --seed 7
인자 없이 실행하면 출동 5,000행·점검 2,000행을 만듭니다. --seed가 같으면 결과도 같습니다.
규칙이 박힌 합성
아무 값이나 채우지 않고, 업무 규칙을 코드에 담습니다. 예를 들어 점검 결과는 불량 항목 수로 갈립니다.
result = "적합" if failed == 0 else ("현지시정" if failed <= 2 else "시정명령")
그리고 재점검일은 "시정명령"일 때만 채워집니다.
"reinspection_due": (d + timedelta(days=30)).isoformat() if result == "시정명령" else "",
규칙 없이 아무 값이나 채우면 어떻게 될까요? "적합"인데 불량 항목이 다섯 개이고, "시정명령"인데 재점검일이 빈 표가 나옵니다. 이런 데이터로는 "시정명령 건의 재점검일 관리" 같은 분석을 연습할 수 없습니다 — 애초에 규칙이 없으니 셀 것이 없습니다. 그래서 합성이라도 업무 논리를 코드에 박아, 실데이터와 같은 방식으로 분석되게 만듭니다.
생성된 데이터는 합성임이 드러나는 ID를 씁니다(SYN-2025-000001). 지명·소방서도 전부 가상입니다.
incident_id,reported_at,incident_type,station,district,response_time_sec SYN-2025-000001,2025-08-08 23:16,화재,솔뫼소방서,다온동,389
합성도 검산합니다
합성 데이터라도 흐름이 맞는지 검산합니다. 특히 규칙이 지켜졌는지 봅니다.
[출동 검산] incident_id 중복 / reported_at 변환 실패 / response_time_sec 범위(60~1800) / 집계 합 = 전체 행 수 [점검 검산] items_failed > items_checked 행 0 / 시정명령인데 reinspection_due 빈 행 0 / 적합인데 items_failed가 0이 아닌 행 0
왜 합성인데도 검산할까요? 합성 데이터는 사람이 만든 규칙 위에 서 있고, 규칙을 코드로 옮기다 실수가 날 수 있기 때문입니다. 재점검일 조건을 반대로 걸면 "적합"인데 재점검일이 붙는 데이터가 조용히 만들어집니다. 검산은 그 조용한 버그를 잡습니다 — 실데이터를 검산하는 습관을 합성 데이터에서 미리 들이는 셈이기도 합니다. 통과하면 대략 이런 줄이 뜹니다.
[출동 검산] 중복 0 · 변환실패 0 · 범위이탈 0 · 집계합 5,000 = 전체 5,000 ✓ [점검 검산] items_failed>checked 0 · 시정명령·재점검일 누락 0 · 적합·불량>0 0 ✓
가상 상황: 신규 직원에게 집계를 가르칠 때
가상의 상황을 하나 들어 보겠습니다. 이번 주에 배치된 신규 직원에게 월간 출동 집계를 가르쳐야 합니다. 가장 좋은 교재는 실제 출동 CSV겠지만, 거기엔 신고자 정보가 들어 있어 교육용으로 건네기 어렵습니다.
대신 규칙에서 새로 만든 합성 출동 CSV를 건네면, 신규 직원은 실데이터와 같은 형식의 컬럼·의도적으로 넣은 지저분함을 상대로 집계와 검산을 끝까지 연습할 수 있습니다. 실자료를 교육 환경에 복사하지 않고 실패를 반복할 수 있지만, 합성 표기만으로 저장·공유·도구 사용이 승인되는 것은 아닙니다. 시드를 정해 두면 교육생 모두가 같은 데이터를 봐서 "제 화면엔 왜 다르게 나오죠?"가 사라집니다.
이렇게 만든 합성 CSV로 바로 이어 볼 레시피가 출동 통계, CSV 한 장으로 월간 집계와 지저분한 출동 데이터 깔끔하게 정제하기입니다.
가상 사례: 개발 담당자의 집계 회귀 테스트
다음은 교육 사례와 다른 가상 사례입니다. 개발 담당자가 월별 집계 코드를 고친 뒤 기존 결과가 의도 없이 달라지지 않았는지 확인하려 합니다. 입력은 고정 seed로 만든 합성 CSV와 미리 검토한 기대 집계이며, 제약은 실제 출동 자료를 개발 환경에 복사하지 않는 것입니다.
담당자는 고정 seed 한 벌을 기본 회귀 입력으로 두고, 결측·중복을 의도적으로 넣은 작은 경계 사례 파일을 별도로 둡니다. 코드 변경 뒤에는 생성 파일의 검산을 먼저 통과시키고, 월별 합·유형별 합·오류 목록을 기대값과 비교합니다. 차이가 나면 "코드 개선"이라고 가정하지 않고 생성 조건이 달라졌는지부터 확인합니다.
실패 가능성은 생성기와 기대값을 동시에 같은 방식으로 바꾸는 것입니다. 같은 오류가 양쪽에 들어가면 검사가 통과할 수 있습니다. 사람은 규칙 변경 이유와 기대 결과를 따로 검토하고, 승인된 변경만 기준 결과에 반영합니다. 이 사례에서는 실제 성능을 증명하는 것이 아니라 코드 변화의 영향을 재현하는 것이 목표입니다.
공개할 때 붙이는 표시
합성 데이터로 만든 표·차트를 공개하면, 다음 문구 중 하나를 붙입니다.
이 표는 119 Fire AI Studio의 합성 데이터로 만든 교육용 예시입니다. 실제 사건, 실제 주소, 실제 기관 통계를 나타내지 않습니다.
왜 굳이 표시할까요? 합성 데이터로 만든 표는 진짜 통계와 똑같이 생겼습니다. 표시가 없으면 다음 사람이 이 숫자를 실제 관할 통계로 오해할 수 있습니다. 생성 조건(명령·seed)을 함께 남기면 누구든 같은 표를 다시 만들어 검증할 수 있으니, 표시는 예의가 아니라 재현과 신뢰의 문제입니다.
합성 데이터의 한계
합성 데이터의 힘은 딱 하나 — 분석 연습 — 에서 나옵니다. 그 선을 넘으면 위험합니다.
합성 데이터의 분포는 우리가 코드에 적어 넣은 단순화한 설정값입니다. 실제 세상의 계절성, 지역 특성, 드문 대형 사고 같은 결은 담기지 않았습니다. 그래서 합성 데이터로 "이 지역이 위험하다"거나 "출동이 기준시간을 넘겼다"고 판단하면, 현실이 아니라 우리가 넣은 가정을 되읽는 꼴이 됩니다.
그래서 쓰임을 이렇게 나눕니다.
- 된다: 코드·레시피 연습, 도구 시연, 파이프라인 테스트, 신규 직원 교육.
- 안 된다: 현실에 대한 사실 주장 — 구체 항목은 아래 경고에 정리했습니다.
가장 위험한 것은 실제 자료를 '조금 바꿔' 합성인 척 섞는 것입니다. 그 순간 개인정보 위험은 그대로 남는데 '합성'이라는 방패만 잘못 씌워집니다.
문제 해결
| 증상 | 가능한 원인 | 처방 | 확인 |
|---|---|---|---|
| 같은 seed인데 결과가 달라짐 | 실행 인자·행 수·생성 순서·코드가 달라짐 | 명령, seed, 코드 버전, 생성 조건을 함께 고정해 비교 | 기록된 조건을 그대로 재실행해 파일과 검산 결과 대조 |
| 모순된 상태 조합이 생김 | 열을 각각 뽑고 관계 규칙을 적용하지 않음 | 상태를 먼저 정한 뒤 종속 열을 조건에 따라 생성 | 모순 조건별 위반 행 수가 0인지 확인 |
| 연습 코드가 한 데이터에서만 통과함 | 고정 seed 한 벌의 우연한 값에 과도하게 맞춤 | 여러 seed와 별도 경계 사례로 다시 실행 | 각 입력에서 검산과 기대 오류 목록을 비교 |
| 합성 차트가 실제 통계로 오해됨 | 제목·파일명·설명에 합성 표기가 없음 | 합성 문구와 생성 조건을 표·차트 가까이에 표시 | 원본 없이 화면만 봐도 합성임을 알 수 있는지 확인 |
자주 묻는 질문
Q. 실제 데이터에서 이름만 바꾸면 합성 데이터인가요?
아닙니다. 실제 행의 관계와 희귀 조합이 남아 재식별 위험이 이어질 수 있습니다. 이 안내서의 합성 데이터는 규칙에서 새 행을 생성하며, 실자료를 조금 바꾼 파일과 구분합니다.
Q. seed만 기록하면 같은 데이터를 재현할 수 있나요?
seed와 함께 실행 명령, 행 수, 생성 규칙과 코드 상태를 기록해야 합니다. 입력 조건이나 값 선택 순서가 달라지면 같은 seed라도 비교 대상이 달라질 수 있습니다.
Q. 합성 데이터가 검산을 통과하면 현실 분석에도 쓸 수 있나요?
검산은 작성한 생성 규칙의 일관성을 보여 줍니다. 실제 분포와 업무 사실을 대표한다는 뜻은 아니므로 현실 판단이나 성과 근거로 사용하지 않습니다.
Q. 공개할 때 파일에만 합성이라고 쓰면 충분한가요?
파일에서 떨어져 나온 표·차트도 오해될 수 있습니다. 결과물 가까이에 합성 표시를 두고, 재현이 필요한 경우 생성 조건도 함께 남깁니다.
핵심 정리
- 합성 데이터는 스키마·값 범위·열 사이 관계를 규칙으로 만들어 새 행을 생성합니다.
- 고정 seed는 재현에, 여러 seed와 경계 사례는 입력 다양성 점검에 사용합니다.
- 생성 규칙과 독립된 검산 조건으로 모순 행을 찾아야 합니다.
- 합성 결과는 분석 연습용이며 현실 사실·성과·위험 판단의 근거가 아닙니다.
다음 단계
- 지저분한 출동 데이터 깔끔하게 정제하기 — 의도적으로 넣은 결측·중복·표기 흔들림을 안전한 자료로 연습할 수 있습니다.
- 출동 통계, CSV 한 장으로 월간 집계 — 고정 seed 데이터로 집계 합과 전체 행 수 검산을 반복할 수 있습니다.
- 개인정보, AI에 넣기 전에 점검하기 — 합성이라고 주장하는 파일에 실제 정보가 섞이지 않았는지 사용 전에 확인합니다.